bug 125359, by default the ASN.1 en/decoder should treat all numbers as signed. But many source/target items desire unsigned integers (specifically, bignums in the crypto stuff), so implement an siUnsignedInteger type which notifies the en/decoder to handle the conversion.

r=nelsonb
This commit is contained in:
ian.mcgreer%sun.com 2002-02-21 22:41:44 +00:00
Родитель 6cabe1f1a6
Коммит e5c7125aba
12 изменённых файлов: 256 добавлений и 47 удалений

Просмотреть файл

@ -149,8 +149,10 @@ DSAU_EncodeDerSig(SECItem *dest, SECItem *src)
** prepend with leading zero. ** prepend with leading zero.
** Must remove all but one leading zero byte from numbers. ** Must remove all but one leading zero byte from numbers.
*/ */
sig.r.type = siUnsignedInteger;
sig.r.data = signedR; sig.r.data = signedR;
sig.r.len = sizeof signedR; sig.r.len = sizeof signedR;
sig.s.type = siUnsignedInteger;
sig.s.data = signedS; sig.s.data = signedS;
sig.s.len = sizeof signedR; sig.s.len = sizeof signedR;
@ -193,6 +195,8 @@ DSAU_DecodeDerSig(SECItem *item)
if (result->data == NULL) if (result->data == NULL)
goto loser; goto loser;
sig.r.type = siUnsignedInteger;
sig.s.type = siUnsignedInteger;
status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item); status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item);
if (status != SECSuccess) if (status != SECSuccess)
goto loser; goto loser;

Просмотреть файл

