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. */ |