diff options
Diffstat (limited to 'security/nss/lib/softoken/lowcert.c')
-rw-r--r-- | security/nss/lib/softoken/lowcert.c | 625 |
1 files changed, 0 insertions, 625 deletions
diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c deleted file mode 100644 index 1ef4021fb..000000000 --- a/security/nss/lib/softoken/lowcert.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): - * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -/* - * Certificate handling code - * - * $Id$ - */ - -#include "seccomon.h" -#include "secder.h" -#include "nssilock.h" -#include "prmon.h" -#include "prtime.h" -#include "lowkeyi.h" -#include "pcert.h" -#include "secasn1.h" -#include "secoid.h" - -#ifdef NSS_ENABLE_ECC -extern SECStatus EC_FillParams(PRArenaPool *arena, - const SECItem *encodedParams, - ECParams *params); -#endif - -static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) }, - { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_BIT_STRING, - offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), }, - { 0, } -}; - -static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) }, - { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), }, - { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), }, - { 0, } -}; -static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = { - { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), }, - { 0, } -}; -static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = { - { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), }, - { 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 - * have to pass the handle all over the place. - */ -static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0; - -void -nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle) -{ - default_pcert_db_handle = handle; - - return; -} - -NSSLOWCERTCertDBHandle * -nsslowcert_GetDefaultCertDB(void) -{ - return(default_pcert_db_handle); -} - -/* - * simple cert decoder to avoid the cost of asn1 engine - */ -static unsigned char * -nsslowcert_dataStart(unsigned char *buf, unsigned int length, - unsigned int *data_length, PRBool includeTag, - unsigned char* rettag) { - unsigned char tag; - unsigned int used_length= 0; - - tag = buf[used_length++]; - - if (rettag) { - *rettag = tag; - } - - /* blow out when we come to the end */ - if (tag == 0) { - return NULL; - } - - *data_length = buf[used_length++]; - - if (*data_length&0x80) { - int len_count = *data_length & 0x7f; - - *data_length = 0; - - while (len_count-- > 0) { - *data_length = (*data_length << 8) | buf[used_length++]; - } - } - - if (*data_length > (length-used_length) ) { - *data_length = length-used_length; - return NULL; - } - if (includeTag) *data_length += used_length; - - return (buf + (includeTag ? 0 : used_length)); -} - -static void SetTimeType(SECItem* item, unsigned char tagtype) -{ - switch (tagtype) { - case SEC_ASN1_UTC_TIME: - item->type = siUTCTime; - break; - - case SEC_ASN1_GENERALIZED_TIME: - item->type = siGeneralizedTime; - break; - - default: - PORT_Assert(0); - break; - } -} - -static int -nsslowcert_GetValidityFields(unsigned char *buf,int buf_length, - SECItem *notBefore, SECItem *notAfter) -{ - unsigned char tagtype; - notBefore->data = nsslowcert_dataStart(buf,buf_length, - ¬Before->len,PR_FALSE, &tagtype); - if (notBefore->data == NULL) return SECFailure; - SetTimeType(notBefore, tagtype); - buf_length -= (notBefore->data-buf) + notBefore->len; - buf = notBefore->data + notBefore->len; - notAfter->data = nsslowcert_dataStart(buf,buf_length, - ¬After->len,PR_FALSE, &tagtype); - if (notAfter->data == NULL) return SECFailure; - SetTimeType(notAfter, tagtype); - return SECSuccess; -} - -static int -nsslowcert_GetCertFields(unsigned char *cert,int cert_length, - SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject, - SECItem *valid, SECItem *subjkey) -{ - unsigned char *buf; - unsigned int buf_length; - unsigned char *dummy; - unsigned int dummylen; - - /* get past the signature wrap */ - buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL); - if (buf == NULL) return SECFailure; - /* get into the raw cert data */ - buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL); - if (buf == NULL) return SECFailure; - /* skip past any optional version number */ - if ((buf[0] & 0xa0) == 0xa0) { - dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL); - if (dummy == NULL) return SECFailure; - buf_length -= (dummy-buf) + dummylen; - buf = dummy + dummylen; - } - /* serial number */ - if (derSN) { - derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL); - } - serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL); - if (serial->data == NULL) return SECFailure; - buf_length -= (serial->data-buf) + serial->len; - buf = serial->data + serial->len; - /* skip the OID */ - dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL); - if (dummy == NULL) return SECFailure; - buf_length -= (dummy-buf) + dummylen; - buf = dummy + dummylen; - /* issuer */ - issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL); - if (issuer->data == NULL) return SECFailure; - buf_length -= (issuer->data-buf) + issuer->len; - buf = issuer->data + issuer->len; - - /* only wanted issuer/SN */ - if (valid == NULL) { - return SECSuccess; - } - /* validity */ - valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL); - if (valid->data == NULL) return SECFailure; - buf_length -= (valid->data-buf) + valid->len; - buf = valid->data + valid->len; - /*subject */ - subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL); - if (subject->data == NULL) return SECFailure; - buf_length -= (subject->data-buf) + subject->len; - buf = subject->data + subject->len; - /* subject key info */ - subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL); - if (subjkey->data == NULL) return SECFailure; - buf_length -= (subjkey->data-buf) + subjkey->len; - buf = subjkey->data + subjkey->len; - return SECSuccess; -} - -SECStatus -nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter) -{ - int rv; - NSSLOWCERTValidity validity; - - rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len, - &validity.notBefore,&validity.notAfter); - if (rv != SECSuccess) { - return rv; - } - - /* convert DER not-before time */ - rv = CERT_DecodeTimeChoice(notBefore, &validity.notBefore); - if (rv) { - return(SECFailure); - } - - /* convert DER not-after time */ - rv = CERT_DecodeTimeChoice(notAfter, &validity.notAfter); - if (rv) { - return(SECFailure); - } - - return(SECSuccess); -} - -/* - * is certa newer than certb? If one is expired, pick the other one. - */ -PRBool -nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb) -{ - PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now; - SECStatus rv; - PRBool newerbefore, newerafter; - - rv = nsslowcert_GetCertTimes(certa, ¬BeforeA, ¬AfterA); - if ( rv != SECSuccess ) { - return(PR_FALSE); - } - - rv = nsslowcert_GetCertTimes(certb, ¬BeforeB, ¬AfterB); - if ( rv != SECSuccess ) { - return(PR_TRUE); - } - - newerbefore = PR_FALSE; - if ( LL_CMP(notBeforeA, >, notBeforeB) ) { - newerbefore = PR_TRUE; - } - - newerafter = PR_FALSE; - if ( LL_CMP(notAfterA, >, notAfterB) ) { - newerafter = PR_TRUE; - } - - if ( newerbefore && newerafter ) { - return(PR_TRUE); - } - - if ( ( !newerbefore ) && ( !newerafter ) ) { - return(PR_FALSE); - } - - /* get current time */ - now = PR_Now(); - - if ( newerbefore ) { - /* cert A was issued after cert B, but expires sooner */ - /* if A is expired, then pick B */ - if ( LL_CMP(notAfterA, <, now ) ) { - return(PR_FALSE); - } - return(PR_TRUE); - } else { - /* cert B was issued after cert A, but expires sooner */ - /* if B is expired, then pick A */ - if ( LL_CMP(notAfterB, <, now ) ) { - return(PR_TRUE); - } - return(PR_FALSE); - } -} - -#define SOFT_DEFAULT_CHUNKSIZE 2048 - - -static SECStatus -nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn, - SECItem *key) -{ - unsigned int len = sn->len + issuer->len; - - - if (arena) { - key->data = (unsigned char*)PORT_ArenaAlloc(arena, len); - } else { - if (len > key->len) { - key->data = (unsigned char*)PORT_ArenaAlloc(arena, len); - } - } - if ( !key->data ) { - goto loser; - } - - key->len = len; - /* copy the serialNumber */ - PORT_Memcpy(key->data, sn->data, sn->len); - - /* copy the issuer */ - PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len); - - return(SECSuccess); - -loser: - return(SECFailure); -} - - - -/* - * take a DER certificate and decode it into a certificate structure - */ -NSSLOWCERTCertificate * -nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname) -{ - NSSLOWCERTCertificate *cert; - int rv; - - /* allocate the certificate structure */ - cert = nsslowcert_CreateCert(); - - if ( !cert ) { - goto loser; - } - - /* point to passed in DER data */ - cert->derCert = *derSignedCert; - cert->nickname = NULL; - cert->certKey.data = NULL; - cert->referenceCount = 1; - - /* decode the certificate info */ - rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len, - &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject, - &cert->validity, &cert->derSubjKeyInfo); - - /* cert->subjectKeyID; x509v3 subject key identifier */ - cert->subjectKeyID.data = NULL; - cert->subjectKeyID.len = 0; - cert->dbEntry = NULL; - cert ->trust = NULL; - - /* generate and save the database key for the cert */ - cert->certKey.data = cert->certKeySpace; - cert->certKey.len = sizeof(cert->certKeySpace); - rv = nsslowcert_KeyFromIssuerAndSN(NULL, &cert->derIssuer, - &cert->serialNumber, &cert->certKey); - if ( rv ) { - goto loser; - } - - /* set the nickname */ - if ( nickname == NULL ) { - cert->nickname = NULL; - } else { - /* copy and install the nickname */ - cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace, - sizeof(cert->nicknameSpace)); - } - -#ifdef FIXME - /* initialize the subjectKeyID */ - rv = cert_GetKeyID(cert); - if ( rv != SECSuccess ) { - goto loser; - } - - /* set the email address */ - cert->emailAddr = CERT_GetCertificateEmailAddress(cert); - -#endif - - cert->referenceCount = 1; - - return(cert); - -loser: - if (cert) { - nsslowcert_DestroyCertificate(cert); - } - - return(0); -} - -char * -nsslowcert_FixupEmailAddr(char *emailAddr) -{ - char *retaddr; - char *str; - - if ( emailAddr == NULL ) { - return(NULL); - } - - /* copy the string */ - str = retaddr = PORT_Strdup(emailAddr); - if ( str == NULL ) { - return(NULL); - } - - /* make it lower case */ - while ( *str ) { - *str = tolower( *str ); - str++; - } - - return(retaddr); -} - - -/* - * Generate a database key, based on serial number and issuer, from a - * DER certificate. - */ -SECStatus -nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key) -{ - int rv; - NSSLOWCERTCertKey certkey; - - PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey)); - - rv = nsslowcert_GetCertFields(derCert->data, derCert->len, - &certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL); - - if ( rv ) { - goto loser; - } - - return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer, - &certkey.serialNumber, key)); -loser: - return(SECFailure); -} - -NSSLOWKEYPublicKey * -nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert) -{ - NSSLOWCERTSubjectPublicKeyInfo spki; - NSSLOWKEYPublicKey *pubk; - SECItem os; - SECStatus rv; - PRArenaPool *arena; - SECOidTag tag; - SECItem newDerSubjKeyInfo; - - arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) - return NULL; - - pubk = (NSSLOWKEYPublicKey *) - PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey)); - if (pubk == NULL) { - PORT_FreeArena (arena, PR_FALSE); - return NULL; - } - - pubk->arena = arena; - PORT_Memset(&spki,0,sizeof(spki)); - - /* copy the DER into the arena, since Quick DER returns data that points - into the DER input, which may get freed by the caller */ - rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo); - if ( rv != SECSuccess ) { - PORT_FreeArena (arena, PR_FALSE); - return NULL; - } - - /* we haven't bothered decoding the spki struct yet, do it now */ - rv = SEC_QuickDERDecodeItem(arena, &spki, - nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo); - if (rv != SECSuccess) { - PORT_FreeArena (arena, PR_FALSE); - return NULL; - } - - /* Convert bit string length from bits to bytes */ - os = spki.subjectPublicKey; - DER_ConvertBitString (&os); - - tag = SECOID_GetAlgorithmTag(&spki.algorithm); - switch ( tag ) { - case SEC_OID_X500_RSA_ENCRYPTION: - case SEC_OID_PKCS1_RSA_ENCRYPTION: - pubk->keyType = NSSLOWKEYRSAKey; - prepare_low_rsa_pub_key_for_asn1(pubk); - rv = SEC_QuickDERDecodeItem(arena, pubk, - nsslowcert_RSAPublicKeyTemplate, &os); - if (rv == SECSuccess) - return pubk; - break; - case SEC_OID_ANSIX9_DSA_SIGNATURE: - pubk->keyType = NSSLOWKEYDSAKey; - prepare_low_dsa_pub_key_for_asn1(pubk); - rv = SEC_QuickDERDecodeItem(arena, pubk, - nsslowcert_DSAPublicKeyTemplate, &os); - if (rv == SECSuccess) return pubk; - break; - case SEC_OID_X942_DIFFIE_HELMAN_KEY: - pubk->keyType = NSSLOWKEYDHKey; - prepare_low_dh_pub_key_for_asn1(pubk); - rv = SEC_QuickDERDecodeItem(arena, pubk, - nsslowcert_DHPublicKeyTemplate, &os); - if (rv == SECSuccess) return pubk; - break; -#ifdef NSS_ENABLE_ECC - case SEC_OID_ANSIX962_EC_PUBLIC_KEY: - pubk->keyType = NSSLOWKEYECKey; - /* Since PKCS#11 directly takes the DER encoding of EC params - * and public value, we don't need any decoding here. - */ - rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding, - &spki.algorithm.parameters); - if ( rv != SECSuccess ) - break; - - /* Fill out the rest of the ecParams structure - * based on the encoded params - */ - if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding, - &pubk->u.ec.ecParams) != SECSuccess) - break; - - rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os); - if (rv == SECSuccess) return pubk; - break; -#endif /* NSS_ENABLE_ECC */ - default: - rv = SECFailure; - break; - } - - nsslowkey_DestroyPublicKey (pubk); - return NULL; -} - |