@ -143,6 +143,48 @@ SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate) SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate) SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
{
pubk->u.rsa.modulus.type = siUnsignedInteger;
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
}
static void
prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
{
pubk->u.dsa.publicValue.type = siUnsignedInteger;
}
static void
prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
{
params->prime.type = siUnsignedInteger;
params->subPrime.type = siUnsignedInteger;
params->base.type = siUnsignedInteger;
}
static void
prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
{
pubk->u.dh.prime.type = siUnsignedInteger;
pubk->u.dh.base.type = siUnsignedInteger;
pubk->u.dh.publicValue.type = siUnsignedInteger;
}
static void
prepare_kea_pub_key_for_asn1(SECKEYPublicKey *pubk)
{
pubk->u.kea.publicValue.type = siUnsignedInteger;
}
/* Create an RSA key pair is any slot able to do so. /* Create an RSA key pair is any slot able to do so.
** The created keys are "session" (temporary), not "token" (permanent), ** The created keys are "session" (temporary), not "token" (permanent),
@ -509,6 +551,7 @@ SECKEY_FortezzaDecodePQGtoOld(PRArenaPool *arena, SECKEYPublicKey *pubk,
/* PQG params are in the standard format */ /* PQG params are in the standard format */
/* Store DSA PQG parameters */ /* Store DSA PQG parameters */
prepare_pqg_params_for_asn1(&pubk->u.fortezza.params);
rv = SEC_ASN1DecodeItem(arena, &pubk->u.fortezza.params, rv = SEC_ASN1DecodeItem(arena, &pubk->u.fortezza.params,
SECKEY_PQGParamsTemplate, SECKEY_PQGParamsTemplate,
params); params);
@ -628,6 +671,7 @@ SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params)
(params->data[0] != 0xa0)) { (params->data[0] != 0xa0)) {
/* PQG params are in the standard format */ /* PQG params are in the standard format */
prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
rv = SEC_ASN1DecodeItem(arena, &pubk->u.dsa.params, rv = SEC_ASN1DecodeItem(arena, &pubk->u.dsa.params,
SECKEY_PQGParamsTemplate, SECKEY_PQGParamsTemplate,
params); params);
@ -875,6 +919,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
case SEC_OID_X500_RSA_ENCRYPTION: case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION: case SEC_OID_PKCS1_RSA_ENCRYPTION:
pubk->keyType = rsaKey; pubk->keyType = rsaKey;
prepare_rsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &os); rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &os);
if (rv == SECSuccess) if (rv == SECSuccess)
return pubk; return pubk;
@ -882,6 +927,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_SDN702_DSA_SIGNATURE: case SEC_OID_SDN702_DSA_SIGNATURE:
pubk->keyType = dsaKey; pubk->keyType = dsaKey;
prepare_dsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &os); rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &os);
if (rv != SECSuccess) break; if (rv != SECSuccess) break;
@ -892,6 +938,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
break; break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY: case SEC_OID_X942_DIFFIE_HELMAN_KEY:
pubk->keyType = dhKey; pubk->keyType = dhKey;
prepare_dh_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &os); rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &os);
if (rv != SECSuccess) break; if (rv != SECSuccess) break;
@ -914,6 +961,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
case SEC_OID_MISSI_KEA: case SEC_OID_MISSI_KEA:
pubk->keyType = keaKey; pubk->keyType = keaKey;
prepare_kea_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, rv = SEC_ASN1DecodeItem(arena, pubk,
SECKEY_KEAPublicKeyTemplate, &os); SECKEY_KEAPublicKeyTemplate, &os);
if (rv != SECSuccess) break; if (rv != SECSuccess) break;
@ -1269,6 +1317,7 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
/* /*
* DER encode the public key into the subjectPublicKeyInfo. * DER encode the public key into the subjectPublicKeyInfo.
*/ */
prepare_rsa_pub_key_for_asn1(pubk);
rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
pubk, SECKEY_RSAPublicKeyTemplate); pubk, SECKEY_RSAPublicKeyTemplate);
if (rv_item != NULL) { if (rv_item != NULL) {
@ -1286,6 +1335,7 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
break; break;
case dsaKey: case dsaKey:
/* DER encode the params. */ /* DER encode the params. */
prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params, rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
SECKEY_PQGParamsTemplate); SECKEY_PQGParamsTemplate);
if (rv_item != NULL) { if (rv_item != NULL) {
@ -1296,6 +1346,7 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
/* /*
* DER encode the public key into the subjectPublicKeyInfo. * DER encode the public key into the subjectPublicKeyInfo.
*/ */
prepare_dsa_pub_key_for_asn1(pubk);
rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
pubk, pubk,
SECKEY_DSAPublicKeyTemplate); SECKEY_DSAPublicKeyTemplate);
@ -1390,6 +1441,7 @@ SECKEY_DecodeDERPublicKey(SECItem *pubkder)
pubk->arena = arena; pubk->arena = arena;
pubk->pkcs11Slot = NULL; pubk->pkcs11Slot = NULL;
pubk->pkcs11ID = 0; pubk->pkcs11ID = 0;
prepare_rsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
pubkder); pubkder);
if (rv == SECSuccess) if (rv == SECSuccess)
@ -1732,14 +1784,17 @@ SECKEY_ImportDERPublicKey(SECItem *derKey, CK_KEY_TYPE type)
switch( type ) { switch( type ) {
case CKK_RSA: case CKK_RSA:
prepare_rsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_RSAPublicKeyTemplate,derKey); rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_RSAPublicKeyTemplate,derKey);
pubk->keyType = rsaKey; pubk->keyType = rsaKey;
break; break;
case CKK_DSA: case CKK_DSA:
prepare_dsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_DSAPublicKeyTemplate,derKey); rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_DSAPublicKeyTemplate,derKey);
pubk->keyType = dsaKey; pubk->keyType = dsaKey;
break; break;
case CKK_DH: case CKK_DH:
prepare_dh_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_DHPublicKeyTemplate, derKey); rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_DHPublicKeyTemplate, derKey);
pubk->keyType = dhKey; pubk->keyType = dhKey;
break; break;

Просмотреть файл

