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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdlib.h> 29 #include <string.h> 30 #include <strings.h> 31 #include <sys/types.h> 32 #include <security/cryptoki.h> 33 #include <bignum.h> 34 #include <des_impl.h> 35 #include "softGlobal.h" 36 #include "softSession.h" 37 #include "softObject.h" 38 #include "softDH.h" 39 #include "softRandom.h" 40 #include "softCrypt.h" 41 42 43 /* 44 * This function converts the big integer of the specified attribute 45 * to an octet string and store it in the corresponding key object. 46 */ 47 CK_RV 48 soft_genDHkey_set_attribute(soft_object_t *key, BIGNUM *bn, 49 CK_ATTRIBUTE_TYPE type, uint32_t prime_len, boolean_t public) 50 { 51 52 uchar_t *buf; 53 uint32_t buflen; 54 CK_RV rv = CKR_OK; 55 biginteger_t *dst = NULL; 56 biginteger_t src; 57 58 /* 59 * Allocate the buffer used to store the value of key fields 60 * for bignum2bytestring. Since bignum only deals with a buffer 61 * whose size is multiple of 4, prime_len is rounded up to be 62 * multiple of 4. 63 */ 64 if ((buf = malloc((prime_len + sizeof (BIG_CHUNK_TYPE) - 1) & 65 ~(sizeof (BIG_CHUNK_TYPE) - 1))) == NULL) { 66 rv = CKR_HOST_MEMORY; 67 goto cleanexit; 68 } 69 70 buflen = bn->len * (int)sizeof (BIG_CHUNK_TYPE); 71 bignum2bytestring(buf, bn, buflen); 72 73 switch (type) { 74 75 case CKA_VALUE: 76 if (public) 77 dst = OBJ_PUB_DH_VALUE(key); 78 else 79 dst = OBJ_PRI_DH_VALUE(key); 80 break; 81 82 case CKA_PRIME: 83 dst = OBJ_PRI_DH_PRIME(key); 84 break; 85 86 case CKA_BASE: 87 dst = OBJ_PRI_DH_BASE(key); 88 break; 89 } 90 91 src.big_value_len = buflen; 92 93 if ((src.big_value = malloc(buflen)) == NULL) { 94 rv = CKR_HOST_MEMORY; 95 goto cleanexit; 96 } 97 (void) memcpy(src.big_value, buf, buflen); 98 99 /* Copy the attribute in the key object. */ 100 copy_bigint_attr(&src, dst); 101 102 cleanexit: 103 free(buf); 104 return (rv); 105 106 } 107 108 /* 109 * This function covers the DH Key agreement. 110 */ 111 CK_RV 112 soft_dh_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 113 { 114 CK_RV rv; 115 BIG_ERR_CODE brv; 116 uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 117 uint32_t prime_len = sizeof (prime); 118 uint32_t primebit_len; 119 uint32_t value_bits; 120 uchar_t base[MAX_KEY_ATTR_BUFLEN]; 121 uint32_t base_len = sizeof (base); 122 BIGNUM bnprime; 123 BIGNUM bnbase; 124 BIGNUM bnprival; 125 BIGNUM bnpubval; 126 CK_ATTRIBUTE template; 127 128 if ((pubkey->class != CKO_PUBLIC_KEY) || 129 (pubkey->key_type != CKK_DH)) { 130 return (CKR_KEY_TYPE_INCONSISTENT); 131 } 132 133 if ((prikey->class != CKO_PRIVATE_KEY) || 134 (prikey->key_type != CKK_DH)) { 135 return (CKR_KEY_TYPE_INCONSISTENT); 136 } 137 138 /* 139 * The input to the first phase shall be the Diffie-Hellman 140 * parameters, which include prime, base, and private-value length. 141 */ 142 rv = soft_get_public_attr(pubkey, CKA_PRIME, prime, &prime_len); 143 144 if (rv != CKR_OK) { 145 return (rv); 146 } 147 148 if ((prime_len < (MIN_DH_KEYLENGTH / 8)) || 149 (prime_len > (MAX_DH_KEYLENGTH / 8))) { 150 rv = CKR_ATTRIBUTE_VALUE_INVALID; 151 goto ret0; 152 } 153 154 if ((brv = big_init(&bnprime, CHARLEN2BIGNUMLEN(prime_len))) != 155 BIG_OK) { 156 rv = convert_rv(brv); 157 goto ret0; 158 } 159 160 /* Convert the prime octet string to big integer format. */ 161 bytestring2bignum(&bnprime, prime, prime_len); 162 163 rv = soft_get_public_attr(pubkey, CKA_BASE, base, &base_len); 164 165 if (rv != CKR_OK) { 166 goto ret1; 167 } 168 169 if ((brv = big_init(&bnbase, CHARLEN2BIGNUMLEN(base_len))) != BIG_OK) { 170 rv = convert_rv(brv); 171 goto ret1; 172 } 173 174 /* Convert the base octet string to big integer format. */ 175 bytestring2bignum(&bnbase, base, base_len); 176 177 if (big_cmp_abs(&bnbase, &bnprime) >= 0) { 178 rv = CKR_ATTRIBUTE_VALUE_INVALID; 179 goto ret2; 180 } 181 182 primebit_len = big_bitlength(&bnprime); 183 184 template.pValue = malloc(sizeof (CK_ULONG)); 185 186 if (template.pValue == NULL) { 187 rv = CKR_HOST_MEMORY; 188 goto ret2; 189 } 190 191 template.ulValueLen = sizeof (CK_ULONG); 192 193 rv = get_ulong_attr_from_object(OBJ_PRI_DH_VAL_BITS(prikey), 194 &template); 195 196 if (rv != CKR_OK) { 197 goto ret2; 198 } 199 200 /* 201 * The intention of selecting a private-value length is to reduce 202 * the computation time for key agreement, while maintaining a 203 * given level of security. 204 */ 205 206 #ifdef __sparcv9 207 /* LINTED */ 208 value_bits = (uint32_t)(*((CK_ULONG *)(template.pValue))); 209 #else /* !__sparcv9 */ 210 value_bits = *((CK_ULONG *)(template.pValue)); 211 #endif /* __sparcv9 */ 212 213 if (value_bits > primebit_len) { 214 rv = CKR_ATTRIBUTE_VALUE_INVALID; 215 goto ret3; 216 } 217 218 /* Generate DH key pair private and public values. */ 219 if ((brv = big_init(&bnprival, CHARLEN2BIGNUMLEN(prime_len))) 220 != BIG_OK) { 221 rv = convert_rv(brv); 222 goto ret3; 223 } 224 225 if ((brv = big_init(&bnpubval, CHARLEN2BIGNUMLEN(prime_len))) 226 != BIG_OK) { 227 rv = convert_rv(brv); 228 goto ret4; 229 } 230 231 /* 232 * The big integer of the private value shall be generated privately 233 * and randomly. 234 */ 235 if ((brv = random_bignum(&bnprival, (value_bits == 0) ? 236 primebit_len : value_bits, (IS_TOKEN_OBJECT(pubkey) || 237 IS_TOKEN_OBJECT(prikey)))) != BIG_OK) { 238 rv = convert_rv(brv); 239 goto ret5; 240 } 241 242 /* 243 * The base g shall be raised to the private value x modulo p to 244 * give an integer y, the integer public value. 245 */ 246 if ((brv = big_modexp(&bnpubval, 247 &bnbase, &bnprival, &bnprime, NULL)) != BIG_OK) { 248 rv = convert_rv(brv); 249 goto ret5; 250 } 251 252 /* 253 * The integer public value y shall be converted to an octet 254 * string PV of length k, the public value. 255 */ 256 if ((rv = soft_genDHkey_set_attribute(pubkey, &bnpubval, 257 CKA_VALUE, prime_len, B_TRUE)) != CKR_OK) { 258 goto ret5; 259 } 260 261 /* Convert the big integer private value to an octet string. */ 262 if ((rv = soft_genDHkey_set_attribute(prikey, &bnprival, 263 CKA_VALUE, prime_len, B_FALSE)) != CKR_OK) { 264 goto ret5; 265 } 266 267 /* Convert the big integer prime to an octet string. */ 268 if ((rv = soft_genDHkey_set_attribute(prikey, &bnprime, 269 CKA_PRIME, prime_len, B_FALSE)) != CKR_OK) { 270 goto ret5; 271 } 272 273 /* Convert the big integer base to an octet string. */ 274 if ((rv = soft_genDHkey_set_attribute(prikey, &bnbase, 275 CKA_BASE, prime_len, B_FALSE)) != CKR_OK) { 276 goto ret5; 277 } 278 279 if (value_bits == 0) { 280 OBJ_PRI_DH_VAL_BITS(prikey) = primebit_len; 281 } 282 283 284 ret5: 285 big_finish(&bnpubval); 286 ret4: 287 big_finish(&bnprival); 288 ret3: 289 free(template.pValue); 290 ret2: 291 big_finish(&bnbase); 292 ret1: 293 big_finish(&bnprime); 294 ret0: 295 return (rv); 296 } 297 298 CK_RV 299 soft_dh_key_derive(soft_object_t *basekey, soft_object_t *secretkey, 300 void *publicvalue, size_t publicvaluelen) 301 { 302 uchar_t privatevalue[MAX_KEY_ATTR_BUFLEN]; 303 uint32_t privatevaluelen = sizeof (privatevalue); 304 uchar_t privateprime[MAX_KEY_ATTR_BUFLEN]; 305 uint32_t privateprimelen = sizeof (privateprime); 306 uchar_t *value; 307 uint32_t valuelen; 308 uint32_t keylen; 309 uchar_t *buf = NULL; 310 CK_RV rv; 311 BIG_ERR_CODE brv; 312 BIGNUM bnprime; 313 BIGNUM bnpublic; 314 BIGNUM bnprivate; 315 BIGNUM bnsecret; 316 317 rv = soft_get_private_attr(basekey, CKA_VALUE, privatevalue, 318 &privatevaluelen); 319 if (rv != CKR_OK) { 320 return (rv); 321 } 322 323 rv = soft_get_private_attr(basekey, CKA_PRIME, privateprime, 324 &privateprimelen); 325 if (rv != CKR_OK) { 326 goto ret0; 327 } 328 329 if ((brv = big_init(&bnprime, CHARLEN2BIGNUMLEN(privateprimelen))) != 330 BIG_OK) { 331 rv = convert_rv(brv); 332 goto ret0; 333 } 334 335 bytestring2bignum(&bnprime, privateprime, privateprimelen); 336 337 if ((brv = big_init(&bnprivate, CHARLEN2BIGNUMLEN(privatevaluelen))) != 338 BIG_OK) { 339 rv = convert_rv(brv); 340 goto ret1; 341 } 342 343 bytestring2bignum(&bnprivate, privatevalue, privatevaluelen); 344 345 #ifdef __sparcv9 346 if ((brv = big_init(&bnpublic, 347 (int)CHARLEN2BIGNUMLEN(publicvaluelen))) != BIG_OK) { 348 #else /* !__sparcv9 */ 349 if ((brv = big_init(&bnpublic, 350 CHARLEN2BIGNUMLEN(publicvaluelen))) != BIG_OK) { 351 #endif /* __sparcv9 */ 352 rv = convert_rv(brv); 353 goto ret2; 354 } 355 356 bytestring2bignum(&bnpublic, (uchar_t *)publicvalue, publicvaluelen); 357 358 if ((brv = big_init(&bnsecret, 359 CHARLEN2BIGNUMLEN(privateprimelen))) != BIG_OK) { 360 rv = convert_rv(brv); 361 goto ret3; 362 } 363 364 if ((brv = big_modexp(&bnsecret, &bnpublic, &bnprivate, &bnprime, 365 NULL)) != BIG_OK) { 366 rv = convert_rv(brv); 367 goto ret4; 368 } 369 370 if ((buf = malloc((privateprimelen + sizeof (BIG_CHUNK_TYPE) - 1) & 371 ~(sizeof (BIG_CHUNK_TYPE) - 1))) == NULL) { 372 rv = CKR_HOST_MEMORY; 373 goto ret4; 374 } 375 376 value = buf; 377 valuelen = bnsecret.len * (int)sizeof (BIG_CHUNK_TYPE); 378 bignum2bytestring(value, &bnsecret, valuelen); 379 380 switch (secretkey->key_type) { 381 382 case CKK_DES: 383 keylen = DES_KEYSIZE; 384 break; 385 case CKK_DES2: 386 keylen = DES2_KEYSIZE; 387 break; 388 case CKK_DES3: 389 keylen = DES3_KEYSIZE; 390 break; 391 case CKK_RC4: 392 case CKK_AES: 393 case CKK_GENERIC_SECRET: 394 #ifdef __sparcv9 395 /* LINTED */ 396 keylen = (uint32_t)OBJ_SEC_VALUE_LEN(secretkey); 397 #else /* !__sparcv9 */ 398 keylen = OBJ_SEC_VALUE_LEN(secretkey); 399 #endif /* __sparcv9 */ 400 break; 401 } 402 403 if (keylen == 0) { 404 /* 405 * keylen == 0 only if CKA_VALUE_LEN did not specify. 406 */ 407 keylen = valuelen; 408 } 409 /* 410 * Note: No need to have "default:" case here since invalid key type 411 * if any has been detected at function soft_build_secret_key_object() 412 * before it gets here. 413 */ 414 415 if (keylen > valuelen) { 416 rv = CKR_ATTRIBUTE_VALUE_INVALID; 417 goto ret5; 418 } 419 420 if ((OBJ_SEC_VALUE(secretkey) = malloc(keylen)) == NULL) { 421 rv = CKR_HOST_MEMORY; 422 goto ret5; 423 } 424 OBJ_SEC_VALUE_LEN(secretkey) = keylen; 425 426 /* 427 * The truncation removes bytes from the leading end of the 428 * secret value. 429 */ 430 (void) memcpy(OBJ_SEC_VALUE(secretkey), (value + valuelen - keylen), 431 keylen); 432 433 ret5: 434 free(buf); 435 ret4: 436 big_finish(&bnsecret); 437 ret3: 438 big_finish(&bnpublic); 439 ret2: 440 big_finish(&bnprivate); 441 ret1: 442 big_finish(&bnprime); 443 ret0: 444 return (rv); 445 } 446