diff options
Diffstat (limited to 'security/nss/lib')
-rw-r--r-- | security/nss/lib/cryptohi/keyhi.h | 11 | ||||
-rw-r--r-- | security/nss/lib/cryptohi/seckey.c | 15 | ||||
-rw-r--r-- | security/nss/lib/nss/nss.def | 9 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11skey.c | 5 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11slot.c | 5 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11.c | 44 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11c.c | 15 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11t.h | 5 | ||||
-rw-r--r-- | security/nss/lib/ssl/ssl3con.c | 310 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslenum.c | 10 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslimpl.h | 5 | ||||
-rw-r--r-- | security/nss/lib/ssl/sslsock.c | 8 |
12 files changed, 403 insertions, 39 deletions
diff --git a/security/nss/lib/cryptohi/keyhi.h b/security/nss/lib/cryptohi/keyhi.h index 6c1a70546..b0a99698b 100644 --- a/security/nss/lib/cryptohi/keyhi.h +++ b/security/nss/lib/cryptohi/keyhi.h @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -99,10 +100,16 @@ extern SECKEYPublicKey *SECKEY_CopyPublicKey(SECKEYPublicKey *pubKey); extern SECKEYPublicKey *SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privateKey); /* - * create a new RSA key pair. The public Key is returned... + * create a new RSA key pair. The private Key is returned... */ SECKEYPrivateKey *SECKEY_CreateRSAPrivateKey(int keySizeInBits, SECKEYPublicKey **pubk, void *cx); + +/* + * create a new DH key pair. The private Key is returned... + */ +SECKEYPrivateKey *SECKEY_CreateDHPrivateKey(DHParams *param, + SECKEYPublicKey **pubk, void *cx); /* ** Create a subject-public-key-info based on a public key. */ diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 76c4b8ef4..4ffa67fd6 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -159,6 +160,18 @@ SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx) return(privk); } +SECKEYPrivateKey * +SECKEY_CreateDHPrivateKey(DHParams *param, SECKEYPublicKey **pubk, void *cx) +{ + SECKEYPrivateKey *privk; + PK11SlotInfo *slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx); + + privk = PK11_GenerateKeyPair(slot,CKM_DH_PKCS_KEY_PAIR_GEN,param,pubk, + PR_FALSE, PR_TRUE, cx); + PK11_FreeSlot(slot); + return(privk); +} + void SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk) { diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 755fec374..be658f7e5 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -16,7 +16,8 @@ ;+# Copyright (C) 2000 Netscape Communications Corporation. All ;+# Rights Reserved. ;+# -;+# Contributor(s): +;+# Contributor(s): +;+# Dr Stephen Henson <stephen.henson@gemplus.com> ;+# ;+# Alternatively, the contents of this file may be used under the ;+# terms of the GNU General Public License Version 2 or later (the @@ -447,3 +448,9 @@ PK11_NeedUserInit; ;+ local: ;+ *; ;+}; +;+NSS_3.3 { # NSS 3.3. release +;+ global: +SECKEY_CreateDHPrivateKey; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 9ccaa2f53..3e15ec9c3 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -780,7 +781,7 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount); if (crv != CKR_OK) break; - if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) { + if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) { crv = CKR_OBJECT_HANDLE_INVALID; break; } diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index 571177438..c725a7797 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -2680,10 +2681,12 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) case CKM_SSL3_PRE_MASTER_KEY_GEN: case CKM_GENERIC_SECRET_KEY_GEN: case CKM_SSL3_MASTER_KEY_DERIVE: + case CKM_SSL3_MASTER_KEY_DERIVE_DH: case CKM_SSL3_KEY_AND_MAC_DERIVE: case CKM_SSL3_SHA1_MAC: case CKM_SSL3_MD5_MAC: case CKM_TLS_MASTER_KEY_DERIVE: + case CKM_TLS_MASTER_KEY_DERIVE_DH: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 8bf141df7..e0a73fa2b 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -378,6 +379,7 @@ static struct mechanismList mechanisms[] = { /* ---------------------- SSL Key Derivations ------------------------- */ {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}, PR_FALSE}, {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, + {CKM_SSL3_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, {CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE}, PR_FALSE}, {CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE}, PR_FALSE}, @@ -385,6 +387,7 @@ static struct mechanismList mechanisms[] = { {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE}, {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, + {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, /* ---------------------- PBE Key Derivations ------------------------ */ {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, @@ -703,10 +706,11 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) } break; case CKK_DSA: - if ( !pk11_hasAttribute(object, CKA_PRIME)) { + if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { + case CKK_DH: + if ( !pk11_hasAttribute(object, CKA_PRIME)) { return CKR_TEMPLATE_INCOMPLETE; } if ( !pk11_hasAttribute(object, CKA_BASE)) { @@ -719,7 +723,6 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) recover = CK_FALSE; wrap = CK_FALSE; break; - case CKK_DH: default: return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -925,26 +928,26 @@ pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type) break; case CKK_DSA: - if ( !pk11_hasAttribute(object, CKA_PRIME)) { + if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { + if ( !pk11_hasAttribute(object, CKA_NETSCAPE_DB)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !pk11_hasAttribute(object, CKA_BASE)) { + case CKK_DH: + if ( !pk11_hasAttribute(object, CKA_PRIME)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !pk11_hasAttribute(object, CKA_VALUE)) { + if ( !pk11_hasAttribute(object, CKA_BASE)) { return CKR_TEMPLATE_INCOMPLETE; } - if ( !pk11_hasAttribute(object, CKA_NETSCAPE_DB)) { + if ( !pk11_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } encrypt = CK_FALSE; recover = CK_FALSE; wrap = CK_FALSE; break; - case CKK_DH: default: return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -1959,6 +1962,16 @@ SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) object,CKA_VALUE); break; case CKK_DH: + pubKey->keyType = dhKey; + crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.prime, + object,CKA_PRIME); + if (crv != CKR_OK) break; + crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dh.base, + object,CKA_BASE); + if (crv != CKR_OK) break; + crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.publicValue, + object,CKA_VALUE); + break; default: crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -2044,7 +2057,18 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) object,CKA_NETSCAPE_DB); /* can't set the public value.... */ break; + case CKK_DH: + privKey->keyType = dhKey; + crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.prime, + object,CKA_PRIME); + if (crv != CKR_OK) break; + crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.base, + object,CKA_BASE); + if (crv != CKR_OK) break; + crv = pk11_Attribute2SSecItem(arena,&privKey->u.dh.privateValue, + object,CKA_VALUE); + break; default: crv = CKR_KEY_TYPE_INCONSISTENT; break; diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index cdd1c19e1..2c9927063 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -4413,6 +4414,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, CK_OBJECT_CLASS classType = CKO_SECRET_KEY; CK_KEY_DERIVATION_STRING_DATA *stringPtr; PRBool isTLS = PR_FALSE; + PRBool isDH = PR_FALSE; SECStatus rv; int i; unsigned int outLen; @@ -4493,15 +4495,20 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, * generate the master secret */ case CKM_TLS_MASTER_KEY_DERIVE: + case CKM_TLS_MASTER_KEY_DERIVE_DH: isTLS = PR_TRUE; /* fall thru */ case CKM_SSL3_MASTER_KEY_DERIVE: + case CKM_SSL3_MASTER_KEY_DERIVE_DH: { CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; SSL3RSAPreMasterSecret *rsa_pms; + if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || + (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH)) + isDH = PR_TRUE; - /* first do the consistancy checkes */ - if (att->attrib.ulValueLen != SSL3_PMS_LENGTH) { + /* first do the consistancy checks */ + if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { crv = CKR_KEY_TYPE_INCONSISTENT; break; } @@ -5465,5 +5472,3 @@ CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) pk11_FreeAttribute(att); return crv; } - - diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h index 49238be86..c626036c8 100644 --- a/security/nss/lib/softoken/pkcs11t.h +++ b/security/nss/lib/softoken/pkcs11t.h @@ -16,7 +16,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -1114,6 +1115,8 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; #define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L #define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L #define CKM_TLS_PRF_GENERAL 0x80000373L +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x80000374L +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x80000375L /* define used to pass in the database key for DSA private keys */ #define CKA_NETSCAPE_DB 0xD5A0DB00L diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index d4fec698c..f8e173d8f 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -18,7 +18,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -92,6 +93,9 @@ static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, */ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { /* cipher_suite policy enabled is_present*/ + { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, @@ -99,6 +103,8 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { { 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}, { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, @@ -221,7 +227,10 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = { #endif {SSL_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_rsa}, {SSL_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa}, - + {SSL_DHE_DSS_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_dhe_dss}, + {SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, + cipher_3des, mac_sha, kea_dhe_dss}, + {TLS_DHE_DSS_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_dhe_dss}, #if 0 /* not implemented */ {SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, cipher_des40, mac_sha, kea_dh_dss_export}, @@ -230,15 +239,16 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = { {SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, cipher_des40, mac_sha, kea_dh_rsa_export}, {SSL_DH_RSA_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_rsa}, - {SSL_DH_RSA_3DES_CBC_SHA, cipher_des, mac_sha, kea_dh_rsa}, + {SSL_DH_RSA_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_rsa}, {SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, cipher_des40, mac_sha, kea_dh_dss_export}, - {SSL_DHE_DSS_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_dss}, - {SSL_DHE_DSS_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_dss}, {SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, cipher_des40, mac_sha, kea_dh_rsa_export}, - {SSL_DHE_RSA_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_rsa}, - {SSL_DHE_RSA_3DES_CBC_SHA, cipher_des, mac_sha, kea_dh_rsa}, +#endif + {SSL_DHE_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_dhe_rsa}, + {SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + cipher_3des, mac_sha, kea_dhe_rsa}, +#if 0 {SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4_40, mac_md5, kea_dh_anon_export}, {SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4, mac_md5, kea_dh_anon_export}, {SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, @@ -631,6 +641,8 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, return SECFailure; } + + switch (key->keyType) { case rsaKey: hashItem.data = hash->md5; @@ -758,6 +770,96 @@ done: /* Caller must set hiLevel error code. */ static SECStatus +ssl3_ComputeDHKeyHash(SECItem dh_p, SECItem dh_g, SECItem dh_Ys, + SSL3Random *client_rand, SSL3Random *server_rand, + SSL3Hashes *hashes) +{ + PK11Context * md5 = NULL; + PK11Context * sha = NULL; + PRUint8 * hashBuf; + PRUint8 * pBuf; + SECStatus rv = SECSuccess; + unsigned int outLen; + unsigned int bufLen; + PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8]; + + bufLen = 2*SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len; + if (bufLen <= sizeof buf) { + hashBuf = buf; + } else { + hashBuf = PORT_Alloc(bufLen); + if (!hashBuf) { + return SECFailure; + } + } + + md5 = PK11_CreateDigestContext(SEC_OID_MD5); + if (md5 == NULL) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; /* Caller must set hiLevel error code. */ + goto done; + } + sha = PK11_CreateDigestContext(SEC_OID_SHA1); + if (sha == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; /* Caller must set hiLevel error code. */ + goto done; + } + + 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)(dh_p.len >> 8); + pBuf[1] = (PRUint8)(dh_p.len); + pBuf += 2; + memcpy(pBuf, dh_p.data, dh_p.len); + pBuf += dh_p.len; + pBuf[0] = (PRUint8)(dh_g.len >> 8); + pBuf[1] = (PRUint8)(dh_g.len); + pBuf += 2; + memcpy(pBuf, dh_g.data, dh_g.len); + pBuf += dh_g.len; + pBuf[0] = (PRUint8)(dh_Ys.len >> 8); + pBuf[1] = (PRUint8)(dh_Ys.len); + pBuf += 2; + memcpy(pBuf, dh_Ys.data, dh_Ys.len); + pBuf += dh_Ys.len; + PORT_Assert(pBuf - hashBuf == bufLen); + + rv = PK11_DigestBegin(md5); + rv |= PK11_DigestOp(md5, hashBuf, bufLen); + rv |= PK11_DigestFinal(md5, hashes->md5, &outLen, MD5_LENGTH); + PORT_Assert(rv != SECSuccess || outLen == MD5_LENGTH); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; + goto done; + } + + rv = PK11_DigestBegin(sha); + rv |= PK11_DigestOp(sha, hashBuf, bufLen); + rv |= PK11_DigestFinal(sha, hashes->sha, &outLen, SHA1_LENGTH); + PORT_Assert(rv != SECSuccess || outLen == SHA1_LENGTH); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; + goto done; + } + + 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)); + +done: + if (md5 != NULL) PK11_DestroyContext(md5, PR_TRUE); + if (sha != NULL) PK11_DestroyContext(sha, PR_TRUE); + if (hashBuf != buf && hashBuf != NULL) + PORT_Free(hashBuf); + return rv; +} +/* Caller must set hiLevel error code. */ +static SECStatus ssl3_ComputeFortezzaPublicKeyHash(SECItem publicValue, unsigned char * hash) { PK11Context *sha = NULL; @@ -1811,6 +1913,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) PRBool skipKeysAndIVs = (PRBool) ((cipher_def->calg == calg_fortezza) || (cipher_def->calg == calg_null)); + PRBool isDH = (PRBool) (ss->ssl3->hs.kea_def->exchKeyType == kt_dh); CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; CK_MECHANISM_TYPE bulk_mechanism; @@ -1825,13 +1928,14 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert( ssl_HaveSpecWriteLock(ss)); PORT_Assert(ss->ssl3->prSpec == ss->ssl3->pwSpec); - if (isTLS) { - master_derive = CKM_TLS_MASTER_KEY_DERIVE; + 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; keyFlags = CKF_SIGN | CKF_VERIFY; } else { - master_derive = CKM_SSL3_MASTER_KEY_DERIVE; + if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; + else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; keyFlags = 0; } @@ -1851,7 +1955,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) pwSpec->master_secret = PK11_DeriveWithFlags((PK11SymKey *)pms, master_derive, ¶ms, key_derive, CKA_DERIVE, 0, keyFlags); - if (pwSpec->master_secret != NULL && ss->detectRollBack) { + if (!isDH && pwSpec->master_secret && ss->detectRollBack) { SSL3ProtocolVersion client_version; client_version = pms_version.major << 8 | pms_version.minor; if (client_version != ss->clientHelloVersion) { @@ -3065,6 +3169,92 @@ loser: return rv; } +/* Called from ssl3_SendClientKeyExchange(). */ +static SECStatus +sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) +{ + PK11SymKey * pms = NULL; + SECStatus rv = SECFailure; + PRBool isTLS; + CK_MECHANISM_TYPE target; + + DHParams dhParam; /* DH parameters */ + SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */ + SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */ + + PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ssl_HaveXmitBufLock(ss)); + + isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); + + /* Copy DH parameters from server key */ + + dhParam.prime.data = svrPubKey->u.dh.prime.data; + dhParam.prime.len = svrPubKey->u.dh.prime.len; + dhParam.base.data = svrPubKey->u.dh.base.data; + dhParam.base.len = svrPubKey->u.dh.base.len; + + /* Generate ephemeral DH keypair */ + privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL); + if (!privKey || !pubKey) { + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); + rv = SECFailure; + goto loser; + } + PRINT_BUF(50, (ss, "DH public value:", + pubKey->u.dh.publicValue.data, + pubKey->u.dh.publicValue.len)); + + if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; + else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + + /* Determine the PMS */ + + pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL, + CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL); + + if (pms == NULL) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + + SECKEY_DestroyPrivateKey(privKey); + privKey = NULL; + + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); pms = NULL; + + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + + rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, + pubKey->u.dh.publicValue.len + 2); + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshake* */ + } + rv = ssl3_AppendHandshakeVariable(ss, + pubKey->u.dh.publicValue.data, + pubKey->u.dh.publicValue.len, 2); + SECKEY_DestroyPublicKey(pubKey); + pubKey = NULL; + + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshake* */ + } + + rv = SECSuccess; + + +loser: + + if(pms) PK11_FreeSymKey(pms); + if(privKey) SECKEY_DestroyPrivateKey(privKey); + if(pubKey) SECKEY_DestroyPublicKey(pubKey); + return rv; +} + /* fortezza client-auth portion of ClientKeyExchange message * This function appends the KEA public key from the client's V3 cert * (empty for a V1 cert) to the outgoing ClientKeyExchange message. @@ -3542,6 +3732,10 @@ ssl3_SendClientKeyExchange(sslSocket *ss) rv = sendFortezzaClientKeyExchange(ss, serverKey); break; + case kt_dh: + rv = sendDHClientKeyExchange(ss, serverKey); + break; + default: /* got an unknown or unsupported Key Exchange Algorithm. */ SEND_ALERT @@ -3907,6 +4101,9 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECItem modulus = {siBuffer, NULL, 0}; SECItem exponent = {siBuffer, NULL, 0}; SECItem signature = {siBuffer, NULL, 0}; + SECItem dh_p = {siBuffer, NULL, 0}; + SECItem dh_g = {siBuffer, NULL, 0}; + SECItem dh_Ys = {siBuffer, NULL, 0}; SSL3Hashes hashes; SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake", @@ -3929,6 +4126,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) isTLS = (PRBool)(ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); switch (ss->ssl3->hs.kea_def->exchKeyType) { + case kt_rsa: rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length); if (rv != SECSuccess) { @@ -4004,6 +4202,90 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->ssl3->hs.ws = wait_cert_request; return SECSuccess; + case kt_dh: + rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + if (length != 0) { + if (isTLS) + desc = decode_error; + goto alert_loser; /* malformed. */ + } + + PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len)); + PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len)); + PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len)); + + /* failures after this point are not malformed handshakes. */ + /* TLS: send decrypt_error if signature failed. */ + desc = isTLS ? decrypt_error : handshake_failure; + + /* + * check to make sure the hash is signed by right guy + */ + rv = ssl3_ComputeDHKeyHash(dh_p, dh_g, dh_Ys, + &ss->ssl3->hs.client_random, + &ss->ssl3->hs.server_random, &hashes); + if (rv != SECSuccess) { + errCode = + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto alert_loser; + } + rv = ssl3_VerifySignedHashes(&hashes, ss->sec->peerCert, &signature, + isTLS, ss->pkcs11PinArg); + if (rv != SECSuccess) { + errCode = + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto alert_loser; + } + + /* + * we really need to build a new key here because we can no longer + * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate + * pkcs11 slots and ID's. + */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + goto no_memory; + } + + ss->sec->peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); + if (peerKey == NULL) { + goto no_memory; + } + + peerKey->arena = arena; + peerKey->keyType = dhKey; + peerKey->pkcs11Slot = NULL; + peerKey->pkcs11ID = CK_INVALID_KEY; + + if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) || + SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) || + SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys)) + { + PORT_FreeArena(arena, PR_FALSE); + goto no_memory; + } + ss->sec->peerKey = peerKey; + SECITEM_FreeItem(&dh_p, PR_FALSE); + SECITEM_FreeItem(&dh_g, PR_FALSE); + SECITEM_FreeItem(&dh_Ys, PR_FALSE); + ss->ssl3->hs.ws = wait_cert_request; + return SECSuccess; + case kt_fortezza: /* Fortezza needs *BOTH* a server cert message @@ -4036,6 +4318,9 @@ loser: if (modulus.data != NULL) SECITEM_FreeItem(&modulus, PR_FALSE); if (exponent.data != NULL) SECITEM_FreeItem(&exponent, PR_FALSE); if (signature.data != NULL) SECITEM_FreeItem(&signature, PR_FALSE); + if (dh_p.data != NULL) SECITEM_FreeItem(&dh_p, PR_FALSE); + if (dh_g.data != NULL) SECITEM_FreeItem(&dh_g, PR_FALSE); + if (dh_Ys.data != NULL) SECITEM_FreeItem(&dh_Ys, PR_FALSE); PORT_SetError( errCode ); return SECFailure; @@ -6166,7 +6451,8 @@ cert_block: ssl3->hs.ws = wait_cert_request; /* disallow server_key_exchange */ if (ssl3->hs.kea_def->is_limited || /* XXX OR server cert is signing only. */ - ssl3->hs.kea_def->kea == kea_fortezza) { + ssl3->hs.kea_def->kea == kea_fortezza || + ssl3->hs.kea_def->exchKeyType == kt_dh) { ssl3->hs.ws = wait_server_key; /* allow server_key_exchange */ } } diff --git a/security/nss/lib/ssl/sslenum.c b/security/nss/lib/ssl/sslenum.c index 10cf965d4..fe32b8f14 100644 --- a/security/nss/lib/ssl/sslenum.c +++ b/security/nss/lib/ssl/sslenum.c @@ -19,7 +19,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -68,6 +69,13 @@ const PRUint16 SSL_ImplementedCiphers[] = { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_FIPS_WITH_DES_CBC_SHA, + /* DHE ciphersuites */ + SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, + SSL_DHE_RSA_WITH_DES_CBC_SHA, + SSL_DHE_DSS_WITH_DES_CBC_SHA, + TLS_DHE_DSS_WITH_RC4_128_SHA, + 0 }; diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 53aba0a86..bccaab54c 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -19,7 +19,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -220,7 +221,7 @@ typedef struct { #endif } ssl3CipherSuiteCfg; -#define ssl_V3_SUITES_IMPLEMENTED 14 +#define ssl_V3_SUITES_IMPLEMENTED 19 typedef struct sslOptionsStr { unsigned int useSecurity : 1; /* 1 */ diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index ab9c8c0a2..9d555d943 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -20,7 +20,8 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -73,6 +74,11 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */ { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, { SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, + { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, + { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, + { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, + { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, + { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED, SSL_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 }, |