security/nss/lib/softoken/legacydb/lowkey.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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" 
    11 SEC_ASN1_MKSUB(SEC_AnyTemplate)
    12 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
    13 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
    14 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
    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 };
    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 };
    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 };
    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 };                                                                            
    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 };
    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 };
    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 };
   102 #ifndef NSS_DISABLE_ECC
   104 /* XXX This is just a placeholder for later when we support
   105  * generic curves and need full-blown support for parsing EC
   106  * parameters. For now, we only support named curves in which
   107  * EC params are simply encoded as an object ID and we don't
   108  * use lg_nsslowkey_ECParamsTemplate.
   109  */
   110 const SEC_ASN1Template lg_nsslowkey_ECParamsTemplate[] = {
   111     { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
   112     { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
   113     { 0, }
   114 };
   117 /* NOTE: The SECG specification allows the private key structure
   118  * to contain curve parameters but recommends that they be stored
   119  * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
   120  * instead.
   121  */
   122 const SEC_ASN1Template lg_nsslowkey_ECPrivateKeyTemplate[] = {
   123     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
   124     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
   125     { SEC_ASN1_OCTET_STRING, 
   126       offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
   127     /* XXX The following template works for now since we only
   128      * support named curves for which the parameters are
   129      * encoded as an object ID. When we support generic curves,
   130      * we'll need to define lg_nsslowkey_ECParamsTemplate
   131      */
   132 #if 1
   133     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
   134       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 
   135       offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID), 
   136       SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, 
   137 #else
   138     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
   139       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
   140       offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams), 
   141       lg_nsslowkey_ECParamsTemplate }, 
   142 #endif
   143     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
   144       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
   145       SEC_ASN1_XTRN | 1, 
   146       offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
   147       SEC_ASN1_SUB(SEC_BitStringTemplate) }, 
   148     { 0, }
   149 };
   152 /*
   153  * smaller version of EC_FillParams. In this code, we only need
   154  * oid and DER data.
   155  */
   156 SECStatus
   157 LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
   158     ECParams *params)
   159 {
   160     SECOidTag tag;
   161     SECItem oid = { siBuffer, NULL, 0};
   163 #if EC_DEBUG
   164     int i;
   166     printf("Encoded params in EC_DecodeParams: ");
   167     for (i = 0; i < encodedParams->len; i++) {
   168 	    printf("%02x:", encodedParams->data[i]);
   169     }
   170     printf("\n");
   171 #endif
   173     oid.len = encodedParams->len - 2;
   174     oid.data = encodedParams->data + 2;
   175     if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
   176 	((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { 
   177 	    PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   178 	    return SECFailure;
   179     }
   181     params->arena = arena;
   183     /* For named curves, fill out curveOID */
   184     params->curveOID.len = oid.len;
   185     params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
   186     if (params->curveOID.data == NULL)  {
   187 	return SECFailure;
   188     }
   189     memcpy(params->curveOID.data, oid.data, oid.len);
   191     return SECSuccess;
   192 }
   194 /* Copy all of the fields from srcParams into dstParams
   195  */
   196 SECStatus
   197 LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
   198 	      const ECParams *srcParams)
   199 {
   200     SECStatus rv = SECFailure;
   202     dstParams->arena = arena;
   203     rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
   204 				 &srcParams->DEREncoding);
   205     if (rv != SECSuccess) {
   206 	goto loser;
   207     }
   208     rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
   209 				&srcParams->curveOID);
   210     if (rv != SECSuccess) {
   211 	goto loser;
   212     }
   214     return SECSuccess;
   216 loser:
   217     return SECFailure;
   218 }
   219 #endif /* NSS_DISABLE_ECC */
   220 /*
   221  * See bugzilla bug 125359
   222  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
   223  * all of the templates above that en/decode into integers must be converted
   224  * from ASN.1's signed integer type.  This is done by marking either the
   225  * source or destination (encoding or decoding, respectively) type as
   226  * siUnsignedInteger.
   227  */
   229 void
   230 lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
   231 {
   232     key->u.rsa.modulus.type = siUnsignedInteger;
   233     key->u.rsa.publicExponent.type = siUnsignedInteger;
   234     key->u.rsa.privateExponent.type = siUnsignedInteger;
   235     key->u.rsa.prime1.type = siUnsignedInteger;
   236     key->u.rsa.prime2.type = siUnsignedInteger;
   237     key->u.rsa.exponent1.type = siUnsignedInteger;
   238     key->u.rsa.exponent2.type = siUnsignedInteger;
   239     key->u.rsa.coefficient.type = siUnsignedInteger;
   240 }
   242 void
   243 lg_prepare_low_pqg_params_for_asn1(PQGParams *params)
   244 {
   245     params->prime.type = siUnsignedInteger;
   246     params->subPrime.type = siUnsignedInteger;
   247     params->base.type = siUnsignedInteger;
   248 }
   250 void
   251 lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
   252 {
   253     key->u.dsa.publicValue.type = siUnsignedInteger;
   254     key->u.dsa.privateValue.type = siUnsignedInteger;
   255     key->u.dsa.params.prime.type = siUnsignedInteger;
   256     key->u.dsa.params.subPrime.type = siUnsignedInteger;
   257     key->u.dsa.params.base.type = siUnsignedInteger;
   258 }
   260 void
   261 lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
   262 {
   263     key->u.dh.prime.type = siUnsignedInteger;
   264     key->u.dh.base.type = siUnsignedInteger;
   265     key->u.dh.publicValue.type = siUnsignedInteger;
   266     key->u.dh.privateValue.type = siUnsignedInteger;
   267 }
   269 #ifndef NSS_DISABLE_ECC
   270 void
   271 lg_prepare_low_ecparams_for_asn1(ECParams *params)
   272 {
   273     params->DEREncoding.type = siUnsignedInteger;
   274     params->curveOID.type = siUnsignedInteger;
   275 }
   277 void
   278 lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
   279 {
   280     key->u.ec.version.type = siUnsignedInteger;
   281     key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
   282     key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
   283     key->u.ec.privateValue.type = siUnsignedInteger;
   284     key->u.ec.publicValue.type = siUnsignedInteger;
   285 }
   286 #endif /* NSS_DISABLE_ECC */
   288 void
   289 lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
   290 {
   291     if (privk && privk->arena) {
   292 	PORT_FreeArena(privk->arena, PR_TRUE);
   293     }
   294 }
   296 void
   297 lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
   298 {
   299     if (pubk && pubk->arena) {
   300 	PORT_FreeArena(pubk->arena, PR_FALSE);
   301     }
   302 }
   304 NSSLOWKEYPublicKey *
   305 lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
   306 {
   307     NSSLOWKEYPublicKey *pubk;
   308     PLArenaPool *arena;
   311     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
   312     if (arena == NULL) {
   313         PORT_SetError (SEC_ERROR_NO_MEMORY);
   314         return NULL;
   315     }
   317     switch(privk->keyType) {
   318       case NSSLOWKEYRSAKey:
   319       case NSSLOWKEYNullKey:
   320 	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
   321 						sizeof (NSSLOWKEYPublicKey));
   322 	if (pubk != NULL) {
   323 	    SECStatus rv;
   325 	    pubk->arena = arena;
   326 	    pubk->keyType = privk->keyType;
   327 	    if (privk->keyType == NSSLOWKEYNullKey) return pubk;
   328 	    rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
   329 				  &privk->u.rsa.modulus);
   330 	    if (rv == SECSuccess) {
   331 		rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
   332 				       &privk->u.rsa.publicExponent);
   333 		if (rv == SECSuccess)
   334 		    return pubk;
   335 	    }
   336 	} else {
   337 	    PORT_SetError (SEC_ERROR_NO_MEMORY);
   338 	}
   339 	break;
   340       case NSSLOWKEYDSAKey:
   341 	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
   342 						    sizeof(NSSLOWKEYPublicKey));
   343 	if (pubk != NULL) {
   344 	    SECStatus rv;
   346 	    pubk->arena = arena;
   347 	    pubk->keyType = privk->keyType;
   348 	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
   349 				  &privk->u.dsa.publicValue);
   350 	    if (rv != SECSuccess) break;
   351 	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
   352 				  &privk->u.dsa.params.prime);
   353 	    if (rv != SECSuccess) break;
   354 	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
   355 				  &privk->u.dsa.params.subPrime);
   356 	    if (rv != SECSuccess) break;
   357 	    rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
   358 				  &privk->u.dsa.params.base);
   359 	    if (rv == SECSuccess) return pubk;
   360 	}
   361 	break;
   362       case NSSLOWKEYDHKey:
   363 	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
   364 						    sizeof(NSSLOWKEYPublicKey));
   365 	if (pubk != NULL) {
   366 	    SECStatus rv;
   368 	    pubk->arena = arena;
   369 	    pubk->keyType = privk->keyType;
   370 	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
   371 				  &privk->u.dh.publicValue);
   372 	    if (rv != SECSuccess) break;
   373 	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
   374 				  &privk->u.dh.prime);
   375 	    if (rv != SECSuccess) break;
   376 	    rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
   377 				  &privk->u.dh.base);
   378 	    if (rv == SECSuccess) return pubk;
   379 	}
   380 	break;
   381 #ifndef NSS_DISABLE_ECC
   382       case NSSLOWKEYECKey:
   383 	pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
   384 						    sizeof(NSSLOWKEYPublicKey));
   385 	if (pubk != NULL) {
   386 	    SECStatus rv;
   388 	    pubk->arena = arena;
   389 	    pubk->keyType = privk->keyType;
   390 	    rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
   391 				  &privk->u.ec.publicValue);
   392 	    if (rv != SECSuccess) break;
   393 	    pubk->u.ec.ecParams.arena = arena;
   394 	    /* Copy the rest of the params */
   395 	    rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
   396 			       &(privk->u.ec.ecParams));
   397 	    if (rv == SECSuccess) return pubk;
   398 	}
   399 	break;
   400 #endif /* NSS_DISABLE_ECC */
   401 	/* No Fortezza in Low Key implementations (Fortezza keys aren't
   402 	 * stored in our data base */
   403     default:
   404 	break;
   405     }
   407     PORT_FreeArena (arena, PR_FALSE);
   408     return NULL;
   409 }

mercurial