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