Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / lib / isc / hmacmd5.c
1 /*
2  * Copyright (C) 2004, 2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: hmacmd5.c,v 1.5.12.5 2006/02/26 23:49:48 marka Exp $ */
19
20 /*
21  * This code implements the HMAC-MD5 keyed hash algorithm
22  * described in RFC 2104.
23  */
24
25 #include "config.h"
26
27 #include <isc/assertions.h>
28 #include <isc/hmacmd5.h>
29 #include <isc/md5.h>
30 #include <isc/string.h>
31 #include <isc/types.h>
32 #include <isc/util.h>
33
34 #define PADLEN 64
35 #define IPAD 0x36
36 #define OPAD 0x5C
37
38 /*
39  * Start HMAC-MD5 process.  Initialize an md5 context and digest the key.
40  */
41 void
42 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
43                  unsigned int len)
44 {
45         unsigned char ipad[PADLEN];
46         int i;
47
48         memset(ctx->key, 0, sizeof(ctx->key));
49         if (len > sizeof(ctx->key)) {
50                 isc_md5_t md5ctx;
51                 isc_md5_init(&md5ctx);
52                 isc_md5_update(&md5ctx, key, len);
53                 isc_md5_final(&md5ctx, ctx->key);
54         } else
55                 memcpy(ctx->key, key, len);
56
57         isc_md5_init(&ctx->md5ctx);
58         memset(ipad, IPAD, sizeof(ipad));
59         for (i = 0; i < PADLEN; i++)
60                 ipad[i] ^= ctx->key[i];
61         isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
62 }
63
64 void
65 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
66         isc_md5_invalidate(&ctx->md5ctx);
67         memset(ctx->key, 0, sizeof(ctx->key));
68 }
69
70 /*
71  * Update context to reflect the concatenation of another buffer full
72  * of bytes.
73  */
74 void
75 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
76                    unsigned int len)
77 {
78         isc_md5_update(&ctx->md5ctx, buf, len);
79 }
80
81 /*
82  * Compute signature - finalize MD5 operation and reapply MD5.
83  */
84 void
85 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
86         unsigned char opad[PADLEN];
87         int i;
88
89         isc_md5_final(&ctx->md5ctx, digest);
90
91         memset(opad, OPAD, sizeof(opad));
92         for (i = 0; i < PADLEN; i++)
93                 opad[i] ^= ctx->key[i];
94
95         isc_md5_init(&ctx->md5ctx);
96         isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
97         isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
98         isc_md5_final(&ctx->md5ctx, digest);
99         isc_hmacmd5_invalidate(ctx);
100 }
101
102 /*
103  * Verify signature - finalize MD5 operation and reapply MD5, then
104  * compare to the supplied digest.
105  */
106 isc_boolean_t
107 isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
108         unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
109
110         isc_hmacmd5_sign(ctx, newdigest);
111         return (ISC_TF(memcmp(digest, newdigest, ISC_MD5_DIGESTLENGTH) == 0));
112 }