1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/legacydb/lowkey.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,410 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "lowkeyi.h" 1.8 +#include "secoid.h" 1.9 +#include "secitem.h" 1.10 +#include "secder.h" 1.11 +#include "secasn1.h" 1.12 +#include "secerr.h" 1.13 + 1.14 +SEC_ASN1_MKSUB(SEC_AnyTemplate) 1.15 +SEC_ASN1_MKSUB(SEC_BitStringTemplate) 1.16 +SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) 1.17 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.18 + 1.19 +static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = { 1.20 + { SEC_ASN1_SEQUENCE, 1.21 + 0, NULL, sizeof(NSSLOWKEYAttribute) }, 1.22 + { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) }, 1.23 + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue), 1.24 + SEC_ASN1_SUB(SEC_AnyTemplate) }, 1.25 + { 0 } 1.26 +}; 1.27 + 1.28 +static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = { 1.29 + { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate }, 1.30 +}; 1.31 +/* ASN1 Templates for new decoder/encoder */ 1.32 +const SEC_ASN1Template lg_nsslowkey_PrivateKeyInfoTemplate[] = { 1.33 + { SEC_ASN1_SEQUENCE, 1.34 + 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, 1.35 + { SEC_ASN1_INTEGER, 1.36 + offsetof(NSSLOWKEYPrivateKeyInfo,version) }, 1.37 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.38 + offsetof(NSSLOWKEYPrivateKeyInfo,algorithm), 1.39 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.40 + { SEC_ASN1_OCTET_STRING, 1.41 + offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) }, 1.42 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.43 + offsetof(NSSLOWKEYPrivateKeyInfo, attributes), 1.44 + nsslowkey_SetOfAttributeTemplate }, 1.45 + { 0 } 1.46 +}; 1.47 + 1.48 +const SEC_ASN1Template lg_nsslowkey_PQGParamsTemplate[] = { 1.49 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, 1.50 + { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) }, 1.51 + { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) }, 1.52 + { SEC_ASN1_INTEGER, offsetof(PQGParams,base) }, 1.53 + { 0, } 1.54 +}; 1.55 + 1.56 +const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate[] = { 1.57 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 1.58 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) }, 1.59 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) }, 1.60 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) }, 1.61 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) }, 1.62 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) }, 1.63 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) }, 1.64 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) }, 1.65 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) }, 1.66 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) }, 1.67 + { 0 } 1.68 +}; 1.69 + 1.70 +/* 1.71 + * Allows u.rsa.modulus to be zero length for secret keys with an empty 1.72 + * CKA_ID incorrectly generated in NSS 3.13.3 or earlier. Only used for 1.73 + * decoding. See bug 715073. 1.74 + */ 1.75 +const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate2[] = { 1.76 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 1.77 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) }, 1.78 + { SEC_ASN1_ANY, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) }, 1.79 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) }, 1.80 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) }, 1.81 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) }, 1.82 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) }, 1.83 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) }, 1.84 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) }, 1.85 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) }, 1.86 + { 0 } 1.87 +}; 1.88 + 1.89 +const SEC_ASN1Template lg_nsslowkey_DSAPrivateKeyTemplate[] = { 1.90 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 1.91 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) }, 1.92 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) }, 1.93 + { 0, } 1.94 +}; 1.95 + 1.96 +const SEC_ASN1Template lg_nsslowkey_DHPrivateKeyTemplate[] = { 1.97 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 1.98 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) }, 1.99 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) }, 1.100 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) }, 1.101 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) }, 1.102 + { 0, } 1.103 +}; 1.104 + 1.105 +#ifndef NSS_DISABLE_ECC 1.106 + 1.107 +/* XXX This is just a placeholder for later when we support 1.108 + * generic curves and need full-blown support for parsing EC 1.109 + * parameters. For now, we only support named curves in which 1.110 + * EC params are simply encoded as an object ID and we don't 1.111 + * use lg_nsslowkey_ECParamsTemplate. 1.112 + */ 1.113 +const SEC_ASN1Template lg_nsslowkey_ECParamsTemplate[] = { 1.114 + { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) }, 1.115 + { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named }, 1.116 + { 0, } 1.117 +}; 1.118 + 1.119 + 1.120 +/* NOTE: The SECG specification allows the private key structure 1.121 + * to contain curve parameters but recommends that they be stored 1.122 + * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo 1.123 + * instead. 1.124 + */ 1.125 +const SEC_ASN1Template lg_nsslowkey_ECPrivateKeyTemplate[] = { 1.126 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, 1.127 + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) }, 1.128 + { SEC_ASN1_OCTET_STRING, 1.129 + offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) }, 1.130 + /* XXX The following template works for now since we only 1.131 + * support named curves for which the parameters are 1.132 + * encoded as an object ID. When we support generic curves, 1.133 + * we'll need to define lg_nsslowkey_ECParamsTemplate 1.134 + */ 1.135 +#if 1 1.136 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 1.137 + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1.138 + offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID), 1.139 + SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, 1.140 +#else 1.141 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 1.142 + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.143 + offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams), 1.144 + lg_nsslowkey_ECParamsTemplate }, 1.145 +#endif 1.146 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 1.147 + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1.148 + SEC_ASN1_XTRN | 1, 1.149 + offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue), 1.150 + SEC_ASN1_SUB(SEC_BitStringTemplate) }, 1.151 + { 0, } 1.152 +}; 1.153 + 1.154 + 1.155 +/* 1.156 + * smaller version of EC_FillParams. In this code, we only need 1.157 + * oid and DER data. 1.158 + */ 1.159 +SECStatus 1.160 +LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, 1.161 + ECParams *params) 1.162 +{ 1.163 + SECOidTag tag; 1.164 + SECItem oid = { siBuffer, NULL, 0}; 1.165 + 1.166 +#if EC_DEBUG 1.167 + int i; 1.168 + 1.169 + printf("Encoded params in EC_DecodeParams: "); 1.170 + for (i = 0; i < encodedParams->len; i++) { 1.171 + printf("%02x:", encodedParams->data[i]); 1.172 + } 1.173 + printf("\n"); 1.174 +#endif 1.175 + 1.176 + oid.len = encodedParams->len - 2; 1.177 + oid.data = encodedParams->data + 2; 1.178 + if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || 1.179 + ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { 1.180 + PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 1.181 + return SECFailure; 1.182 + } 1.183 + 1.184 + params->arena = arena; 1.185 + 1.186 + /* For named curves, fill out curveOID */ 1.187 + params->curveOID.len = oid.len; 1.188 + params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len); 1.189 + if (params->curveOID.data == NULL) { 1.190 + return SECFailure; 1.191 + } 1.192 + memcpy(params->curveOID.data, oid.data, oid.len); 1.193 + 1.194 + return SECSuccess; 1.195 +} 1.196 + 1.197 +/* Copy all of the fields from srcParams into dstParams 1.198 + */ 1.199 +SECStatus 1.200 +LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams, 1.201 + const ECParams *srcParams) 1.202 +{ 1.203 + SECStatus rv = SECFailure; 1.204 + 1.205 + dstParams->arena = arena; 1.206 + rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding, 1.207 + &srcParams->DEREncoding); 1.208 + if (rv != SECSuccess) { 1.209 + goto loser; 1.210 + } 1.211 + rv =SECITEM_CopyItem(arena, &dstParams->curveOID, 1.212 + &srcParams->curveOID); 1.213 + if (rv != SECSuccess) { 1.214 + goto loser; 1.215 + } 1.216 + 1.217 + return SECSuccess; 1.218 + 1.219 +loser: 1.220 + return SECFailure; 1.221 +} 1.222 +#endif /* NSS_DISABLE_ECC */ 1.223 +/* 1.224 + * See bugzilla bug 125359 1.225 + * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, 1.226 + * all of the templates above that en/decode into integers must be converted 1.227 + * from ASN.1's signed integer type. This is done by marking either the 1.228 + * source or destination (encoding or decoding, respectively) type as 1.229 + * siUnsignedInteger. 1.230 + */ 1.231 + 1.232 +void 1.233 +lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 1.234 +{ 1.235 + key->u.rsa.modulus.type = siUnsignedInteger; 1.236 + key->u.rsa.publicExponent.type = siUnsignedInteger; 1.237 + key->u.rsa.privateExponent.type = siUnsignedInteger; 1.238 + key->u.rsa.prime1.type = siUnsignedInteger; 1.239 + key->u.rsa.prime2.type = siUnsignedInteger; 1.240 + key->u.rsa.exponent1.type = siUnsignedInteger; 1.241 + key->u.rsa.exponent2.type = siUnsignedInteger; 1.242 + key->u.rsa.coefficient.type = siUnsignedInteger; 1.243 +} 1.244 + 1.245 +void 1.246 +lg_prepare_low_pqg_params_for_asn1(PQGParams *params) 1.247 +{ 1.248 + params->prime.type = siUnsignedInteger; 1.249 + params->subPrime.type = siUnsignedInteger; 1.250 + params->base.type = siUnsignedInteger; 1.251 +} 1.252 + 1.253 +void 1.254 +lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 1.255 +{ 1.256 + key->u.dsa.publicValue.type = siUnsignedInteger; 1.257 + key->u.dsa.privateValue.type = siUnsignedInteger; 1.258 + key->u.dsa.params.prime.type = siUnsignedInteger; 1.259 + key->u.dsa.params.subPrime.type = siUnsignedInteger; 1.260 + key->u.dsa.params.base.type = siUnsignedInteger; 1.261 +} 1.262 + 1.263 +void 1.264 +lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 1.265 +{ 1.266 + key->u.dh.prime.type = siUnsignedInteger; 1.267 + key->u.dh.base.type = siUnsignedInteger; 1.268 + key->u.dh.publicValue.type = siUnsignedInteger; 1.269 + key->u.dh.privateValue.type = siUnsignedInteger; 1.270 +} 1.271 + 1.272 +#ifndef NSS_DISABLE_ECC 1.273 +void 1.274 +lg_prepare_low_ecparams_for_asn1(ECParams *params) 1.275 +{ 1.276 + params->DEREncoding.type = siUnsignedInteger; 1.277 + params->curveOID.type = siUnsignedInteger; 1.278 +} 1.279 + 1.280 +void 1.281 +lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) 1.282 +{ 1.283 + key->u.ec.version.type = siUnsignedInteger; 1.284 + key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger; 1.285 + key->u.ec.ecParams.curveOID.type = siUnsignedInteger; 1.286 + key->u.ec.privateValue.type = siUnsignedInteger; 1.287 + key->u.ec.publicValue.type = siUnsignedInteger; 1.288 +} 1.289 +#endif /* NSS_DISABLE_ECC */ 1.290 + 1.291 +void 1.292 +lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) 1.293 +{ 1.294 + if (privk && privk->arena) { 1.295 + PORT_FreeArena(privk->arena, PR_TRUE); 1.296 + } 1.297 +} 1.298 + 1.299 +void 1.300 +lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk) 1.301 +{ 1.302 + if (pubk && pubk->arena) { 1.303 + PORT_FreeArena(pubk->arena, PR_FALSE); 1.304 + } 1.305 +} 1.306 + 1.307 +NSSLOWKEYPublicKey * 1.308 +lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) 1.309 +{ 1.310 + NSSLOWKEYPublicKey *pubk; 1.311 + PLArenaPool *arena; 1.312 + 1.313 + 1.314 + arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); 1.315 + if (arena == NULL) { 1.316 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.317 + return NULL; 1.318 + } 1.319 + 1.320 + switch(privk->keyType) { 1.321 + case NSSLOWKEYRSAKey: 1.322 + case NSSLOWKEYNullKey: 1.323 + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 1.324 + sizeof (NSSLOWKEYPublicKey)); 1.325 + if (pubk != NULL) { 1.326 + SECStatus rv; 1.327 + 1.328 + pubk->arena = arena; 1.329 + pubk->keyType = privk->keyType; 1.330 + if (privk->keyType == NSSLOWKEYNullKey) return pubk; 1.331 + rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus, 1.332 + &privk->u.rsa.modulus); 1.333 + if (rv == SECSuccess) { 1.334 + rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent, 1.335 + &privk->u.rsa.publicExponent); 1.336 + if (rv == SECSuccess) 1.337 + return pubk; 1.338 + } 1.339 + } else { 1.340 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.341 + } 1.342 + break; 1.343 + case NSSLOWKEYDSAKey: 1.344 + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 1.345 + sizeof(NSSLOWKEYPublicKey)); 1.346 + if (pubk != NULL) { 1.347 + SECStatus rv; 1.348 + 1.349 + pubk->arena = arena; 1.350 + pubk->keyType = privk->keyType; 1.351 + rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue, 1.352 + &privk->u.dsa.publicValue); 1.353 + if (rv != SECSuccess) break; 1.354 + rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime, 1.355 + &privk->u.dsa.params.prime); 1.356 + if (rv != SECSuccess) break; 1.357 + rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime, 1.358 + &privk->u.dsa.params.subPrime); 1.359 + if (rv != SECSuccess) break; 1.360 + rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base, 1.361 + &privk->u.dsa.params.base); 1.362 + if (rv == SECSuccess) return pubk; 1.363 + } 1.364 + break; 1.365 + case NSSLOWKEYDHKey: 1.366 + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 1.367 + sizeof(NSSLOWKEYPublicKey)); 1.368 + if (pubk != NULL) { 1.369 + SECStatus rv; 1.370 + 1.371 + pubk->arena = arena; 1.372 + pubk->keyType = privk->keyType; 1.373 + rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue, 1.374 + &privk->u.dh.publicValue); 1.375 + if (rv != SECSuccess) break; 1.376 + rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime, 1.377 + &privk->u.dh.prime); 1.378 + if (rv != SECSuccess) break; 1.379 + rv = SECITEM_CopyItem(arena, &pubk->u.dh.base, 1.380 + &privk->u.dh.base); 1.381 + if (rv == SECSuccess) return pubk; 1.382 + } 1.383 + break; 1.384 +#ifndef NSS_DISABLE_ECC 1.385 + case NSSLOWKEYECKey: 1.386 + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, 1.387 + sizeof(NSSLOWKEYPublicKey)); 1.388 + if (pubk != NULL) { 1.389 + SECStatus rv; 1.390 + 1.391 + pubk->arena = arena; 1.392 + pubk->keyType = privk->keyType; 1.393 + rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, 1.394 + &privk->u.ec.publicValue); 1.395 + if (rv != SECSuccess) break; 1.396 + pubk->u.ec.ecParams.arena = arena; 1.397 + /* Copy the rest of the params */ 1.398 + rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams), 1.399 + &(privk->u.ec.ecParams)); 1.400 + if (rv == SECSuccess) return pubk; 1.401 + } 1.402 + break; 1.403 +#endif /* NSS_DISABLE_ECC */ 1.404 + /* No Fortezza in Low Key implementations (Fortezza keys aren't 1.405 + * stored in our data base */ 1.406 + default: 1.407 + break; 1.408 + } 1.409 + 1.410 + PORT_FreeArena (arena, PR_FALSE); 1.411 + return NULL; 1.412 +} 1.413 +