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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/errno.h> 29 #include <sys/kmem.h> 30 #include <sys/systm.h> 31 #include <sys/sha1.h> 32 #include <sys/crypto/common.h> 33 #include <sys/cmn_err.h> 34 #ifndef _KERNEL 35 #include <stdlib.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <stdio.h> 39 #include <security/cryptoki.h> 40 #include <cryptoutil.h> 41 #include "softMAC.h" 42 #endif 43 #include <sha1/sha1_impl.h> 44 45 /* 46 * fips_sha1_build_context() 47 * 48 * Description: 49 * This function allocates and initializes SHA1 context 50 * context. 51 */ 52 SHA1_CTX * 53 fips_sha1_build_context(void) 54 { 55 SHA1_CTX *sha1_context; 56 57 58 #ifndef _KERNEL 59 if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL) 60 #else 61 if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX), 62 KM_SLEEP)) == NULL) 63 #endif 64 return (NULL); 65 66 SHA1Init(sha1_context); 67 68 return (sha1_context); 69 70 } 71 72 /* 73 * fips_sha1_hash() 74 * 75 * Arguments: 76 * sha1_context: pointer to SHA1 context 77 * in: pointer to the input data to be hashed 78 * inlen: length of the input data 79 * out: pointer to the output data after hashing 80 * 81 * Description: 82 * This function calls the low-level SHA1 routines for hashing. 83 * 84 */ 85 int 86 fips_sha1_hash(SHA1_CTX *sha1_context, uchar_t *in, ulong_t inlen, uchar_t *out) 87 { 88 89 if (in != NULL) { 90 #ifdef __sparcv9 91 SHA1Update((SHA1_CTX *)sha1_context, in, (uint_t)inlen); 92 #else /* !__sparcv9 */ 93 SHA1Update((SHA1_CTX *)sha1_context, in, inlen); 94 #endif /* __sparcv9 */ 95 SHA1Final(out, (SHA1_CTX *)sha1_context); 96 return (CKR_OK); 97 } else 98 return (CKR_ARGUMENTS_BAD); 99 100 } 101 102 103 #ifndef _KERNEL 104 soft_hmac_ctx_t * 105 fips_sha1_hmac_build_context(uint8_t *secret_key, 106 unsigned int secret_key_length) 107 { 108 109 soft_hmac_ctx_t *hmac_ctx; 110 uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK]; 111 uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK]; 112 113 hmac_ctx = malloc(sizeof (soft_hmac_ctx_t)); 114 115 if (hmac_ctx == NULL) { 116 return (NULL); 117 } 118 119 hmac_ctx->hmac_len = SHA1_HASH_SIZE; 120 bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE); 121 bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE); 122 123 (void) memcpy(sha1_ipad, secret_key, secret_key_length); 124 (void) memcpy(sha1_opad, secret_key, secret_key_length); 125 126 sha1_hmac_ctx_init(&hmac_ctx->hc_ctx_u.sha1_ctx, sha1_ipad, 127 sha1_opad); 128 129 return (hmac_ctx); 130 131 } 132 133 CK_RV 134 fips_hmac_sha1_hash(unsigned char *hmac_computed, 135 uint8_t *secret_key, 136 unsigned int secret_key_length, 137 uint8_t *message, 138 unsigned int message_length) 139 { 140 141 soft_hmac_ctx_t *hmac_ctx = NULL; 142 143 hmac_ctx = fips_sha1_hmac_build_context(secret_key, 144 secret_key_length); 145 146 if (hmac_ctx == NULL) 147 return (CKR_HOST_MEMORY); 148 149 if (message != NULL) { 150 SOFT_MAC_UPDATE(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), 151 message, message_length); 152 } 153 154 SOFT_MAC_FINAL(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), hmac_computed); 155 156 free(hmac_ctx); 157 return (CKR_OK); 158 } 159 160 #else /* _KERNEL */ 161 162 /* 163 * Initialize a SHA1-HMAC context. 164 */ 165 void 166 sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 167 { 168 uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK]; 169 uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK]; 170 uint_t i; 171 172 bzero(ipad, SHA1_HMAC_BLOCK_SIZE); 173 bzero(opad, SHA1_HMAC_BLOCK_SIZE); 174 175 bcopy(keyval, ipad, length_in_bytes); 176 bcopy(keyval, opad, length_in_bytes); 177 178 /* XOR key with ipad (0x36) and opad (0x5c) */ 179 for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) { 180 ipad[i] ^= 0x36363636; 181 opad[i] ^= 0x5c5c5c5c; 182 } 183 184 /* perform SHA1 on ipad */ 185 SHA1Init(&ctx->hc_icontext); 186 SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE); 187 188 /* perform SHA1 on opad */ 189 SHA1Init(&ctx->hc_ocontext); 190 SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE); 191 } 192 193 sha1_hmac_ctx_t * 194 fips_sha1_hmac_build_context(uint8_t *secret_key, 195 unsigned int secret_key_length) 196 { 197 sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl; 198 199 200 /* 201 * Allocate and initialize SHA1 context. 202 */ 203 sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t), 204 KM_SLEEP); 205 if (sha1_hmac_ctx_tmpl == NULL) 206 return (NULL); 207 208 /* 209 * initialize ctx->hc_icontext and ctx->hc_ocontext 210 */ 211 sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, secret_key, 212 secret_key_length); 213 214 215 sha1_hmac_ctx_tmpl->hc_mech_type = SHA1_HMAC_MECH_INFO_TYPE; 216 217 218 return (sha1_hmac_ctx_tmpl); 219 } 220 221 void 222 fips_hmac_sha1_hash(sha1_hmac_ctx_t *sha1_hmac_ctx, 223 uint8_t *message, uint32_t message_len, 224 uint8_t *hmac_computed) 225 { 226 227 /* do a SHA1 update of the inner context using the specified data */ 228 SHA1Update(&((sha1_hmac_ctx)->hc_icontext), message, 229 message_len); 230 231 /* 232 * Do a SHA1 final on the inner context. 233 */ 234 SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_icontext)); 235 236 /* 237 * Do an SHA1 update on the outer context, feeding the inner 238 * digest as data. 239 */ 240 SHA1Update(&((sha1_hmac_ctx)->hc_ocontext), hmac_computed, 241 SHA1_HASH_SIZE); 242 243 /* 244 * Do a SHA1 final on the outer context, storing the computed 245 * digest in the caller's buffer. 246 */ 247 SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_ocontext)); 248 249 } 250 251 #endif 252 253 /* 254 * SHA1 Power-On SelfTest(s). 255 */ 256 int 257 fips_sha1_post(void) 258 { 259 260 /* 261 * SHA-1 Known Hash Message 262 * Source from NIST SHA1ShortMsg (L = 512-bits). 263 */ 264 static uint8_t sha1_known_hash_message[] = { 265 0x7e, 0x3a, 0x4c, 0x32, 0x5c, 0xb9, 0xc5, 0x2b, 266 0x88, 0x38, 0x7f, 0x93, 0xd0, 0x1a, 0xe8, 0x6d, 267 0x42, 0x09, 0x8f, 0x5e, 0xfa, 0x7f, 0x94, 0x57, 268 0x38, 0x8b, 0x5e, 0x74, 0xb6, 0xd2, 0x8b, 0x24, 269 0x38, 0xd4, 0x2d, 0x8b, 0x64, 0x70, 0x33, 0x24, 270 0xd4, 0xaa, 0x25, 0xab, 0x6a, 0xad, 0x15, 0x3a, 271 0xe3, 0x0c, 0xd2, 0xb2, 0xaf, 0x4d, 0x5e, 0x5c, 272 0x00, 0xa8, 0xa2, 0xd0, 0x22, 0x0c, 0x61, 0x16 273 }; 274 275 /* SHA-1 Known Digest Message (160-bits). */ 276 static uint8_t sha1_known_digest[] = { 277 0xa3, 0x05, 0x44, 0x27, 0xcd, 0xb1, 0x3f, 0x16, 278 0x4a, 0x61, 0x0b, 0x34, 0x87, 0x02, 0x72, 0x4c, 279 0x80, 0x8a, 0x0d, 0xcc 280 }; 281 282 /* Source from NIST HMAC.txt Count = 0 */ 283 static uint8_t HMAC_known_secret_key[] = { 284 0x7b, 0x10, 0xf4, 0x12, 0x4b, 0x15, 0xc8, 0x2e 285 }; 286 287 static uint8_t HMAC_known_secret_key_length 288 = sizeof (HMAC_known_secret_key); 289 290 /* known SHA1 hmac - truncated (10 bytes) */ 291 static uint8_t known_SHA1_hmac[] = { 292 0x4e, 0xad, 0x12, 0xc2, 0xfe, 0x3d, 0x6e, 0xa4, 293 0x3a, 0xcb 294 }; 295 296 static uint8_t hmac_sha1_known_hash_message[] = { 297 0x27, 0xdc, 0xb5, 0xb1, 0xda, 0xf6, 0x0c, 0xfd, 298 0x3e, 0x2f, 0x73, 0xd4, 0xd6, 0x4c, 0xa9, 0xc6, 299 0x84, 0xf8, 0xbf, 0x71, 0xfc, 0x68, 0x2a, 0x46, 300 0x79, 0x3b, 0x17, 0x90, 0xaf, 0xa4, 0xfe, 0xb1, 301 0x00, 0xca, 0x7a, 0xaf, 0xf2, 0x6f, 0x58, 0xf0, 302 0xe1, 0xd0, 0xed, 0x42, 0xf1, 0xcd, 0xad, 0x1f, 303 0x47, 0x4a, 0xfa, 0x2e, 0x79, 0xd5, 0x3a, 0x0c, 304 0x42, 0x89, 0x2c, 0x4d, 0x7b, 0x32, 0x7c, 0xbe, 305 0x46, 0xb2, 0x95, 0xed, 0x8d, 0xa3, 0xb6, 0xec, 306 0xab, 0x3d, 0x48, 0x51, 0x68, 0x7a, 0x6f, 0x81, 307 0x2b, 0x79, 0xdf, 0x2f, 0x6b, 0x20, 0xf1, 0x1f, 308 0x67, 0x06, 0xf5, 0x30, 0x17, 0x90, 0xca, 0x99, 309 0x62, 0x5a, 0xad, 0x73, 0x91, 0xd8, 0x4f, 0x78, 310 0x04, 0x3d, 0x2a, 0x0a, 0x23, 0x9b, 0x14, 0x77, 311 0x98, 0x4c, 0x15, 0x7b, 0xbc, 0x92, 0x76, 0x06, 312 0x4e, 0x7a, 0x1a, 0x40, 0x6b, 0x06, 0x12, 0xca 313 }; 314 315 /* SHA-1 variables. */ 316 uint8_t sha1_computed_digest[SHA1_DIGEST_LENGTH]; 317 uint8_t hmac_computed[SHA1_HMAC_BLOCK_SIZE]; 318 SHA1_CTX *sha1_context = NULL; 319 320 #ifdef _KERNEL 321 sha1_hmac_ctx_t *sha1_hmac_ctx = NULL; 322 #endif 323 324 int rv; 325 326 /* SHA-1 Known Answer Hashing Test. */ 327 sha1_context = fips_sha1_build_context(); 328 if (sha1_context == NULL) 329 return (CKR_HOST_MEMORY); 330 331 rv = fips_sha1_hash(sha1_context, sha1_known_hash_message, 332 FIPS_KNOWN_HMAC_MESSAGE_LENGTH, sha1_computed_digest); 333 334 if ((rv != CKR_OK) || 335 (memcmp(sha1_computed_digest, sha1_known_digest, 336 SHA1_DIGEST_LENGTH) != 0)) 337 return (CKR_DEVICE_ERROR); 338 339 #ifdef _KERNEL 340 /* SHA-1 HMAC Known Answer Hashing Test */ 341 sha1_hmac_ctx = fips_sha1_hmac_build_context(HMAC_known_secret_key, 342 HMAC_known_secret_key_length); 343 344 if (sha1_hmac_ctx == NULL) 345 return (CKR_HOST_MEMORY); 346 347 fips_hmac_sha1_hash(sha1_hmac_ctx, hmac_sha1_known_hash_message, 348 sizeof (hmac_sha1_known_hash_message), hmac_computed); 349 #else 350 rv = fips_hmac_sha1_hash(hmac_computed, HMAC_known_secret_key, 351 HMAC_known_secret_key_length, hmac_sha1_known_hash_message, 352 sizeof (hmac_sha1_known_hash_message)); 353 354 #endif 355 356 #ifdef _KERNEL 357 if (memcmp(hmac_computed, known_SHA1_hmac, 358 sizeof (known_SHA1_hmac)) != 0) 359 return (CKR_DEVICE_ERROR); 360 #else 361 if ((rv != CKR_OK) || 362 (memcmp(hmac_computed, known_SHA1_hmac, 363 sizeof (known_SHA1_hmac)) != 0)) 364 return (CKR_DEVICE_ERROR); 365 #endif 366 367 return (rv); 368 369 } 370