Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / hmacmd5.c
1 /*
2  * Copyright (C) 2004  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.2.1 2004/03/09 06:11:46 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         memset(ctx, 0, sizeof (ctx));
69 }
70
71 /*
72  * Update context to reflect the concatenation of another buffer full
73  * of bytes.
74  */
75 void
76 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
77                    unsigned int len)
78 {
79         isc_md5_update(&ctx->md5ctx, buf, len);
80 }
81
82 /*
83  * Compute signature - finalize MD5 operation and reapply MD5.
84  */
85 void
86 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
87         unsigned char opad[PADLEN];
88         int i;
89
90         isc_md5_final(&ctx->md5ctx, digest);
91
92         memset(opad, OPAD, sizeof (opad));
93         for (i = 0; i < PADLEN; i++)
94                 opad[i] ^= ctx->key[i];
95
96         isc_md5_init(&ctx->md5ctx);
97         isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
98         isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
99         isc_md5_final(&ctx->md5ctx, digest);
100         isc_hmacmd5_invalidate(ctx);
101 }
102
103 /*
104  * Verify signature - finalize MD5 operation and reapply MD5, then
105  * compare to the supplied digest.
106  */
107 isc_boolean_t
108 isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
109         unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
110
111         isc_hmacmd5_sign(ctx, newdigest);
112         return (ISC_TF(memcmp(digest, newdigest, ISC_MD5_DIGESTLENGTH) == 0));
113 }