xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softMAC.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <pthread.h>
30 #include <sys/md5.h>
31 #include <sys/sha1.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <sys/types.h>
36 #include <security/cryptoki.h>
37 #include "softObject.h"
38 #include "softOps.h"
39 #include "softSession.h"
40 #include "softMAC.h"
41 
42 /*
43  * IPAD = 0x36 repeated 48 times for ssl md5, repeated 40 times for ssl sha1
44  * OPAD = 0x5C repeated 48 times for SSL md5, repeated 40 times for ssl sha1
45  */
46 const uint32_t md5_ssl_ipad[] = {
47 	0x36363636, 0x36363636, 0x36363636, 0x36363636, 0x36363636,
48 	0x36363636, 0x36363636, 0x36363636, 0x36363636, 0x36363636,
49 	0x36363636, 0x36363636};
50 const uint32_t sha1_ssl_ipad[] = {
51 	0x36363636, 0x36363636, 0x36363636, 0x36363636, 0x36363636,
52 	0x36363636, 0x36363636, 0x36363636, 0x36363636, 0x36363636};
53 const uint32_t md5_ssl_opad[] = {
54 	0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c,
55 	0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c,
56 	0x5c5c5c5c, 0x5c5c5c5c};
57 const uint32_t sha1_ssl_opad[] = {
58 	0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c,
59 	0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c};
60 
61 /*
62  * Allocate and initialize a HMAC context, and save the context pointer in
63  * the session struct. For General-length HMAC, checks the length in the
64  * parameter to see if it is in the right range.
65  */
66 CK_RV
67 soft_hmac_sign_verify_init_common(soft_session_t *session_p,
68     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
69 {
70 
71 	soft_hmac_ctx_t *hmac_ctx;
72 	CK_RV rv = CKR_OK;
73 
74 	if ((key_p->class != CKO_SECRET_KEY) ||
75 	    (key_p->key_type != CKK_GENERIC_SECRET)) {
76 		return (CKR_KEY_TYPE_INCONSISTENT);
77 	}
78 
79 	hmac_ctx = malloc(sizeof (soft_hmac_ctx_t));
80 
81 	if (hmac_ctx == NULL) {
82 		return (CKR_HOST_MEMORY);
83 	}
84 
85 	switch (pMechanism->mechanism) {
86 
87 	case CKM_SSL3_MD5_MAC:
88 	case CKM_SSL3_SHA1_MAC:
89 	case CKM_MD5_HMAC_GENERAL:
90 	case CKM_SHA_1_HMAC_GENERAL:
91 
92 		if (pMechanism->ulParameterLen !=
93 		    sizeof (CK_MAC_GENERAL_PARAMS)) {
94 			free(hmac_ctx);
95 			return (CKR_MECHANISM_PARAM_INVALID);
96 		}
97 
98 		if (pMechanism->mechanism == CKM_MD5_HMAC_GENERAL ||
99 		    pMechanism->mechanism == CKM_SSL3_MD5_MAC) {
100 			if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
101 			    MD5_HASH_SIZE) {
102 				free(hmac_ctx);
103 				return (CKR_MECHANISM_PARAM_INVALID);
104 			}
105 		} else {
106 			if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
107 			    SHA1_HASH_SIZE) {
108 				free(hmac_ctx);
109 				return (CKR_MECHANISM_PARAM_INVALID);
110 			}
111 		}
112 
113 		hmac_ctx->hmac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
114 		    pMechanism->pParameter);
115 
116 		/*FALLTHRU*/
117 	case CKM_MD5_HMAC:
118 	case CKM_SHA_1_HMAC:
119 
120 		if (pMechanism->mechanism == CKM_MD5_HMAC) {
121 			hmac_ctx->hmac_len = MD5_HASH_SIZE;
122 		} else if (pMechanism->mechanism == CKM_SHA_1_HMAC) {
123 			hmac_ctx->hmac_len = SHA1_HASH_SIZE;
124 		}
125 
126 		/* Initialize a MAC context. */
127 		rv = mac_init_ctx(session_p, key_p, hmac_ctx,
128 		    pMechanism->mechanism);
129 		if (rv != CKR_OK)
130 			return (rv);
131 
132 		(void) pthread_mutex_lock(&session_p->session_mutex);
133 
134 		if (sign_op) {
135 			session_p->sign.mech.mechanism =
136 			    pMechanism->mechanism;
137 			session_p->sign.context = hmac_ctx;
138 		} else {
139 			session_p->verify.mech.mechanism =
140 			    pMechanism->mechanism;
141 			session_p->verify.context = hmac_ctx;
142 		}
143 
144 		(void) pthread_mutex_unlock(&session_p->session_mutex);
145 
146 		break;
147 	}
148 
149 	return (CKR_OK);
150 }
151 
152 
153 /*
154  * Initialize a HMAC context.
155  */
156 CK_RV
157 mac_init_ctx(soft_session_t *session_p, soft_object_t *key,
158     soft_hmac_ctx_t *ctx, CK_MECHANISM_TYPE mech)
159 {
160 	CK_RV rv = CKR_OK;
161 
162 	switch (mech) {
163 	case CKM_SSL3_MD5_MAC:
164 	{
165 		CK_BYTE md5_ipad[MD5_SSL_PAD_AND_KEY_SIZE];
166 		CK_BYTE md5_opad[MD5_SSL_PAD_AND_KEY_SIZE];
167 
168 		if (OBJ_SEC(key)->sk_value_len > MD5_SSL_PAD_AND_KEY_SIZE) {
169 			return (CKR_KEY_SIZE_RANGE);
170 		}
171 
172 		bzero(md5_ipad, MD5_SSL_PAD_AND_KEY_SIZE);
173 		bzero(md5_opad, MD5_SSL_PAD_AND_KEY_SIZE);
174 
175 		/* SSL MAC is HASH(key + opad + HASH(key + ipad + data)) */
176 		(void) memcpy(md5_ipad, OBJ_SEC(key)->sk_value,
177 		    OBJ_SEC(key)->sk_value_len);
178 		(void) memcpy(&md5_ipad[OBJ_SEC(key)->sk_value_len],
179 		    md5_ssl_ipad, MD5_SSL_PAD_SIZE);
180 		(void) memcpy(md5_opad, OBJ_SEC(key)->sk_value,
181 		    OBJ_SEC(key)->sk_value_len);
182 		(void) memcpy(&md5_opad[OBJ_SEC(key)->sk_value_len],
183 		    md5_ssl_opad, MD5_SSL_PAD_SIZE);
184 
185 		SOFT_MAC_INIT_CTX(MD5, &(ctx->hc_ctx_u.md5_ctx),
186 		    md5_ipad, md5_opad, MD5_SSL_PAD_AND_KEY_SIZE);
187 
188 		break;
189 	}
190 	case CKM_MD5_HMAC_GENERAL:
191 	case CKM_MD5_HMAC:
192 	{
193 		uint32_t md5_ipad[MD5_HMAC_INTS_PER_BLOCK];
194 		uint32_t md5_opad[MD5_HMAC_INTS_PER_BLOCK];
195 		CK_MECHANISM digest_mech;
196 		CK_ULONG hash_len = MD5_HASH_SIZE;
197 
198 		bzero(md5_ipad, MD5_HMAC_BLOCK_SIZE);
199 		bzero(md5_opad, MD5_HMAC_BLOCK_SIZE);
200 
201 		if (OBJ_SEC(key)->sk_value_len > MD5_HMAC_BLOCK_SIZE) {
202 			/*
203 			 * Hash the key when it is longer than 64 bytes.
204 			 */
205 			digest_mech.mechanism = CKM_MD5;
206 			digest_mech.pParameter = NULL_PTR;
207 			digest_mech.ulParameterLen = 0;
208 			rv = soft_digest_init_internal(session_p, &digest_mech);
209 			if (rv != CKR_OK)
210 				return (rv);
211 			rv = soft_digest(session_p, OBJ_SEC(key)->sk_value,
212 			    OBJ_SEC(key)->sk_value_len, (CK_BYTE_PTR)md5_ipad,
213 			    &hash_len);
214 			session_p->digest.flags = 0;
215 			if (rv != CKR_OK)
216 				return (rv);
217 			(void) memcpy(md5_opad, md5_ipad, hash_len);
218 		} else {
219 			(void) memcpy(md5_ipad, OBJ_SEC(key)->sk_value,
220 			    OBJ_SEC(key)->sk_value_len);
221 			(void) memcpy(md5_opad, OBJ_SEC(key)->sk_value,
222 			    OBJ_SEC(key)->sk_value_len);
223 		}
224 
225 		md5_hmac_ctx_init(&ctx->hc_ctx_u.md5_ctx, md5_ipad, md5_opad);
226 		break;
227 	}
228 
229 	case CKM_SSL3_SHA1_MAC:
230 	{
231 		CK_BYTE sha1_ipad[SHA1_SSL_PAD_AND_KEY_SIZE];
232 		CK_BYTE sha1_opad[SHA1_SSL_PAD_AND_KEY_SIZE];
233 
234 		if (OBJ_SEC(key)->sk_value_len > SHA1_HMAC_BLOCK_SIZE) {
235 			return (CKR_KEY_SIZE_RANGE);
236 		}
237 
238 		bzero(sha1_ipad, SHA1_SSL_PAD_AND_KEY_SIZE);
239 		bzero(sha1_opad, SHA1_SSL_PAD_AND_KEY_SIZE);
240 
241 		/* SSL MAC is HASH(key + opad + HASH(key + ipad + data)) */
242 		(void) memcpy(sha1_ipad, OBJ_SEC(key)->sk_value,
243 		    OBJ_SEC(key)->sk_value_len);
244 		(void) memcpy(&sha1_ipad[OBJ_SEC(key)->sk_value_len],
245 		    sha1_ssl_ipad, SHA1_SSL_PAD_SIZE);
246 		(void) memcpy(sha1_opad, OBJ_SEC(key)->sk_value,
247 		    OBJ_SEC(key)->sk_value_len);
248 		(void) memcpy(&sha1_opad[OBJ_SEC(key)->sk_value_len],
249 		    sha1_ssl_opad, SHA1_SSL_PAD_SIZE);
250 
251 		SOFT_MAC_INIT_CTX(SHA1, &(ctx->hc_ctx_u.sha1_ctx),
252 		    sha1_ipad, sha1_opad, SHA1_SSL_PAD_AND_KEY_SIZE);
253 
254 		break;
255 	}
256 	case CKM_SHA_1_HMAC_GENERAL:
257 	case CKM_SHA_1_HMAC:
258 	{
259 		uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK];
260 		uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK];
261 		CK_MECHANISM digest_mech;
262 		CK_ULONG hash_len = SHA1_HASH_SIZE;
263 
264 		bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
265 		bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
266 
267 		if (OBJ_SEC(key)->sk_value_len > SHA1_HMAC_BLOCK_SIZE) {
268 			/*
269 			 * Hash the key when it is longer than 64 bytes.
270 			 */
271 			digest_mech.mechanism = CKM_SHA_1;
272 			digest_mech.pParameter = NULL_PTR;
273 			digest_mech.ulParameterLen = 0;
274 			rv = soft_digest_init_internal(session_p, &digest_mech);
275 			if (rv != CKR_OK)
276 				return (rv);
277 			rv = soft_digest(session_p, OBJ_SEC(key)->sk_value,
278 			    OBJ_SEC(key)->sk_value_len, (CK_BYTE_PTR)sha1_ipad,
279 			    &hash_len);
280 			session_p->digest.flags = 0;
281 			if (rv != CKR_OK)
282 				return (rv);
283 			(void) memcpy(sha1_opad, sha1_ipad, hash_len);
284 		} else {
285 			(void) memcpy(sha1_ipad, OBJ_SEC(key)->sk_value,
286 			    OBJ_SEC(key)->sk_value_len);
287 			(void) memcpy(sha1_opad, OBJ_SEC(key)->sk_value,
288 			    OBJ_SEC(key)->sk_value_len);
289 		}
290 
291 		sha1_hmac_ctx_init(&ctx->hc_ctx_u.sha1_ctx, sha1_ipad,
292 		    sha1_opad);
293 
294 		break;
295 	}
296 	}
297 	return (rv);
298 }
299 
300 
301 /*
302  * Called by soft_sign(), soft_sign_final(), soft_verify() or
303  * soft_verify_final().
304  */
305 CK_RV
306 soft_hmac_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
307     CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
308     boolean_t sign_op)
309 {
310 
311 	soft_hmac_ctx_t	*hmac_ctx;
312 	CK_MECHANISM_TYPE	mechanism;
313 #ifdef	__sparcv9
314 	/* LINTED */
315 	uint_t datalen = (uint_t)ulDataLen;
316 #else	/* __sparcv9 */
317 	uint_t datalen = ulDataLen;
318 #endif	/* __sparcv9 */
319 
320 	if (sign_op) {
321 		hmac_ctx = (soft_hmac_ctx_t *)session_p->sign.context;
322 		mechanism = session_p->sign.mech.mechanism;
323 
324 		/*
325 		 * If application asks for the length of the output buffer
326 		 * to hold the signature?
327 		 */
328 		if (pSigned == NULL) {
329 			*pulSignedLen = hmac_ctx->hmac_len;
330 			return (CKR_OK);
331 		}
332 
333 		/* Is the application-supplied buffer large enough? */
334 		if (*pulSignedLen < hmac_ctx->hmac_len) {
335 			*pulSignedLen = hmac_ctx->hmac_len;
336 			return (CKR_BUFFER_TOO_SMALL);
337 		}
338 	} else {
339 		hmac_ctx = (soft_hmac_ctx_t *)session_p->verify.context;
340 		mechanism = session_p->verify.mech.mechanism;
341 	}
342 
343 	switch (mechanism) {
344 
345 	case CKM_SSL3_MD5_MAC:
346 	case CKM_MD5_HMAC_GENERAL:
347 	case CKM_MD5_HMAC:
348 
349 		if (pData != NULL) {
350 			/* Called by soft_sign() or soft_verify(). */
351 			SOFT_MAC_UPDATE(MD5, &(hmac_ctx->hc_ctx_u.md5_ctx),
352 			    pData, datalen);
353 		}
354 		SOFT_MAC_FINAL(MD5, &(hmac_ctx->hc_ctx_u.md5_ctx), pSigned);
355 		*pulSignedLen = hmac_ctx->hmac_len;
356 
357 		break;
358 
359 	case CKM_SSL3_SHA1_MAC:
360 	case CKM_SHA_1_HMAC_GENERAL:
361 	case CKM_SHA_1_HMAC:
362 
363 		if (pData != NULL) {
364 			/* Called by soft_sign() or soft_verify(). */
365 			SOFT_MAC_UPDATE(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx),
366 			    pData, datalen);
367 		}
368 		SOFT_MAC_FINAL(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), pSigned);
369 		*pulSignedLen = hmac_ctx->hmac_len;
370 
371 		break;
372 	}
373 
374 clean_exit:
375 
376 	(void) pthread_mutex_lock(&session_p->session_mutex);
377 
378 	if (sign_op) {
379 		bzero(session_p->sign.context, sizeof (soft_hmac_ctx_t));
380 		free(session_p->sign.context);
381 		session_p->sign.context = NULL;
382 	} else {
383 		bzero(session_p->verify.context, sizeof (soft_hmac_ctx_t));
384 		free(session_p->verify.context);
385 		session_p->verify.context = NULL;
386 	}
387 
388 	(void) pthread_mutex_unlock(&session_p->session_mutex);
389 
390 	return (CKR_OK);
391 }
392 
393 
394 /*
395  * Called by soft_sign_update() or soft_verify_update().
396  */
397 CK_RV
398 soft_hmac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
399 	CK_ULONG ulPartLen, boolean_t sign_op)
400 {
401 
402 	soft_hmac_ctx_t	*hmac_ctx;
403 	CK_MECHANISM_TYPE	mechanism;
404 #ifdef	__sparcv9
405 	/* LINTED */
406 	uint_t partlen = (uint_t)ulPartLen;
407 #else	/* __sparcv9 */
408 	uint_t partlen = ulPartLen;
409 #endif	/* __sparcv9 */
410 
411 	if (sign_op) {
412 		hmac_ctx = (soft_hmac_ctx_t *)session_p->sign.context;
413 		mechanism = session_p->sign.mech.mechanism;
414 	} else {
415 		hmac_ctx = (soft_hmac_ctx_t *)session_p->verify.context;
416 		mechanism = session_p->verify.mech.mechanism;
417 	}
418 
419 	switch (mechanism) {
420 
421 	case CKM_SSL3_MD5_MAC:
422 	case CKM_MD5_HMAC_GENERAL:
423 	case CKM_MD5_HMAC:
424 
425 		SOFT_MAC_UPDATE(MD5, &(hmac_ctx->hc_ctx_u.md5_ctx), pPart,
426 		    partlen);
427 		break;
428 
429 	case CKM_SSL3_SHA1_MAC:
430 	case CKM_SHA_1_HMAC_GENERAL:
431 	case CKM_SHA_1_HMAC:
432 
433 		SOFT_MAC_UPDATE(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), pPart,
434 		    partlen);
435 
436 		break;
437 	}
438 	return (CKR_OK);
439 }
440 
441 /*
442  * The following 2 functions expect the MAC key to be alreay copied in
443  * the ipad and opad
444  */
445 void
446 md5_hmac_ctx_init(md5_hc_ctx_t *md5_hmac_ctx, uint32_t *ipad, uint32_t *opad)
447 {
448 	int i;
449 	/* XOR key with ipad (0x36) and opad (0x5c) */
450 	for (i = 0; i < MD5_HMAC_INTS_PER_BLOCK; i++) {
451 		ipad[i] ^= 0x36363636;
452 		opad[i] ^= 0x5c5c5c5c;
453 	}
454 	SOFT_MAC_INIT_CTX(MD5, md5_hmac_ctx, ipad, opad, MD5_HMAC_BLOCK_SIZE);
455 }
456 
457 void
458 sha1_hmac_ctx_init(sha1_hc_ctx_t *sha1_hmac_ctx, uint32_t *ipad, uint32_t *opad)
459 {
460 	int i;
461 	/* XOR key with ipad (0x36) and opad (0x5c) */
462 	for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) {
463 		ipad[i] ^= 0x36363636;
464 		opad[i] ^= 0x5c5c5c5c;
465 	}
466 	SOFT_MAC_INIT_CTX(SHA1, sha1_hmac_ctx, (const uchar_t *)ipad,
467 	    (const uchar_t *)opad, SHA1_HMAC_BLOCK_SIZE);
468 }
469