@ -185,6 +185,45 @@ SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate) SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate) SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.rsa.modulus.type = siUnsignedInteger;
key->u.rsa.publicExponent.type = siUnsignedInteger;
key->u.rsa.privateExponent.type = siUnsignedInteger;
key->u.rsa.prime1.type = siUnsignedInteger;
key->u.rsa.prime2.type = siUnsignedInteger;
key->u.rsa.exponent1.type = siUnsignedInteger;
key->u.rsa.exponent2.type = siUnsignedInteger;
key->u.rsa.coefficient.type = siUnsignedInteger;
}
static void
prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.dsa.privateValue.type = siUnsignedInteger;
key->u.dsa.params.prime.type = siUnsignedInteger;
key->u.dsa.params.subPrime.type = siUnsignedInteger;
key->u.dsa.params.base.type = siUnsignedInteger;
}
static void
prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.dh.privateValue.type = siUnsignedInteger;
key->u.dh.prime.type = siUnsignedInteger;
key->u.dh.base.type = siUnsignedInteger;
}
SECStatus SECStatus
PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI, PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI,
@ -437,6 +476,7 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
case SEC_OID_PKCS1_RSA_ENCRYPTION: case SEC_OID_PKCS1_RSA_ENCRYPTION:
prepare_rsa_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_RSAPrivateKeyExportTemplate; keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
paramTemplate = NULL; paramTemplate = NULL;
paramDest = NULL; paramDest = NULL;
@ -444,6 +484,7 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
keyType = CKK_RSA; keyType = CKK_RSA;
break; break;
case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE:
prepare_dsa_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_DSAPrivateKeyExportTemplate; keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
paramTemplate = SECKEY_PQGParamsTemplate; paramTemplate = SECKEY_PQGParamsTemplate;
paramDest = &(lpk->u.dsa.params); paramDest = &(lpk->u.dsa.params);
@ -454,6 +495,7 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
if(!publicValue) { if(!publicValue) {
goto loser; goto loser;
} }
prepare_dh_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_DHPrivateKeyExportTemplate; keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
paramTemplate = NULL; paramTemplate = NULL;
paramDest = NULL; paramDest = NULL;

Просмотреть файл

