4 * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: hmacmd5.c,v 1.16 2009/02/06 23:47:42 tbox Exp */
23 * This code implements the HMAC-MD5 keyed hash algorithm
24 * described in RFC2104.
29 #include <isc/assertions.h>
30 #include <isc/hmacmd5.h>
32 #include <isc/platform.h>
33 #include <isc/string.h>
34 #include <isc/types.h>
37 #ifdef ISC_PLATFORM_OPENSSLHASH
40 isc_hmacmd5_init(isc_hmacmd5_t
*ctx
, const unsigned char *key
,
43 HMAC_Init(ctx
, (const void *) key
, (int) len
, EVP_md5());
47 isc_hmacmd5_invalidate(isc_hmacmd5_t
*ctx
) {
48 HMAC_CTX_cleanup(ctx
);
52 isc_hmacmd5_update(isc_hmacmd5_t
*ctx
, const unsigned char *buf
,
55 HMAC_Update(ctx
, buf
, (int) len
);
59 isc_hmacmd5_sign(isc_hmacmd5_t
*ctx
, unsigned char *digest
) {
60 HMAC_Final(ctx
, digest
, NULL
);
61 HMAC_CTX_cleanup(ctx
);
71 * Start HMAC-MD5 process. Initialize an md5 context and digest the key.
74 isc_hmacmd5_init(isc_hmacmd5_t
*ctx
, const unsigned char *key
,
77 unsigned char ipad
[PADLEN
];
80 memset(ctx
->key
, 0, sizeof(ctx
->key
));
81 if (len
> sizeof(ctx
->key
)) {
83 isc_md5_init(&md5ctx
);
84 isc_md5_update(&md5ctx
, key
, len
);
85 isc_md5_final(&md5ctx
, ctx
->key
);
87 memcpy(ctx
->key
, key
, len
);
89 isc_md5_init(&ctx
->md5ctx
);
90 memset(ipad
, IPAD
, sizeof(ipad
));
91 for (i
= 0; i
< PADLEN
; i
++)
92 ipad
[i
] ^= ctx
->key
[i
];
93 isc_md5_update(&ctx
->md5ctx
, ipad
, sizeof(ipad
));
97 isc_hmacmd5_invalidate(isc_hmacmd5_t
*ctx
) {
98 isc_md5_invalidate(&ctx
->md5ctx
);
99 memset(ctx
->key
, 0, sizeof(ctx
->key
));
103 * Update context to reflect the concatenation of another buffer full
107 isc_hmacmd5_update(isc_hmacmd5_t
*ctx
, const unsigned char *buf
,
110 isc_md5_update(&ctx
->md5ctx
, buf
, len
);
114 * Compute signature - finalize MD5 operation and reapply MD5.
117 isc_hmacmd5_sign(isc_hmacmd5_t
*ctx
, unsigned char *digest
) {
118 unsigned char opad
[PADLEN
];
121 isc_md5_final(&ctx
->md5ctx
, digest
);
123 memset(opad
, OPAD
, sizeof(opad
));
124 for (i
= 0; i
< PADLEN
; i
++)
125 opad
[i
] ^= ctx
->key
[i
];
127 isc_md5_init(&ctx
->md5ctx
);
128 isc_md5_update(&ctx
->md5ctx
, opad
, sizeof(opad
));
129 isc_md5_update(&ctx
->md5ctx
, digest
, ISC_MD5_DIGESTLENGTH
);
130 isc_md5_final(&ctx
->md5ctx
, digest
);
131 isc_hmacmd5_invalidate(ctx
);
133 #endif /* !ISC_PLATFORM_OPENSSLHASH */
136 * Verify signature - finalize MD5 operation and reapply MD5, then
137 * compare to the supplied digest.
140 isc_hmacmd5_verify(isc_hmacmd5_t
*ctx
, unsigned char *digest
) {
141 return (isc_hmacmd5_verify2(ctx
, digest
, ISC_MD5_DIGESTLENGTH
));
145 isc_hmacmd5_verify2(isc_hmacmd5_t
*ctx
, unsigned char *digest
, size_t len
) {
146 unsigned char newdigest
[ISC_MD5_DIGESTLENGTH
];
148 REQUIRE(len
<= ISC_MD5_DIGESTLENGTH
);
149 isc_hmacmd5_sign(ctx
, newdigest
);
150 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));