| Index: net/third_party/nss/patches/tls-srp.patch
|
| diff --git a/net/third_party/nss/patches/tls-srp.patch b/net/third_party/nss/patches/tls-srp.patch
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..28c3bb77b5ef1395d982713ebc68bfa035cf37cf
|
| --- /dev/null
|
| +++ b/net/third_party/nss/patches/tls-srp.patch
|
| @@ -0,0 +1,1469 @@
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def
|
| +index 76417d0..0af96ba 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl.def
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl.def
|
| +@@ -136,6 +136,10 @@ SSL_ReHandshakeWithTimeout;
|
| + ;+NSS_3.11.8 { # NSS 3.11.8 release
|
| + ;+ global:
|
| + SSL_CanBypass;
|
| ++
|
| ++SSL_SetUserLogin;
|
| ++SSL_UserPasswdHook;
|
| ++SSL_GetSRPParamsHook;
|
| + ;+ local:
|
| + ;+*;
|
| + ;+};
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
|
| +index 21d7c8d..5906ca9 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl.h
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl.h
|
| +@@ -437,6 +437,43 @@ SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd);
|
| + */
|
| + SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a);
|
| +
|
| ++
|
| ++/*
|
| ++ * Set the client side user name and password non-interactively.
|
| ++ */
|
| ++SSL_IMPORT SECStatus SSL_SetUserLogin(PRFileDesc *fd,
|
| ++ const char *u,
|
| ++ const char *p);
|
| ++
|
| ++/*
|
| ++ * This sets the client side callback for SSL to retrieve the user password.
|
| ++ * fd - the file descriptor for the connection in question
|
| ++ * func - callback function pointer
|
| ++ * pw - user password
|
| ++ */
|
| ++
|
| ++typedef SECStatus (PR_CALLBACK *SSLUserPasswdCB)(PRFileDesc *fd,
|
| ++ SECItem *pw, void *arg);
|
| ++
|
| ++SSL_IMPORT SECStatus SSL_UserPasswdHook(PRFileDesc *fd, SSLUserPasswdCB func,
|
| ++ void *arg);
|
| ++
|
| ++/*
|
| ++ * This sets the server side callback function for SSL to retrieve the SRP
|
| ++ * authentication parameters associated with a specific user login.
|
| ++ * fd - the file descriptor of the connection
|
| ++ * func - pointer to the callback function
|
| ++ * user - username to lookup in app database
|
| ++ * srp - SRP auth paramters supplied to SSL by app
|
| ++ */
|
| ++
|
| ++typedef SECStatus (PR_CALLBACK *SSLGetSRPParamsCB)(PRFileDesc *fd,
|
| ++ SECKEYSRPParams *srp,
|
| ++ void *arg);
|
| ++
|
| ++SSL_IMPORT SECStatus SSL_GetSRPParamsHook(PRFileDesc *fd,
|
| ++ SSLGetSRPParamsCB func, void *arg);
|
| ++
|
| + /*
|
| + ** This is a callback for dealing with server certs that are not authenticated
|
| + ** by the client. The client app can decide that it actually likes the
|
| +@@ -703,6 +740,7 @@ SSL_IMPORT SSL3Statistics * SSL_GetStatistics(void);
|
| + /* Report more information than SSL_SecurityStatus.
|
| + ** Caller supplies the info struct. Function fills it in.
|
| + */
|
| ++SSL_IMPORT SECStatus SSL_GetChannelUsername(PRFileDesc *fd, SECItem *user);
|
| + SSL_IMPORT SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info,
|
| + PRUintn len);
|
| + SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
|
| +index f5c0880..21caea4 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl3con.c
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl3con.c
|
| +@@ -118,6 +118,9 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
|
| + #endif /* NSS_ENABLE_ECC */
|
| + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| +
|
| + #ifdef NSS_ENABLE_ECC
|
| + { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| +@@ -141,11 +144,15 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
|
| + { SSL_RSA_WITH_RC4_128_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE},
|
| + { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| +
|
| + #ifdef NSS_ENABLE_ECC
|
| + { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + #endif /* NSS_ENABLE_ECC */
|
| ++ { TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| + #ifdef NSS_ENABLE_ECC
|
| +@@ -154,6 +161,8 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
|
| + #endif /* NSS_ENABLE_ECC */
|
| + { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE},
|
| + { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE},
|
| ++ { TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| ++ { TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| +
|
| +
|
| + { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE},
|
| +@@ -283,6 +292,9 @@ static const ssl3KEADef kea_defs[] =
|
| + {kea_dh_anon, kt_dh, sign_null, PR_FALSE, 0, PR_FALSE},
|
| + {kea_dh_anon_export, kt_dh, sign_null, PR_TRUE, 512, PR_FALSE},
|
| + {kea_rsa_fips, kt_rsa, sign_rsa, PR_FALSE, 0, PR_TRUE },
|
| ++ {kea_srp, kt_srp, sign_null, PR_FALSE, 0, PR_FALSE},
|
| ++ {kea_srp_rsa, kt_srp, sign_rsa, PR_FALSE, 0, PR_FALSE},
|
| ++ {kea_srp_dss, kt_srp, sign_dsa, PR_FALSE, 0, PR_FALSE},
|
| + #ifdef NSS_ENABLE_ECC
|
| + {kea_ecdh_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE},
|
| + {kea_ecdhe_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE},
|
| +@@ -344,6 +356,21 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
|
| +
|
| +
|
| + /* New TLS cipher suites */
|
| ++ {TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_srp},
|
| ++ {TLS_SRP_SHA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_srp},
|
| ++ {TLS_SRP_SHA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_srp},
|
| ++ {TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
| ++ cipher_3des, mac_sha, kea_srp_rsa},
|
| ++ {TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
| ++ cipher_3des, mac_sha, kea_srp_dss},
|
| ++ {TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
| ++ cipher_aes_128, mac_sha, kea_srp_rsa},
|
| ++ {TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
| ++ cipher_aes_128, mac_sha, kea_srp_dss},
|
| ++ {TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
| ++ cipher_aes_256, mac_sha, kea_srp_rsa},
|
| ++ {TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
| ++ cipher_aes_256, mac_sha, kea_srp_dss},
|
| + {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa},
|
| + {TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_dss},
|
| + {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_rsa},
|
| +@@ -420,7 +447,8 @@ static const CK_MECHANISM_TYPE kea_alg_defs[] = {
|
| + CKM_RSA_PKCS,
|
| + CKM_DH_PKCS_DERIVE,
|
| + CKM_KEA_KEY_DERIVE,
|
| +- CKM_ECDH1_DERIVE
|
| ++ CKM_ECDH1_DERIVE,
|
| ++ CKM_NSS_SRP_DERIVE
|
| + };
|
| +
|
| + typedef struct SSLCipher2MechStr {
|
| +@@ -695,12 +723,27 @@ ssl3_config_match_init(sslSocket *ss)
|
| + }
|
| + #endif /* NSS_ENABLE_ECC */
|
| +
|
| ++ /* XXX this should be merged with switch(kea) from above */
|
| ++ switch (cipher_def->key_exchange_alg) {
|
| ++ case kea_srp_rsa:
|
| ++ svrAuth = ss->serverCerts + kt_rsa;
|
| ++ break;
|
| ++ case kea_srp_dss:
|
| ++ svrAuth = ss->serverCerts + kt_null; /* don't ask me..*/
|
| ++ break;
|
| ++ default:
|
| ++ svrAuth = ss->serverCerts + exchKeyType;
|
| ++ break;
|
| ++ }
|
| ++
|
| ++
|
| + /* Mark the suites that are backed by real tokens, certs and keys */
|
| + suite->isPresent = (PRBool)
|
| + (((exchKeyType == kt_null) ||
|
| + ((!isServer || (svrAuth->serverKeyPair &&
|
| + svrAuth->SERVERKEY &&
|
| +- svrAuth->serverCertChain)) &&
|
| ++ svrAuth->serverCertChain) ||
|
| ++ cipher_def->key_exchange_alg == kea_srp) &&
|
| + PK11_TokenExists(kea_alg_defs[exchKeyType]))) &&
|
| + ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech)));
|
| + if (suite->isPresent)
|
| +@@ -1080,6 +1123,57 @@ ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem publicExponent,
|
| + return rv;
|
| + }
|
| +
|
| ++/* Caller must set hiLevel error code.
|
| ++ * Called from ssl3_SendSRPServerKeyExchange */
|
| ++static SECStatus
|
| ++ssl3_ComputeSRPKeyHash(SECItem *N, SECItem *g, SECItem *s, SECItem *B,
|
| ++ SSL3Random *client_rand, SSL3Random *server_rand,
|
| ++ SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| ++{
|
| ++ PRUint8 * hashBuf;
|
| ++ PRUint8 * pBuf;
|
| ++ SECStatus rv = SECFailure;
|
| ++ unsigned int bufLen;
|
| ++
|
| ++ bufLen = 2*SSL3_RANDOM_LENGTH + N->len + 2 + g->len + 2
|
| ++ + s->len + 1 + B->len + 2;
|
| ++
|
| ++ hashBuf = PORT_Alloc(bufLen);
|
| ++ if (!hashBuf) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
|
| ++ pBuf = hashBuf + SSL3_RANDOM_LENGTH;
|
| ++ memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
|
| ++ pBuf += SSL3_RANDOM_LENGTH;
|
| ++ pBuf[0] = (PRUint8)(N->len >> 8);
|
| ++ pBuf[1] = (PRUint8)(N->len);
|
| ++ pBuf+=2;
|
| ++ memcpy(pBuf, N->data, N->len);
|
| ++ pBuf += N->len;
|
| ++ pBuf[0] = (PRUint8)(g->len >> 8);
|
| ++ pBuf[1] = (PRUint8)(g->len);
|
| ++ pBuf+=2;
|
| ++ memcpy(pBuf, g->data, g->len);
|
| ++ pBuf += g->len;
|
| ++ pBuf[0] = (PRUint8)(s->len);
|
| ++ pBuf+=1;
|
| ++ memcpy(pBuf, s->data, s->len);
|
| ++ pBuf += s->len;
|
| ++ pBuf[0] = (PRUint8)(B->len >> 8);
|
| ++ pBuf[1] = (PRUint8)(B->len);
|
| ++ pBuf+=2;
|
| ++ memcpy(pBuf, B->data, B->len);
|
| ++ pBuf += B->len;
|
| ++
|
| ++ rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
|
| ++
|
| ++ if (hashBuf)
|
| ++ PORT_Free(hashBuf);
|
| ++ return rv;
|
| ++}
|
| ++
|
| + /* Caller must set hiLevel error code. */
|
| + /* Called from ssl3_HandleServerKeyExchange. */
|
| + static SECStatus
|
| +@@ -2663,6 +2757,8 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
|
| + error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT; break;
|
| + case bad_certificate_hash_value:
|
| + error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT; break;
|
| ++ case unknown_psk_identity:
|
| ++ error = SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT; break;
|
| + default: error = SSL_ERROR_RX_UNKNOWN_ALERT; break;
|
| + }
|
| + if (level == alert_fatal) {
|
| +@@ -2828,7 +2924,8 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
|
| + * data into a 48-byte value.
|
| + */
|
| + PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
|
| +- (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
|
| ++ (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh) ||
|
| ++ (ss->ssl3.hs.kea_def->exchKeyType == kt_srp));
|
| + SECStatus rv = SECFailure;
|
| + CK_MECHANISM_TYPE master_derive;
|
| + CK_MECHANISM_TYPE key_derive;
|
| +@@ -4733,8 +4830,241 @@ loser:
|
| + return rv;
|
| + }
|
| +
|
| ++/* Read srp values from datastream and verify the signature
|
| ++ * if requiried by cipher. Save parameters to ss->sec.peerKey.
|
| ++ *
|
| ++ * called from ssl3_HandleServerKeyExchange
|
| ++ */
|
| ++static SECStatus
|
| ++ssl3_HandleSRPServerKeyExchange(sslSocket *ss, SSL3Opaque *b,
|
| ++ PRUint32 length) {
|
| ++
|
| ++ SECItem signature = {siBuffer, NULL, 0};
|
| ++ PRArenaPool *arena = NULL;
|
| ++ SECKEYPublicKey *peerKey = NULL;
|
| ++ SECStatus rv;
|
| ++ SSL3Hashes hashes;
|
| ++ SECItem srp_N, srp_g, srp_s, srp_ppub;
|
| ++ int errCode;
|
| ++
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &srp_N, 2, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed. */
|
| ++ }
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &srp_g, 2, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed. */
|
| ++ }
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &srp_s, 1, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed. */
|
| ++ }
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &srp_ppub, 2, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed. */
|
| ++ }
|
| ++
|
| ++ if (ss->ssl3.hs.kea_def->kea != kea_srp) { /* there MUST be a signature */
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed. */
|
| ++ }
|
| ++ rv = ssl3_ComputeSRPKeyHash(&srp_N, &srp_g, &srp_s, &srp_ppub,
|
| ++ &ss->ssl3.hs.client_random,
|
| ++ &ss->ssl3.hs.server_random,
|
| ++ &hashes, ss->opt.bypassPKCS11);
|
| ++ if (rv != SECSuccess) {
|
| ++ errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ goto alert_loser;
|
| ++ }
|
| ++ rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
|
| ++ PR_TRUE, ss->pkcs11PinArg);
|
| ++ if (rv != SECSuccess) {
|
| ++ errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ goto alert_loser;
|
| ++ }
|
| ++ }
|
| ++
|
| ++ /* all ok, save and return */
|
| ++ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| ++ if (arena == NULL) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++ ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
|
| ++ if (peerKey == NULL) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++ peerKey->arena = arena;
|
| ++ peerKey->keyType = srpKey;
|
| ++ peerKey->pkcs11Slot = NULL;
|
| ++ peerKey->pkcs11ID = CK_INVALID_HANDLE;
|
| ++
|
| ++ if (SECITEM_CopyItem(arena, &peerKey->u.srp.N, &srp_N) ||
|
| ++ SECITEM_CopyItem(arena, &peerKey->u.srp.g, &srp_g) ||
|
| ++ SECITEM_CopyItem(arena, &peerKey->u.srp.s, &srp_s) ||
|
| ++ SECITEM_CopyItem(arena, &peerKey->u.srp.ppub, &srp_ppub)) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++ return SECSuccess;
|
| ++
|
| ++alert_loser:
|
| ++ (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| ++loser:
|
| ++ PORT_SetError(errCode);
|
| ++ return SECFailure;
|
| ++}
|
| ++
|
| ++/* Calculate ClientKeyExchange and Pre-Master-Secret via SRP_GenKeys(),
|
| ++ * then send ClientKeyExchange and derive SSL master key
|
| ++ *
|
| ++ * called from ssl3_SendClientKeyExchange()
|
| ++ */
|
| ++static SECStatus
|
| ++ssl3_SendSRPClientKeyExchange(sslSocket *ss, SECKEYPublicKey * pubKey) {
|
| ++
|
| ++ SECKEYSRPParams *srpParam;
|
| ++ SECStatus rv;
|
| ++
|
| ++ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| ++ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
|
| ++
|
| ++ srpParam = PORT_ZAlloc(sizeof(SECKEYSRPParams));
|
| ++ if (!srpParam) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ goto loser;
|
| ++ }
|
| ++
|
| ++ /* PW-Callback overrides SSL_SetUserLogin. If both fail to
|
| ++ * provide a password, the token must know it or fail. */
|
| ++ if (ss->getUserPasswd) {
|
| ++ if (!ss->sec.userPasswd)
|
| ++ ss->sec.userPasswd = SECITEM_AllocItem(NULL,NULL,0);
|
| ++ SECITEM_FreeItem(ss->sec.userPasswd, PR_FALSE);
|
| ++ ss->getUserPasswd(ss->fd, ss->sec.userPasswd, ss->getUserPasswdArg);
|
| ++ }
|
| ++ if (ss->sec.userPasswd) {
|
| ++ srpParam->secret.data = ss->sec.userPasswd->data;
|
| ++ srpParam->secret.len = ss->sec.userPasswd->len;
|
| ++ ss->sec.userPasswd = NULL;
|
| ++ }
|
| +
|
| ++ /* calculate client key pair and PMS, then send key exchange data */
|
| ++ if (ss->opt.bypassPKCS11) {
|
| ++ SECItem pms = {0, NULL, 0};
|
| ++ SRPPrivateKey *prvKey;
|
| ++ SRPKeyPairParams keyPairParam;
|
| ++ keyPairParam.N.data = pubKey->u.srp.N.data;
|
| ++ keyPairParam.N.len = pubKey->u.srp.N.len;
|
| ++ keyPairParam.g.data = pubKey->u.srp.g.data;
|
| ++ keyPairParam.g.len = pubKey->u.srp.g.len;
|
| ++ keyPairParam.secret.data = srpParam->secret.data;
|
| ++ keyPairParam.secret.len = srpParam->secret.len;
|
| ++
|
| ++ rv = SRP_NewClientKeyPair(&prvKey, &keyPairParam);
|
| ++ if (rv != SECSuccess) goto loser; /* err set by SRP_ClientDerive */
|
| ++
|
| ++ SRPDeriveParams deriveParam;
|
| ++ deriveParam.N.data = pubKey->u.srp.N.data;
|
| ++ deriveParam.N.len = pubKey->u.srp.N.len;
|
| ++ deriveParam.g.data = pubKey->u.srp.g.data;
|
| ++ deriveParam.g.len = pubKey->u.srp.g.len;
|
| ++ deriveParam.s.data = pubKey->u.srp.s.data;
|
| ++ deriveParam.s.len = pubKey->u.srp.s.len;
|
| ++ deriveParam.u.data = ss->sec.userName->data;
|
| ++ deriveParam.u.len = ss->sec.userName->len;
|
| ++ deriveParam.ppub.data= pubKey->u.srp.ppub.data;
|
| ++ deriveParam.ppub.len = pubKey->u.srp.ppub.len;
|
| ++
|
| ++
|
| ++ if (SECSuccess != SRP_ClientDerive(prvKey, &deriveParam, &pms)) {
|
| ++ goto derive_fail;
|
| ++ }
|
| ++
|
| ++ /* client key exchange data */
|
| ++ rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
|
| ++ prvKey->pubKey.len + 2);
|
| ++ if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* */
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, prvKey->pubKey.data,
|
| ++ prvKey->pubKey.len, 2);
|
| ++ if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* */
|
| ++
|
| ++ /* init pending cipher spec*/
|
| ++ rv = ssl3_MasterKeyDeriveBypass(ss->ssl3.pwSpec,
|
| ++ (unsigned char *)&ss->ssl3.hs.client_random,
|
| ++ (unsigned char *)&ss->ssl3.hs.server_random,
|
| ++ &pms, PR_TRUE, PR_FALSE);
|
| ++ if (rv != SECSuccess) {
|
| ++ ss->ssl3.pwSpec->msItem.data = ss->ssl3.pwSpec->raw_master_secret;
|
| ++ ss->ssl3.pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
|
| ++ PK11_GenerateRandom(ss->ssl3.pwSpec->msItem.data,
|
| ++ SSL3_MASTER_SECRET_LENGTH);
|
| ++ }
|
| ++ rv = ssl3_InitPendingCipherSpec(ss, NULL);
|
| ++
|
| ++ SECITEM_FreeItem(&pms, PR_FALSE);
|
| ++ PORT_FreeArena(prvKey->arena, PR_TRUE);
|
| ++ } else { /* PK11 path */
|
| ++ PK11SymKey *pms = NULL;
|
| ++ SECKEYPrivateKey *prvKey = NULL;
|
| ++ SECKEYPublicKey *newPub = NULL;
|
| ++
|
| ++ srpParam->N.data = pubKey->u.srp.N.data;
|
| ++ srpParam->N.len = pubKey->u.srp.N.len;
|
| ++ srpParam->g.data = pubKey->u.srp.g.data;
|
| ++ srpParam->g.len = pubKey->u.srp.g.len;
|
| ++ srpParam->s.data = pubKey->u.srp.s.data;
|
| ++ srpParam->s.len = pubKey->u.srp.s.len;
|
| ++ srpParam->u.data = ss->sec.userName->data;
|
| ++ srpParam->u.len = ss->sec.userName->len;
|
| ++
|
| ++ /* The token handles (missing) info supplied in srpParam
|
| ++ * The template not actually involved in key generation,
|
| ++ * but it's important in the server key exchange */
|
| ++
|
| ++ prvKey = SECKEY_CreateSRPPrivateKey(srpParam, &newPub, PR_FALSE, NULL);
|
| ++ if (!prvKey) {
|
| ++ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
|
| ++ rv = SECFailure;
|
| ++ goto loser;
|
| ++ }
|
| ++ SECITEM_CopyItem(newPub->arena, &newPub->u.srp.ppub, &pubKey->u.srp.ppub);
|
| ++
|
| ++ /* Now all data is in newPub and prvKey, compute pms with them */
|
| ++ pms = PK11_PubDerive(prvKey, newPub, PR_FALSE, NULL, NULL,
|
| ++ CKM_NSS_SRP_DERIVE, CKM_TLS_MASTER_KEY_DERIVE, CKF_DERIVE, 0, NULL);
|
| +
|
| ++ if (!pms) {
|
| ++ goto derive_fail;
|
| ++ }
|
| ++
|
| ++ /* init pending cipher spec*/
|
| ++ rv = ssl3_InitPendingCipherSpec(ss, pms);
|
| ++
|
| ++
|
| ++ /* client key exchange data */
|
| ++ rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
|
| ++ newPub->u.srp.pub.len + 2);
|
| ++ if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* */
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, newPub->u.srp.pub.data,
|
| ++ newPub->u.srp.pub.len, 2);
|
| ++ if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* */
|
| ++
|
| ++ if (pms) PK11_FreeSymKey(pms);
|
| ++ SECKEY_DestroyPublicKey(newPub);
|
| ++ } /* end of PK11 path */
|
| ++
|
| ++loser:
|
| ++ SECITEM_ZfreeItem(ss->sec.userPasswd, PR_TRUE);
|
| ++ PORT_Free(srpParam);
|
| ++ /* caller frees pubKey */
|
| ++ return rv;
|
| ++derive_fail:
|
| ++ if (PORT_GetError() == SEC_ERROR_SRP_UNSUPPORTED_GROUP)
|
| ++ SSL3_SendAlert(ss, alert_fatal, insufficient_security);
|
| ++ if (PORT_GetError() == SEC_ERROR_SRP_ILLEGAL_PARAMETER)
|
| ++ SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| ++ return SECFailure;
|
| ++}
|
| +
|
| +
|
| + /* Called from ssl3_HandleServerHelloDone(). */
|
| +@@ -4794,7 +5124,9 @@ ssl3_SendClientKeyExchange(sslSocket *ss)
|
| + rv = ssl3_SendECDHClientKeyExchange(ss, serverKey);
|
| + break;
|
| + #endif /* NSS_ENABLE_ECC */
|
| +-
|
| ++ case kt_srp:
|
| ++ rv = ssl3_SendSRPClientKeyExchange(ss, serverKey);
|
| ++ break;
|
| + default:
|
| + /* got an unknown or unsupported Key Exchange Algorithm. */
|
| + SEND_ALERT
|
| +@@ -5284,7 +5616,8 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
| + desc = unexpected_message;
|
| + goto alert_loser;
|
| + }
|
| +- if (ss->sec.peerCert == NULL) {
|
| ++ if (ss->sec.peerCert == NULL &&
|
| ++ ss->ssl3.hs.suite_def->key_exchange_alg != kea_srp) {
|
| + errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
|
| + desc = unexpected_message;
|
| + goto alert_loser;
|
| +@@ -5473,6 +5806,13 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
| + rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
|
| + return rv;
|
| + #endif /* NSS_ENABLE_ECC */
|
| ++ case kt_srp:
|
| ++ rv = ssl3_HandleSRPServerKeyExchange(ss, b, length);
|
| ++ if (rv != SECSuccess) {
|
| ++ errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ goto alert_loser;
|
| ++ }
|
| ++ return rv;
|
| +
|
| + default:
|
| + desc = handshake_failure;
|
| +@@ -6034,16 +6374,20 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
|
| + if (rv != SECSuccess) {
|
| + return rv; /* err code is set. */
|
| + }
|
| +- rv = ssl3_SendCertificate(ss);
|
| +- if (rv != SECSuccess) {
|
| +- return rv; /* error code is set. */
|
| +- }
|
| + /* We have to do this after the call to ssl3_SendServerHello,
|
| + * because kea_def is set up by ssl3_SendServerHello().
|
| + */
|
| + kea_def = ss->ssl3.hs.kea_def;
|
| + ss->ssl3.hs.usedStepDownKey = PR_FALSE;
|
| +
|
| ++
|
| ++ if (kea_def->kea != kea_srp) { /* SRP auth only */
|
| ++ rv = ssl3_SendCertificate(ss);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv; /* error code is set. */
|
| ++ }
|
| ++ }
|
| ++
|
| + if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) {
|
| + /* see if we can legally use the key in the cert. */
|
| + int keyLen; /* bytes */
|
| +@@ -6075,6 +6419,11 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
|
| + return rv; /* err code was set. */
|
| + }
|
| + #endif /* NSS_ENABLE_ECC */
|
| ++ } else if ( kea_def->exchKeyType == kt_srp ) {
|
| ++ rv = ssl3_SendServerKeyExchange(ss);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv; /* err code was set. */
|
| ++ }
|
| + }
|
| +
|
| + if (ss->opt.requestCertificate) {
|
| +@@ -7099,6 +7448,195 @@ ssl3_SendServerHello(sslSocket *ss)
|
| + return SECSuccess;
|
| + }
|
| +
|
| ++/* ssl3_SendSRPServerKeyExchange()
|
| ++ * called by ssl3_SendServerKeyExchange()
|
| ++ *
|
| ++ * - make sure we got a userid in the srp client hello extension
|
| ++ * - retrieve verifier and parameters for the user via callback func
|
| ++ * - if user nonexistant, CB makes something up if it wants to
|
| ++ * - continue by creating and sending the SRP key exchange data:
|
| ++ *
|
| ++ * N, g, s, v = <read from password file>
|
| ++ * b = random()
|
| ++ * k = SHA1(N | PAD(g))
|
| ++ * B = k*v + g^b % N
|
| ++ * send (N,g,s,B)
|
| ++ *
|
| ++ * save values b,v,N for calculation of pms in ssl3_HandleSRPClientKeyExchange
|
| ++ */
|
| ++
|
| ++SECStatus
|
| ++ssl3_SendSRPServerKeyExchange(sslSocket *ss) {
|
| ++
|
| ++ int bytes = 0;
|
| ++ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
|
| ++ SECItem signed_hash = {siBuffer, NULL, 0};
|
| ++ SECStatus rv = SECFailure;
|
| ++ SECKEYSRPPublicKey *srp = NULL;
|
| ++ SECKEYPublicKey *pubKey = NULL;
|
| ++ SECKEYPrivateKey *prvKey = NULL;
|
| ++ SECKEYSRPParams *srpParams;
|
| ++ SSL3Hashes hashes;
|
| ++
|
| ++ /* send error if no userid was supplied in Client Hello */
|
| ++ if (!ss->sec.userName || !ss->sec.userName->data)
|
| ++ goto unknown_id;
|
| ++
|
| ++ /* Ask application for SRP parameters for specified username.
|
| ++ * Information provided via callback overrides data set on token.
|
| ++ * If no params provided, the token must supply them or fail.
|
| ++ * Callback may fail for nonexistant user.
|
| ++ */
|
| ++
|
| ++ srpParams = PORT_ZAlloc(sizeof(SECKEYSRPParams));
|
| ++ if (!srpParams) goto no_memory;
|
| ++
|
| ++ srpParams->u.data = ss->sec.userName->data;
|
| ++ srpParams->u.len = ss->sec.userName->len;
|
| ++
|
| ++ if (ss->getSRPParams) {
|
| ++ rv = ss->getSRPParams(ss->fd, srpParams, ss->getSRPParamsArg);
|
| ++ if (rv != SECSuccess) {
|
| ++ SECITEM_FreeItem(&srpParams->N, PR_FALSE);
|
| ++ SECITEM_FreeItem(&srpParams->g, PR_FALSE);
|
| ++ SECITEM_FreeItem(&srpParams->s, PR_FALSE);
|
| ++ SECITEM_ZfreeItem(&srpParams->secret, PR_FALSE);
|
| ++ PORT_Free(srpParams);
|
| ++ goto unknown_id;
|
| ++ }
|
| ++ }
|
| ++
|
| ++ /* create SRP server key pair */
|
| ++ if (ss->opt.bypassPKCS11) {
|
| ++ /* srpParams, keyPairParams are temporary. pubKey and prvKey have
|
| ++ * own arenas and are saved for ssl3_HandleSRPClientKeyExchange */
|
| ++ SRPPrivateKey *srpPrv;
|
| ++ SRPKeyPairParams keyPairParams;
|
| ++
|
| ++ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| ++ if (!arena) goto no_memory;
|
| ++
|
| ++ keyPairParams.N.data = srpParams->N.data;
|
| ++ keyPairParams.N.len = srpParams->N.len;
|
| ++ keyPairParams.g.data = srpParams->g.data;
|
| ++ keyPairParams.g.len = srpParams->g.len;
|
| ++ keyPairParams.secret.data = srpParams->secret.data;
|
| ++ keyPairParams.secret.len = srpParams->secret.len;
|
| ++
|
| ++ rv = SRP_NewServerKeyPair(&srpPrv, &keyPairParams);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
|
| ++ return rv;
|
| ++ }
|
| ++ prvKey = (SECKEYPrivateKey *)srpPrv;
|
| ++
|
| ++ /* create pubKey from temporary stuff */
|
| ++ pubKey = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
|
| ++ if (!pubKey) goto no_memory;
|
| ++ pubKey->arena = arena;
|
| ++ srp = &pubKey->u.srp;
|
| ++
|
| ++ SECITEM_CopyItem(arena, &srp->N, &srpParams->N);
|
| ++ SECITEM_CopyItem(arena, &srp->g, &srpParams->g);
|
| ++ SECITEM_CopyItem(arena, &srp->s, &srpParams->s);
|
| ++ SECITEM_CopyItem(arena, &srp->u, &srpParams->u);
|
| ++ SECITEM_CopyItem(arena, &srp->pub, &srpPrv->pubKey);
|
| ++
|
| ++ } else {
|
| ++
|
| ++ /* input: srpParams, output: prvKey = b,B,v, pubKey = N,g,s,u,B */
|
| ++ prvKey = SECKEY_CreateSRPPrivateKey(srpParams, &pubKey, PR_TRUE, NULL);
|
| ++ if (!prvKey) {
|
| ++ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
|
| ++ rv = SECFailure;
|
| ++ goto cleanup;
|
| ++ }
|
| ++ srp = &pubKey->u.srp;
|
| ++ }
|
| ++
|
| ++ /* send N,g,s,B as ServerKeyExchange to Client */
|
| ++ /* optionally include signature for additional DSS/RSA auth */
|
| ++
|
| ++ if (kea_def->kea != kea_srp) { /* we need a RSA/DSA signature */
|
| ++ rv = ssl3_ComputeSRPKeyHash(&srp->N, &srp->g, &srp->s, &srp->pub,
|
| ++ &ss->ssl3.hs.client_random,
|
| ++ &ss->ssl3.hs.server_random,
|
| ++ &hashes, ss->opt.bypassPKCS11);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ goto loser;
|
| ++ }
|
| ++ /* look if we have a certificate for selected algo */
|
| ++ if (kea_def->kea == kea_srp_rsa)
|
| ++ bytes = kt_rsa;
|
| ++ else
|
| ++ bytes = kt_null;
|
| ++
|
| ++ if (!(&ss->serverCerts[bytes])) {
|
| ++ /* ciphersuite signing algo does not match supplied certificate */
|
| ++ PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ rv = ssl3_SignHashes(&hashes, ss->serverCerts[bytes].SERVERKEY,
|
| ++ &signed_hash, PR_TRUE);
|
| ++ bytes = 2 + signed_hash.len;
|
| ++ }
|
| ++
|
| ++ bytes += srp->N.len + srp->g.len + srp->s.len + srp->pub.len + 7;
|
| ++
|
| ++ rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, bytes);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, srp->N.data, srp->N.len, 2);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, srp->g.data, srp->g.len, 2);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, srp->s.data, srp->s.len, 1);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, srp->pub.data, srp->pub.len, 2);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++
|
| ++ if (kea_def->kea != kea_srp) {
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
|
| ++ signed_hash.len, 2);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv; /* err set by AppendHandshake. */
|
| ++ }
|
| ++ SECITEM_FreeItem(&signed_hash, PR_FALSE);
|
| ++ }
|
| ++
|
| ++ /* save prvKey / pubKey for use in HandleSRPClientExchange
|
| ++ * XXX in bypassPK11, prvKey is no PK11 object and must be casted */
|
| ++ ssl3KeyPair *srpPair = ssl3_NewKeyPair(prvKey, pubKey);
|
| ++ ss->serverCerts[kt_srp].serverKeyPair = srpPair;
|
| ++
|
| ++cleanup:
|
| ++ SECITEM_FreeItem(&srpParams->N, PR_FALSE);
|
| ++ SECITEM_FreeItem(&srpParams->g, PR_FALSE);
|
| ++ SECITEM_FreeItem(&srpParams->s, PR_FALSE);
|
| ++ SECITEM_ZfreeItem(&srpParams->secret, PR_FALSE);
|
| ++ if (srpParams) PORT_Free(srpParams);
|
| ++ return rv;
|
| ++loser:
|
| ++ PORT_SetError(SSL_ERROR_INTERNAL_ERROR_ALERT);
|
| ++ (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
|
| ++ return SECFailure;
|
| ++unknown_id:
|
| ++ PORT_SetError(SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT);
|
| ++ (void)SSL3_SendAlert(ss, alert_fatal, unknown_psk_identity);
|
| ++ return SECFailure;
|
| ++no_memory:
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ return SECFailure;
|
| ++}
|
| +
|
| + static SECStatus
|
| + ssl3_SendServerKeyExchange(sslSocket *ss)
|
| +@@ -7183,7 +7721,9 @@ const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
|
| + return rv;
|
| + }
|
| + #endif /* NSS_ENABLE_ECC */
|
| +-
|
| ++ case kt_srp:
|
| ++ rv = ssl3_SendSRPServerKeyExchange(ss);
|
| ++ return rv;
|
| + case kt_dh:
|
| + case kt_null:
|
| + default:
|
| +@@ -7536,6 +8076,101 @@ double_bypass:
|
| + return SECSuccess;
|
| + }
|
| +
|
| ++/*
|
| ++ * extract SRP value A from ClientKeyExchange
|
| ++ * calculate pre-master-secret and init cipher specs
|
| ++ *
|
| ++ * called by ssl3_HandleClientKeyExchange
|
| ++ */
|
| ++SECStatus
|
| ++ssl3_HandleSRPClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
|
| ++ PRUint32 length) {
|
| ++
|
| ++ SECItem ppub; /* peers public key ('A') */
|
| ++ sslServerCerts sc;
|
| ++ SECStatus rv = SECFailure;
|
| ++ SECKEYPublicKey *pubKey = NULL;
|
| ++
|
| ++
|
| ++ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| ++ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| ++
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &ppub, 2, &b, &length);
|
| ++ if (rv != SECSuccess) {
|
| ++ PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ sc = ss->serverCerts[kt_srp];
|
| ++ pubKey = sc.serverKeyPair->pubKey;
|
| ++
|
| ++ SECITEM_CopyItem(pubKey->arena, &pubKey->u.srp.ppub, &ppub);
|
| ++
|
| ++ if (ss->opt.bypassPKCS11) {
|
| ++ SRPPrivateKey *prvKey = NULL;
|
| ++ SECItem pms = { 0, NULL, 0 };
|
| ++ SRPDeriveParams param;
|
| ++
|
| ++ prvKey = (SRPPrivateKey *)sc.serverKeyPair->privKey;
|
| ++
|
| ++ param.N.data = pubKey->u.srp.N.data;
|
| ++ param.N.len = pubKey->u.srp.N.len;
|
| ++ param.g.data = pubKey->u.srp.g.data;
|
| ++ param.g.len = pubKey->u.srp.g.len;
|
| ++ param.ppub.data = pubKey->u.srp.ppub.data;
|
| ++ param.ppub.len = pubKey->u.srp.ppub.len;
|
| ++
|
| ++ if (SECSuccess != SRP_ServerDerive(prvKey, ¶m, &pms))
|
| ++ goto derive_fail;
|
| ++
|
| ++ ssl_GetSpecWriteLock(ss);
|
| ++ /* create MS out of MS, bypassing PKCS11 */
|
| ++ rv = ssl3_MasterKeyDeriveBypass(ss->ssl3.pwSpec,
|
| ++ (unsigned char *)&ss->ssl3.hs.client_random,
|
| ++ (unsigned char *)&ss->ssl3.hs.server_random,
|
| ++ &pms, PR_TRUE, PR_FALSE);
|
| ++ if (rv != SECSuccess) {
|
| ++ ss->ssl3.pwSpec->msItem.data = ss->ssl3.pwSpec->raw_master_secret;
|
| ++ ss->ssl3.pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
|
| ++ PK11_GenerateRandom(ss->ssl3.pwSpec->msItem.data, ss->ssl3.pwSpec->msItem.len);
|
| ++ }
|
| ++
|
| ++ rv = ssl3_InitPendingCipherSpec(ss, NULL);
|
| ++
|
| ++ SECITEM_ZfreeItem(&pms, PR_FALSE);
|
| ++ PORT_FreeArena(prvKey->arena, PR_TRUE); /* XXX FreeArena does not zeroize! */
|
| ++ sc.serverKeyPair->privKey = NULL;
|
| ++
|
| ++ } else {
|
| ++ SECKEYPrivateKey *prvKey = NULL;
|
| ++ PK11SymKey *pms = NULL; /* pre-master secret */
|
| ++
|
| ++ prvKey = sc.serverKeyPair->privKey;
|
| ++
|
| ++ /* Calculate PMS based on clntKey and public params */
|
| ++ pms = PK11_PubDerive(prvKey, pubKey, PR_TRUE, NULL, NULL,
|
| ++ CKM_NSS_SRP_DERIVE, CKM_TLS_MASTER_KEY_DERIVE, CKF_DERIVE, 0, NULL);
|
| ++
|
| ++ if (!pms) {
|
| ++ goto derive_fail;
|
| ++ }
|
| ++
|
| ++ ssl_GetSpecWriteLock(ss);
|
| ++ /* derive master secret from pms */
|
| ++ rv = ssl3_InitPendingCipherSpec(ss, pms);
|
| ++ ssl_ReleaseSpecWriteLock(ss);
|
| ++
|
| ++ PK11_FreeSymKey(pms);
|
| ++ /*SECKEY_DestroyPrivateKey(prvKey);*/
|
| ++ }
|
| ++
|
| ++ return rv;
|
| ++derive_fail:
|
| ++ if (PORT_GetError() == SEC_ERROR_SRP_ILLEGAL_PARAMETER)
|
| ++ SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| ++ return rv;
|
| ++}
|
| ++
|
| +
|
| + /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
|
| + * ssl3 ClientKeyExchange message from the remote client
|
| +@@ -7608,7 +8243,8 @@ skip:
|
| + serverKey = serverKeyPair->privKey;
|
| + }
|
| +
|
| +- if (serverKey == NULL) {
|
| ++ /* XXX hack, figure out this serverKey thing..*/
|
| ++ if (serverKey == NULL && kea_def->exchKeyType != kt_srp) {
|
| + SEND_ALERT
|
| + PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
|
| + return SECFailure;
|
| +@@ -7649,7 +8285,12 @@ skip:
|
| + }
|
| + break;
|
| + #endif /* NSS_ENABLE_ECC */
|
| +-
|
| ++ case kt_srp:
|
| ++ rv = ssl3_HandleSRPClientKeyExchange(ss, b, length);
|
| ++ if (rv != SECSuccess) {
|
| ++ return SECFailure; /* error code set */
|
| ++ }
|
| ++ break;
|
| + default:
|
| + (void) ssl3_HandshakeFailure(ss);
|
| + PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
| +@@ -7823,8 +8464,12 @@ ssl3_SendCertificate(sslSocket *ss)
|
| + * using EC certificates.
|
| + */
|
| + if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
|
| +- (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
|
| ++ (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) ||
|
| ++ (ss->ssl3.hs.kea_def->kea == kea_srp_rsa)) {
|
| + certIndex = kt_rsa;
|
| ++ } else if
|
| ++ (ss->ssl3.hs.kea_def->kea == kea_srp_dss) {
|
| ++ certIndex = kt_null;
|
| + } else {
|
| + certIndex = ss->ssl3.hs.kea_def->exchKeyType;
|
| + }
|
| +@@ -8244,7 +8889,9 @@ cert_block:
|
| + ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
|
| + ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
|
| + #endif /* NSS_ENABLE_ECC */
|
| +- ss->ssl3.hs.kea_def->exchKeyType == kt_dh) {
|
| ++ ss->ssl3.hs.kea_def->exchKeyType == kt_dh ||
|
| ++ ss->ssl3.hs.kea_def->kea == kea_srp_dss ||
|
| ++ ss->ssl3.hs.kea_def->kea == kea_srp_rsa) {
|
| + ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */
|
| + }
|
| + }
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl3ecc.c b/mozilla/security/nss/lib/ssl/ssl3ecc.c
|
| +index 778c7ab..b899038 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl3ecc.c
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl3ecc.c
|
| +@@ -1191,3 +1191,60 @@ loser:
|
| + }
|
| +
|
| + #endif /* NSS_ENABLE_ECC */
|
| ++
|
| ++/* send user mapping indication using info from ss->sec.userlogin
|
| ++ * called from ssl3_CallHelloExtensionSenders */
|
| ++PRInt32
|
| ++ssl3_SendSRPHelloExtension(sslSocket * ss, PRBool append,
|
| ++ PRUint32 maxBytes)
|
| ++{
|
| ++ SECItem * user = ss->sec.userName;
|
| ++
|
| ++ if (user == NULL)
|
| ++ return 0; /* no credentials, no extension */
|
| ++
|
| ++ if (append && maxBytes >= user->len + 5) {
|
| ++ SECStatus rv;
|
| ++ /* extension_type 6 */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, 12, 2);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* length of extension */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, user->len + 1, 2);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* length of data */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, user->len, 1);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* extension_data = srp user name */
|
| ++ rv = ssl3_AppendHandshake(ss, user->data, user->len);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ }
|
| ++ return user->len+5;
|
| ++}
|
| ++
|
| ++SECStatus
|
| ++ssl3_HandleSRPHelloExtension(sslSocket *ss, PRUint16 ext, SECItem *data)
|
| ++{
|
| ++ SECStatus rv;
|
| ++ SECItem username;
|
| ++
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &username, 1, &data->data, &data->len);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv;
|
| ++
|
| ++ /* enforce SRP username length constrain */
|
| ++ if (data->len > MAX_SRP_USERNAME_LENGTH)
|
| ++ data->len = MAX_SRP_USERNAME_LENGTH;
|
| ++
|
| ++ ss->sec.userName = PORT_ZAlloc(sizeof(SECItem));
|
| ++ if (!ss->sec.userName)
|
| ++ goto no_memory;
|
| ++
|
| ++ rv = SECITEM_CopyItem(NULL, ss->sec.userName, &username);
|
| ++ if (rv != SECSuccess)
|
| ++ goto no_memory;
|
| ++
|
| ++ return rv;
|
| ++no_memory:
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ return SECFailure;
|
| ++}
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c
|
| +index b93671e..c2a27b4 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl3ext.c
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl3ext.c
|
| +@@ -78,6 +78,11 @@ static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss,
|
| + PRBool append, PRUint32 maxBytes);
|
| + static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
|
| + PRUint16 ex_type, SECItem *data);
|
| ++static SECStatus ssl3_HandleSRPHelloXtn(sslSocket *ss, PRUint16 ext,
|
| ++ SECItem *data);
|
| ++PRInt32 ssl3_SendSRPHelloXtn(sslSocket * ss, PRBool append,
|
| ++ PRUint32 maxBytes);
|
| ++
|
| +
|
| + /*
|
| + * Write bytes. Using this function means the SECItem structure
|
| +@@ -254,6 +259,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
|
| +
|
| + static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
|
| + { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
|
| ++ { ssl_srp_hello_xtn, &ssl3_HandleSRPHelloXtn },
|
| + { -1, NULL }
|
| + };
|
| +
|
| +@@ -272,6 +278,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
|
| + { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
|
| + #endif
|
| + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
|
| ++ { ssl_srp_hello_xtn, &ssl3_SendSRPHelloXtn },
|
| + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn },
|
| + { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
|
| + { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn }
|
| +@@ -1720,3 +1727,59 @@ ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| + return rv;
|
| + }
|
| +
|
| ++/* send user mapping indication using info from ss->sec.userlogin
|
| ++ * called from ssl3_CallHelloExtensionSenders */
|
| ++PRInt32
|
| ++ssl3_SendSRPHelloXtn(sslSocket * ss, PRBool append,
|
| ++ PRUint32 maxBytes)
|
| ++{
|
| ++ SECItem * user = ss->sec.userName;
|
| ++
|
| ++ if (user == NULL)
|
| ++ return 0; /* no credentials, no extension */
|
| ++
|
| ++ if (append && maxBytes >= user->len + 5) {
|
| ++ SECStatus rv;
|
| ++ /* extension_type 6 */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, 12, 2);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* length of extension */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, user->len + 1, 2);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* length of data */
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, user->len, 1);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ /* extension_data = srp user name */
|
| ++ rv = ssl3_AppendHandshake(ss, user->data, user->len);
|
| ++ if (rv != SECSuccess) return 0;
|
| ++ }
|
| ++ return user->len+5;
|
| ++}
|
| ++
|
| ++SECStatus
|
| ++ssl3_HandleSRPHelloXtn(sslSocket *ss, PRUint16 ext, SECItem *data)
|
| ++{
|
| ++ SECStatus rv;
|
| ++ SECItem username;
|
| ++
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &username, 1, &data->data, &data->len);
|
| ++ if (rv != SECSuccess)
|
| ++ return rv;
|
| ++
|
| ++ /* enforce SRP username length constrain */
|
| ++ if (data->len > MAX_SRP_USERNAME_LENGTH)
|
| ++ data->len = MAX_SRP_USERNAME_LENGTH;
|
| ++
|
| ++ ss->sec.userName = PORT_ZAlloc(sizeof(SECItem));
|
| ++ if (!ss->sec.userName)
|
| ++ goto no_memory;
|
| ++
|
| ++ rv = SECITEM_CopyItem(NULL, ss->sec.userName, &username);
|
| ++ if (rv != SECSuccess)
|
| ++ goto no_memory;
|
| ++
|
| ++ return rv;
|
| ++no_memory:
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| ++ return SECFailure;
|
| ++}
|
| +diff --git a/mozilla/security/nss/lib/ssl/ssl3prot.h b/mozilla/security/nss/lib/ssl/ssl3prot.h
|
| +index aeaacdd..a043577 100644
|
| +--- a/mozilla/security/nss/lib/ssl/ssl3prot.h
|
| ++++ b/mozilla/security/nss/lib/ssl/ssl3prot.h
|
| +@@ -63,6 +63,8 @@ typedef uint16 ssl3CipherSuite;
|
| +
|
| + #define MAX_FRAGMENT_LENGTH 16384
|
| +
|
| ++#define MAX_SRP_USERNAME_LENGTH 255
|
| ++
|
| + typedef enum {
|
| + content_change_cipher_spec = 20,
|
| + content_alert = 21,
|
| +@@ -137,7 +139,9 @@ typedef enum {
|
| + certificate_unobtainable = 111,
|
| + unrecognized_name = 112,
|
| + bad_certificate_status_response = 113,
|
| +- bad_certificate_hash_value = 114
|
| ++ bad_certificate_hash_value = 114,
|
| ++
|
| ++ unknown_psk_identity = 115
|
| +
|
| + } SSL3AlertDescription;
|
| +
|
| +@@ -215,6 +219,9 @@ typedef enum {
|
| + kea_dh_anon,
|
| + kea_dh_anon_export,
|
| + kea_rsa_fips,
|
| ++ kea_srp,
|
| ++ kea_srp_rsa,
|
| ++ kea_srp_dss,
|
| + kea_ecdh_ecdsa,
|
| + kea_ecdhe_ecdsa,
|
| + kea_ecdh_rsa,
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslauth.c b/mozilla/security/nss/lib/ssl/sslauth.c
|
| +index 3f4924d..8282cf8 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslauth.c
|
| ++++ b/mozilla/security/nss/lib/ssl/sslauth.c
|
| +@@ -291,6 +291,80 @@ SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
|
| + return SECSuccess;
|
| + }
|
| +
|
| ++/* register callback function to provide the user password */
|
| ++SECStatus
|
| ++SSL_UserPasswdHook(PRFileDesc *s, SSLUserPasswdCB func, void *arg)
|
| ++{
|
| ++ sslSocket *ss;
|
| ++
|
| ++ ss = ssl_FindSocket(s);
|
| ++ if (!ss) {
|
| ++ SSL_DBG(("%d: SSL[%d]: bad socket in UserPasswdHook",
|
| ++ SSL_GETPID(), s));
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ ss->getUserPasswd = func;
|
| ++ ss->getUserPasswdArg = arg;
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| ++/* used by client to provide user credentials non-interactively */
|
| ++SECStatus
|
| ++SSL_SetUserLogin(PRFileDesc *s, const char *user, const char *passwd)
|
| ++{
|
| ++ sslSocket *ss = NULL;
|
| ++ int len;
|
| ++
|
| ++ ss = ssl_FindSocket(s);
|
| ++ if (!ss) {
|
| ++ SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
|
| ++ SSL_GETPID(), s));
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ if (user) {
|
| ++ len = PORT_Strlen(user);
|
| ++ if (len > MAX_SRP_USERNAME_LENGTH)
|
| ++ len = MAX_SRP_USERNAME_LENGTH;
|
| ++ ss->sec.userName = SECITEM_AllocItem(NULL, NULL, len);
|
| ++ if (!ss->sec.userName) {
|
| ++ PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ PORT_Memcpy(ss->sec.userName->data, user, ss->sec.userName->len);
|
| ++ }
|
| ++
|
| ++ if (passwd) {
|
| ++ len = PORT_Strlen(passwd);
|
| ++ ss->sec.userPasswd = SECITEM_AllocItem(NULL, NULL, len);
|
| ++ if (!ss->sec.userPasswd) {
|
| ++ PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ PORT_Memcpy(ss->sec.userPasswd->data, passwd, ss->sec.userPasswd->len);
|
| ++ }
|
| ++
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| ++/* register callback function to provide SRP user authentication params */
|
| ++SECStatus
|
| ++SSL_GetSRPParamsHook(PRFileDesc *s, SSLGetSRPParamsCB func, void *arg)
|
| ++{
|
| ++ sslSocket *ss;
|
| ++
|
| ++ ss = ssl_FindSocket(s);
|
| ++ if (!ss) {
|
| ++ SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
|
| ++ SSL_GETPID(), s));
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ ss->getSRPParams = func;
|
| ++ ss->getSRPParamsArg = arg;
|
| ++ return SECSuccess;
|
| ++}
|
| +
|
| + /* This is the "default" authCert callback function. It is called when a
|
| + * certificate message is received from the peer and the local application
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslenum.c b/mozilla/security/nss/lib/ssl/sslenum.c
|
| +index b8aa8cc..196ed30 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslenum.c
|
| ++++ b/mozilla/security/nss/lib/ssl/sslenum.c
|
| +@@ -74,6 +74,9 @@ const PRUint16 SSL_ImplementedCiphers[] = {
|
| + #endif /* NSS_ENABLE_ECC */
|
| + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
| + TLS_RSA_WITH_AES_256_CBC_SHA,
|
| ++ TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
| ++ TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
| ++ TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
| +
|
| + /* 128-bit */
|
| + #ifdef NSS_ENABLE_ECC
|
| +@@ -98,12 +101,16 @@ const PRUint16 SSL_ImplementedCiphers[] = {
|
| + SSL_RSA_WITH_RC4_128_MD5,
|
| + SSL_RSA_WITH_RC4_128_SHA,
|
| + TLS_RSA_WITH_AES_128_CBC_SHA,
|
| ++ TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
| ++ TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
| ++ TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
| +
|
| + /* 112-bit 3DES */
|
| + #ifdef NSS_ENABLE_ECC
|
| + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
| + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
| + #endif /* NSS_ENABLE_ECC */
|
| ++ TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
| + SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
| + SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
| + #ifdef NSS_ENABLE_ECC
|
| +@@ -112,6 +119,8 @@ const PRUint16 SSL_ImplementedCiphers[] = {
|
| + #endif /* NSS_ENABLE_ECC */
|
| + SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
|
| + SSL_RSA_WITH_3DES_EDE_CBC_SHA,
|
| ++ TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
| ++ TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
| +
|
| + /* 56-bit DES "domestic" cipher suites */
|
| + SSL_DHE_RSA_WITH_DES_CBC_SHA,
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslerr.h b/mozilla/security/nss/lib/ssl/sslerr.h
|
| +index eb56ea9..a0c4b9d 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslerr.h
|
| ++++ b/mozilla/security/nss/lib/ssl/sslerr.h
|
| +@@ -205,6 +205,8 @@ SSL_ERROR_WEAK_SERVER_KEY = (SSL_ERROR_BASE + 115),
|
| +
|
| + SSL_ERROR_RX_UNEXPECTED_CERT_STATUS = (SSL_ERROR_BASE + 116),
|
| +
|
| ++SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT = (SSL_ERROR_BASE + 116),
|
| ++
|
| + SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
|
| + } SSLErrorCodes;
|
| + #endif /* NO_SECURITY_ERROR_ENUM */
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
|
| +index 1ea82da..0a0808a 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslimpl.h
|
| ++++ b/mozilla/security/nss/lib/ssl/sslimpl.h
|
| +@@ -317,9 +317,9 @@ typedef struct {
|
| + } ssl3CipherSuiteCfg;
|
| +
|
| + #ifdef NSS_ENABLE_ECC
|
| +-#define ssl_V3_SUITES_IMPLEMENTED 50
|
| ++#define ssl_V3_SUITES_IMPLEMENTED 59
|
| + #else
|
| +-#define ssl_V3_SUITES_IMPLEMENTED 30
|
| ++#define ssl_V3_SUITES_IMPLEMENTED 39
|
| + #endif /* NSS_ENABLE_ECC */
|
| +
|
| + typedef struct sslOptionsStr {
|
| +@@ -1050,6 +1050,8 @@ struct sslSecurityInfoStr {
|
| + CERTCertificate *localCert; /* ssl 2 & 3 */
|
| + CERTCertificate *peerCert; /* ssl 2 & 3 */
|
| + SECKEYPublicKey *peerKey; /* ssl3 only */
|
| ++ SECItem *userName; /* SSL username credential */
|
| ++ SECItem *userPasswd; /* SSL userpasswd credential */
|
| +
|
| + SSLSignType authAlgorithm;
|
| + PRUint32 authKeyBits;
|
| +@@ -1159,6 +1161,10 @@ const unsigned char * preferredCipher;
|
| + SSLHandshakeCallback handshakeCallback;
|
| + void *handshakeCallbackData;
|
| + void *pkcs11PinArg;
|
| ++ SSLUserPasswdCB getUserPasswd;
|
| ++ void *getUserPasswdArg;
|
| ++ SSLGetSRPParamsCB getSRPParams;
|
| ++ void *getSRPParamsArg;
|
| +
|
| + PRIntervalTime rTimeout; /* timeout for NSPR I/O */
|
| + PRIntervalTime wTimeout; /* timeout for NSPR I/O */
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslinfo.c b/mozilla/security/nss/lib/ssl/sslinfo.c
|
| +index c1c3fd7..2599ef1 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslinfo.c
|
| ++++ b/mozilla/security/nss/lib/ssl/sslinfo.c
|
| +@@ -54,6 +54,27 @@ ssl_GetCompressionMethodName(SSLCompressionMethod compression)
|
| + }
|
| + }
|
| +
|
| ++SECStatus
|
| ++SSL_GetChannelUsername(PRFileDesc *fd, SECItem *user)
|
| ++{
|
| ++ SECItem * username;
|
| ++ sslSocket * ss;
|
| ++
|
| ++ ss = ssl_FindSocket(fd);
|
| ++ if (!ss) {
|
| ++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelUsername",
|
| ++ SSL_GETPID(), fd));
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ if (ss->sec.userName == NULL) {
|
| ++ PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ return SECITEM_CopyItem(NULL, user, ss->sec.userName);
|
| ++}
|
| ++
|
| + SECStatus
|
| + SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
|
| + {
|
| +@@ -141,6 +162,9 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
|
| + #define K_KEA "KEA", kt_kea
|
| + #define K_ECDH "ECDH", kt_ecdh
|
| + #define K_ECDHE "ECDHE", kt_ecdh
|
| ++#define K_SRP "SRP", ssl_kea_srp
|
| ++#define K_SRP_RSA "SRP_RSA", ssl_kea_srp_rsa
|
| ++#define K_SRP_DSS "SRP_DSS", ssl_kea_srp_dss
|
| +
|
| + #define C_SEED "SEED", calg_seed
|
| + #define C_CAMELLIA "CAMELLIA", calg_camellia
|
| +@@ -201,6 +225,17 @@ static const SSLCipherSuiteInfo suiteInfo[] = {
|
| + {0,CS(SSL_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0, },
|
| + {0,CS(SSL_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0, },
|
| +
|
| ++/* SRP cipher suites */
|
| ++{0,CS(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA), S_KEA, K_SRP, C_3DES,B_3DES,M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA), S_KEA, K_SRP_RSA, C_3DES,B_3DES,M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA), S_KEA, K_SRP_DSS, C_3DES,B_3DES,M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_WITH_AES_128_CBC_SHA), S_KEA, K_SRP, C_AES, B_128, M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA), S_KEA, K_SRP_RSA, C_AES, B_128, M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA), S_KEA, K_SRP_DSS, C_AES, B_128, M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_WITH_AES_256_CBC_SHA), S_KEA, K_SRP, C_AES, B_256, M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA), S_KEA, K_SRP_RSA, C_AES, B_256, M_SHA, 0, 0, 0, },
|
| ++{0,CS(TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA), S_KEA, K_SRP_DSS, C_AES, B_256, M_SHA, 0, 0, 0, },
|
| ++
|
| + #ifdef NSS_ENABLE_ECC
|
| + /* ECC cipher suites */
|
| + {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslproto.h b/mozilla/security/nss/lib/ssl/sslproto.h
|
| +index b534d0b..cbf6250 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslproto.h
|
| ++++ b/mozilla/security/nss/lib/ssl/sslproto.h
|
| +@@ -220,6 +220,16 @@
|
| + #define TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
|
| + #define TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
|
| +
|
| ++#define TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0xC01A
|
| ++#define TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0xC01B
|
| ++#define TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0xC01C
|
| ++#define TLS_SRP_SHA_WITH_AES_128_CBC_SHA 0xC01D
|
| ++#define TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0xC01E
|
| ++#define TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0xC01F
|
| ++#define TLS_SRP_SHA_WITH_AES_256_CBC_SHA 0xC020
|
| ++#define TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0xC021
|
| ++#define TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0xC022
|
| ++
|
| + /* Netscape "experimental" cipher suites. */
|
| + #define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
|
| + #define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslsecur.c b/mozilla/security/nss/lib/ssl/sslsecur.c
|
| +index 49a81bc..fe1465d 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslsecur.c
|
| ++++ b/mozilla/security/nss/lib/ssl/sslsecur.c
|
| +@@ -902,6 +902,14 @@ ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
|
| + if (os->sec.rcvSecret.data && !ss->sec.rcvSecret.data)
|
| + goto loser;
|
| +
|
| ++ SECITEM_CopyItem(0, ss->sec.userName, os->sec.userName);
|
| ++ if (os->sec.userName->data && !ss->sec.userName->data)
|
| ++ goto loser;
|
| ++ SECITEM_CopyItem(0, ss->sec.userPasswd, os->sec.userPasswd);
|
| ++ if (os->sec.userPasswd->data && !ss->sec.userPasswd->data)
|
| ++ goto loser;
|
| ++
|
| ++
|
| + /* XXX following code is wrong if either cx != 0 */
|
| + PORT_Assert(os->sec.readcx == 0);
|
| + PORT_Assert(os->sec.writecx == 0);
|
| +@@ -983,6 +991,15 @@ ssl_DestroySecurityInfo(sslSecurityInfo *sec)
|
| + {
|
| + ssl_ResetSecurityInfo(sec, PR_FALSE);
|
| +
|
| ++ if (sec->userName) {
|
| ++ SECITEM_FreeItem(sec->userName, PR_TRUE);
|
| ++ sec->userName = NULL;
|
| ++ }
|
| ++ if (sec->userPasswd) {
|
| ++ SECITEM_FreeItem(sec->userPasswd, PR_TRUE);
|
| ++ sec->userPasswd = NULL;
|
| ++ }
|
| ++
|
| + PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
|
| + sec->writeBuf.buf = 0;
|
| +
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
|
| +index b14a935..18ee612 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslsock.c
|
| ++++ b/mozilla/security/nss/lib/ssl/sslsock.c
|
| +@@ -102,6 +102,15 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */
|
| + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| + { TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| ++ { TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED },
|
| + { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED },
|
| + { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED },
|
| + #ifdef NSS_ENABLE_ECC
|
| +diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h
|
| +index 3fa3f9b..9cb000b 100644
|
| +--- a/mozilla/security/nss/lib/ssl/sslt.h
|
| ++++ b/mozilla/security/nss/lib/ssl/sslt.h
|
| +@@ -74,6 +74,9 @@ typedef enum {
|
| + ssl_kea_dh = 2,
|
| + ssl_kea_fortezza = 3, /* deprecated, now unused */
|
| + ssl_kea_ecdh = 4,
|
| ++ ssl_kea_srp = 5,
|
| ++ ssl_kea_srp_rsa = 6,
|
| ++ ssl_kea_srp_dss = 7,
|
| + ssl_kea_size /* number of ssl_kea_ algorithms */
|
| + } SSLKEAType;
|
| +
|
| +@@ -88,6 +91,7 @@ typedef enum {
|
| + #define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */
|
| + #define kt_ecdh ssl_kea_ecdh
|
| + #define kt_kea_size ssl_kea_size
|
| ++#define kt_srp ssl_kea_srp
|
| +
|
| + typedef enum {
|
| + ssl_sign_null = 0,
|
| +@@ -203,13 +207,14 @@ typedef enum {
|
| + ssl_elliptic_curves_xtn = 10,
|
| + ssl_ec_point_formats_xtn = 11,
|
| + #endif
|
| ++ ssl_srp_hello_xtn = 12,
|
| + ssl_session_ticket_xtn = 35,
|
| + ssl_next_proto_neg_xtn = 13172,
|
| + ssl_snap_start_xtn = 13174,
|
| + ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
|
| + } SSLExtensionType;
|
| +
|
| +-#define SSL_MAX_EXTENSIONS 8
|
| ++#define SSL_MAX_EXTENSIONS 9
|
| +
|
| + typedef enum {
|
| + /* No Snap Start handshake was attempted. */
|
|
|