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