@ -32,7 +32,7 @@
* *
* Private Key Database code * Private Key Database code
* *
* $Id: keydb.c,v 1.12 2001-12-07 01:36:17 relyea%netscape.com Exp $ * $Id: keydb.c,v 1.13 2002-02-21 22:41:37 ian.mcgreer%sun.com Exp $
*/ */
#include "lowkeyi.h" #include "lowkeyi.h"
@ -1579,6 +1579,7 @@ seckey_encrypt_private_key(
/* Encode the key, and set the algorithm (with params) */ /* Encode the key, and set the algorithm (with params) */
switch (pk->keyType) { switch (pk->keyType) {
case NSSLOWKEYRSAKey: case NSSLOWKEYRSAKey:
prepare_low_rsa_priv_key_for_asn1(pk);
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
nsslowkey_RSAPrivateKeyTemplate); nsslowkey_RSAPrivateKeyTemplate);
if (dummy == NULL) { if (dummy == NULL) {
@ -1594,6 +1595,7 @@ seckey_encrypt_private_key(
break; break;
case NSSLOWKEYDSAKey: case NSSLOWKEYDSAKey:
prepare_low_dsa_priv_key_for_asn1(pk);
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
nsslowkey_DSAPrivateKeyTemplate); nsslowkey_DSAPrivateKeyTemplate);
if (dummy == NULL) { if (dummy == NULL) {
@ -1601,6 +1603,7 @@ seckey_encrypt_private_key(
goto loser; goto loser;
} }
prepare_low_pqg_params_for_asn1(&pk->u.dsa.params);
dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params, dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params,
nsslowkey_PQGParamsTemplate); nsslowkey_PQGParamsTemplate);
if (dummy == NULL) { if (dummy == NULL) {
@ -1616,6 +1619,7 @@ seckey_encrypt_private_key(
break; break;
case NSSLOWKEYDHKey: case NSSLOWKEYDHKey:
prepare_low_dh_priv_key_for_asn1(pk);
dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
nsslowkey_DHPrivateKeyTemplate); nsslowkey_DHPrivateKeyTemplate);
if (dummy == NULL) { if (dummy == NULL) {
@ -1860,23 +1864,27 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki,
case SEC_OID_X500_RSA_ENCRYPTION: case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION: case SEC_OID_PKCS1_RSA_ENCRYPTION:
pk->keyType = NSSLOWKEYRSAKey; pk->keyType = NSSLOWKEYRSAKey;
prepare_low_rsa_priv_key_for_asn1(pk);
rv = SEC_ASN1DecodeItem(permarena, pk, rv = SEC_ASN1DecodeItem(permarena, pk,
nsslowkey_RSAPrivateKeyTemplate, nsslowkey_RSAPrivateKeyTemplate,
&pki->privateKey); &pki->privateKey);
break; break;
case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE:
pk->keyType = NSSLOWKEYDSAKey; pk->keyType = NSSLOWKEYDSAKey;
prepare_low_dsa_priv_key_for_asn1(pk);
rv = SEC_ASN1DecodeItem(permarena, pk, rv = SEC_ASN1DecodeItem(permarena, pk,
nsslowkey_DSAPrivateKeyTemplate, nsslowkey_DSAPrivateKeyTemplate,
&pki->privateKey); &pki->privateKey);
if (rv != SECSuccess) if (rv != SECSuccess)
goto loser; goto loser;
prepare_low_pqg_params_for_asn1(&pk->u.dsa.params);
rv = SEC_ASN1DecodeItem(permarena, &pk->u.dsa.params, rv = SEC_ASN1DecodeItem(permarena, &pk->u.dsa.params,
nsslowkey_PQGParamsTemplate, nsslowkey_PQGParamsTemplate,
&pki->algorithm.parameters); &pki->algorithm.parameters);
break; break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY: case SEC_OID_X942_DIFFIE_HELMAN_KEY:
pk->keyType = NSSLOWKEYDHKey; pk->keyType = NSSLOWKEYDHKey;
prepare_low_dh_priv_key_for_asn1(pk);
rv = SEC_ASN1DecodeItem(permarena, pk, rv = SEC_ASN1DecodeItem(permarena, pk,
nsslowkey_DHPrivateKeyTemplate, nsslowkey_DHPrivateKeyTemplate,
&pki->privateKey); &pki->privateKey);

Просмотреть файл

@ -34,7 +34,7 @@
/* /*
* Certificate handling code * Certificate handling code
* *
* $Id: lowcert.c,v 1.5 2002-01-17 00:20:52 ian.mcgreer%sun.com Exp $ * $Id: lowcert.c,v 1.6 2002-02-21 22:41:37 ian.mcgreer%sun.com Exp $
*/ */
#include "seccomon.h" #include "seccomon.h"
@ -117,6 +117,39 @@ const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
{ 0, } { 0, }
}; };
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.rsa.modulus.type = siUnsignedInteger;
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
}
static void
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dsa.publicValue.type = siUnsignedInteger;
pubk->u.dsa.params.prime.type = siUnsignedInteger;
pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
pubk->u.dsa.params.base.type = siUnsignedInteger;
}
static void
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dh.prime.type = siUnsignedInteger;
pubk->u.dh.base.type = siUnsignedInteger;
pubk->u.dh.publicValue.type = siUnsignedInteger;
}
/* /*
* Allow use of default cert database, so that apps(such as mozilla) don't * Allow use of default cert database, so that apps(such as mozilla) don't
* have to pass the handle all over the place. * have to pass the handle all over the place.
@ -339,45 +372,23 @@ nsslowcert_FixupEmailAddr(char *emailAddr)
return(retaddr); return(retaddr);
} }
/* NSS has traditionally keyed certificate entries in the cert database
* by (serial number, DER_ISSUER). The serial number may have a leading zero
* in order to make it a signed integer. However, the ASN.1 decoder now
* strips the leading zero, treating any INTEGER as unsigned. In order to
* be compatible with version 7 of the database, it is necessary to reapply
* that leading zero to the serial number when needed, before computing the
* database key.
*/
static SECStatus static SECStatus
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn, nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
SECItem *key) SECItem *key)
{ {
PRBool leadingZero = PR_FALSE;
int start;
key->len = sn->len + issuer->len; key->len = sn->len + issuer->len;
if (sn->data[0] & 0x80) {
leadingZero = PR_TRUE;
key->len++;
}
key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len); key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
if ( !key->data ) { if ( !key->data ) {
goto loser; goto loser;
} }
if (leadingZero) {
key->data[0] = 0;
start = 1;
} else {
start = 0;
}
/* copy the serialNumber */ /* copy the serialNumber */
PORT_Memcpy(key->data + start, sn->data, sn->len); PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */ /* copy the issuer */
PORT_Memcpy(&key->data[start + sn->len], issuer->data, issuer->len); PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess); return(SECSuccess);
@ -453,6 +464,7 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
case SEC_OID_X500_RSA_ENCRYPTION: case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION: case SEC_OID_PKCS1_RSA_ENCRYPTION:
pubk->keyType = NSSLOWKEYRSAKey; pubk->keyType = NSSLOWKEYRSAKey;
prepare_low_rsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, rv = SEC_ASN1DecodeItem(arena, pubk,
nsslowcert_RSAPublicKeyTemplate, &os); nsslowcert_RSAPublicKeyTemplate, &os);
if (rv == SECSuccess) if (rv == SECSuccess)
@ -460,12 +472,14 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
break; break;
case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE:
pubk->keyType = NSSLOWKEYDSAKey; pubk->keyType = NSSLOWKEYDSAKey;
prepare_low_dsa_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, rv = SEC_ASN1DecodeItem(arena, pubk,
nsslowcert_DSAPublicKeyTemplate, &os); nsslowcert_DSAPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk; if (rv == SECSuccess) return pubk;
break; break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY: case SEC_OID_X942_DIFFIE_HELMAN_KEY:
pubk->keyType = NSSLOWKEYDHKey; pubk->keyType = NSSLOWKEYDHKey;
prepare_low_dh_pub_key_for_asn1(pubk);
rv = SEC_ASN1DecodeItem(arena, pubk, rv = SEC_ASN1DecodeItem(arena, pubk,
nsslowcert_DHPublicKeyTemplate, &os); nsslowcert_DHPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk; if (rv == SECSuccess) return pubk;

Просмотреть файл

@ -83,6 +83,61 @@ const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
{ 0, } { 0, }
}; };
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
void
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.rsa.modulus.type = siUnsignedInteger;
key->u.rsa.publicExponent.type = siUnsignedInteger;
key->u.rsa.privateExponent.type = siUnsignedInteger;
key->u.rsa.prime1.type = siUnsignedInteger;
key->u.rsa.prime2.type = siUnsignedInteger;
key->u.rsa.exponent1.type = siUnsignedInteger;
key->u.rsa.exponent2.type = siUnsignedInteger;
key->u.rsa.coefficient.type = siUnsignedInteger;
}
void
prepare_low_pqg_params_for_asn1(PQGParams *params)
{
params->prime.type = siUnsignedInteger;
params->subPrime.type = siUnsignedInteger;
params->base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.publicValue.type = siUnsignedInteger;
key->u.dsa.privateValue.type = siUnsignedInteger;
key->u.dsa.params.prime.type = siUnsignedInteger;
key->u.dsa.params.subPrime.type = siUnsignedInteger;
key->u.dsa.params.base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.privateValue.type = siUnsignedInteger;
}
void
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dh.prime.type = siUnsignedInteger;
key->u.dh.base.type = siUnsignedInteger;
key->u.dh.publicValue.type = siUnsignedInteger;
key->u.dh.privateValue.type = siUnsignedInteger;
}
void void
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
{ {

Просмотреть файл

@ -32,7 +32,7 @@
* *
* key.h - public data structures and prototypes for the private key library * key.h - public data structures and prototypes for the private key library
* *
* $Id: lowkeyi.h,v 1.4 2001-12-07 01:36:18 relyea%netscape.com Exp $ * $Id: lowkeyi.h,v 1.5 2002-02-21 22:41:38 ian.mcgreer%sun.com Exp $
*/ */
#ifndef _LOWKEYI_H_ #ifndef _LOWKEYI_H_
@ -46,6 +46,20 @@
SEC_BEGIN_PROTOS SEC_BEGIN_PROTOS
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion); typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
/* /*

Просмотреть файл

@ -3327,13 +3327,16 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key)
param = NULL; param = NULL;
switch(lk->keyType) { switch(lk->keyType) {
case NSSLOWKEYRSAKey: case NSSLOWKEYRSAKey:
prepare_low_rsa_priv_key_for_asn1(lk);
dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
nsslowkey_RSAPrivateKeyTemplate); nsslowkey_RSAPrivateKeyTemplate);
algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
break; break;
case NSSLOWKEYDSAKey: case NSSLOWKEYDSAKey:
prepare_low_dsa_priv_key_export_for_asn1(lk);
dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
nsslowkey_DSAPrivateKeyExportTemplate); nsslowkey_DSAPrivateKeyExportTemplate);
prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
nsslowkey_PQGParamsTemplate); nsslowkey_PQGParamsTemplate);
algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
@ -3530,12 +3533,15 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
paramTemplate = NULL; paramTemplate = NULL;
paramDest = NULL; paramDest = NULL;
lpk->keyType = NSSLOWKEYRSAKey; lpk->keyType = NSSLOWKEYRSAKey;
prepare_low_rsa_priv_key_for_asn1(lpk);
break; break;
case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE:
keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
paramTemplate = nsslowkey_PQGParamsTemplate; paramTemplate = nsslowkey_PQGParamsTemplate;
paramDest = &(lpk->u.dsa.params); paramDest = &(lpk->u.dsa.params);
lpk->keyType = NSSLOWKEYDSAKey; lpk->keyType = NSSLOWKEYDSAKey;
prepare_low_dsa_priv_key_export_for_asn1(lpk);
prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
break; break;
/* case NSSLOWKEYDHKey: */ /* case NSSLOWKEYDHKey: */
default: default:

Просмотреть файл

@ -35,7 +35,7 @@
* Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
* Encoding Rules). * Encoding Rules).
* *
* $Id: secasn1d.c,v 1.14 2002-01-14 23:20:42 ian.mcgreer%sun.com Exp $ * $Id: secasn1d.c,v 1.15 2002-02-21 22:41:42 ian.mcgreer%sun.com Exp $
*/ */
#include "secasn1.h" #include "secasn1.h"
@ -1338,9 +1338,10 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state,
item = (SECItem *)(state->dest); item = (SECItem *)(state->dest);
if (item != NULL && item->data != NULL) { if (item != NULL && item->data != NULL) {
/* Strip leading zeroes */ /* Strip leading zeroes when target is unsigned integer */
if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */ if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
item->len == 0) /* MSB */ item->len == 0 && /* MSB */
item->type == siUnsignedInteger) /* unsigned */
{ {
while (len > 1 && buf[0] == 0) { /* leading 0 */ while (len > 1 && buf[0] == 0) { /* leading 0 */
buf++; buf++;

Просмотреть файл

@ -35,7 +35,7 @@
* Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished * Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished
* Encoding Rules). * Encoding Rules).
* *
* $Id: secasn1e.c,v 1.6 2002-01-22 22:48:26 ian.mcgreer%sun.com Exp $ * $Id: secasn1e.c,v 1.7 2002-02-21 22:41:42 ian.mcgreer%sun.com Exp $
*/ */
#include "secasn1.h" #include "secasn1.h"
@ -685,17 +685,18 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
break; break;
case SEC_ASN1_INTEGER: case SEC_ASN1_INTEGER:
/* ASN.1 INTEGERs are signed. PKCS#11 BigIntegers are unsigned. NSS /* ASN.1 INTEGERs are signed.
* will treat numbers going in and out of the ASN.1 encoder as * If the source is an unsigned integer, the encoder will need
* unsigned, so the encoder must handle the conversion. * to handle the conversion here.
*/ */
{ {
unsigned char *buf = ((SECItem *)src)->data; unsigned char *buf = ((SECItem *)src)->data;
SECItemType integerType = ((SECItem *)src)->type;
len = ((SECItem *)src)->len; len = ((SECItem *)src)->len;
while (len > 0) { while (len > 0) {
if (*buf != 0) { if (*buf != 0) {
if (*buf & 0x80) { if (*buf & 0x80 && integerType == siUnsignedInteger) {
len++; /* leading zero needed */ len++; /* leading zero needed to make number signed */
} }
break; /* reached beginning of number */ break; /* reached beginning of number */
} }
@ -1007,17 +1008,18 @@ sec_asn1e_write_contents (sec_asn1e_state *state,
goto process_string; goto process_string;
case SEC_ASN1_INTEGER: case SEC_ASN1_INTEGER:
/* ASN.1 INTEGERs are signed. PKCS#11 BigIntegers are unsigned. /* ASN.1 INTEGERs are signed. If the source is an unsigned
* NSS will treat numbers going in and out of the ASN.1 encoder as * integer, the encoder will need to handle the conversion here.
* unsigned, so the encoder must handle the conversion.
*/ */
{ {
unsigned int blen; unsigned int blen;
unsigned char *buf; unsigned char *buf;
SECItemType integerType;
blen = ((SECItem *)state->src)->len; blen = ((SECItem *)state->src)->len;
buf = ((SECItem *)state->src)->data; buf = ((SECItem *)state->src)->data;
integerType = ((SECItem *)state->src)->type;
while (blen > 0) { while (blen > 0) {
if (*buf & 0x80) { if (*buf & 0x80 && integerType == siUnsignedInteger) {
char zero = 0; /* write a leading 0 */ char zero = 0; /* write a leading 0 */
sec_asn1e_write_contents_bytes(state, &zero, 1); sec_asn1e_write_contents_bytes(state, &zero, 1);
/* and then the remaining buffer */ /* and then the remaining buffer */
@ -1025,10 +1027,16 @@ sec_asn1e_write_contents (sec_asn1e_state *state,
(char *)buf, blen); (char *)buf, blen);
break; break;
} }
if (*buf != 0 || blen == 1) { /* Check three possibilities:
/* no leading zeros, msb of MSB is not 1, so write * 1. No leading zeros, msb of MSB is not 1;
* the remaining buffer (0 itself also goes here) * 2. The number is zero itself;
*/ * 3. Encoding a signed integer with a leading zero,
* keep the zero so that the number is positive.
*/
if (*buf != 0 ||
blen == 1 ||
(buf[1] & 0x80 && integerType != siUnsignedInteger) )
{
sec_asn1e_write_contents_bytes(state, sec_asn1e_write_contents_bytes(state,
(char *)buf, blen); (char *)buf, blen);
break; break;

Просмотреть файл

@ -38,7 +38,7 @@
* for security libraries. It should not be dependent on any other * for security libraries. It should not be dependent on any other
* headers, and should not require linking with any libraries. * headers, and should not require linking with any libraries.
* *
* $Id: seccomon.h,v 1.2 2001-01-18 16:36:43 wtc%netscape.com Exp $ * $Id: seccomon.h,v 1.3 2002-02-21 22:41:44 ian.mcgreer%sun.com Exp $
*/ */
#ifndef _SECCOMMON_H_ #ifndef _SECCOMMON_H_
@ -67,7 +67,8 @@ typedef enum {
siEncodedNameBuffer = 6, siEncodedNameBuffer = 6,
siAsciiNameString = 7, siAsciiNameString = 7,
siAsciiString = 8, siAsciiString = 8,
siDEROID = 9 siDEROID = 9,
siUnsignedInteger = 10
} SECItemType; } SECItemType;
typedef struct SECItemStr SECItem; typedef struct SECItemStr SECItem;

Просмотреть файл

@ -34,7 +34,7 @@
/* /*
* Support routines for SECItem data structure. * Support routines for SECItem data structure.
* *
* $Id: secitem.c,v 1.5 2001-12-07 01:36:25 relyea%netscape.com Exp $ * $Id: secitem.c,v 1.6 2002-02-21 22:41:44 ian.mcgreer%sun.com Exp $
*/ */
#include "seccomon.h" #include "seccomon.h"
@ -196,6 +196,7 @@ SECITEM_DupItem(const SECItem *from)
SECStatus SECStatus
SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from) SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from)
{ {
to->type = from->type;
if (from->data && from->len) { if (from->data && from->len) {
if ( arena ) { if ( arena ) {
to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len); to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len);