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 /* 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <stdlib.h> 27 #include <string.h> 28 #include <strings.h> 29 #include <sys/types.h> 30 #include <security/cryptoki.h> 31 #include <sys/crypto/common.h> 32 #include <des_impl.h> 33 #include <cryptoutil.h> 34 #include "softGlobal.h" 35 #include "softSession.h" 36 #include "softObject.h" 37 #include "softDH.h" 38 #include "softCrypt.h" 39 40 41 /* 42 * This function takes a converted big integer of the specified attribute 43 * as an octet string and stores it in the corresponding key object. 44 */ 45 static CK_RV 46 soft_genDHkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 47 uchar_t *buf, uint32_t buflen, boolean_t public) 48 { 49 50 CK_RV rv = CKR_OK; 51 biginteger_t *dst = NULL; 52 biginteger_t src; 53 54 switch (type) { 55 56 case CKA_VALUE: 57 if (public) 58 dst = OBJ_PUB_DH_VALUE(key); 59 else 60 dst = OBJ_PRI_DH_VALUE(key); 61 break; 62 63 case CKA_PRIME: 64 dst = OBJ_PRI_DH_PRIME(key); 65 break; 66 67 case CKA_BASE: 68 dst = OBJ_PRI_DH_BASE(key); 69 break; 70 } 71 72 if ((rv = dup_bigint_attr(&src, buf, buflen)) != CKR_OK) 73 goto cleanexit; 74 75 /* Copy the attribute in the key object. */ 76 copy_bigint_attr(&src, dst); 77 78 cleanexit: 79 /* No need to free big_value because dst holds it now after copy. */ 80 return (rv); 81 82 } 83 84 /* 85 * This function covers the DH Key agreement. 86 */ 87 CK_RV 88 soft_dh_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 89 { 90 CK_RV rv; 91 CK_ATTRIBUTE template; 92 uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 93 uint32_t prime_len = sizeof (prime); 94 uchar_t base[MAX_KEY_ATTR_BUFLEN]; 95 uint32_t base_len = sizeof (base); 96 uint32_t value_bits; 97 uchar_t private_x[MAX_KEY_ATTR_BUFLEN]; 98 uchar_t public_y[MAX_KEY_ATTR_BUFLEN]; 99 DHbytekey k; 100 101 if ((pubkey->class != CKO_PUBLIC_KEY) || 102 (pubkey->key_type != CKK_DH)) { 103 return (CKR_KEY_TYPE_INCONSISTENT); 104 } 105 106 if ((prikey->class != CKO_PRIVATE_KEY) || 107 (prikey->key_type != CKK_DH)) { 108 return (CKR_KEY_TYPE_INCONSISTENT); 109 } 110 111 /* Get private-value length in bits */ 112 template.pValue = malloc(sizeof (CK_ULONG)); 113 if (template.pValue == NULL) { 114 return (CKR_HOST_MEMORY); 115 } 116 template.ulValueLen = sizeof (CK_ULONG); 117 rv = get_ulong_attr_from_object(OBJ_PRI_DH_VAL_BITS(prikey), 118 &template); 119 if (rv != CKR_OK) { 120 free(template.pValue); 121 return (rv); 122 } 123 124 #ifdef __sparcv9 125 /* LINTED */ 126 value_bits = (uint32_t)(*((CK_ULONG *)(template.pValue))); 127 #else /* !__sparcv9 */ 128 value_bits = *((CK_ULONG *)(template.pValue)); 129 #endif /* __sparcv9 */ 130 131 free(template.pValue); 132 133 /* 134 * The input to the first phase shall be the Diffie-Hellman 135 * parameters, which include prime, base, and private-value length. 136 */ 137 rv = soft_get_public_value(pubkey, CKA_PRIME, prime, &prime_len); 138 if (rv != CKR_OK) { 139 return (rv); 140 } 141 142 rv = soft_get_public_value(pubkey, CKA_BASE, base, &base_len); 143 if (rv != CKR_OK) { 144 goto ret; 145 } 146 147 /* Inputs to DH key pair generation. */ 148 k.prime = prime; 149 k.prime_bits = CRYPTO_BYTES2BITS(prime_len); 150 k.base = base; 151 k.base_bytes = base_len; 152 k.value_bits = value_bits; 153 k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ? 154 pkcs11_get_random : pkcs11_get_urandom; 155 156 /* Outputs from DH key pair generation. */ 157 k.private_x = private_x; 158 k.public_y = public_y; 159 160 /* If value_bits is 0, it will return as same size as prime */ 161 if ((rv = dh_genkey_pair(&k)) != CKR_OK) { 162 goto ret; 163 } 164 165 /* 166 * The integer public value y shall be converted to an octet 167 * string PV of length k, the public value. 168 */ 169 if ((rv = soft_genDHkey_set_attribute(pubkey, CKA_VALUE, public_y, 170 CRYPTO_BITS2BYTES(k.value_bits), B_TRUE)) != CKR_OK) { 171 goto ret; 172 } 173 174 /* Convert the big integer private value to an octet string. */ 175 if ((rv = soft_genDHkey_set_attribute(prikey, CKA_VALUE, private_x, 176 CRYPTO_BITS2BYTES(k.value_bits), B_FALSE)) != CKR_OK) { 177 goto ret; 178 } 179 180 /* Convert the big integer prime to an octet string. */ 181 if ((rv = soft_genDHkey_set_attribute(prikey, CKA_PRIME, prime, 182 CRYPTO_BITS2BYTES(k.prime_bits), B_FALSE)) != CKR_OK) { 183 goto ret; 184 } 185 186 /* Convert the big integer base to an octet string. */ 187 if ((rv = soft_genDHkey_set_attribute(prikey, CKA_BASE, base, 188 k.base_bytes, B_FALSE)) != CKR_OK) { 189 goto ret; 190 } 191 192 /* Update private-value length in bits; could have been 0 before */ 193 OBJ_PRI_DH_VAL_BITS(prikey) = k.value_bits; 194 195 ret: 196 return (rv); 197 } 198 199 /* ARGSUSED3 */ 200 CK_RV 201 soft_dh_key_derive(soft_object_t *basekey, soft_object_t *secretkey, 202 void *publicvalue, size_t publicvaluelen) 203 { 204 CK_RV rv; 205 uchar_t privatevalue[MAX_KEY_ATTR_BUFLEN]; 206 uint32_t privatevaluelen = sizeof (privatevalue); 207 uchar_t privateprime[MAX_KEY_ATTR_BUFLEN]; 208 uint32_t privateprimelen = sizeof (privateprime); 209 uchar_t key[MAX_KEY_ATTR_BUFLEN]; 210 uint32_t keylen; 211 DHbytekey k; 212 213 rv = soft_get_private_value(basekey, CKA_VALUE, privatevalue, 214 &privatevaluelen); 215 if (rv != CKR_OK) { 216 return (rv); 217 } 218 219 rv = soft_get_private_value(basekey, CKA_PRIME, privateprime, 220 &privateprimelen); 221 if (rv != CKR_OK) { 222 goto ret; 223 } 224 225 /* keylen may be 0 if CKA_VALUE_LEN did not specify */ 226 keylen = OBJ_SEC_VALUE_LEN(secretkey); 227 if (keylen > sizeof (key)) { /* check for overflow */ 228 rv = CKR_ATTRIBUTE_VALUE_INVALID; 229 goto ret; 230 } 231 232 k.prime = privateprime; 233 k.prime_bits = CRYPTO_BYTES2BITS(privateprimelen); 234 k.value_bits = CRYPTO_BYTES2BITS(privatevaluelen); 235 k.private_x = privatevalue; 236 k.public_y = publicvalue; 237 k.rfunc = NULL; 238 239 /* keylen may be modified if it was 0 or conflicts with key type */ 240 rv = dh_key_derive(&k, secretkey->key_type, key, &keylen); 241 242 if (rv != CKR_OK) { 243 goto ret; 244 } 245 246 if ((OBJ_SEC_VALUE(secretkey) = malloc(keylen)) == NULL) { 247 rv = CKR_HOST_MEMORY; 248 goto ret; 249 } 250 251 OBJ_SEC_VALUE_LEN(secretkey) = keylen; 252 (void) memcpy(OBJ_SEC_VALUE(secretkey), key, keylen); 253 254 ret: 255 return (rv); 256 } 257