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 2005 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 <stdlib.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <sys/types.h> 33 #include <security/cryptoki.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 + 3) & ~3)) == NULL) { 66 rv = CKR_HOST_MEMORY; 67 goto cleanexit; 68 } 69 70 buflen = bn->len * (int)sizeof (uint32_t); 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 129 if ((pubkey->class != CKO_PUBLIC_KEY) || 130 (pubkey->key_type != CKK_DH)) 131 return (CKR_KEY_TYPE_INCONSISTENT); 132 133 if ((prikey->class != CKO_PRIVATE_KEY) || 134 (prikey->key_type != CKK_DH)) 135 return (CKR_KEY_TYPE_INCONSISTENT); 136 137 /* 138 * The input to the first phase shall be the Diffie-Hellman 139 * parameters, which include prime, base, and private-value length. 140 */ 141 rv = soft_get_public_attr(pubkey, CKA_PRIME, prime, &prime_len); 142 143 if (rv != CKR_OK) { 144 return (rv); 145 } 146 147 if ((prime_len < (MIN_DH_KEYLENGTH / 8)) || 148 (prime_len > (MAX_DH_KEYLENGTH / 8))) { 149 rv = CKR_ATTRIBUTE_VALUE_INVALID; 150 goto ret0; 151 } 152 153 if ((brv = big_init(&bnprime, (prime_len + 3)/4)) != BIG_OK) { 154 rv = convert_rv(brv); 155 goto ret0; 156 } 157 158 /* Convert the prime octet string to big integer format. */ 159 bytestring2bignum(&bnprime, prime, prime_len); 160 161 rv = soft_get_public_attr(pubkey, CKA_BASE, base, &base_len); 162 163 if (rv != CKR_OK) { 164 goto ret1; 165 } 166 167 if ((brv = big_init(&bnbase, (base_len + 3)/4)) != BIG_OK) { 168 rv = convert_rv(brv); 169 goto ret1; 170 } 171 172 /* Convert the base octet string to big integer format. */ 173 bytestring2bignum(&bnbase, base, base_len); 174 175 if (big_cmp_abs(&bnbase, &bnprime) >= 0) { 176 rv = CKR_ATTRIBUTE_VALUE_INVALID; 177 goto ret2; 178 } 179 180 primebit_len = big_bitlength(&bnprime); 181 182 template.pValue = malloc(sizeof (CK_ULONG)); 183 184 if (template.pValue == NULL) { 185 rv = CKR_HOST_MEMORY; 186 goto ret2; 187 } 188 189 template.ulValueLen = sizeof (CK_ULONG); 190 191 rv = get_ulong_attr_from_object(OBJ_PRI_DH_VAL_BITS(prikey), 192 &template); 193 194 if (rv != CKR_OK) { 195 goto ret2; 196 } 197 198 /* 199 * The intention of selecting a private-value length is to reduce 200 * the computation time for key agreement, while maintaining a 201 * given level of security. 202 */ 203 204 #ifdef __sparcv9 205 /* LINTED */ 206 value_bits = (uint32_t)(*((CK_ULONG *)(template.pValue))); 207 #else /* !__sparcv9 */ 208 value_bits = *((CK_ULONG *)(template.pValue)); 209 #endif /* __sparcv9 */ 210 211 if (value_bits > primebit_len) { 212 rv = CKR_ATTRIBUTE_VALUE_INVALID; 213 goto ret3; 214 } 215 216 /* Generate DH key pair private and public values. */ 217 if ((brv = big_init(&bnprival, (prime_len + 3)/4)) != BIG_OK) { 218 rv = convert_rv(brv); 219 goto ret3; 220 } 221 222 if ((brv = big_init(&bnpubval, (prime_len + 3)/4)) != BIG_OK) { 223 rv = convert_rv(brv); 224 goto ret4; 225 } 226 227 /* 228 * The big integer of the private value shall be generated privately 229 * and randomly. 230 */ 231 if ((brv = random_bignum(&bnprival, (value_bits == 0) ? 232 primebit_len : value_bits, (IS_TOKEN_OBJECT(pubkey) || 233 IS_TOKEN_OBJECT(prikey)))) != BIG_OK) { 234 rv = convert_rv(brv); 235 goto ret5; 236 } 237 238 /* 239 * The base g shall be raised to the private value x modulo p to 240 * give an integer y, the integer public value. 241 */ 242 if ((brv = big_modexp(&bnpubval, 243 &bnbase, &bnprival, &bnprime, NULL)) != BIG_OK) { 244 rv = convert_rv(brv); 245 goto ret5; 246 } 247 248 /* 249 * The integer public value y shall be converted to an octet 250 * string PV of length k, the public value. 251 */ 252 if ((rv = soft_genDHkey_set_attribute(pubkey, &bnpubval, 253 CKA_VALUE, prime_len, B_TRUE)) != CKR_OK) { 254 goto ret5; 255 } 256 257 /* Convert the big integer private value to an octet string. */ 258 if ((rv = soft_genDHkey_set_attribute(prikey, &bnprival, 259 CKA_VALUE, prime_len, B_FALSE)) != CKR_OK) { 260 goto ret5; 261 } 262 263 /* Convert the big integer prime to an octet string. */ 264 if ((rv = soft_genDHkey_set_attribute(prikey, &bnprime, 265 CKA_PRIME, prime_len, B_FALSE)) != CKR_OK) { 266 goto ret5; 267 } 268 269 /* Convert the big integer base to an octet string. */ 270 if ((rv = soft_genDHkey_set_attribute(prikey, &bnbase, 271 CKA_BASE, prime_len, B_FALSE)) != CKR_OK) { 272 goto ret5; 273 } 274 275 if (value_bits == 0) { 276 OBJ_PRI_DH_VAL_BITS(prikey) = primebit_len; 277 } 278 279 280 ret5: 281 big_finish(&bnpubval); 282 ret4: 283 big_finish(&bnprival); 284 ret3: 285 free(template.pValue); 286 ret2: 287 big_finish(&bnbase); 288 ret1: 289 big_finish(&bnprime); 290 ret0: 291 return (rv); 292 } 293 294 CK_RV 295 soft_dh_key_derive(soft_object_t *basekey, soft_object_t *secretkey, 296 void *publicvalue, size_t publicvaluelen) 297 { 298 uchar_t privatevalue[MAX_KEY_ATTR_BUFLEN]; 299 uint32_t privatevaluelen = sizeof (privatevalue); 300 uchar_t privateprime[MAX_KEY_ATTR_BUFLEN]; 301 uint32_t privateprimelen = sizeof (privateprime); 302 uchar_t *value; 303 uint32_t valuelen; 304 uint32_t keylen; 305 uchar_t *buf = NULL; 306 CK_RV rv; 307 BIG_ERR_CODE brv; 308 BIGNUM bnprime; 309 BIGNUM bnpublic; 310 BIGNUM bnprivate; 311 BIGNUM bnsecret; 312 313 314 rv = soft_get_private_attr(basekey, CKA_VALUE, privatevalue, 315 &privatevaluelen); 316 if (rv != CKR_OK) { 317 return (rv); 318 } 319 320 rv = soft_get_private_attr(basekey, CKA_PRIME, privateprime, 321 &privateprimelen); 322 if (rv != CKR_OK) { 323 goto ret0; 324 } 325 326 if ((brv = big_init(&bnprime, (privateprimelen + 3)/4)) != BIG_OK) { 327 rv = convert_rv(brv); 328 goto ret0; 329 } 330 331 bytestring2bignum(&bnprime, privateprime, privateprimelen); 332 333 if ((brv = big_init(&bnprivate, (privatevaluelen + 3)/4)) != BIG_OK) { 334 rv = convert_rv(brv); 335 goto ret1; 336 } 337 338 bytestring2bignum(&bnprivate, privatevalue, privatevaluelen); 339 340 #ifdef __sparcv9 341 /* LINTED */ 342 if ((brv = big_init(&bnpublic, (int)(publicvaluelen + 3)/4)) != 343 BIG_OK) { 344 #else /* !__sparcv9 */ 345 if ((brv = big_init(&bnpublic, (publicvaluelen + 3)/4)) != BIG_OK) { 346 #endif /* __sparcv9 */ 347 rv = convert_rv(brv); 348 goto ret2; 349 } 350 351 bytestring2bignum(&bnpublic, (uchar_t *)publicvalue, publicvaluelen); 352 353 if ((brv = big_init(&bnsecret, (privateprimelen + 3)/4)) != BIG_OK) { 354 rv = convert_rv(brv); 355 goto ret3; 356 } 357 358 if ((brv = big_modexp(&bnsecret, &bnpublic, &bnprivate, &bnprime, 359 NULL)) != BIG_OK) { 360 rv = convert_rv(brv); 361 goto ret4; 362 } 363 364 if ((buf = malloc((privateprimelen + 3) & ~3)) == NULL) { 365 rv = CKR_HOST_MEMORY; 366 goto ret4; 367 } 368 369 value = buf; 370 valuelen = bnsecret.len * (int)sizeof (uint32_t); 371 bignum2bytestring(value, &bnsecret, valuelen); 372 373 switch (secretkey->key_type) { 374 375 case CKK_DES: 376 keylen = DES_KEYSIZE; 377 break; 378 case CKK_DES2: 379 keylen = DES2_KEYSIZE; 380 break; 381 case CKK_DES3: 382 keylen = DES3_KEYSIZE; 383 break; 384 case CKK_RC4: 385 case CKK_AES: 386 case CKK_GENERIC_SECRET: 387 #ifdef __sparcv9 388 /* LINTED */ 389 keylen = (uint32_t)OBJ_SEC_VALUE_LEN(secretkey); 390 #else /* !__sparcv9 */ 391 keylen = OBJ_SEC_VALUE_LEN(secretkey); 392 #endif /* __sparcv9 */ 393 break; 394 } 395 396 if (keylen == 0) { 397 /* 398 * keylen == 0 only if CKA_VALUE_LEN did not specify. 399 */ 400 keylen = valuelen; 401 } 402 /* 403 * Note: No need to have "default:" case here since invalid key type 404 * if any has been detected at function soft_build_secret_key_object() 405 * before it gets here. 406 */ 407 408 if (keylen > valuelen) { 409 rv = CKR_ATTRIBUTE_VALUE_INVALID; 410 goto ret5; 411 } 412 413 if ((OBJ_SEC_VALUE(secretkey) = malloc(keylen)) == NULL) { 414 rv = CKR_HOST_MEMORY; 415 goto ret5; 416 } 417 OBJ_SEC_VALUE_LEN(secretkey) = keylen; 418 419 /* 420 * The truncation removes bytes from the leading end of the 421 * secret value. 422 */ 423 (void) memcpy(OBJ_SEC_VALUE(secretkey), (value + valuelen - keylen), 424 keylen); 425 426 ret5: 427 free(buf); 428 ret4: 429 big_finish(&bnsecret); 430 ret3: 431 big_finish(&bnpublic); 432 ret2: 433 big_finish(&bnprivate); 434 ret1: 435 big_finish(&bnprime); 436 ret0: 437 return (rv); 438 } 439