4 * Copyright (C) 2004-2007 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.14 2007/06/19 23:47:17 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/string.h>
33 #include <isc/types.h>
41 * Start HMAC-MD5 process. Initialize an md5 context and digest the key.
44 isc_hmacmd5_init(isc_hmacmd5_t
*ctx
, const unsigned char *key
,
47 unsigned char ipad
[PADLEN
];
50 memset(ctx
->key
, 0, sizeof(ctx
->key
));
51 if (len
> sizeof(ctx
->key
)) {
53 isc_md5_init(&md5ctx
);
54 isc_md5_update(&md5ctx
, key
, len
);
55 isc_md5_final(&md5ctx
, ctx
->key
);
57 memcpy(ctx
->key
, key
, len
);
59 isc_md5_init(&ctx
->md5ctx
);
60 memset(ipad
, IPAD
, sizeof(ipad
));
61 for (i
= 0; i
< PADLEN
; i
++)
62 ipad
[i
] ^= ctx
->key
[i
];
63 isc_md5_update(&ctx
->md5ctx
, ipad
, sizeof(ipad
));
67 isc_hmacmd5_invalidate(isc_hmacmd5_t
*ctx
) {
68 isc_md5_invalidate(&ctx
->md5ctx
);
69 memset(ctx
->key
, 0, sizeof(ctx
->key
));
73 * Update context to reflect the concatenation of another buffer full
77 isc_hmacmd5_update(isc_hmacmd5_t
*ctx
, const unsigned char *buf
,
80 isc_md5_update(&ctx
->md5ctx
, buf
, len
);
84 * Compute signature - finalize MD5 operation and reapply MD5.
87 isc_hmacmd5_sign(isc_hmacmd5_t
*ctx
, unsigned char *digest
) {
88 unsigned char opad
[PADLEN
];
91 isc_md5_final(&ctx
->md5ctx
, digest
);
93 memset(opad
, OPAD
, sizeof(opad
));
94 for (i
= 0; i
< PADLEN
; i
++)
95 opad
[i
] ^= ctx
->key
[i
];
97 isc_md5_init(&ctx
->md5ctx
);
98 isc_md5_update(&ctx
->md5ctx
, opad
, sizeof(opad
));
99 isc_md5_update(&ctx
->md5ctx
, digest
, ISC_MD5_DIGESTLENGTH
);
100 isc_md5_final(&ctx
->md5ctx
, digest
);
101 isc_hmacmd5_invalidate(ctx
);
105 * Verify signature - finalize MD5 operation and reapply MD5, then
106 * compare to the supplied digest.
109 isc_hmacmd5_verify(isc_hmacmd5_t
*ctx
, unsigned char *digest
) {
110 return (isc_hmacmd5_verify2(ctx
, digest
, ISC_MD5_DIGESTLENGTH
));
114 isc_hmacmd5_verify2(isc_hmacmd5_t
*ctx
, unsigned char *digest
, size_t len
) {
115 unsigned char newdigest
[ISC_MD5_DIGESTLENGTH
];
117 REQUIRE(len
<= ISC_MD5_DIGESTLENGTH
);
118 isc_hmacmd5_sign(ctx
, newdigest
);
119 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));