diff --git a/CHANGES b/CHANGES index b7b6b99035df5f8ffaf9bb90687c9bd5d92edc78..0e7f968846d1290ec56e612702d44ec24d96b383 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,14 @@ Changes between 0.9.7c and 0.9.8 [xx XXX xxxx] + *) Update support for ECC-based TLS ciphersuites according to + draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with + SHA-1 now is only used for "small" curves (where the + representation of a field element takes up to 24 bytes); for + larger curves, the field element resulting from ECDH is directly + used as premaster secret. + [Douglas Stebila (Sun Microsystems Laboratories)] + *) Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2 curve secp160r1 to the tests. [Douglas Stebila (Sun Microsystems Laboratories)] diff --git a/apps/speed.c b/apps/speed.c index a634b117298f4c718b488f9010840c0f855eaed0..1c2b9cded042d695f9762a33e3c10aa103d0d3b2 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -2079,12 +2079,28 @@ int MAIN(int argc, char **argv) } else { - secret_size_a = ECDH_compute_key(secret_a, KDF1_SHA1_len, + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). + */ + int field_size, outlen; + void *(*kdf)(void *in, size_t inlen, void *out, size_t outlen); + field_size = EC_GROUP_get_degree(ecdh_a[j]->group); + if (field_size <= 24 * 8) + { + outlen = KDF1_SHA1_len; + kdf = KDF1_SHA1; + } + else + { + outlen = (field_size+7)/8; + kdf = NULL; + } + secret_size_a = ECDH_compute_key(secret_a, outlen, ecdh_b[j]->pub_key, - ecdh_a[j], KDF1_SHA1); - secret_size_b = ECDH_compute_key(secret_b, KDF1_SHA1_len, + ecdh_a[j], kdf); + secret_size_b = ECDH_compute_key(secret_b, outlen, ecdh_a[j]->pub_key, - ecdh_b[j], KDF1_SHA1); + ecdh_b[j], kdf); if (secret_size_a != secret_size_b) ecdh_checks = 0; else @@ -2113,9 +2129,9 @@ int MAIN(int argc, char **argv) Time_F(START); for (count=0,run=1; COND(ecdh_c[j][0]); count++) { - ECDH_compute_key(secret_a, KDF1_SHA1_len, + ECDH_compute_key(secret_a, outlen, ecdh_b[j]->pub_key, - ecdh_a[j], KDF1_SHA1); + ecdh_a[j], kdf); } d=Time_F(STOP); BIO_printf(bio_err, mr ? "+R7:%ld:%d:%.2f\n" :"%ld %d-bit ECDH ops in %.2fs\n", diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index dcffc8c049049e077ae9cedd38d4fd26e9376746..8f4d4e1818e2348ebea9d8018c61a2aeec8e5be9 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -158,6 +158,7 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN int EC_GROUP_set_curve_GF2m(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int EC_GROUP_get_curve_GF2m(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); +/* returns the number of bits needed to represent a field element */ int EC_GROUP_get_degree(const EC_GROUP *); /* EC_GROUP_check() returns 1 if 'group' defines a valid group, 0 otherwise */ diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 7a187aff6d0245919a017f9c77a80753f7fcedce..090719a6d29b0ba8845ee7becdb0fbb2be34aa32 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -62,12 +62,12 @@ * [including the GNU Public Licence.] */ -#define NUM_NID 721 -#define NUM_SN 716 -#define NUM_LN 716 -#define NUM_OBJ 690 +#define NUM_NID 724 +#define NUM_SN 719 +#define NUM_LN 719 +#define NUM_OBJ 693 -static unsigned char lvalues[4879]={ +static unsigned char lvalues[4882]={ 0x00, /* [ 0] OBJ_undef */ 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 1] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 7] OBJ_pkcs */ @@ -432,7 +432,7 @@ static unsigned char lvalues[4879]={ 0x2B,0x06,0x01,0x04,0x01,0x8B,0x3A,0x82,0x58,/* [2865] OBJ_dcObject */ 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x19,/* [2874] OBJ_domainComponent */ 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0D,/* [2884] OBJ_Domain */ -0x50, /* [2894] OBJ_joint_iso_ccitt */ +0x00, /* [2894] OBJ_joint_iso_ccitt */ 0x55,0x01,0x05, /* [2895] OBJ_selected_attribute_types */ 0x55,0x01,0x05,0x37, /* [2898] OBJ_clearance */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x03,/* [2902] OBJ_md4WithRSAEncryption */ @@ -758,6 +758,9 @@ static unsigned char lvalues[4879]={ 0x55,0x1D,0x20,0x00, /* [4868] OBJ_any_policy */ 0x55,0x1D,0x21, /* [4872] OBJ_policy_mappings */ 0x55,0x1D,0x1E, /* [4875] OBJ_name_constraints */ +0x00, /* [4878] OBJ_itu_t */ +0x50, /* [4879] OBJ_joint_iso_itu_t */ +0x67, /* [4880] OBJ_international_organizations */ }; static ASN1_OBJECT nid_objs[NUM_NID]={ @@ -1370,8 +1373,7 @@ static ASN1_OBJECT nid_objs[NUM_NID]={ {"dcobject","dcObject",NID_dcObject,9,&(lvalues[2865]),0}, {"DC","domainComponent",NID_domainComponent,10,&(lvalues[2874]),0}, {"domain","Domain",NID_Domain,10,&(lvalues[2884]),0}, -{"JOINT-ISO-CCITT","joint-iso-ccitt",NID_joint_iso_ccitt,1, - &(lvalues[2894]),0}, +{"NULL","NULL",NID_joint_iso_ccitt,1,&(lvalues[2894]),0}, {"selected-attribute-types","Selected Attribute Types", NID_selected_attribute_types,3,&(lvalues[2895]),0}, {"clearance","clearance",NID_clearance,4,&(lvalues[2898]),0}, @@ -1389,7 +1391,7 @@ static ASN1_OBJECT nid_objs[NUM_NID]={ &(lvalues[2941]),0}, {"noRevAvail","X509v3 No Revocation Available",NID_no_rev_avail,3, &(lvalues[2944]),0}, -{"CCITT","ccitt",NID_ccitt,1,&(lvalues[2947]),0}, +{"NULL","NULL",NID_ccitt,1,&(lvalues[2947]),0}, {"ansi-X9-62","ANSI X9.62",NID_ansi_X9_62,5,&(lvalues[2948]),0}, {"prime-field","prime-field",NID_X9_62_prime_field,7,&(lvalues[2953]),0}, {"characteristic-two-field","characteristic-two-field", @@ -1887,6 +1889,11 @@ static ASN1_OBJECT nid_objs[NUM_NID]={ &(lvalues[4872]),0}, {"nameConstraints","X509v3 Name Constraints",NID_name_constraints,3, &(lvalues[4875]),0}, +{"ITU-T","itu-t",NID_itu_t,1,&(lvalues[4878]),0}, +{"JOINT-ISO-ITU-T","joint-iso-itu-t",NID_joint_iso_itu_t,1, + &(lvalues[4879]),0}, +{"international-organizations","International Organizations", + NID_international_organizations,1,&(lvalues[4880]),0}, }; static ASN1_OBJECT *sn_objs[NUM_SN]={ @@ -1912,7 +1919,6 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={ &(nid_objs[110]),/* "CAST5-CFB" */ &(nid_objs[109]),/* "CAST5-ECB" */ &(nid_objs[111]),/* "CAST5-OFB" */ -&(nid_objs[404]),/* "CCITT" */ &(nid_objs[13]),/* "CN" */ &(nid_objs[141]),/* "CRLReason" */ &(nid_objs[417]),/* "CSPName" */ @@ -1947,7 +1953,8 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={ &(nid_objs[46]),/* "IDEA-OFB" */ &(nid_objs[181]),/* "ISO" */ &(nid_objs[183]),/* "ISO-US" */ -&(nid_objs[393]),/* "JOINT-ISO-CCITT" */ +&(nid_objs[721]),/* "ITU-T" */ +&(nid_objs[722]),/* "JOINT-ISO-ITU-T" */ &(nid_objs[15]),/* "L" */ &(nid_objs[ 3]),/* "MD2" */ &(nid_objs[257]),/* "MD4" */ @@ -1955,6 +1962,8 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={ &(nid_objs[114]),/* "MD5-SHA1" */ &(nid_objs[95]),/* "MDC2" */ &(nid_objs[388]),/* "Mail" */ +&(nid_objs[393]),/* "NULL" */ +&(nid_objs[404]),/* "NULL" */ &(nid_objs[57]),/* "Netscape" */ &(nid_objs[366]),/* "Nonce" */ &(nid_objs[17]),/* "O" */ @@ -2291,6 +2300,7 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={ &(nid_objs[527]),/* "identified-organization" */ &(nid_objs[461]),/* "info" */ &(nid_objs[101]),/* "initials" */ +&(nid_objs[723]),/* "international-organizations" */ &(nid_objs[142]),/* "invalidityDate" */ &(nid_objs[294]),/* "ipsecEndSystem" */ &(nid_objs[295]),/* "ipsecTunnel" */ @@ -2634,6 +2644,7 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ &(nid_objs[296]),/* "IPSec User" */ &(nid_objs[182]),/* "ISO Member Body" */ &(nid_objs[183]),/* "ISO US Member Body" */ +&(nid_objs[723]),/* "International Organizations" */ &(nid_objs[142]),/* "Invalidity Date" */ &(nid_objs[569]),/* "MIME MHS" */ &(nid_objs[388]),/* "Mail" */ @@ -2647,6 +2658,8 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ &(nid_objs[716]),/* "Microsoft Smartcardlogin" */ &(nid_objs[136]),/* "Microsoft Trust List Signing" */ &(nid_objs[717]),/* "Microsoft Universal Principal Name" */ +&(nid_objs[393]),/* "NULL" */ +&(nid_objs[404]),/* "NULL" */ &(nid_objs[72]),/* "Netscape Base Url" */ &(nid_objs[76]),/* "Netscape CA Policy Url" */ &(nid_objs[74]),/* "Netscape CA Revocation Url" */ @@ -2765,7 +2778,6 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ &(nid_objs[110]),/* "cast5-cfb" */ &(nid_objs[109]),/* "cast5-ecb" */ &(nid_objs[111]),/* "cast5-ofb" */ -&(nid_objs[404]),/* "ccitt" */ &(nid_objs[152]),/* "certBag" */ &(nid_objs[528]),/* "certicom-arc" */ &(nid_objs[581]),/* "certificate extensions" */ @@ -3015,8 +3027,9 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ &(nid_objs[101]),/* "initials" */ &(nid_objs[181]),/* "iso" */ &(nid_objs[687]),/* "issuer capabilities" */ +&(nid_objs[721]),/* "itu-t" */ &(nid_objs[492]),/* "janetMailbox" */ -&(nid_objs[393]),/* "joint-iso-ccitt" */ +&(nid_objs[722]),/* "joint-iso-itu-t" */ &(nid_objs[150]),/* "keyBag" */ &(nid_objs[477]),/* "lastModifiedBy" */ &(nid_objs[476]),/* "lastModifiedTime" */ @@ -3329,14 +3342,17 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ static ASN1_OBJECT *obj_objs[NUM_OBJ]={ &(nid_objs[ 0]),/* OBJ_undef 0 */ -&(nid_objs[404]),/* OBJ_ccitt 0 */ +&(nid_objs[721]),/* OBJ_itu_t 0 */ +&(nid_objs[393]),/* OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t */ +&(nid_objs[404]),/* OBJ_ccitt OBJ_itu_t */ &(nid_objs[434]),/* OBJ_data 0 9 */ &(nid_objs[181]),/* OBJ_iso 1 */ &(nid_objs[182]),/* OBJ_member_body 1 2 */ &(nid_objs[379]),/* OBJ_org 1 3 */ &(nid_objs[527]),/* OBJ_identified_organization 1 3 */ -&(nid_objs[393]),/* OBJ_joint_iso_ccitt 2 */ +&(nid_objs[722]),/* OBJ_joint_iso_itu_t 2 */ &(nid_objs[11]),/* OBJ_X500 2 5 */ +&(nid_objs[723]),/* OBJ_international_organizations 2 23 */ &(nid_objs[380]),/* OBJ_dod 1 3 6 */ &(nid_objs[12]),/* OBJ_X509 2 5 4 */ &(nid_objs[378]),/* OBJ_X500algorithms 2 5 8 */ diff --git a/demos/ssltest-ecc/README b/demos/ssltest-ecc/README index b045c28fb66ade1914a03f6b428ea359a3b5178e..71c070af161eb178775e7a6821a56255519ebb8f 100644 --- a/demos/ssltest-ecc/README +++ b/demos/ssltest-ecc/README @@ -1,6 +1,6 @@ Scripts for using ECC ciphersuites with test/testssl (these ciphersuites are described in the Internet Draft available at -http://www.ietf.org/internet-drafts/draft-ietf-tls-ecc-02.txt). +http://www.ietf.org/internet-drafts/draft-ietf-tls-ecc-03.txt). Use ECCcertgen.sh, RSAcertgen.sh, ECC-RSAcertgen.sh to generate root, client and server certs of the following types: diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 211dd03b110bd0ae491403ec8f841f94d5be85d4..7eff4f1d5ef1eb696874d5148d24a5378bb33548 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -1870,6 +1870,7 @@ static int ssl3_send_client_key_exchange(SSL *s) { EC_GROUP *srvr_group = NULL; int ecdh_clnt_cert = 0; + int field_size = 0; /* Did we send out the client's * ECDH share for use in premaster @@ -1962,7 +1963,21 @@ static int ssl3_send_client_key_exchange(SSL *s) * make sure to clear it out afterwards */ - n=ECDH_compute_key(p, KDF1_SHA1_len, srvr_ecpoint, clnt_ecdh, KDF1_SHA1); + field_size = EC_GROUP_get_degree(clnt_ecdh->group); + if (field_size <= 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_ECDH_LIB); + goto err; + } + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt; + * this is new with this version of the Internet Draft). + */ + if (field_size <= 24 * 8) + n=ECDH_compute_key(p, KDF1_SHA1_len, srvr_ecpoint, clnt_ecdh, KDF1_SHA1); + else + n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, @@ -2375,7 +2390,8 @@ err: /* This is the complement of nid2curve_id in s3_srvr.c. */ static int curve_id2nid(int curve_id) { - /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */ + /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) + * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */ static int nid_list[26] = { 0, diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index c2ac8cb2fc257450385196acb9c016c462d0b615..32ddc480900b03458f1db2abb7bc999b1fc81872 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -1962,6 +1962,7 @@ static int ssl3_get_client_key_exchange(SSL *s) if ((l & SSL_kECDH) || (l & SSL_kECDHE)) { int ret = 1; + int field_size = 0; /* initialize structures for server's ECDH key pair */ if ((srvr_ecdh = EC_KEY_new()) == NULL) @@ -2062,7 +2063,21 @@ static int ssl3_get_client_key_exchange(SSL *s) } /* Compute the shared pre-master secret */ - i = ECDH_compute_key(p, KDF1_SHA1_len, clnt_ecpoint, srvr_ecdh, KDF1_SHA1); + field_size = EC_GROUP_get_degree(srvr_ecdh->group); + if (field_size <= 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_ECDH_LIB); + goto err; + } + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt; + * this is new with this version of the Internet Draft). + */ + if (field_size <= 24 * 8) + i = ECDH_compute_key(p, KDF1_SHA1_len, clnt_ecpoint, srvr_ecdh, KDF1_SHA1); + else + i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, @@ -2459,7 +2474,8 @@ int ssl3_send_server_certificate(SSL *s) /* This is the complement of curve_id2nid in s3_clnt.c. */ static int nid2curve_id(int nid) { - /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */ + /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) + * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */ switch (nid) { case NID_sect163k1: /* sect163k1 (1) */ return 1; diff --git a/ssl/tls1.h b/ssl/tls1.h index 7f4a2f308580847b490a2252538e701c112bda20..be15445384122f7a3ddfdf2455c28274a52ce4f3 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -131,6 +131,10 @@ extern "C" { * suites to use 5B and 5C instead (this may change with future * updates to the IETF draft). */ +/* draft-ietf-tls-ecc-03.txt (June 2003) gives a changed list of + * ciphersuites, but does not define numbers for all of them + * because of possible conflicts with other Internet Drafts; + * most numbers are still subject to change. */ #define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x03000047 #define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x03000048 #define TLS1_CK_ECDH_ECDSA_WITH_DES_CBC_SHA 0x03000049