Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / isc / hmacmd5.c
blob08a98a55183c40d8c355c2e2184a410304967cd5
1 /* $NetBSD: hmacmd5.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2007, 2009, 2013, 2014 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 */
22 /*! \file
23 * This code implements the HMAC-MD5 keyed hash algorithm
24 * described in RFC2104.
27 #include "config.h"
29 #include <isc/assertions.h>
30 #include <isc/hmacmd5.h>
31 #include <isc/md5.h>
32 #include <isc/platform.h>
33 #include <isc/safe.h>
34 #include <isc/string.h>
35 #include <isc/types.h>
36 #include <isc/util.h>
38 #if PKCS11CRYPTO || PKCS11CRYPTOWITHHMAC
39 #include <pk11/internal.h>
40 #include <pk11/pk11.h>
41 #endif
43 #ifdef ISC_PLATFORM_OPENSSLHASH
45 void
46 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
47 unsigned int len)
49 #ifdef HMAC_RETURN_INT
50 RUNTIME_CHECK(HMAC_Init(ctx, (const void *) key,
51 (int) len, EVP_md5()) == 1);
52 #else
53 HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
54 #endif
57 void
58 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
59 HMAC_CTX_cleanup(ctx);
62 void
63 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
64 unsigned int len)
66 #ifdef HMAC_RETURN_INT
67 RUNTIME_CHECK(HMAC_Update(ctx, buf, (int) len) == 1);
68 #else
69 HMAC_Update(ctx, buf, (int) len);
70 #endif
73 void
74 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
75 #ifdef HMAC_RETURN_INT
76 RUNTIME_CHECK(HMAC_Final(ctx, digest, NULL) == 1);
77 #else
78 HMAC_Final(ctx, digest, NULL);
79 #endif
80 HMAC_CTX_cleanup(ctx);
83 #elif PKCS11CRYPTOWITHHMAC
85 static CK_BBOOL truevalue = TRUE;
86 static CK_BBOOL falsevalue = FALSE;
88 void
89 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
90 unsigned int len)
92 CK_RV rv;
93 CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 };
94 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
95 CK_KEY_TYPE keyType = CKK_MD5_HMAC;
96 CK_ATTRIBUTE keyTemplate[] =
98 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
99 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
100 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
101 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
102 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
103 { CKA_VALUE, NULL, (CK_ULONG) len }
106 DE_CONST(key, keyTemplate[5].pValue);
107 RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
108 ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
109 ctx->object = CK_INVALID_HANDLE;
110 PK11_FATALCHECK(pkcs_C_CreateObject,
111 (ctx->session, keyTemplate,
112 (CK_ULONG) 6, &ctx->object));
113 INSIST(ctx->object != CK_INVALID_HANDLE);
114 PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
117 void
118 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
119 CK_BYTE garbage[ISC_MD5_DIGESTLENGTH];
120 CK_ULONG len = ISC_MD5_DIGESTLENGTH;
122 if (ctx->handle == NULL)
123 return;
124 (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
125 memset(garbage, 0, sizeof(garbage));
126 if (ctx->object != CK_INVALID_HANDLE)
127 (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
128 ctx->object = CK_INVALID_HANDLE;
129 pk11_return_session(ctx);
132 void
133 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
134 unsigned int len)
136 CK_RV rv;
137 CK_BYTE_PTR pPart;
139 DE_CONST(buf, pPart);
140 PK11_FATALCHECK(pkcs_C_SignUpdate,
141 (ctx->session, pPart, (CK_ULONG) len));
144 void
145 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
146 CK_RV rv;
147 CK_ULONG len = ISC_MD5_DIGESTLENGTH;
149 PK11_FATALCHECK(pkcs_C_SignFinal,
150 (ctx->session, (CK_BYTE_PTR) digest, &len));
151 if (ctx->object != CK_INVALID_HANDLE)
152 (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
153 ctx->object = CK_INVALID_HANDLE;
154 pk11_return_session(ctx);
157 #elif PKCS11CRYPTO
159 #define PADLEN 64
160 #define IPAD 0x36
161 #define OPAD 0x5C
163 void
164 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
165 unsigned int len)
167 CK_RV rv;
168 CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
169 unsigned char ipad[PADLEN];
170 unsigned int i;
172 RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
173 ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
174 RUNTIME_CHECK((ctx->key = pk11_mem_get(PADLEN)) != NULL);
175 if (len > PADLEN) {
176 CK_BYTE_PTR kPart;
177 CK_ULONG kl;
179 PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
180 DE_CONST(key, kPart);
181 PK11_FATALCHECK(pkcs_C_DigestUpdate,
182 (ctx->session, kPart, (CK_ULONG) len));
183 kl = ISC_MD5_DIGESTLENGTH;
184 PK11_FATALCHECK(pkcs_C_DigestFinal,
185 (ctx->session, (CK_BYTE_PTR) ctx->key, &kl));
186 } else
187 memmove(ctx->key, key, len);
188 PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
189 memset(ipad, IPAD, PADLEN);
190 for (i = 0; i < PADLEN; i++)
191 ipad[i] ^= ctx->key[i];
192 PK11_FATALCHECK(pkcs_C_DigestUpdate,
193 (ctx->session, ipad, (CK_ULONG) PADLEN));
196 void
197 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
198 if (ctx->key != NULL)
199 pk11_mem_put(ctx->key, PADLEN);
200 ctx->key = NULL;
201 isc_md5_invalidate(ctx);
204 void
205 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
206 unsigned int len)
208 CK_RV rv;
209 CK_BYTE_PTR pPart;
211 DE_CONST(buf, pPart);
212 PK11_FATALCHECK(pkcs_C_DigestUpdate,
213 (ctx->session, pPart, (CK_ULONG) len));
216 void
217 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
218 CK_RV rv;
219 CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
220 CK_ULONG len = ISC_MD5_DIGESTLENGTH;
221 CK_BYTE opad[PADLEN];
222 unsigned int i;
224 PK11_FATALCHECK(pkcs_C_DigestFinal,
225 (ctx->session, (CK_BYTE_PTR) digest,
226 (CK_ULONG_PTR) &len));
227 memset(opad, OPAD, PADLEN);
228 for (i = 0; i < PADLEN; i++)
229 opad[i] ^= ctx->key[i];
230 pk11_mem_put(ctx->key, PADLEN);
231 ctx->key = NULL;
232 PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
233 PK11_FATALCHECK(pkcs_C_DigestUpdate,
234 (ctx->session, opad, (CK_ULONG) PADLEN));
235 PK11_FATALCHECK(pkcs_C_DigestUpdate,
236 (ctx->session, (CK_BYTE_PTR) digest, len));
237 PK11_FATALCHECK(pkcs_C_DigestFinal,
238 (ctx->session,
239 (CK_BYTE_PTR) digest,
240 (CK_ULONG_PTR) &len));
241 pk11_return_session(ctx);
244 #else
246 #define PADLEN 64
247 #define IPAD 0x36
248 #define OPAD 0x5C
251 * Start HMAC-MD5 process. Initialize an md5 context and digest the key.
253 void
254 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
255 unsigned int len)
257 unsigned char ipad[PADLEN];
258 int i;
260 memset(ctx->key, 0, sizeof(ctx->key));
261 if (len > sizeof(ctx->key)) {
262 isc_md5_t md5ctx;
263 isc_md5_init(&md5ctx);
264 isc_md5_update(&md5ctx, key, len);
265 isc_md5_final(&md5ctx, ctx->key);
266 } else
267 memmove(ctx->key, key, len);
269 isc_md5_init(&ctx->md5ctx);
270 memset(ipad, IPAD, sizeof(ipad));
271 for (i = 0; i < PADLEN; i++)
272 ipad[i] ^= ctx->key[i];
273 isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
276 void
277 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
278 isc_md5_invalidate(&ctx->md5ctx);
279 memset(ctx->key, 0, sizeof(ctx->key));
283 * Update context to reflect the concatenation of another buffer full
284 * of bytes.
286 void
287 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
288 unsigned int len)
290 isc_md5_update(&ctx->md5ctx, buf, len);
294 * Compute signature - finalize MD5 operation and reapply MD5.
296 void
297 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
298 unsigned char opad[PADLEN];
299 int i;
301 isc_md5_final(&ctx->md5ctx, digest);
303 memset(opad, OPAD, sizeof(opad));
304 for (i = 0; i < PADLEN; i++)
305 opad[i] ^= ctx->key[i];
307 isc_md5_init(&ctx->md5ctx);
308 isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
309 isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
310 isc_md5_final(&ctx->md5ctx, digest);
311 isc_hmacmd5_invalidate(ctx);
314 #endif /* !ISC_PLATFORM_OPENSSLHASH */
317 * Verify signature - finalize MD5 operation and reapply MD5, then
318 * compare to the supplied digest.
320 isc_boolean_t
321 isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
322 return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH));
325 isc_boolean_t
326 isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) {
327 unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
329 REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
330 isc_hmacmd5_sign(ctx, newdigest);
331 return (isc_safe_memcmp(digest, newdigest, len));