| Index: net/third_party/nss/patches/tls12.patch
|
| ===================================================================
|
| --- net/third_party/nss/patches/tls12.patch (revision 0)
|
| +++ net/third_party/nss/patches/tls12.patch (revision 0)
|
| @@ -0,0 +1,1942 @@
|
| +Index: net/third_party/nss/ssl/sslt.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslt.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/sslt.h (working copy)
|
| +@@ -193,6 +193,7 @@
|
| + ssl_elliptic_curves_xtn = 10,
|
| + ssl_ec_point_formats_xtn = 11,
|
| + #endif
|
| ++ ssl_signature_algorithms_xtn = 13,
|
| + ssl_use_srtp_xtn = 14,
|
| + ssl_session_ticket_xtn = 35,
|
| + ssl_next_proto_nego_xtn = 13172,
|
| +@@ -200,6 +201,6 @@
|
| + ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
|
| + } SSLExtensionType;
|
| +
|
| +-#define SSL_MAX_EXTENSIONS 9
|
| ++#define SSL_MAX_EXTENSIONS 10
|
| +
|
| + #endif /* __sslt_h_ */
|
| +Index: net/third_party/nss/ssl/sslproto.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslproto.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/sslproto.h (working copy)
|
| +@@ -16,6 +16,7 @@
|
| + #define SSL_LIBRARY_VERSION_3_0 0x0300
|
| + #define SSL_LIBRARY_VERSION_TLS_1_0 0x0301
|
| + #define SSL_LIBRARY_VERSION_TLS_1_1 0x0302
|
| ++#define SSL_LIBRARY_VERSION_TLS_1_2 0x0303
|
| + /* Note: this is the internal format, not the wire format */
|
| + #define SSL_LIBRARY_VERSION_DTLS_1_0 0x0302
|
| +
|
| +Index: net/third_party/nss/ssl/SSLerrs.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/SSLerrs.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/SSLerrs.h (working copy)
|
| +@@ -412,3 +412,12 @@
|
| +
|
| + ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 128),
|
| + "The application could not get a TLS Channel ID.")
|
| ++
|
| ++ER3(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, (SSL_ERROR_BASE + 129),
|
| ++"Unsupported hash algorithm used by TLS peer.")
|
| ++
|
| ++ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR_BASE + 130),
|
| ++"Digest function failed.")
|
| ++
|
| ++ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 131),
|
| ++"Incorrect signature algorithm specified in a digitally-signed element.")
|
| +Index: net/third_party/nss/ssl/sslerr.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslerr.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/sslerr.h (working copy)
|
| +@@ -194,6 +194,10 @@
|
| + SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 127),
|
| + SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 128),
|
| +
|
| ++SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM = (SSL_ERROR_BASE + 129),
|
| ++SSL_ERROR_DIGEST_FAILURE = (SSL_ERROR_BASE + 130),
|
| ++SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 131),
|
| ++
|
| + SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
|
| + } SSLErrorCodes;
|
| + #endif /* NO_SECURITY_ERROR_ENUM */
|
| +Index: net/third_party/nss/ssl/sslimpl.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslimpl.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/sslimpl.h (working copy)
|
| +@@ -799,6 +799,7 @@
|
| + PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
|
| + PK11Context * md5; /* handshake running hashes */
|
| + PK11Context * sha;
|
| ++ PK11Context * tls12_handshake_hash;
|
| + const ssl3KEADef * kea_def;
|
| + ssl3CipherSuite cipher_suite;
|
| + const ssl3CipherSuiteDef *suite_def;
|
| +@@ -820,7 +821,7 @@
|
| + PRUint16 finishedBytes; /* size of single finished below */
|
| + union {
|
| + TLSFinished tFinished[2]; /* client, then server */
|
| +- SSL3Hashes sFinished[2];
|
| ++ SSL3Finished sFinished[2];
|
| + SSL3Opaque data[72];
|
| + } finishedMsgs;
|
| + #ifdef NSS_ENABLE_ECC
|
| +@@ -835,6 +836,12 @@
|
| + /* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
|
| + PRBool cacheSID;
|
| +
|
| ++ /* clientSigAndHash contains the contents of the signature_algorithms
|
| ++ * extension (if any) from the client. This is only valid for TLS 1.2
|
| ++ * or later. */
|
| ++ SSL3SignatureAndHashAlgorithm *clientSigAndHash;
|
| ++ unsigned int numClientSigAndHash;
|
| ++
|
| + /* This group of values is used for DTLS */
|
| + PRUint16 sendMessageSeq; /* The sending message sequence
|
| + * number */
|
| +@@ -1473,7 +1480,7 @@
|
| + * runtime to determine which versions are supported by the version of libssl
|
| + * in use.
|
| + */
|
| +-#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_1
|
| ++#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_2
|
| +
|
| + /* Rename this macro SSL_ALL_VERSIONS_DISABLED when SSL 2.0 is removed. */
|
| + #define SSL3_ALL_VERSIONS_DISABLED(vrange) \
|
| +@@ -1639,10 +1646,12 @@
|
| + SSL3Opaque *b, PRUint32 length,
|
| + SECKEYPublicKey *srvrPubKey,
|
| + SECKEYPrivateKey *srvrPrivKey);
|
| +-extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss);
|
| ++extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss,
|
| ++ const SSL3SignatureAndHashAlgorithm *sigAndHash);
|
| + #endif
|
| +
|
| +-extern SECStatus ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf,
|
| ++extern SECStatus ssl3_ComputeCommonKeyHash(SECOidTag hashAlg,
|
| ++ PRUint8 * hashBuf,
|
| + unsigned int bufLen, SSL3Hashes *hashes,
|
| + PRBool bypassPKCS11);
|
| + extern void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName);
|
| +@@ -1655,12 +1664,21 @@
|
| + PRInt32 lenSize);
|
| + extern SECStatus ssl3_AppendHandshakeVariable( sslSocket *ss,
|
| + const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize);
|
| ++extern SECStatus ssl3_AppendSignatureAndHashAlgorithm(sslSocket *ss,
|
| ++ const SSL3SignatureAndHashAlgorithm* sigAndHash);
|
| + extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes,
|
| + SSL3Opaque **b, PRUint32 *length);
|
| + extern PRInt32 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes,
|
| + SSL3Opaque **b, PRUint32 *length);
|
| + extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i,
|
| + PRInt32 bytes, SSL3Opaque **b, PRUint32 *length);
|
| ++extern SECOidTag ssl3_TLSHashAlgorithmToOID(int hashFunc);
|
| ++extern SECStatus ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ const SSL3SignatureAndHashAlgorithm *sigAndHash,
|
| ++ CERTCertificate* cert);
|
| ++extern SECStatus ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
|
| ++ SSL3Opaque **b, PRUint32 *length,
|
| ++ SSL3SignatureAndHashAlgorithm *out);
|
| + extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key,
|
| + SECItem *buf, PRBool isTLS);
|
| + extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash,
|
| +Index: net/third_party/nss/ssl/ssl3prot.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3prot.h (revision 202696)
|
| ++++ net/third_party/nss/ssl/ssl3prot.h (working copy)
|
| +@@ -212,11 +212,51 @@
|
| + } u;
|
| + } SSL3ServerParams;
|
| +
|
| ++/* This enum reflects HashAlgorithm enum from
|
| ++ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
|
| ++ *
|
| ++ * When updating, be sure to also update ssl3_TLSHashAlgorithmToOID. */
|
| ++enum {
|
| ++ tls_hash_md5 = 1,
|
| ++ tls_hash_sha1 = 2,
|
| ++ tls_hash_sha224 = 3,
|
| ++ tls_hash_sha256 = 4,
|
| ++ tls_hash_sha384 = 5,
|
| ++ tls_hash_sha512 = 6
|
| ++};
|
| ++
|
| ++/* This enum reflects SignatureAlgorithm enum from
|
| ++ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++typedef enum {
|
| ++ tls_sig_rsa = 1,
|
| ++ tls_sig_dsa = 2,
|
| ++ tls_sig_ecdsa = 3
|
| ++} TLSSignatureAlgorithm;
|
| ++
|
| + typedef struct {
|
| ++ SECOidTag hashAlg;
|
| ++ TLSSignatureAlgorithm sigAlg;
|
| ++} SSL3SignatureAndHashAlgorithm;
|
| ++
|
| ++/* SSL3HashesIndividually contains a combination MD5/SHA1 hash, as used in TLS
|
| ++ * prior to 1.2. */
|
| ++typedef struct {
|
| + uint8 md5[16];
|
| + uint8 sha[20];
|
| ++} SSL3HashesIndividually;
|
| ++
|
| ++/* SSL3Hashes contains an SSL hash value. The digest is contained in |u.raw|
|
| ++ * which, if |hashAlg==SEC_OID_UNKNOWN| is also a SSL3HashesIndividually
|
| ++ * struct. */
|
| ++typedef struct {
|
| ++ unsigned int len;
|
| ++ SECOidTag hashAlg;
|
| ++ union {
|
| ++ PRUint8 raw[64];
|
| ++ SSL3HashesIndividually s;
|
| ++ } u;
|
| + } SSL3Hashes;
|
| +-
|
| ++
|
| + typedef struct {
|
| + union {
|
| + SSL3Opaque anonymous;
|
| +@@ -274,7 +314,7 @@
|
| + sender_server = 0x53525652
|
| + } SSL3Sender;
|
| +
|
| +-typedef SSL3Hashes SSL3Finished;
|
| ++typedef SSL3HashesIndividually SSL3Finished;
|
| +
|
| + typedef struct {
|
| + SSL3Opaque verify_data[12];
|
| +Index: net/third_party/nss/ssl/ssl3ecc.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3ecc.c (revision 202696)
|
| ++++ net/third_party/nss/ssl/ssl3ecc.c (working copy)
|
| +@@ -217,9 +223,10 @@
|
| +
|
| + /* Caller must set hiLevel error code. */
|
| + static SECStatus
|
| +-ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
|
| +- SSL3Random *client_rand, SSL3Random *server_rand,
|
| +- SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| ++ssl3_ComputeECDHKeyHash(SECOidTag hashAlg,
|
| ++ SECItem ec_params, SECItem server_ecpoint,
|
| ++ SSL3Random *client_rand, SSL3Random *server_rand,
|
| ++ SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| + {
|
| + PRUint8 * hashBuf;
|
| + PRUint8 * pBuf;
|
| +@@ -255,11 +262,14 @@
|
| + pBuf += server_ecpoint.len;
|
| + PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
|
| +
|
| +- rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
|
| ++ rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
|
| ++ bypassPKCS11);
|
| +
|
| + PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
|
| +- PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
|
| +- PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
|
| ++ PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result",
|
| ++ hashes->u.s.md5, MD5_LENGTH));
|
| ++ PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result",
|
| ++ hashes->u.s.sha, SHA1_LENGTH));
|
| +
|
| + if (hashBuf != buf)
|
| + PORT_Free(hashBuf);
|
| +@@ -273,7 +283,7 @@
|
| + {
|
| + PK11SymKey * pms = NULL;
|
| + SECStatus rv = SECFailure;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| + CK_MECHANISM_TYPE target;
|
| + SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */
|
| + SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
|
| +@@ -282,6 +292,7 @@
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
|
| +
|
| + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| +
|
| + /* Generate ephemeral EC keypair */
|
| + if (svrPubKey->keyType != ecKey) {
|
| +@@ -300,8 +311,13 @@
|
| + pubKey->u.ec.publicValue.data,
|
| + pubKey->u.ec.publicValue.len));
|
| +
|
| +- if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
| +- else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
| ++ if (isTLS12) {
|
| ++ target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
|
| ++ } else if (isTLS) {
|
| ++ target = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
| ++ } else {
|
| ++ target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
| ++ }
|
| +
|
| + /* Determine the PMS */
|
| + pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
|
| +@@ -365,7 +381,7 @@
|
| + SECStatus rv;
|
| + SECKEYPublicKey clntPubKey;
|
| + CK_MECHANISM_TYPE target;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| +
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| +@@ -384,9 +400,15 @@
|
| + }
|
| +
|
| + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| +
|
| +- if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
| +- else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
| ++ if (isTLS12) {
|
| ++ target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
|
| ++ } else if (isTLS) {
|
| ++ target = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
| ++ } else {
|
| ++ target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
| ++ }
|
| +
|
| + /* Determine the PMS */
|
| + pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
|
| +@@ -582,7 +604,7 @@
|
| + {
|
| + PRArenaPool * arena = NULL;
|
| + SECKEYPublicKey *peerKey = NULL;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| + SECStatus rv;
|
| + int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
|
| + SSL3AlertDescription desc = illegal_parameter;
|
| +@@ -592,8 +614,12 @@
|
| + SECItem ec_params = {siBuffer, NULL, 0};
|
| + SECItem ec_point = {siBuffer, NULL, 0};
|
| + unsigned char paramBuf[3]; /* only for curve_type == named_curve */
|
| ++ SSL3SignatureAndHashAlgorithm sigAndHash;
|
| +
|
| ++ sigAndHash.hashAlg = SEC_OID_UNKNOWN;
|
| ++
|
| + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| +
|
| + /* XXX This works only for named curves, revisit this when
|
| + * we support generic curves.
|
| +@@ -625,6 +651,19 @@
|
| + goto alert_loser;
|
| + }
|
| +
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
|
| ++ &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed or unsupported. */
|
| ++ }
|
| ++ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ &sigAndHash, ss->sec.peerCert);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser;
|
| ++ }
|
| ++ }
|
| ++
|
| + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
|
| + if (rv != SECSuccess) {
|
| + goto loser; /* malformed. */
|
| +@@ -647,10 +686,10 @@
|
| + /*
|
| + * check to make sure the hash is signed by right guy
|
| + */
|
| +- rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,
|
| +- &ss->ssl3.hs.client_random,
|
| +- &ss->ssl3.hs.server_random,
|
| +- &hashes, ss->opt.bypassPKCS11);
|
| ++ rv = ssl3_ComputeECDHKeyHash(sigAndHash.hashAlg, ec_params, ec_point,
|
| ++ &ss->ssl3.hs.client_random,
|
| ++ &ss->ssl3.hs.server_random,
|
| ++ &hashes, ss->opt.bypassPKCS11);
|
| +
|
| + if (rv != SECSuccess) {
|
| + errCode =
|
| +@@ -714,12 +753,14 @@
|
| + }
|
| +
|
| + SECStatus
|
| +-ssl3_SendECDHServerKeyExchange(sslSocket *ss)
|
| ++ssl3_SendECDHServerKeyExchange(
|
| ++ sslSocket *ss,
|
| ++ const SSL3SignatureAndHashAlgorithm *sigAndHash)
|
| + {
|
| +-const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
|
| ++ const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
|
| + SECStatus rv = SECFailure;
|
| + int length;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| + SECItem signed_hash = {siBuffer, NULL, 0};
|
| + SSL3Hashes hashes;
|
| +
|
| +@@ -729,7 +770,6 @@
|
| + ECName curve;
|
| + SSL3KEAType certIndex;
|
| +
|
| +-
|
| + /* Generate ephemeral ECDH key pair and send the public key */
|
| + curve = ssl3_GetCurveNameForServerSocket(ss);
|
| + if (curve == ec_noName) {
|
| +@@ -758,16 +798,19 @@
|
| + goto loser;
|
| + }
|
| +
|
| +- rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue,
|
| +- &ss->ssl3.hs.client_random,
|
| +- &ss->ssl3.hs.server_random,
|
| +- &hashes, ss->opt.bypassPKCS11);
|
| ++ rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg,
|
| ++ ec_params,
|
| ++ ecdhePub->u.ec.publicValue,
|
| ++ &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;
|
| + }
|
| +
|
| + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| +
|
| + /* XXX SSLKEAType isn't really a good choice for
|
| + * indexing certificates but that's all we have
|
| +@@ -791,7 +834,7 @@
|
| +
|
| + length = ec_params.len +
|
| + 1 + ecdhePub->u.ec.publicValue.len +
|
| +- 2 + signed_hash.len;
|
| ++ (isTLS12 ? 2 : 0) + 2 + signed_hash.len;
|
| +
|
| + rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
|
| + if (rv != SECSuccess) {
|
| +@@ -809,6 +852,13 @@
|
| + goto loser; /* err set by AppendHandshake. */
|
| + }
|
| +
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* err set by AppendHandshake. */
|
| ++ }
|
| ++ }
|
| ++
|
| + rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
|
| + signed_hash.len, 2);
|
| + if (rv != SECSuccess) {
|
| +Index: net/third_party/nss/ssl/ssl3ext.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3ext.c (revision 202696)
|
| ++++ net/third_party/nss/ssl/ssl3ext.c (working copy)
|
| +@@ -74,6 +74,10 @@
|
| + SECItem *data);
|
| + static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
|
| + PRUint32 maxBytes);
|
| ++static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
|
| ++ PRUint32 maxBytes);
|
| ++static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
|
| ++ SECItem *data);
|
| +
|
| + /*
|
| + * Write bytes. Using this function means the SECItem structure
|
| +@@ -236,6 +240,7 @@
|
| + { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
|
| + { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
|
| + { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
|
| ++ { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
|
| + { -1, NULL }
|
| + };
|
| +
|
| +@@ -276,7 +281,8 @@
|
| + { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
|
| + { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
|
| + { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
|
| +- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }
|
| ++ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
|
| ++ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
|
| + /* any extra entries will appear as { 0, NULL } */
|
| + };
|
| +
|
| +@@ -2039,3 +2045,134 @@
|
| + return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn,
|
| + ssl3_SendUseSRTPXtn);
|
| + }
|
| ++
|
| ++/* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension
|
| ++ * from a client.
|
| ++ * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++static SECStatus
|
| ++ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| ++{
|
| ++ SECStatus rv;
|
| ++ SECItem algorithms;
|
| ++ const unsigned char *b;
|
| ++ unsigned int numAlgorithms, i;
|
| ++
|
| ++ /* Ignore this extension if we aren't doing TLS 1.2 or greater. */
|
| ++ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ return SECSuccess;
|
| ++ }
|
| ++
|
| ++ /* Keep track of negotiated extensions. */
|
| ++ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
|
| ++
|
| ++ rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &data->data,
|
| ++ &data->len);
|
| ++ if (rv != SECSuccess) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++ /* Trailing data or odd-length parameters is invalid. */
|
| ++ if (data->len != 0 || (algorithms.len & 1) != 0) {
|
| ++ PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ numAlgorithms = algorithms.len/2;
|
| ++
|
| ++ if (numAlgorithms == 0) {
|
| ++ return SECSuccess;
|
| ++ }
|
| ++ /* We don't care to process excessive numbers of algorithms. */
|
| ++ if (numAlgorithms > 512) {
|
| ++ numAlgorithms = 512;
|
| ++ }
|
| ++
|
| ++ ss->ssl3.hs.clientSigAndHash =
|
| ++ PORT_NewArray(SSL3SignatureAndHashAlgorithm, numAlgorithms);
|
| ++ if (!ss->ssl3.hs.clientSigAndHash) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++ ss->ssl3.hs.numClientSigAndHash = 0;
|
| ++
|
| ++ b = algorithms.data;
|
| ++ for (i = 0; i < numAlgorithms; i++) {
|
| ++ unsigned char tls_hash = *(b++);
|
| ++ unsigned char tls_sig = *(b++);
|
| ++ SECOidTag hash = ssl3_TLSHashAlgorithmToOID(tls_hash);
|
| ++
|
| ++ if (hash == SEC_OID_UNKNOWN) {
|
| ++ /* We ignore formats that we don't understand. */
|
| ++ continue;
|
| ++ }
|
| ++ /* tls_sig support will be checked later in
|
| ++ * ssl3_PickSignatureHashAlgorithm. */
|
| ++ ss->ssl3.hs.clientSigAndHash[i].hashAlg = hash;
|
| ++ ss->ssl3.hs.clientSigAndHash[i].sigAlg = tls_sig;
|
| ++ ss->ssl3.hs.numClientSigAndHash++;
|
| ++ }
|
| ++
|
| ++ if (!ss->ssl3.hs.numClientSigAndHash) {
|
| ++ /* We didn't understand any of the client's requested signature
|
| ++ * formats. We'll use the defaults. */
|
| ++ PORT_Free(ss->ssl3.hs.clientSigAndHash);
|
| ++ ss->ssl3.hs.clientSigAndHash = NULL;
|
| ++ }
|
| ++
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| ++/* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS
|
| ++ * 1.2 ClientHellos. */
|
| ++static PRInt32
|
| ++ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| ++{
|
| ++ static const unsigned char signatureAlgorithms[] = {
|
| ++ /* This block is the contents of our signature_algorithms extension, in
|
| ++ * wire format. See
|
| ++ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++ tls_hash_sha256, tls_sig_rsa,
|
| ++ tls_hash_sha384, tls_sig_rsa,
|
| ++ tls_hash_sha1, tls_sig_rsa,
|
| ++#ifdef NSS_ENABLE_ECC
|
| ++ tls_hash_sha256, tls_sig_ecdsa,
|
| ++ tls_hash_sha384, tls_sig_ecdsa,
|
| ++ tls_hash_sha1, tls_sig_ecdsa,
|
| ++#endif
|
| ++ tls_hash_sha256, tls_sig_dsa,
|
| ++ tls_hash_sha1, tls_sig_dsa,
|
| ++ };
|
| ++ PRInt32 extension_length;
|
| ++
|
| ++ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ return 0;
|
| ++ }
|
| ++
|
| ++ extension_length =
|
| ++ 2 /* extension type */ +
|
| ++ 2 /* extension length */ +
|
| ++ 2 /* supported_signature_algorithms length */ +
|
| ++ sizeof(signatureAlgorithms);
|
| ++
|
| ++ if (append && maxBytes >= extension_length) {
|
| ++ SECStatus rv;
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2);
|
| ++ if (rv != SECSuccess)
|
| ++ goto loser;
|
| ++ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
|
| ++ if (rv != SECSuccess)
|
| ++ goto loser;
|
| ++ rv = ssl3_AppendHandshakeVariable(ss, signatureAlgorithms,
|
| ++ sizeof(signatureAlgorithms), 2);
|
| ++ if (rv != SECSuccess)
|
| ++ goto loser;
|
| ++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ++ ssl_signature_algorithms_xtn;
|
| ++ } else if (maxBytes < extension_length) {
|
| ++ PORT_Assert(0);
|
| ++ return 0;
|
| ++ }
|
| ++
|
| ++ return extension_length;
|
| ++
|
| ++loser:
|
| ++ return -1;
|
| ++}
|
| +Index: net/third_party/nss/ssl/sslsock.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslsock.c (revision 202696)
|
| ++++ net/third_party/nss/ssl/sslsock.c (working copy)
|
| +@@ -782,6 +789,17 @@
|
| + rv = SECFailure;
|
| + } else {
|
| + if (PR_FALSE != on) {
|
| ++ /* TLS 1.2 isn't supported in bypass mode. */
|
| ++ if (ss->vrange.min >= SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ /* If the user requested a minimum version of TLS 1.2 then
|
| ++ * we don't silently downgrade. */
|
| ++ PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
|
| ++ rv = SECFailure;
|
| ++ break;
|
| ++ }
|
| ++ if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ ss->vrange.max = SSL_LIBRARY_VERSION_TLS_1_1;
|
| ++ }
|
| + if (PR_SUCCESS == SSL_BypassSetup() ) {
|
| + #ifdef NO_PKCS11_BYPASS
|
| + ss->opt.bypassPKCS11 = PR_FALSE;
|
| +Index: net/third_party/nss/ssl/ssl3con.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3con.c (revision 202696)
|
| ++++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| +@@ -15,6 +15,7 @@
|
| + #include "keyhi.h"
|
| + #include "secder.h"
|
| + #include "secitem.h"
|
| ++#include "sechash.h"
|
| +
|
| + #include "sslimpl.h"
|
| + #include "sslproto.h"
|
| +@@ -64,6 +74,7 @@
|
| + const unsigned char *b,
|
| + unsigned int l);
|
| + static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
|
| ++static int ssl3_OIDToTLSHashAlgorithm(SECOidTag oid);
|
| +
|
| + static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
|
| + int maxOutputLen, const unsigned char *input,
|
| +@@ -811,32 +822,36 @@
|
| + SECItem hashItem;
|
| +
|
| + buf->data = NULL;
|
| +- signatureLen = PK11_SignatureLen(key);
|
| +- if (signatureLen <= 0) {
|
| +- PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| +- goto done;
|
| +- }
|
| +
|
| +- buf->len = (unsigned)signatureLen;
|
| +- buf->data = (unsigned char *)PORT_Alloc(signatureLen);
|
| +- if (!buf->data)
|
| +- goto done; /* error code was set. */
|
| +-
|
| + switch (key->keyType) {
|
| + case rsaKey:
|
| +- hashItem.data = hash->md5;
|
| +- hashItem.len = sizeof(SSL3Hashes);
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| + break;
|
| + case dsaKey:
|
| + doDerEncode = isTLS;
|
| +- hashItem.data = hash->sha;
|
| +- hashItem.len = sizeof(hash->sha);
|
| ++ /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
|
| ++ * In that case, we use just the SHA1 part. */
|
| ++ if (hash->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ hashItem.data = hash->u.s.sha;
|
| ++ hashItem.len = sizeof(hash->u.s.sha);
|
| ++ } else {
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| ++ }
|
| + break;
|
| + #ifdef NSS_ENABLE_ECC
|
| + case ecKey:
|
| + doDerEncode = PR_TRUE;
|
| +- hashItem.data = hash->sha;
|
| +- hashItem.len = sizeof(hash->sha);
|
| ++ /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
|
| ++ * In that case, we use just the SHA1 part. */
|
| ++ if (hash->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ hashItem.data = hash->u.s.sha;
|
| ++ hashItem.len = sizeof(hash->u.s.sha);
|
| ++ } else {
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| ++ }
|
| + break;
|
| + #endif /* NSS_ENABLE_ECC */
|
| + default:
|
| +@@ -845,7 +860,22 @@
|
| + }
|
| + PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
|
| +
|
| +- rv = PK11_Sign(key, buf, &hashItem);
|
| ++ if (hash->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ signatureLen = PK11_SignatureLen(key);
|
| ++ if (signatureLen <= 0) {
|
| ++ PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| ++ goto done;
|
| ++ }
|
| ++
|
| ++ buf->len = (unsigned)signatureLen;
|
| ++ buf->data = (unsigned char *)PORT_Alloc(signatureLen);
|
| ++ if (!buf->data)
|
| ++ goto done; /* error code was set. */
|
| ++
|
| ++ rv = PK11_Sign(key, buf, &hashItem);
|
| ++ } else {
|
| ++ rv = SGN_Digest(key, hash->hashAlg, buf, &hashItem);
|
| ++ }
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
|
| + } else if (doDerEncode) {
|
| +@@ -879,9 +909,8 @@
|
| + SECItem * signature = NULL;
|
| + SECStatus rv;
|
| + SECItem hashItem;
|
| +-#ifdef NSS_ENABLE_ECC
|
| +- unsigned int len;
|
| +-#endif /* NSS_ENABLE_ECC */
|
| ++ SECOidTag encAlg;
|
| ++ SECOidTag hashAlg;
|
| +
|
| +
|
| + PRINT_BUF(60, (NULL, "check signed hashes",
|
| +@@ -893,14 +922,24 @@
|
| + return SECFailure;
|
| + }
|
| +
|
| ++ hashAlg = hash->hashAlg;
|
| + switch (key->keyType) {
|
| + case rsaKey:
|
| +- hashItem.data = hash->md5;
|
| +- hashItem.len = sizeof(SSL3Hashes);
|
| ++ encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| + break;
|
| + case dsaKey:
|
| +- hashItem.data = hash->sha;
|
| +- hashItem.len = sizeof(hash->sha);
|
| ++ encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
|
| ++ /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
|
| ++ * In that case, we use just the SHA1 part. */
|
| ++ if (hash->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ hashItem.data = hash->u.s.sha;
|
| ++ hashItem.len = sizeof(hash->u.s.sha);
|
| ++ } else {
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| ++ }
|
| + /* Allow DER encoded DSA signatures in SSL 3.0 */
|
| + if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
|
| + signature = DSAU_DecodeDerSig(buf);
|
| +@@ -914,25 +953,21 @@
|
| +
|
| + #ifdef NSS_ENABLE_ECC
|
| + case ecKey:
|
| +- hashItem.data = hash->sha;
|
| +- hashItem.len = sizeof(hash->sha);
|
| +- /*
|
| +- * ECDSA signatures always encode the integers r and s
|
| +- * using ASN (unlike DSA where ASN encoding is used
|
| +- * with TLS but not with SSL3)
|
| ++ encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
| ++ /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash.
|
| ++ * In that case, we use just the SHA1 part.
|
| ++ * ECDSA signatures always encode the integers r and s using ASN.1
|
| ++ * (unlike DSA where ASN.1 encoding is used with TLS but not with
|
| ++ * SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
|
| + */
|
| +- len = SECKEY_SignatureLen(key);
|
| +- if (len == 0) {
|
| +- SECKEY_DestroyPublicKey(key);
|
| +- PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
| +- return SECFailure;
|
| ++ if (hash->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ hashAlg = SEC_OID_SHA1;
|
| ++ hashItem.data = hash->u.s.sha;
|
| ++ hashItem.len = sizeof(hash->u.s.sha);
|
| ++ } else {
|
| ++ hashItem.data = hash->u.raw;
|
| ++ hashItem.len = hash->len;
|
| + }
|
| +- signature = DSAU_DecodeDerSigToLen(buf, len);
|
| +- if (!signature) {
|
| +- PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
|
| +- return SECFailure;
|
| +- }
|
| +- buf = signature;
|
| + break;
|
| + #endif /* NSS_ENABLE_ECC */
|
| +
|
| +@@ -945,7 +980,17 @@
|
| + PRINT_BUF(60, (NULL, "hash(es) to be verified",
|
| + hashItem.data, hashItem.len));
|
| +
|
| +- rv = PK11_Verify(key, buf, &hashItem, pwArg);
|
| ++ if (hashAlg == SEC_OID_UNKNOWN || key->keyType == dsaKey) {
|
| ++ /* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
|
| ++ * DSA signatures are DER-encoded in TLS but not in SSL3 and the code
|
| ++ * above always removes the DER encoding of DSA signatures when
|
| ++ * present. Thus DSA signatures are always verified with PK11_Verify.
|
| ++ */
|
| ++ rv = PK11_Verify(key, buf, &hashItem, pwArg);
|
| ++ } else {
|
| ++ rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
|
| ++ pwArg);
|
| ++ }
|
| + SECKEY_DestroyPublicKey(key);
|
| + if (signature) {
|
| + SECITEM_FreeItem(signature, PR_TRUE);
|
| +@@ -961,33 +1006,69 @@
|
| + /* Called from ssl3_ComputeExportRSAKeyHash
|
| + * ssl3_ComputeDHKeyHash
|
| + * which are called from ssl3_HandleServerKeyExchange.
|
| ++ *
|
| ++ * hashAlg: either the OID for a hash algorithm or SEC_OID_UNKNOWN to specify
|
| ++ * the pre-1.2, MD5/SHA1 combination hash.
|
| + */
|
| + SECStatus
|
| +-ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf, unsigned int bufLen,
|
| +- SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| ++ssl3_ComputeCommonKeyHash(SECOidTag hashAlg,
|
| ++ PRUint8 * hashBuf, unsigned int bufLen,
|
| ++ SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| + {
|
| + SECStatus rv = SECSuccess;
|
| +
|
| + #ifndef NO_PKCS11_BYPASS
|
| + if (bypassPKCS11) {
|
| +- MD5_HashBuf (hashes->md5, hashBuf, bufLen);
|
| +- SHA1_HashBuf(hashes->sha, hashBuf, bufLen);
|
| ++ if (hashAlg == SEC_OID_UNKNOWN) {
|
| ++ MD5_HashBuf (hashes->u.s.md5, hashBuf, bufLen);
|
| ++ SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen);
|
| ++ hashes->len = MD5_LENGTH + SHA1_LENGTH;
|
| ++ } else if (hashAlg == SEC_OID_SHA1) {
|
| ++ SHA1_HashBuf(hashes->u.raw, hashBuf, bufLen);
|
| ++ hashes->len = SHA1_LENGTH;
|
| ++ } else if (hashAlg == SEC_OID_SHA256) {
|
| ++ SHA256_HashBuf(hashes->u.raw, hashBuf, bufLen);
|
| ++ hashes->len = SHA256_LENGTH;
|
| ++ } else if (hashAlg == SEC_OID_SHA384) {
|
| ++ SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen);
|
| ++ hashes->len = SHA384_LENGTH;
|
| ++ } else {
|
| ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
|
| ++ return SECFailure;
|
| ++ }
|
| + } else
|
| + #endif
|
| + {
|
| +- rv = PK11_HashBuf(SEC_OID_MD5, hashes->md5, hashBuf, bufLen);
|
| +- if (rv != SECSuccess) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| +- rv = SECFailure;
|
| +- goto done;
|
| +- }
|
| ++ if (hashAlg == SEC_OID_UNKNOWN) {
|
| ++ rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ goto done;
|
| ++ }
|
| +
|
| +- rv = PK11_HashBuf(SEC_OID_SHA1, hashes->sha, hashBuf, bufLen);
|
| +- if (rv != SECSuccess) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| +- rv = SECFailure;
|
| ++ rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ }
|
| ++ hashes->len = MD5_LENGTH + SHA1_LENGTH;
|
| ++ } else {
|
| ++ hashes->len = HASH_ResultLenByOidTag(hashAlg);
|
| ++ if (hashes->len > sizeof(hashes->u.raw)) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
|
| ++ rv = SECFailure;
|
| ++ goto done;
|
| ++ }
|
| ++ rv = PK11_HashBuf(hashAlg, hashes->u.raw, hashBuf, bufLen);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ }
|
| + }
|
| + }
|
| ++ hashes->hashAlg = hashAlg;
|
| ++
|
| + done:
|
| + return rv;
|
| + }
|
| +@@ -997,7 +1078,8 @@
|
| + ** ssl3_HandleServerKeyExchange.
|
| + */
|
| + static SECStatus
|
| +-ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem publicExponent,
|
| ++ssl3_ComputeExportRSAKeyHash(SECOidTag hashAlg,
|
| ++ SECItem modulus, SECItem publicExponent,
|
| + SSL3Random *client_rand, SSL3Random *server_rand,
|
| + SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| + {
|
| +@@ -1033,11 +1115,19 @@
|
| + pBuf += publicExponent.len;
|
| + PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
|
| +
|
| +- rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
|
| ++ rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
|
| ++ bypassPKCS11);
|
| +
|
| + PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
|
| +- PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result", hashes->md5, MD5_LENGTH));
|
| +- PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
|
| ++ if (hashAlg == SEC_OID_UNKNOWN) {
|
| ++ PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
|
| ++ hashes->u.s.md5, MD5_LENGTH));
|
| ++ PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
|
| ++ hashes->u.s.sha, SHA1_LENGTH));
|
| ++ } else {
|
| ++ PRINT_BUF(95, (NULL, "RSAkey hash: result",
|
| ++ hashes->u.raw, hashes->len));
|
| ++ }
|
| +
|
| + if (hashBuf != buf && hashBuf != NULL)
|
| + PORT_Free(hashBuf);
|
| +@@ -1047,9 +1137,10 @@
|
| + /* Caller must set hiLevel error code. */
|
| + /* Called from ssl3_HandleServerKeyExchange. */
|
| + static SECStatus
|
| +-ssl3_ComputeDHKeyHash(SECItem dh_p, SECItem dh_g, SECItem dh_Ys,
|
| +- SSL3Random *client_rand, SSL3Random *server_rand,
|
| +- SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| ++ssl3_ComputeDHKeyHash(SECOidTag hashAlg,
|
| ++ SECItem dh_p, SECItem dh_g, SECItem dh_Ys,
|
| ++ SSL3Random *client_rand, SSL3Random *server_rand,
|
| ++ SSL3Hashes *hashes, PRBool bypassPKCS11)
|
| + {
|
| + PRUint8 * hashBuf;
|
| + PRUint8 * pBuf;
|
| +@@ -1088,11 +1179,19 @@
|
| + pBuf += dh_Ys.len;
|
| + PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
|
| +
|
| +- rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
|
| ++ rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
|
| ++ bypassPKCS11);
|
| +
|
| + PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen));
|
| +- PRINT_BUF(95, (NULL, "DHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
|
| +- PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
|
| ++ if (hashAlg == SEC_OID_UNKNOWN) {
|
| ++ PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
|
| ++ hashes->u.s.md5, MD5_LENGTH));
|
| ++ PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
|
| ++ hashes->u.s.sha, SHA1_LENGTH));
|
| ++ } else {
|
| ++ PRINT_BUF(95, (NULL, "DHkey hash: result",
|
| ++ hashes->u.raw, hashes->len));
|
| ++ }
|
| +
|
| + if (hashBuf != buf && hashBuf != NULL)
|
| + PORT_Free(hashBuf);
|
| +@@ -3190,6 +3289,8 @@
|
| + unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
|
| + PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
|
| + (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
|
| ++ PRBool isTLS12=
|
| ++ (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| + /*
|
| + * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
|
| + * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
|
| +@@ -3208,7 +3309,12 @@
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
|
| + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
|
| +- if (isTLS) {
|
| ++ if (isTLS12) {
|
| ++ if(isDH) master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
|
| ++ else master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256;
|
| ++ key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
|
| ++ keyFlags = CKF_SIGN | CKF_VERIFY;
|
| ++ } else if (isTLS) {
|
| + if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
| + else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
|
| + key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
|
| +@@ -3366,6 +3472,8 @@
|
| + unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
|
| + PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
|
| + (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
|
| ++ PRBool isTLS12=
|
| ++ (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| + /* following variables used in PKCS11 path */
|
| + const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
|
| + PK11SlotInfo * slot = NULL;
|
| +@@ -3423,7 +3531,9 @@
|
| + params.data = (unsigned char *)&key_material_params;
|
| + params.len = sizeof(key_material_params);
|
| +
|
| +- if (isTLS) {
|
| ++ if (isTLS12) {
|
| ++ key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
|
| ++ } else if (isTLS) {
|
| + key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
|
| + } else {
|
| + key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
|
| +@@ -3480,19 +3590,63 @@
|
| + return SECFailure;
|
| + }
|
| +
|
| ++/* ssl3_InitTLS12HandshakeHash creates a handshake hash context for TLS 1.2,
|
| ++ * if needed, and hashes in any buffered messages in ss->ssl3.hs.messages. */
|
| ++static SECStatus
|
| ++ssl3_InitTLS12HandshakeHash(sslSocket *ss)
|
| ++{
|
| ++ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2 &&
|
| ++ ss->ssl3.hs.tls12_handshake_hash == NULL) {
|
| ++ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
|
| ++ * then this will need to be updated. */
|
| ++ ss->ssl3.hs.tls12_handshake_hash =
|
| ++ PK11_CreateDigestContext(SEC_OID_SHA256);
|
| ++ if (!ss->ssl3.hs.tls12_handshake_hash ||
|
| ++ PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash) != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ }
|
| ++
|
| ++ if (ss->ssl3.hs.tls12_handshake_hash && ss->ssl3.hs.messages.len > 0) {
|
| ++ if (PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash,
|
| ++ ss->ssl3.hs.messages.buf,
|
| ++ ss->ssl3.hs.messages.len) != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ }
|
| ++
|
| ++ if (ss->ssl3.hs.messages.buf && !ss->opt.bypassPKCS11) {
|
| ++ PORT_Free(ss->ssl3.hs.messages.buf);
|
| ++ ss->ssl3.hs.messages.buf = NULL;
|
| ++ ss->ssl3.hs.messages.len = 0;
|
| ++ ss->ssl3.hs.messages.space = 0;
|
| ++ }
|
| ++
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| + static SECStatus
|
| + ssl3_RestartHandshakeHashes(sslSocket *ss)
|
| + {
|
| + SECStatus rv = SECSuccess;
|
| +
|
| ++ ss->ssl3.hs.messages.len = 0;
|
| + #ifndef NO_PKCS11_BYPASS
|
| + if (ss->opt.bypassPKCS11) {
|
| +- ss->ssl3.hs.messages.len = 0;
|
| + MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
|
| + SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
|
| + } else
|
| + #endif
|
| + {
|
| ++ if (ss->ssl3.hs.tls12_handshake_hash) {
|
| ++ rv = PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ return rv;
|
| ++ }
|
| ++ }
|
| + rv = PK11_DigestBegin(ss->ssl3.hs.md5);
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| +@@ -3519,25 +3673,21 @@
|
| + * that the master secret will wind up in ...
|
| + */
|
| + SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
|
| +-#ifndef NO_PKCS11_BYPASS
|
| +- if (ss->opt.bypassPKCS11) {
|
| +- PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
|
| +- ss->ssl3.hs.messages.buf = NULL;
|
| +- ss->ssl3.hs.messages.space = 0;
|
| +- } else
|
| +-#endif
|
| +- {
|
| +- ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5);
|
| +- ss->ssl3.hs.sha = sha = PK11_CreateDigestContext(SEC_OID_SHA1);
|
| +- if (md5 == NULL) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| +- goto loser;
|
| +- }
|
| +- if (sha == NULL) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| +- goto loser;
|
| +- }
|
| ++ PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
|
| ++ ss->ssl3.hs.messages.buf = NULL;
|
| ++ ss->ssl3.hs.messages.space = 0;
|
| ++
|
| ++ ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5);
|
| ++ ss->ssl3.hs.sha = sha = PK11_CreateDigestContext(SEC_OID_SHA1);
|
| ++ ss->ssl3.hs.tls12_handshake_hash = NULL;
|
| ++ if (md5 == NULL) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| ++ goto loser;
|
| + }
|
| ++ if (sha == NULL) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ goto loser;
|
| ++ }
|
| + if (SECSuccess == ssl3_RestartHandshakeHashes(ss)) {
|
| + return SECSuccess;
|
| + }
|
| +@@ -3574,6 +3724,17 @@
|
| +
|
| + PRINT_BUF(90, (NULL, "MD5 & SHA handshake hash input:", b, l));
|
| +
|
| ++ if ((ss->version == 0 || ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) &&
|
| ++ !ss->opt.bypassPKCS11 &&
|
| ++ ss->ssl3.hs.tls12_handshake_hash == NULL) {
|
| ++ /* For TLS 1.2 connections we need to buffer the handshake messages
|
| ++ * until we have established which PRF hash function to use. */
|
| ++ rv = sslBuffer_Append(&ss->ssl3.hs.messages, b, l);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv;
|
| ++ }
|
| ++ }
|
| ++
|
| + #ifndef NO_PKCS11_BYPASS
|
| + if (ss->opt.bypassPKCS11) {
|
| + MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l);
|
| +@@ -3584,16 +3745,24 @@
|
| + return rv;
|
| + }
|
| + #endif
|
| +- rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
|
| +- if (rv != SECSuccess) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| +- return rv;
|
| ++ if (ss->ssl3.hs.tls12_handshake_hash) {
|
| ++ rv = PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash, b, l);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ return rv;
|
| ++ }
|
| ++ } else {
|
| ++ rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| ++ return rv;
|
| ++ }
|
| ++ rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ return rv;
|
| ++ }
|
| + }
|
| +- rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
|
| +- if (rv != SECSuccess) {
|
| +- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| +- return rv;
|
| +- }
|
| + return rv;
|
| + }
|
| +
|
| +@@ -3744,6 +3913,25 @@
|
| + return rv; /* error code set by AppendHandshake, if applicable. */
|
| + }
|
| +
|
| ++/* ssl3_AppendSignatureAndHashAlgorithm appends the serialisation of
|
| ++ * |sigAndHash| to the current handshake message. */
|
| ++SECStatus
|
| ++ssl3_AppendSignatureAndHashAlgorithm(
|
| ++ sslSocket *ss, const SSL3SignatureAndHashAlgorithm* sigAndHash)
|
| ++{
|
| ++ unsigned char serialized[2];
|
| ++
|
| ++ serialized[0] = ssl3_OIDToTLSHashAlgorithm(sigAndHash->hashAlg);
|
| ++ if (serialized[0] == 0) {
|
| ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ serialized[1] = sigAndHash->sigAlg;
|
| ++
|
| ++ return ssl3_AppendHandshake(ss, serialized, sizeof(serialized));
|
| ++}
|
| ++
|
| + /**************************************************************************
|
| + * Consume Handshake functions.
|
| + *
|
| +@@ -3850,6 +4038,147 @@
|
| + return SECSuccess;
|
| + }
|
| +
|
| ++/* tlsHashOIDMap contains the mapping between TLS hash identifiers and the
|
| ++ * SECOidTag used internally by NSS. */
|
| ++static const struct {
|
| ++ int tlsHash;
|
| ++ SECOidTag oid;
|
| ++} tlsHashOIDMap[] = {
|
| ++ { tls_hash_md5, SEC_OID_MD5 },
|
| ++ { tls_hash_sha1, SEC_OID_SHA1 },
|
| ++ { tls_hash_sha224, SEC_OID_SHA224 },
|
| ++ { tls_hash_sha256, SEC_OID_SHA256 },
|
| ++ { tls_hash_sha384, SEC_OID_SHA384 },
|
| ++ { tls_hash_sha512, SEC_OID_SHA512 }
|
| ++};
|
| ++
|
| ++/* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value.
|
| ++ * If the hash is not recognised, SEC_OID_UNKNOWN is returned.
|
| ++ *
|
| ++ * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++SECOidTag
|
| ++ssl3_TLSHashAlgorithmToOID(int hashFunc)
|
| ++{
|
| ++ unsigned int i;
|
| ++
|
| ++ for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) {
|
| ++ if (hashFunc == tlsHashOIDMap[i].tlsHash) {
|
| ++ return tlsHashOIDMap[i].oid;
|
| ++ }
|
| ++ }
|
| ++ return SEC_OID_UNKNOWN;
|
| ++}
|
| ++
|
| ++/* ssl3_OIDToTLSHashAlgorithm converts an OID to a TLS hash algorithm
|
| ++ * identifier. If the hash is not recognised, zero is returned.
|
| ++ *
|
| ++ * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++static int
|
| ++ssl3_OIDToTLSHashAlgorithm(SECOidTag oid)
|
| ++{
|
| ++ unsigned int i;
|
| ++
|
| ++ for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) {
|
| ++ if (oid == tlsHashOIDMap[i].oid) {
|
| ++ return tlsHashOIDMap[i].tlsHash;
|
| ++ }
|
| ++ }
|
| ++ return 0;
|
| ++}
|
| ++
|
| ++/* ssl3_TLSSignatureAlgorithmForKeyType returns the TLS 1.2 signature algorithm
|
| ++ * identifier for a given KeyType. */
|
| ++static SECStatus
|
| ++ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType,
|
| ++ TLSSignatureAlgorithm *out)
|
| ++{
|
| ++ switch (keyType) {
|
| ++ case rsaKey:
|
| ++ *out = tls_sig_rsa;
|
| ++ return SECSuccess;
|
| ++ case dsaKey:
|
| ++ *out = tls_sig_dsa;
|
| ++ return SECSuccess;
|
| ++ case ecKey:
|
| ++ *out = tls_sig_ecdsa;
|
| ++ return SECSuccess;
|
| ++ default:
|
| ++ PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| ++ return SECFailure;
|
| ++ }
|
| ++}
|
| ++
|
| ++/* ssl3_TLSSignatureAlgorithmForCertificate returns the TLS 1.2 signature
|
| ++ * algorithm identifier for the given certificate. */
|
| ++static SECStatus
|
| ++ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert,
|
| ++ TLSSignatureAlgorithm *out)
|
| ++{
|
| ++ SECKEYPublicKey *key;
|
| ++ KeyType keyType;
|
| ++
|
| ++ key = CERT_ExtractPublicKey(cert);
|
| ++ if (key == NULL) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ keyType = key->keyType;
|
| ++ SECKEY_DestroyPublicKey(key);
|
| ++ return ssl3_TLSSignatureAlgorithmForKeyType(keyType, out);
|
| ++}
|
| ++
|
| ++/* ssl3_CheckSignatureAndHashAlgorithmConsistency checks that the signature
|
| ++ * algorithm identifier in |sigAndHash| is consistent with the public key in
|
| ++ * |cert|. If so, SECSuccess is returned. Otherwise, PORT_SetError is called
|
| ++ * and SECFailure is returned. */
|
| ++SECStatus
|
| ++ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ const SSL3SignatureAndHashAlgorithm *sigAndHash, CERTCertificate* cert)
|
| ++{
|
| ++ SECStatus rv;
|
| ++ TLSSignatureAlgorithm sigAlg;
|
| ++
|
| ++ rv = ssl3_TLSSignatureAlgorithmForCertificate(cert, &sigAlg);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv;
|
| ++ }
|
| ++ if (sigAlg != sigAndHash->sigAlg) {
|
| ++ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| ++/* ssl3_ConsumeSignatureAndHashAlgorithm reads a SignatureAndHashAlgorithm
|
| ++ * structure from |b| and puts the resulting value into |out|. |b| and |length|
|
| ++ * are updated accordingly.
|
| ++ *
|
| ++ * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++SECStatus
|
| ++ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
|
| ++ SSL3Opaque **b,
|
| ++ PRUint32 *length,
|
| ++ SSL3SignatureAndHashAlgorithm *out)
|
| ++{
|
| ++ unsigned char bytes[2];
|
| ++ SECStatus rv;
|
| ++
|
| ++ rv = ssl3_ConsumeHandshake(ss, bytes, sizeof(bytes), b, length);
|
| ++ if (rv != SECSuccess) {
|
| ++ return rv;
|
| ++ }
|
| ++
|
| ++ out->hashAlg = ssl3_TLSHashAlgorithmToOID(bytes[0]);
|
| ++ if (out->hashAlg == SEC_OID_UNKNOWN) {
|
| ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ out->sigAlg = bytes[1];
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| + /**************************************************************************
|
| + * end of Consume Handshake functions.
|
| + **************************************************************************/
|
| +@@ -3876,6 +4205,7 @@
|
| + SSL3Opaque sha_inner[MAX_MAC_LENGTH];
|
| +
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| ++ hashes->hashAlg = SEC_OID_UNKNOWN;
|
| +
|
| + #ifndef NO_PKCS11_BYPASS
|
| + if (ss->opt.bypassPKCS11) {
|
| +@@ -3939,9 +4269,9 @@
|
| + MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size);
|
| + MD5_Update(md5cx, md5_inner, MD5_LENGTH);
|
| + }
|
| +- MD5_End(md5cx, hashes->md5, &outLength, MD5_LENGTH);
|
| ++ MD5_End(md5cx, hashes->u.s.md5, &outLength, MD5_LENGTH);
|
| +
|
| +- PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH));
|
| ++ PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
|
| +
|
| + if (!isTLS) {
|
| + PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
|
| +@@ -3953,16 +4283,58 @@
|
| + SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size);
|
| + SHA1_Update(shacx, sha_inner, SHA1_LENGTH);
|
| + }
|
| +- SHA1_End(shacx, hashes->sha, &outLength, SHA1_LENGTH);
|
| ++ SHA1_End(shacx, hashes->u.s.sha, &outLength, SHA1_LENGTH);
|
| +
|
| +- PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH));
|
| ++ PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
|
| +
|
| ++ hashes->len = MD5_LENGTH + SHA1_LENGTH;
|
| + rv = SECSuccess;
|
| + #undef md5cx
|
| + #undef shacx
|
| + } else
|
| + #endif
|
| +- {
|
| ++ if (ss->ssl3.hs.tls12_handshake_hash) {
|
| ++ PK11Context *h;
|
| ++ unsigned int stateLen;
|
| ++ unsigned char stackBuf[1024];
|
| ++ unsigned char *stateBuf = NULL;
|
| ++
|
| ++ if (!spec->master_secret) {
|
| ++ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ h = ss->ssl3.hs.tls12_handshake_hash;
|
| ++ stateBuf = PK11_SaveContextAlloc(h, stackBuf,
|
| ++ sizeof(stackBuf), &stateLen);
|
| ++ if (stateBuf == NULL) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ goto tls12_loser;
|
| ++ }
|
| ++ rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
|
| ++ sizeof(hashes->u.raw));
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ goto tls12_loser;
|
| ++ }
|
| ++ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
|
| ++ * then this will need to be updated. */
|
| ++ hashes->hashAlg = SEC_OID_SHA256;
|
| ++ rv = SECSuccess;
|
| ++
|
| ++tls12_loser:
|
| ++ if (stateBuf) {
|
| ++ if (PK11_RestoreContext(ss->ssl3.hs.tls12_handshake_hash, stateBuf,
|
| ++ stateLen) != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ }
|
| ++ if (stateBuf != stackBuf) {
|
| ++ PORT_ZFree(stateBuf, stateLen);
|
| ++ }
|
| ++ }
|
| ++ } else {
|
| + /* compute hases with PKCS11 */
|
| + PK11Context * md5;
|
| + PK11Context * sha = NULL;
|
| +@@ -4051,7 +4423,7 @@
|
| + rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size);
|
| + rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
|
| + }
|
| +- rv |= PK11_DigestFinal(md5, hashes->md5, &outLength, MD5_LENGTH);
|
| ++ rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH);
|
| + PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
|
| +@@ -4059,7 +4431,7 @@
|
| + goto loser;
|
| + }
|
| +
|
| +- PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH));
|
| ++ PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
|
| +
|
| + if (!isTLS) {
|
| + PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
|
| +@@ -4071,7 +4443,7 @@
|
| + rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size);
|
| + rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
|
| + }
|
| +- rv |= PK11_DigestFinal(sha, hashes->sha, &outLength, SHA1_LENGTH);
|
| ++ rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH);
|
| + PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
|
| + if (rv != SECSuccess) {
|
| + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| +@@ -4079,8 +4451,9 @@
|
| + goto loser;
|
| + }
|
| +
|
| +- PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH));
|
| ++ PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
|
| +
|
| ++ hashes->len = MD5_LENGTH + SHA1_LENGTH;
|
| + rv = SECSuccess;
|
| +
|
| + loser:
|
| +@@ -5343,8 +5716,12 @@
|
| + {
|
| + SECStatus rv = SECFailure;
|
| + PRBool isTLS;
|
| ++ PRBool isTLS12;
|
| + SECItem buf = {siBuffer, NULL, 0};
|
| + SSL3Hashes hashes;
|
| ++ KeyType keyType;
|
| ++ unsigned int len;
|
| ++ SSL3SignatureAndHashAlgorithm sigAndHash;
|
| +
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
|
| +@@ -5393,10 +5772,30 @@
|
| + goto done; /* err code was set by ssl3_SignHashes */
|
| + }
|
| +
|
| +- rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, buf.len + 2);
|
| ++ len = buf.len + 2 + (isTLS12 ? 2 : 0);
|
| ++
|
| ++ rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len);
|
| + if (rv != SECSuccess) {
|
| + goto done; /* error code set by AppendHandshake */
|
| + }
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
|
| ++ &sigAndHash.sigAlg);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto done;
|
| ++ }
|
| ++ /* We always sign using the handshake hash function. It's possible that
|
| ++ * a server could support SHA-256 as the handshake hash but not as a
|
| ++ * signature hash. In that case we wouldn't be able to do client
|
| ++ * certificates with it. The alternative is to buffer all handshake
|
| ++ * messages. */
|
| ++ sigAndHash.hashAlg = hashes.hashAlg;
|
| ++
|
| ++ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto done; /* err set by AppendHandshake. */
|
| ++ }
|
| ++ }
|
| + rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2);
|
| + if (rv != SECSuccess) {
|
| + goto done; /* error code set by AppendHandshake */
|
| +@@ -5504,6 +5903,13 @@
|
| + }
|
| + isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
|
| +
|
| ++ rv = ssl3_InitTLS12HandshakeHash(ss);
|
| ++ if (rv != SECSuccess) {
|
| ++ desc = internal_error;
|
| ++ errCode = PORT_GetError();
|
| ++ goto alert_loser;
|
| ++ }
|
| ++
|
| + rv = ssl3_ConsumeHandshake(
|
| + ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
|
| + if (rv != SECSuccess) {
|
| +@@ -5834,13 +6240,16 @@
|
| + {
|
| + PRArenaPool * arena = NULL;
|
| + SECKEYPublicKey *peerKey = NULL;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| + SECStatus rv;
|
| + int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
|
| + SSL3AlertDescription desc = illegal_parameter;
|
| + SSL3Hashes hashes;
|
| + SECItem signature = {siBuffer, NULL, 0};
|
| ++ SSL3SignatureAndHashAlgorithm sigAndHash;
|
| +
|
| ++ sigAndHash.hashAlg = SEC_OID_UNKNOWN;
|
| ++
|
| + SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
|
| + SSL_GETPID(), ss->fd));
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| +@@ -5859,6 +6268,7 @@
|
| + }
|
| +
|
| + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| +
|
| + switch (ss->ssl3.hs.kea_def->exchKeyType) {
|
| +
|
| +@@ -5874,6 +6284,18 @@
|
| + if (rv != SECSuccess) {
|
| + goto loser; /* malformed. */
|
| + }
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
|
| ++ &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed or unsupported. */
|
| ++ }
|
| ++ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ &sigAndHash, ss->sec.peerCert);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser;
|
| ++ }
|
| ++ }
|
| + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
|
| + if (rv != SECSuccess) {
|
| + goto loser; /* malformed. */
|
| +@@ -5891,7 +6313,7 @@
|
| + /*
|
| + * check to make sure the hash is signed by right guy
|
| + */
|
| +- rv = ssl3_ComputeExportRSAKeyHash(modulus, exponent,
|
| ++ rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
|
| + &ss->ssl3.hs.client_random,
|
| + &ss->ssl3.hs.server_random,
|
| + &hashes, ss->opt.bypassPKCS11);
|
| +@@ -5964,6 +6386,18 @@
|
| + }
|
| + if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys))
|
| + goto alert_loser;
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
|
| ++ &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed or unsupported. */
|
| ++ }
|
| ++ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ &sigAndHash, ss->sec.peerCert);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser;
|
| ++ }
|
| ++ }
|
| + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
|
| + if (rv != SECSuccess) {
|
| + goto loser; /* malformed. */
|
| +@@ -5985,7 +6419,7 @@
|
| + /*
|
| + * check to make sure the hash is signed by right guy
|
| + */
|
| +- rv = ssl3_ComputeDHKeyHash(dh_p, dh_g, dh_Ys,
|
| ++ rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
|
| + &ss->ssl3.hs.client_random,
|
| + &ss->ssl3.hs.server_random,
|
| + &hashes, ss->opt.bypassPKCS11);
|
| +@@ -6862,6 +7296,13 @@
|
| + goto alert_loser;
|
| + }
|
| +
|
| ++ rv = ssl3_InitTLS12HandshakeHash(ss);
|
| ++ if (rv != SECSuccess) {
|
| ++ desc = internal_error;
|
| ++ errCode = PORT_GetError();
|
| ++ goto alert_loser;
|
| ++ }
|
| ++
|
| + /* grab the client random data. */
|
| + rv = ssl3_ConsumeHandshake(
|
| + ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
|
| +@@ -7604,6 +8045,13 @@
|
| + goto alert_loser;
|
| + }
|
| +
|
| ++ rv = ssl3_InitTLS12HandshakeHash(ss);
|
| ++ if (rv != SECSuccess) {
|
| ++ desc = internal_error;
|
| ++ errCode = PORT_GetError();
|
| ++ goto alert_loser;
|
| ++ }
|
| ++
|
| + /* if we get a non-zero SID, just ignore it. */
|
| + if (length !=
|
| + SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + rand_length) {
|
| +@@ -7851,7 +8299,86 @@
|
| + return SECSuccess;
|
| + }
|
| +
|
| ++/* ssl3_PickSignatureHashAlgorithm selects a hash algorithm to use when signing
|
| ++ * elements of the handshake. (The negotiated cipher suite determines the
|
| ++ * signature algorithm.) Prior to TLS 1.2, the MD5/SHA1 combination is always
|
| ++ * used. With TLS 1.2, a client may advertise its support for signature and
|
| ++ * hash combinations. */
|
| ++static SECStatus
|
| ++ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
|
| ++ SSL3SignatureAndHashAlgorithm* out)
|
| ++{
|
| ++ TLSSignatureAlgorithm sigAlg;
|
| ++ unsigned int i, j;
|
| ++ /* hashPreference expresses our preferences for hash algorithms, most
|
| ++ * preferable first. */
|
| ++ static const PRUint8 hashPreference[] = {
|
| ++ tls_hash_sha256,
|
| ++ tls_hash_sha384,
|
| ++ tls_hash_sha512,
|
| ++ tls_hash_sha1,
|
| ++ };
|
| +
|
| ++ switch (ss->ssl3.hs.kea_def->kea) {
|
| ++ case kea_rsa:
|
| ++ case kea_rsa_export:
|
| ++ case kea_rsa_export_1024:
|
| ++ case kea_dh_rsa:
|
| ++ case kea_dh_rsa_export:
|
| ++ case kea_dhe_rsa:
|
| ++ case kea_dhe_rsa_export:
|
| ++ case kea_rsa_fips:
|
| ++ case kea_ecdh_rsa:
|
| ++ case kea_ecdhe_rsa:
|
| ++ sigAlg = tls_sig_rsa;
|
| ++ break;
|
| ++ case kea_dh_dss:
|
| ++ case kea_dh_dss_export:
|
| ++ case kea_dhe_dss:
|
| ++ case kea_dhe_dss_export:
|
| ++ sigAlg = tls_sig_dsa;
|
| ++ break;
|
| ++ case kea_ecdh_ecdsa:
|
| ++ case kea_ecdhe_ecdsa:
|
| ++ sigAlg = tls_sig_ecdsa;
|
| ++ break;
|
| ++ default:
|
| ++ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ out->sigAlg = sigAlg;
|
| ++
|
| ++ if (ss->version <= SSL_LIBRARY_VERSION_TLS_1_1) {
|
| ++ /* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and
|
| ++ * prior. */
|
| ++ out->hashAlg = SEC_OID_UNKNOWN;
|
| ++ return SECSuccess;
|
| ++ }
|
| ++
|
| ++ if (ss->ssl3.hs.numClientSigAndHash == 0) {
|
| ++ /* If the client didn't provide any signature_algorithms extension then
|
| ++ * we can assume that they support SHA-1:
|
| ++ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| ++ out->hashAlg = SEC_OID_SHA1;
|
| ++ return SECSuccess;
|
| ++ }
|
| ++
|
| ++ for (i = 0; i < PR_ARRAY_SIZE(hashPreference); i++) {
|
| ++ for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) {
|
| ++ const SSL3SignatureAndHashAlgorithm* sh =
|
| ++ &ss->ssl3.hs.clientSigAndHash[j];
|
| ++ if (sh->sigAlg == sigAlg && sh->hashAlg == hashPreference[i]) {
|
| ++ out->hashAlg = sh->hashAlg;
|
| ++ return SECSuccess;
|
| ++ }
|
| ++ }
|
| ++ }
|
| ++
|
| ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
|
| ++ return SECFailure;
|
| ++}
|
| ++
|
| ++
|
| + static SECStatus
|
| + ssl3_SendServerKeyExchange(sslSocket *ss)
|
| + {
|
| +@@ -7862,6 +8389,7 @@
|
| + SECItem signed_hash = {siBuffer, NULL, 0};
|
| + SSL3Hashes hashes;
|
| + SECKEYPublicKey * sdPub; /* public key for step-down */
|
| ++ SSL3SignatureAndHashAlgorithm sigAndHash;
|
| +
|
| + SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake",
|
| + SSL_GETPID(), ss->fd));
|
| +@@ -7869,6 +8397,10 @@
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
|
| +
|
| ++ if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) {
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| + switch (kea_def->exchKeyType) {
|
| + case kt_rsa:
|
| + /* Perform SSL Step-Down here. */
|
| +@@ -7878,7 +8410,8 @@
|
| + PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
|
| + return SECFailure;
|
| + }
|
| +- rv = ssl3_ComputeExportRSAKeyHash(sdPub->u.rsa.modulus,
|
| ++ rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg,
|
| ++ sdPub->u.rsa.modulus,
|
| + sdPub->u.rsa.publicExponent,
|
| + &ss->ssl3.hs.client_random,
|
| + &ss->ssl3.hs.server_random,
|
| +@@ -7921,6 +8454,13 @@
|
| + goto loser; /* err set by AppendHandshake. */
|
| + }
|
| +
|
| ++ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* err set by AppendHandshake. */
|
| ++ }
|
| ++ }
|
| ++
|
| + rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
|
| + signed_hash.len, 2);
|
| + if (rv != SECSuccess) {
|
| +@@ -7931,7 +8471,7 @@
|
| +
|
| + #ifdef NSS_ENABLE_ECC
|
| + case kt_ecdh: {
|
| +- rv = ssl3_SendECDHServerKeyExchange(ss);
|
| ++ rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash);
|
| + return rv;
|
| + }
|
| + #endif /* NSS_ENABLE_ECC */
|
| +@@ -8045,26 +8585,51 @@
|
| + SECStatus rv;
|
| + int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
|
| + SSL3AlertDescription desc = handshake_failure;
|
| +- PRBool isTLS;
|
| ++ PRBool isTLS, isTLS12;
|
| ++ SSL3SignatureAndHashAlgorithm sigAndHash;
|
| +
|
| + SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
|
| + SSL_GETPID(), ss->fd));
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| +
|
| ++ isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| ++ isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
|
| ++
|
| + if (ss->ssl3.hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) {
|
| + desc = unexpected_message;
|
| + errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
|
| + goto alert_loser;
|
| + }
|
| +
|
| ++ if (isTLS12) {
|
| ++ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
|
| ++ &sigAndHash);
|
| ++ if (rv != SECSuccess) {
|
| ++ goto loser; /* malformed or unsupported. */
|
| ++ }
|
| ++ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
|
| ++ &sigAndHash, ss->sec.peerCert);
|
| ++ if (rv != SECSuccess) {
|
| ++ errCode = PORT_GetError();
|
| ++ desc = decrypt_error;
|
| ++ goto alert_loser;
|
| ++ }
|
| ++
|
| ++ /* We only support CertificateVerify messages that use the handshake
|
| ++ * hash. */
|
| ++ if (sigAndHash.hashAlg != hashes->hashAlg) {
|
| ++ errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM;
|
| ++ desc = decrypt_error;
|
| ++ goto alert_loser;
|
| ++ }
|
| ++ }
|
| ++
|
| + rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
|
| + if (rv != SECSuccess) {
|
| + goto loser; /* malformed. */
|
| + }
|
| +
|
| +- isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
|
| +-
|
| + /* XXX verify that the key & kea match */
|
| + rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
|
| + isTLS, ss->pkcs11PinArg);
|
| +@@ -9163,7 +9728,7 @@
|
| + static SECStatus
|
| + ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
|
| + PRBool isServer,
|
| +- const SSL3Finished * hashes,
|
| ++ const SSL3Hashes * hashes,
|
| + TLSFinished * tlsFinished)
|
| + {
|
| + const char * label;
|
| +@@ -9173,8 +9738,8 @@
|
| + label = isServer ? "server finished" : "client finished";
|
| + len = 15;
|
| +
|
| +- rv = ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->md5,
|
| +- sizeof *hashes, tlsFinished->verify_data,
|
| ++ rv = ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
|
| ++ hashes->len, tlsFinished->verify_data,
|
| + sizeof tlsFinished->verify_data);
|
| +
|
| + return rv;
|
| +@@ -9192,12 +9757,16 @@
|
| + SECStatus rv = SECSuccess;
|
| +
|
| + if (spec->master_secret && !spec->bypassCiphers) {
|
| +- SECItem param = {siBuffer, NULL, 0};
|
| +- PK11Context *prf_context =
|
| +- PK11_CreateContextBySymKey(CKM_TLS_PRF_GENERAL, CKA_SIGN,
|
| +- spec->master_secret, ¶m);
|
| ++ SECItem param = {siBuffer, NULL, 0};
|
| ++ CK_MECHANISM_TYPE mech = CKM_TLS_PRF_GENERAL;
|
| ++ PK11Context *prf_context;
|
| + unsigned int retLen;
|
| +
|
| ++ if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
|
| ++ mech = CKM_NSS_TLS_PRF_GENERAL_SHA256;
|
| ++ }
|
| ++ prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN,
|
| ++ spec->master_secret, ¶m);
|
| + if (!prf_context)
|
| + return SECFailure;
|
| +
|
| +@@ -9496,7 +10066,7 @@
|
| + PRBool isServer = ss->sec.isServer;
|
| + SECStatus rv;
|
| + SSL3Sender sender = isServer ? sender_server : sender_client;
|
| +- SSL3Finished hashes;
|
| ++ SSL3Hashes hashes;
|
| + TLSFinished tlsFinished;
|
| +
|
| + SSL_TRC(3, ("%d: SSL3[%d]: send finished handshake", SSL_GETPID(), ss->fd));
|
| +@@ -9530,14 +10100,15 @@
|
| + goto fail; /* err set by AppendHandshake. */
|
| + } else {
|
| + if (isServer)
|
| +- ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes;
|
| ++ ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes.u.s;
|
| + else
|
| +- ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes;
|
| +- ss->ssl3.hs.finishedBytes = sizeof hashes;
|
| +- rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes);
|
| ++ ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s;
|
| ++ PORT_Assert(hashes.len == sizeof hashes.u.s);
|
| ++ ss->ssl3.hs.finishedBytes = sizeof hashes.u.s;
|
| ++ rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s);
|
| + if (rv != SECSuccess)
|
| + goto fail; /* err set by AppendHandshake. */
|
| +- rv = ssl3_AppendHandshake(ss, &hashes, sizeof hashes);
|
| ++ rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s);
|
| + if (rv != SECSuccess)
|
| + goto fail; /* err set by AppendHandshake. */
|
| + }
|
| +@@ -9686,18 +10257,19 @@
|
| + return SECFailure;
|
| + }
|
| + } else {
|
| +- if (length != sizeof(SSL3Hashes)) {
|
| ++ if (length != sizeof(SSL3Finished)) {
|
| + (void)ssl3_IllegalParameter(ss);
|
| + PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (!isServer)
|
| +- ss->ssl3.hs.finishedMsgs.sFinished[1] = *hashes;
|
| ++ ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes->u.s;
|
| + else
|
| +- ss->ssl3.hs.finishedMsgs.sFinished[0] = *hashes;
|
| +- ss->ssl3.hs.finishedBytes = sizeof *hashes;
|
| +- if (0 != NSS_SecureMemcmp(hashes, b, length)) {
|
| ++ ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes->u.s;
|
| ++ PORT_Assert(hashes->len == sizeof hashes->u.s);
|
| ++ ss->ssl3.hs.finishedBytes = sizeof hashes->u.s;
|
| ++ if (0 != NSS_SecureMemcmp(&hashes->u.s, b, length)) {
|
| + (void)ssl3_HandshakeFailure(ss);
|
| + PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
|
| + return SECFailure;
|
| +@@ -11286,6 +11858,12 @@
|
| + if (ss->ssl3.hs.sha) {
|
| + PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE);
|
| + }
|
| ++ if (ss->ssl3.hs.tls12_handshake_hash) {
|
| ++ PK11_DestroyContext(ss->ssl3.hs.tls12_handshake_hash,PR_TRUE);
|
| ++ }
|
| ++ if (ss->ssl3.hs.clientSigAndHash) {
|
| ++ PORT_Free(ss->ssl3.hs.clientSigAndHash);
|
| ++ }
|
| + if (ss->ssl3.hs.messages.buf) {
|
| + PORT_Free(ss->ssl3.hs.messages.buf);
|
| + ss->ssl3.hs.messages.buf = NULL;
|
|
|