/* * Creates the ephemeral public and private ECDH keys used by * server in ECDHE_RSA and ECDHE_ECDSA handshakes. * For now, the elliptic curve is chosen to be the same * strength as the signing certificate (ECC or RSA). * We need an API to specify the curve. This won't be a real * issue until we further develop server-side support for ECC * cipher suites. */ static SECStatus ssl_CreateECDHEphemeralKeys(sslSocket *ss, const namedGroupDef *ecGroup) { sslEphemeralKeyPair *keyPair = NULL; /* if there's no global key for this curve, make one. */ if (gECDHEKeyPairs[ecGroup->index].pair == NULL) { PRStatus status; status = PR_CallOnce(&gECDHEInitOnce, ssl_ECRegister); if (status != PR_SUCCESS) { PORT_SetError(gECDHEInitError); return SECFailure; } status = PR_CallOnceWithArg(&gECDHEKeyPairs[ecGroup->index].once, ssl_CreateECDHEphemeralKeyPairOnce, (void *)ecGroup); if (status != PR_SUCCESS) { PORT_SetError(gECDHEKeyPairs[ecGroup->index].error); return SECFailure; } } keyPair = ssl_CopyEphemeralKeyPair(gECDHEKeyPairs[ecGroup->index].pair); PORT_Assert(keyPair != NULL); if (!keyPair) return SECFailure; PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs); return SECSuccess; }
xpc_LocalizeContext(JSContext *cx) { JSRuntime* rt = JS_GetRuntime(cx); PR_CallOnceWithArg(&sHookRuntime, HookRuntime, rt); NS_ABORT_IF_FALSE(sHookedRuntime == rt, "created multiple JSRuntimes?"); JS_SetLocaleCallbacks(cx, new XPCLocaleCallbacks()); }
SECStatus ssl_OneTimeCertSetup(sslSocket *ss, const sslServerCert *sc) { if (PR_SUCCESS != PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { return SECFailure; } return SECSuccess; }
SECStatus ssl_OneTimeCertSetup(sslSocket *ss, const sslServerCert *sc) { /* Generate a step-down RSA key. */ if (sc->certType.authType == ssl_auth_rsa_decrypt && sc->serverKeyBits > 512 && !ss->opt.noStepDown && !ss->stepDownKeyPair) { if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) { return SECFailure; } } if (PR_SUCCESS != PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { return SECFailure; } return SECSuccess; }
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 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; }
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; }