seckey.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,652 行 · 第 1/4 页

C
1,652
字号
/* * 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. *  * Contributor(s): *  * 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. */#include "cryptohi.h"#include "keyhi.h"#include "secrng.h"#include "secoid.h"#include "secitem.h"#include "secder.h"#include "base64.h"#include "secasn1.h"#include "cert.h"#include "pk11func.h"#include "secerr.h"#include "secdig.h"#include "prtime.h"const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {    { SEC_ASN1_SEQUENCE,	  0, NULL, sizeof(CERTSubjectPublicKeyInfo) },    { SEC_ASN1_INLINE,	  offsetof(CERTSubjectPublicKeyInfo,algorithm),	  SECOID_AlgorithmIDTemplate },    { SEC_ASN1_BIT_STRING,	  offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },    { 0, }};const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] ={    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },    { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },    { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },    { 0 }};const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },    { 0, }};const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },    { 0, }};const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },    { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },    { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },    { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },    { 0, }};const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },    { 0, }};const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {    { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPublicKey) },    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },    /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */    { SEC_ASN1_SKIP_REST },    { 0, }};const SEC_ASN1Template SECKEY_FortezzaParameterTemplate[] = {    { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(PQGParams) },    { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,prime), },    { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,subPrime), },    { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,base), },    { 0 },}; const SEC_ASN1Template SECKEY_FortezzaDiffParameterTemplate[] = {    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DiffPQGParams) },    { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffKEAParams),                        SECKEY_FortezzaParameterTemplate},    { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffDSAParams),                        SECKEY_FortezzaParameterTemplate},    { 0 },};const SEC_ASN1Template SECKEY_FortezzaPreParamTemplate[] = {    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |      SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(PQGDualParams,CommParams),                SECKEY_FortezzaParameterTemplate},    { 0, }};const SEC_ASN1Template SECKEY_FortezzaAltPreParamTemplate[] = {    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |      SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(PQGDualParams,DiffParams),                SECKEY_FortezzaDiffParameterTemplate},    { 0, }};const SEC_ASN1Template SECKEY_KEAPublicKeyTemplate[] = {    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.kea.publicValue), },    { 0, }};const SEC_ASN1Template SECKEY_KEAParamsTemplate[] = {    { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPublicKey,u.kea.params.hash), },     { 0, }};/* * NOTE: This only generates RSA Private Key's. If you need more, * We need to pass in some more params... */SECKEYPrivateKey *SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx){    SECKEYPrivateKey *privk;    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);    PK11RSAGenParams param;    param.keySizeInBits = keySizeInBits;    param.pe = 65537L;        privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,					PR_FALSE, PR_TRUE, cx);    PK11_FreeSlot(slot);    return(privk);}voidSECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk){    if (privk) {	if (privk->pkcs11Slot) {	    if (privk->pkcs11IsTemp) {	    	PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);	    }	    PK11_FreeSlot(privk->pkcs11Slot);	}    	if (privk->arena) {	    PORT_FreeArena(privk->arena, PR_TRUE);	}    }}voidSECKEY_DestroyPublicKey(SECKEYPublicKey *pubk){    if (pubk) {	if (pubk->pkcs11Slot) {	    PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);	    PK11_FreeSlot(pubk->pkcs11Slot);	}    	if (pubk->arena) {	    PORT_FreeArena(pubk->arena, PR_FALSE);	}    }}SECStatusSECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,			     CERTSubjectPublicKeyInfo *to,			     CERTSubjectPublicKeyInfo *from){    SECStatus rv;    rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);    if (rv == SECSuccess)	rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &from->subjectPublicKey);    return rv;}SECStatusSECKEY_KEASetParams(KEAParams * params, SECKEYPublicKey * pubKey) {    if (pubKey->keyType == fortezzaKey) {        /* the key is a fortezza V1 public key  */	/* obtain hash of pubkey->u.fortezza.params.prime.data +		          pubkey->u.fortezza.params.subPrime.data +			  pubkey->u.fortezza.params.base.data  */	/* store hash in params->hash */    } else if (pubKey->keyType == keaKey) {        /* the key is a new fortezza KEA public key. */        SECITEM_CopyItem(pubKey->arena, &params->hash, 	                 &pubKey->u.kea.params.hash );    } else {	/* the key has no KEA parameters */	return SECFailure;    }}SECStatusSECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2) {    SECStatus rv;    SECOidData *oid=NULL;    CERTSubjectPublicKeyInfo * subjectSpki=NULL;    CERTSubjectPublicKeyInfo * issuerSpki=NULL;    CERTCertificate *issuerCert = NULL;    SECKEYPublicKey *pubKey1 = 0;    SECKEYPublicKey *pubKey2 = 0;    KEAParams params1;    KEAParams params2;    rv = SECFailure;    /* get cert1's public key */    pubKey1 = CERT_ExtractPublicKey(cert1);    if ( !pubKey1 ) {	return(SECFailure);    }        /* get cert2's public key */    pubKey2 = CERT_ExtractPublicKey(cert2);    if ( !pubKey2 ) {	return(SECFailure);    }    /* handle the case when both public keys are new     * fortezza KEA public keys.    */    if ((pubKey1->keyType == keaKey) &&        (pubKey2->keyType == keaKey) ) {        rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.kea.params.hash,	                         &pubKey2->u.kea.params.hash);	goto done;    }    /* handle the case when both public keys are old fortezza     * public keys.              */    if ((pubKey1->keyType == fortezzaKey) &&        (pubKey2->keyType == fortezzaKey) ) {        rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.prime,	                         &pubKey2->u.fortezza.keaParams.prime);	if (rv == SECEqual) {	    rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.subPrime,	                             &pubKey2->u.fortezza.keaParams.subPrime);	}	if (rv == SECEqual) {	    rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.base,	                             &pubKey2->u.fortezza.keaParams.base);	}		goto done;    }    /* handle the case when the public keys are a mixture of      * old and new.                          */    rv = SECKEY_KEASetParams(&params1, pubKey1);    if (rv != SECSuccess) return rv;    rv = SECKEY_KEASetParams(&params2, pubKey2);    if (rv != SECSuccess) return rv;    rv = (SECStatus)SECITEM_CompareItem(&params1.hash, &params2.hash);done:    SECKEY_DestroyPublicKey(pubKey1);    SECKEY_DestroyPublicKey(pubKey2);    return rv;   /* returns SECEqual if parameters are equal */}/* Procedure to update the pqg parameters for a cert's public key. * pqg parameters only need to be updated for DSA and fortezza certificates. * The procedure uses calls to itself recursively to update a certificate * issuer's pqg parameters.  Some important rules are: *    - Do nothing if the cert already has PQG parameters. *    - If the cert does not have PQG parameters, obtain them from the issuer. *    - A valid cert chain cannot have a DSA or Fortezza cert without *      pqg parameters that has a parent that is not a DSA or Fortezza cert. *    - pqg paramters are stored in two different formats: the standard *      DER encoded format and the fortezza-only wrapped format.  The params *      should be copied from issuer to subject cert without modifying the *      formats.  The public key extraction code will deal with the different *      formats at the time of extraction.  */SECStatusseckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count){    SECStatus rv, rvCompare;    SECOidData *oid=NULL;    int tag;    CERTSubjectPublicKeyInfo * subjectSpki=NULL;    CERTSubjectPublicKeyInfo * issuerSpki=NULL;    CERTCertificate *issuerCert = NULL;    rv = SECSuccess;    /* increment cert chain length counter*/    count++;    /* check if cert chain length exceeds the maximum length*/    if (count > CERT_MAX_CERT_CHAIN) {	return SECFailure;    }    oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);                if (oid != NULL) {          tag = oid->offset;                     /* Check if cert has a DSA or Fortezza public key. If not, return         * success since no PQG params need to be updated.  */	if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&	     (tag != SEC_OID_MISSI_DSS_OLD) &&             (tag != SEC_OID_MISSI_KEA_DSS) &&             (tag != SEC_OID_MISSI_DSS) &&                            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&             (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&             (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {                        return SECSuccess;        }    } else {        return SECFailure;  /* return failure if oid is NULL */      }    /* if cert has PQG parameters, return success */    subjectSpki=&subjectCert->subjectPublicKeyInfo;    if (subjectSpki->algorithm.parameters.len != 0) {        return SECSuccess;    }    /* check if the cert is self-signed */    rvCompare = (SECStatus)SECITEM_CompareItem(&subjectCert->derSubject,				    &subjectCert->derIssuer);	if (rvCompare == SECEqual) {	  /* fail since cert is self-signed and has no pqg params. */            return SECFailure;     	}         /* get issuer cert */    issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);	if ( ! issuerCert ) {            return SECFailure;	}    /* if parent is not DSA or fortezza, return failure since       we don't allow this case. */    oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);    if (oid != NULL) {          tag = oid->offset;                     /* Check if issuer cert has a DSA or Fortezza public key. If not,         * return failure.   */	if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&	     (tag != SEC_OID_MISSI_DSS_OLD) &&             (tag != SEC_OID_MISSI_KEA_DSS) &&             (tag != SEC_OID_MISSI_DSS) &&                            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&             (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&             (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?