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,¶m,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, ¶ms->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(¶ms1, pubKey1); if (rv != SECSuccess) return rv; rv = SECKEY_KEASetParams(¶ms2, pubKey2); if (rv != SECSuccess) return rv; rv = (SECStatus)SECITEM_CompareItem(¶ms1.hash, ¶ms2.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 + -
显示快捷键?