SECKEYPrivateKey* PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID, CK_ATTRIBUTE* aTemplate, CK_ULONG aTemplateSize) { // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), aTemplate, aTemplateSize, PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), aObjID, nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }
SECStatus TransportLayerDtls::GetClientAuthDataHook(void *arg, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey) { MOZ_MTLOG(ML_DEBUG, "Server requested client auth"); TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg); stream->CheckThread(); if (!stream->identity_) { MOZ_MTLOG(ML_ERROR, "No identity available"); PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0); return SECFailure; } *pRetCert = CERT_DupCertificate(stream->identity_->cert()); if (!*pRetCert) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return SECFailure; } *pRetKey = SECKEY_CopyPrivateKey(stream->identity_->privkey()); if (!*pRetKey) { CERT_DestroyCertificate(*pRetCert); *pRetCert = nullptr; PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return SECFailure; } return SECSuccess; }
XSECCryptoKey * NSSCryptoKeyRSA::clone() const { NSSCryptoKeyRSA * ret; XSECnew(ret, NSSCryptoKeyRSA(mp_pubkey, mp_privkey)); if (mp_pubkey != 0) { ret->mp_pubkey = SECKEY_CopyPublicKey(mp_pubkey); if (ret->mp_pubkey == 0) { throw XSECCryptoException(XSECCryptoException::MemoryError, "NSS:RSA Error attempting to clone (copy) public key"); } } if (mp_privkey != 0) { ret->mp_privkey = SECKEY_CopyPrivateKey(mp_privkey); if (ret->mp_privkey == 0) { throw XSECCryptoException(XSECCryptoException::MemoryError, "NSS:RSA Error attempting to clone (copy) private key"); } } // Clone modulus if (mp_modulus != 0) { ret->mp_modulus = SECITEM_DupItem(mp_modulus); if (ret->mp_modulus == 0) { throw XSECCryptoException(XSECCryptoException::MemoryError, "NSS:RSA Error attempting to clone (copy) modulus"); } } // Clone exponent if (mp_exponent != 0) { ret->mp_exponent = SECITEM_DupItem(mp_exponent); if (ret->mp_exponent == 0) { throw XSECCryptoException(XSECCryptoException::MemoryError, "NSS:RSA Error attempting to clone (copy) exponent"); } } return ret; }
SECKEYPrivateKey* CryptoKey::GetPrivateKey() const { nsNSSShutDownPreventionLock locker; if (!mPrivateKey || isAlreadyShutDown()) { return nullptr; } return SECKEY_CopyPrivateKey(mPrivateKey.get()); }
void CryptoKey::SetPrivateKey(SECKEYPrivateKey* aPrivateKey) { nsNSSShutDownPreventionLock locker; if (!aPrivateKey || isAlreadyShutDown()) { mPrivateKey = nullptr; return; } mPrivateKey = SECKEY_CopyPrivateKey(aPrivateKey); }
// Unfortunately, the code that uses DtlsIdentity cannot always use that lock // due to external linkage requirements. Therefore, the lock is held on this // object instead. Consequently, the DtlsIdentity that this method returns must // have a lifetime that is strictly shorter than the RTCCertificate. // // RTCPeerConnection provides this guarantee by holding a strong reference to // the RTCCertificate. It will cleanup any DtlsIdentity instances that it // creates before the RTCCertificate reference is released. RefPtr<DtlsIdentity> RTCCertificate::CreateDtlsIdentity() const { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown() || !mPrivateKey || !mCertificate) { return nullptr; } SECKEYPrivateKey* key = SECKEY_CopyPrivateKey(mPrivateKey.get()); CERTCertificate* cert = CERT_DupCertificate(mCertificate.get()); RefPtr<DtlsIdentity> id = new DtlsIdentity(key, cert, mAuthType); return id; }
// Unfortunately, the code that uses DtlsIdentity cannot always use that lock // due to external linkage requirements. Therefore, the lock is held on this // object instead. Consequently, the DtlsIdentity that this method returns must // have a lifetime that is strictly shorter than the RTCCertificate. // // RTCPeerConnection provides this guarantee by holding a strong reference to // the RTCCertificate. It will cleanup any DtlsIdentity instances that it // creates before the RTCCertificate reference is released. RefPtr<DtlsIdentity> RTCCertificate::CreateDtlsIdentity() const { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown() || !mPrivateKey || !mCertificate) { return nullptr; } UniqueSECKEYPrivateKey key(SECKEY_CopyPrivateKey(mPrivateKey.get())); UniqueCERTCertificate cert(CERT_DupCertificate(mCertificate.get())); RefPtr<DtlsIdentity> id = new DtlsIdentity(Move(key), Move(cert), mAuthType); return id; }
nsresult CryptoKey::SetPrivateKey(SECKEYPrivateKey* aPrivateKey) { nsNSSShutDownPreventionLock locker; if (!aPrivateKey || isAlreadyShutDown()) { mPrivateKey = nullptr; return NS_OK; } mPrivateKey = UniqueSECKEYPrivateKey(SECKEY_CopyPrivateKey(aPrivateKey)); return mPrivateKey ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
/* This function adopts pubKey and destroys it if things go wrong. */ static sslKeyPair * ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, SECKEYPublicKey *pubKey) { sslKeyPair *keyPair = NULL; SECKEYPrivateKey *privKeyCopy = NULL; PK11SlotInfo *bestSlot; if (key->pkcs11Slot) { bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (!privKeyCopy) { CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType); /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (!privKeyCopy) { privKeyCopy = SECKEY_CopyPrivateKey(key); } if (privKeyCopy) { keyPair = ssl_NewKeyPair(privKeyCopy, pubKey); } if (!keyPair) { if (privKeyCopy) { SECKEY_DestroyPrivateKey(privKeyCopy); } /* We adopted the public key, so we're responsible. */ if (pubKey) { SECKEY_DestroyPublicKey(pubKey); } } return keyPair; }
SECStatus SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, const CERTCertificateList *certChainOpt, SECKEYPrivateKey *key, SSL3KEAType kea) { sslSocket *ss; SECKEYPublicKey *pubKey = NULL; ssl3KeyPair *keyPair = NULL; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } /* Both key and cert must have a value or be NULL */ /* Passing a value of NULL will turn off key exchange algorithms that were * previously turned on */ if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* make sure the key exchange is recognized */ if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != NSS_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } if (cert) { /* get the size of the cert's public key, and remember it */ pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) return SECFailure; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; keyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (keyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; /* adopted by serverKeyPair */ } if (ssl_ConfigSecureServer(ss, cert, certChainOpt, keyPair, kea) == SECFailure) { goto loser; } /* Only do this once because it's global. */ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { rv = SECSuccess; } loser: if (keyPair) { ssl3_FreeKeyPair(keyPair); } if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } return rv; }
SECStatus NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri, CERTCertificate** retcert, SECKEYPrivateKey** retkey) { CERTCertificate* cert = NULL; NSSCMSRecipient** recipients = NULL; NSSCMSRecipientInfo* recipientInfos[2]; SECStatus rv = SECSuccess; SECKEYPrivateKey* key = NULL; if (!ri) return SECFailure; if (!retcert && !retkey) { /* nothing requested, nothing found, success */ return SECSuccess; } if (retcert) { *retcert = NULL; } if (retkey) { *retkey = NULL; } if (ri->cert) { cert = CERT_DupCertificate(ri->cert); if (!cert) { rv = SECFailure; } } if (SECSuccess == rv && !cert) { /* we don't have the cert, we have to look for it */ /* first build an NSS_CMSRecipient */ recipientInfos[0] = ri; recipientInfos[1] = NULL; recipients = nss_cms_recipient_list_create(recipientInfos); if (recipients) { /* now look for the cert and key */ if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients, ri->cmsg->pwfn_arg)) { cert = CERT_DupCertificate(recipients[0]->cert); key = SECKEY_CopyPrivateKey(recipients[0]->privkey); } else { rv = SECFailure; } nss_cms_recipient_list_destroy(recipients); } else { rv = SECFailure; } } else if (SECSuccess == rv && cert && retkey) { /* we have the cert, we just need the key now */ key = PK11_FindPrivateKeyFromCert(cert->slot, cert, ri->cmsg->pwfn_arg); } if (retcert) { *retcert = cert; } else { if (cert) { CERT_DestroyCertificate(cert); } } if (retkey) { *retkey = key; } else { if (key) { SECKEY_DestroyPrivateKey(key); } } return rv; }
SECStatus SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, const CERTCertificateList *certChainOpt, SECKEYPrivateKey *key, SSL3KEAType kea) { sslSocket *ss; SECKEYPublicKey *pubKey = NULL; ssl3KeyPair *keyPair = NULL; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != NSS_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } if (cert) { pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) return SECFailure; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; bestSlot = PK11_GetBestSlot(keyMech, NULL ); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; keyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (keyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; } if (ssl_ConfigSecureServer(ss, cert, certChainOpt, keyPair, kea) == SECFailure) { goto loser; } if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { rv = SECSuccess; } loser: if (keyPair) { ssl3_FreeKeyPair(keyPair); } if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } return rv; }
NSSCMSSignerInfo * nss_cmssignerinfo_create(NSSCMSMessage *cmsg, NSSCMSSignerIDSelector type, CERTCertificate *cert, SECItem *subjKeyID, SECKEYPublicKey *pubKey, SECKEYPrivateKey *signingKey, SECOidTag digestalgtag) { void *mark; NSSCMSSignerInfo *signerinfo; int version; PLArenaPool *poolp; poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); signerinfo = (NSSCMSSignerInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSSignerInfo)); if (signerinfo == NULL) { PORT_ArenaRelease(poolp, mark); return NULL; } signerinfo->cmsg = cmsg; switch(type) { case NSSCMSSignerID_IssuerSN: signerinfo->signerIdentifier.identifierType = NSSCMSSignerID_IssuerSN; if ((signerinfo->cert = CERT_DupCertificate(cert)) == NULL) goto loser; if ((signerinfo->signerIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) goto loser; break; case NSSCMSSignerID_SubjectKeyID: signerinfo->signerIdentifier.identifierType = NSSCMSSignerID_SubjectKeyID; PORT_Assert(subjKeyID); if (!subjKeyID) goto loser; signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, SECItem); SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID, subjKeyID); signerinfo->signingKey = SECKEY_CopyPrivateKey(signingKey); if (!signerinfo->signingKey) goto loser; signerinfo->pubKey = SECKEY_CopyPublicKey(pubKey); if (!signerinfo->pubKey) goto loser; break; default: goto loser; } /* set version right now */ version = NSS_CMS_SIGNER_INFO_VERSION_ISSUERSN; /* RFC2630 5.3 "version is the syntax version number. If the .... " */ if (signerinfo->signerIdentifier.identifierType == NSSCMSSignerID_SubjectKeyID) version = NSS_CMS_SIGNER_INFO_VERSION_SUBJKEY; (void)SEC_ASN1EncodeInteger(poolp, &(signerinfo->version), (long)version); if (SECOID_SetAlgorithmID(poolp, &signerinfo->digestAlg, digestalgtag, NULL) != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); return signerinfo; loser: PORT_ArenaRelease(poolp, mark); return NULL; }
SECKEYPrivateKey* CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { if (!aJwk.mKty.WasPassed() || !aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) { return nullptr; } // Verify that all of the required parameters are present CryptoBuffer n, e, d, p, q, dp, dq, qi; if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) || !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) || !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) || !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) || !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) || !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) || !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) || !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) { return nullptr; } // Compute the ID for this key // This is generated with a SHA-1 hash, so unlikely to collide ScopedSECItem nItem(n.ToSECItem()); ScopedSECItem objID(PK11_MakeIDFromPubKey(nItem.get())); if (!nItem.get() || !objID.get()) { return nullptr; } // Populate template from parameters CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY; CK_KEY_TYPE rsaValue = CKK_RSA; CK_BBOOL falseValue = CK_FALSE; CK_ATTRIBUTE keyTemplate[14] = { { CKA_CLASS, &privateKeyValue, sizeof(privateKeyValue) }, { CKA_KEY_TYPE, &rsaValue, sizeof(rsaValue) }, { CKA_TOKEN, &falseValue, sizeof(falseValue) }, { CKA_SENSITIVE, &falseValue, sizeof(falseValue) }, { CKA_PRIVATE, &falseValue, sizeof(falseValue) }, { CKA_ID, objID->data, objID->len }, { CKA_MODULUS, (void*) n.Elements(), n.Length() }, { CKA_PUBLIC_EXPONENT, (void*) e.Elements(), e.Length() }, { CKA_PRIVATE_EXPONENT, (void*) d.Elements(), d.Length() }, { CKA_PRIME_1, (void*) p.Elements(), p.Length() }, { CKA_PRIME_2, (void*) q.Elements(), q.Length() }, { CKA_EXPONENT_1, (void*) dp.Elements(), dp.Length() }, { CKA_EXPONENT_2, (void*) dq.Elements(), dq.Length() }, { CKA_COEFFICIENT, (void*) qi.Elements(), qi.Length() }, }; // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), keyTemplate, PR_ARRAY_SIZE(keyTemplate), PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), objID.get(), nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }
SecCmsSignerInfoRef nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, SecCertificateRef cert, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) { void *mark; SecCmsSignerInfoRef signerinfo; int version; PLArenaPool *poolp; poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); signerinfo = (SecCmsSignerInfoRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsSignerInfo)); if (signerinfo == NULL) { PORT_ArenaRelease(poolp, mark); return NULL; } signerinfo->cmsg = cmsg; switch(type) { case SecCmsSignerIDIssuerSN: signerinfo->signerIdentifier.identifierType = SecCmsSignerIDIssuerSN; if ((signerinfo->cert = CERT_DupCertificate(cert)) == NULL) goto loser; if ((signerinfo->signerIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) goto loser; dprintfRC("nss_cmssignerinfo_create: SecCmsSignerIDIssuerSN: cert.rc %d\n", (int)CFGetRetainCount(signerinfo->cert)); break; case SecCmsSignerIDSubjectKeyID: signerinfo->signerIdentifier.identifierType = SecCmsSignerIDSubjectKeyID; PORT_Assert(subjKeyID); if (!subjKeyID) goto loser; signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA); if (SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID, subjKeyID)) { goto loser; } signerinfo->pubKey = SECKEY_CopyPublicKey(pubKey); if (!signerinfo->pubKey) goto loser; break; default: goto loser; } if (!signingKey) goto loser; signerinfo->signingKey = SECKEY_CopyPrivateKey(signingKey); if (!signerinfo->signingKey) goto loser; /* set version right now */ version = SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN; /* RFC2630 5.3 "version is the syntax version number. If the .... " */ if (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDSubjectKeyID) version = SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY; (void)SEC_ASN1EncodeInteger(poolp, &(signerinfo->version), (long)version); if (SECOID_SetAlgorithmID(poolp, &signerinfo->digestAlg, digestalgtag, NULL) != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); return signerinfo; loser: PORT_ArenaRelease(poolp, mark); return NULL; }
SECStatus SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, SECKEYPrivateKey *key, SSL3KEAType kea) { SECStatus rv; sslSocket *ss; sslServerCerts *sc; SECKEYPublicKey * pubKey = NULL; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } /* Both key and cert must have a value or be NULL */ /* Passing a value of NULL will turn off key exchange algorithms that were * previously turned on */ if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* make sure the key exchange is recognized */ if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != ssl_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } sc = ss->serverCerts + kea; /* load the server certificate */ if (sc->serverCert != NULL) { CERT_DestroyCertificate(sc->serverCert); sc->serverCert = NULL; } if (cert) { sc->serverCert = CERT_DupCertificate(cert); if (!sc->serverCert) goto loser; /* get the size of the cert's public key, and remember it */ pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) goto loser; sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey); } /* load the server cert chain */ if (sc->serverCertChain != NULL) { CERT_DestroyCertificateList(sc->serverCertChain); sc->serverCertChain = NULL; } if (cert) { sc->serverCertChain = CERT_CertChainFromCert( sc->serverCert, certUsageSSLServer, PR_TRUE); if (sc->serverCertChain == NULL) goto loser; } /* load the private key */ if (sc->serverKeyPair != NULL) { ssl3_FreeKeyPair(sc->serverKeyPair); sc->serverKeyPair = NULL; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; SECKEY_CacheStaticFlags(keyCopy); sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (sc->serverKeyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; /* adopted by serverKeyPair */ } if (kea == kt_rsa && cert && sc->serverKeyBits > 512) { if (ss->opt.noStepDown) { /* disable all export ciphersuites */ } else { rv = ssl3_CreateRSAStepDownKeys(ss); if (rv != SECSuccess) { return SECFailure; /* err set by ssl3_CreateRSAStepDownKeys */ } } } /* Only do this once because it's global. */ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { return SECSuccess; } loser: if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } if (sc->serverCert != NULL) { CERT_DestroyCertificate(sc->serverCert); sc->serverCert = NULL; } if (sc->serverCertChain != NULL) { CERT_DestroyCertificateList(sc->serverCertChain); sc->serverCertChain = NULL; } if (sc->serverKeyPair != NULL) { ssl3_FreeKeyPair(sc->serverKeyPair); sc->serverKeyPair = NULL; } return SECFailure; }