lowkey.c (14193B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 #include "lowkeyi.h" 5 #include "secoid.h" 6 #include "secitem.h" 7 #include "secder.h" 8 #include "secasn1.h" 9 #include "secerr.h" 10 11 SEC_ASN1_MKSUB(SEC_AnyTemplate) 12 SEC_ASN1_MKSUB(SEC_BitStringTemplate) 13 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) 14 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 15 16 static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = { 17 { SEC_ASN1_SEQUENCE, 18 0, NULL, sizeof(NSSLOWKEYAttribute) }, 19 { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) }, 20 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue), 21 SEC_ASN1_SUB(SEC_AnyTemplate) }, 22 { 0 } 23 }; 24 25 static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = { 26 { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate }, 27 }; 28 /* ASN1 Templates for new decoder/encoder */ 29 const SEC_ASN1Template lg_nsslowkey_PrivateKeyInfoTemplate[] = { 30 { SEC_ASN1_SEQUENCE, 31 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, 32 { SEC_ASN1_INTEGER, 33 offsetof(NSSLOWKEYPrivateKeyInfo, version) }, 34 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 35 offsetof(NSSLOWKEYPrivateKeyInfo, algorithm), 36 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 37 { SEC_ASN1_OCTET_STRING, 38 offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) }, 39 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 40 offsetof(NSSLOWKEYPrivateKeyInfo, attributes), 41 nsslowkey_SetOfAttributeTemplate }, 42 { 0 } 43 }; 44 45 const SEC_ASN1Template lg_nsslowkey_PQGParamsTemplate[] = { 46 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, 47 { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) }, 48 { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) }, 49 { SEC_ASN1_INTEGER, offsetof(PQGParams, base) }, 50 { 0 } 51 }; 52 53 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate[] = { 54 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 55 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) }, 56 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) }, 57 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) }, 58 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) }, 59 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) }, 60 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) }, 61 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) }, 62 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) }, 63 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) }, 64 { 0 } 65 }; 66 67 /* 68 * Allows u.rsa.modulus to be zero length for secret keys with an empty 69 * CKA_ID incorrectly generated in NSS 3.13.3 or earlier. Only used for 70 * decoding. See bug 715073. 71 */ 72 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate2[] = { 73 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 74 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) }, 75 { SEC_ASN1_ANY, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) }, 76 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) }, 77 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) }, 78 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) }, 79 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) }, 80 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) }, 81 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) }, 82 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) }, 83 { 0 } 84 }; 85 86 const SEC_ASN1Template lg_nsslowkey_DSAPrivateKeyTemplate[] = { 87 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 88 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) }, 89 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) }, 90 { 0 } 91 }; 92 93 const SEC_ASN1Template lg_nsslowkey_DHPrivateKeyTemplate[] = { 94 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 95 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) }, 96 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) }, 97 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) }, 98 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) }, 99 { 0 } 100 }; 101 102 /* NOTE: The SECG specification allows the private key structure 103 * to contain curve parameters but recommends that they be stored 104 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo 105 * instead. 106 */ 107 const SEC_ASN1Template lg_nsslowkey_ECPrivateKeyTemplate[] = { 108 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 109 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) }, 110 { SEC_ASN1_OCTET_STRING, 111 offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) }, 112 /* We only support named curves for which the parameters are 113 * encoded as an object ID. 114 */ 115 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 116 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 117 offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID), 118 SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, 119 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 120 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 121 SEC_ASN1_XTRN | 1, 122 offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue), 123 SEC_ASN1_SUB(SEC_BitStringTemplate) }, 124 { 0 } 125 }; 126 127 /* 128 * smaller version of EC_FillParams. In this code, we only need 129 * oid and DER data. 130 */ 131 SECStatus 132 LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, 133 ECParams *params) 134 { 135 SECOidTag tag; 136 SECItem oid = { siBuffer, NULL, 0 }; 137 138 #if EC_DEBUG 139 int i; 140 141 printf("Encoded params in EC_DecodeParams: "); 142 for (i = 0; i < encodedParams->len; i++) { 143 printf("%02x:", encodedParams->data[i]); 144 } 145 printf("\n"); 146 #endif 147 148 oid.len = encodedParams->len - 2; 149 oid.data = encodedParams->data + 2; 150 if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || 151 ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { 152 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 153 return SECFailure; 154 } 155 156 params->arena = arena; 157 158 /* For named curves, fill out curveOID */ 159 params->curveOID.len = oid.len; 160 params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len); 161 if (params->curveOID.data == NULL) { 162 return SECFailure; 163 } 164 memcpy(params->curveOID.data, oid.data, oid.len); 165 166 return SECSuccess; 167 } 168 169 /* Copy all of the fields from srcParams into dstParams 170 */ 171 SECStatus 172 LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams, 173 const ECParams *srcParams) 174 { 175 SECStatus rv = SECFailure; 176 177 dstParams->arena = arena; 178 rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding, 179 &srcParams->DEREncoding); 180 if (rv != SECSuccess) { 181 goto loser; 182 } 183 rv = SECITEM_CopyItem(arena, &dstParams->curveOID, 184 &srcParams->curveOID); 185 if (rv != SECSuccess) { 186 goto loser; 187 } 188 189 return SECSuccess; 190 191 loser: 192 return SECFailure; 193 } 194 /* 195 * See bugzilla bug 125359 196 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, 197 * all of the templates above that en/decode into integers must be converted 198 * from ASN.1's signed integer type. This is done by marking either the 199 * source or destination (encoding or decoding, respectively) type as 200 * siUnsignedInteger. 201 */ 202 203 void 204 lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 205 { 206 key->u.rsa.modulus.type = siUnsignedInteger; 207 key->u.rsa.publicExponent.type = siUnsignedInteger; 208 key->u.rsa.privateExponent.type = siUnsignedInteger; 209 key->u.rsa.prime1.type = siUnsignedInteger; 210 key->u.rsa.prime2.type = siUnsignedInteger; 211 key->u.rsa.exponent1.type = siUnsignedInteger; 212 key->u.rsa.exponent2.type = siUnsignedInteger; 213 key->u.rsa.coefficient.type = siUnsignedInteger; 214 } 215 216 void 217 lg_prepare_low_pqg_params_for_asn1(PQGParams *params) 218 { 219 params->prime.type = siUnsignedInteger; 220 params->subPrime.type = siUnsignedInteger; 221 params->base.type = siUnsignedInteger; 222 } 223 224 void 225 lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 226 { 227 key->u.dsa.publicValue.type = siUnsignedInteger; 228 key->u.dsa.privateValue.type = siUnsignedInteger; 229 key->u.dsa.params.prime.type = siUnsignedInteger; 230 key->u.dsa.params.subPrime.type = siUnsignedInteger; 231 key->u.dsa.params.base.type = siUnsignedInteger; 232 } 233 234 void 235 lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 236 { 237 key->u.dh.prime.type = siUnsignedInteger; 238 key->u.dh.base.type = siUnsignedInteger; 239 key->u.dh.publicValue.type = siUnsignedInteger; 240 key->u.dh.privateValue.type = siUnsignedInteger; 241 } 242 243 void 244 lg_prepare_low_ecparams_for_asn1(ECParams *params) 245 { 246 params->DEREncoding.type = siUnsignedInteger; 247 params->curveOID.type = siUnsignedInteger; 248 } 249 250 void 251 lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 252 { 253 key->u.ec.version.type = siUnsignedInteger; 254 key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger; 255 key->u.ec.ecParams.curveOID.type = siUnsignedInteger; 256 key->u.ec.privateValue.type = siUnsignedInteger; 257 key->u.ec.publicValue.type = siUnsignedInteger; 258 } 259 260 void 261 lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) 262 { 263 if (privk && privk->arena) { 264 PORT_FreeArena(privk->arena, PR_TRUE); 265 } 266 } 267 268 void 269 lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk) 270 { 271 if (pubk && pubk->arena) { 272 PORT_FreeArena(pubk->arena, PR_FALSE); 273 } 274 } 275 276 NSSLOWKEYPublicKey * 277 lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) 278 { 279 NSSLOWKEYPublicKey *pubk; 280 PLArenaPool *arena; 281 282 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 283 if (arena == NULL) { 284 PORT_SetError(SEC_ERROR_NO_MEMORY); 285 return NULL; 286 } 287 288 switch (privk->keyType) { 289 case NSSLOWKEYRSAKey: 290 case NSSLOWKEYNullKey: 291 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 292 sizeof(NSSLOWKEYPublicKey)); 293 if (pubk != NULL) { 294 SECStatus rv; 295 296 pubk->arena = arena; 297 pubk->keyType = privk->keyType; 298 if (privk->keyType == NSSLOWKEYNullKey) 299 return pubk; 300 rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus, 301 &privk->u.rsa.modulus); 302 if (rv == SECSuccess) { 303 rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent, 304 &privk->u.rsa.publicExponent); 305 if (rv == SECSuccess) 306 return pubk; 307 } 308 } else { 309 PORT_SetError(SEC_ERROR_NO_MEMORY); 310 } 311 break; 312 case NSSLOWKEYDSAKey: 313 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 314 sizeof(NSSLOWKEYPublicKey)); 315 if (pubk != NULL) { 316 SECStatus rv; 317 318 pubk->arena = arena; 319 pubk->keyType = privk->keyType; 320 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue, 321 &privk->u.dsa.publicValue); 322 if (rv != SECSuccess) 323 break; 324 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime, 325 &privk->u.dsa.params.prime); 326 if (rv != SECSuccess) 327 break; 328 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime, 329 &privk->u.dsa.params.subPrime); 330 if (rv != SECSuccess) 331 break; 332 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base, 333 &privk->u.dsa.params.base); 334 if (rv == SECSuccess) 335 return pubk; 336 } 337 break; 338 case NSSLOWKEYDHKey: 339 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 340 sizeof(NSSLOWKEYPublicKey)); 341 if (pubk != NULL) { 342 SECStatus rv; 343 344 pubk->arena = arena; 345 pubk->keyType = privk->keyType; 346 rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue, 347 &privk->u.dh.publicValue); 348 if (rv != SECSuccess) 349 break; 350 rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime, 351 &privk->u.dh.prime); 352 if (rv != SECSuccess) 353 break; 354 rv = SECITEM_CopyItem(arena, &pubk->u.dh.base, 355 &privk->u.dh.base); 356 if (rv == SECSuccess) 357 return pubk; 358 } 359 break; 360 case NSSLOWKEYECKey: 361 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 362 sizeof(NSSLOWKEYPublicKey)); 363 if (pubk != NULL) { 364 SECStatus rv; 365 366 pubk->arena = arena; 367 pubk->keyType = privk->keyType; 368 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, 369 &privk->u.ec.publicValue); 370 if (rv != SECSuccess) 371 break; 372 pubk->u.ec.ecParams.arena = arena; 373 /* Copy the rest of the params */ 374 rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams), 375 &(privk->u.ec.ecParams)); 376 if (rv == SECSuccess) 377 return pubk; 378 } 379 break; 380 /* No Fortezza in Low Key implementations (Fortezza keys aren't 381 * stored in our data base */ 382 default: 383 break; 384 } 385 386 PORT_FreeArena(arena, PR_FALSE); 387 return NULL; 388 }