summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2014-12-06 13:51:07 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2014-12-06 13:51:07 +0000
commit8a9669eab3aa8fbefe6c6fc0abcc2b73cfde0f8c (patch)
treed411930744429ef2f7d07e2e310f591dc0bae687
parentea0586b18e6c30ae314a7cced53b5bd49801603b (diff)
Use appropriate internal types for EC curves and formats, rather than
storing and processing in wire encoded form. Inspired by boringssl. ok miod@
-rw-r--r--lib/libssl/ssl.h11
-rw-r--r--lib/libssl/ssl_locl.h6
-rw-r--r--lib/libssl/t1_lib.c218
3 files changed, 124 insertions, 111 deletions
diff --git a/lib/libssl/ssl.h b/lib/libssl/ssl.h
index 2416b46d46f..2b14116e4cd 100644
--- a/lib/libssl/ssl.h
+++ b/lib/libssl/ssl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl.h,v 1.72 2014/11/18 05:33:43 miod Exp $ */
+/* $OpenBSD: ssl.h,v 1.73 2014/12/06 13:51:06 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -500,9 +500,10 @@ struct ssl_session_st {
struct ssl_session_st *prev, *next;
char *tlsext_hostname;
size_t tlsext_ecpointformatlist_length;
- unsigned char *tlsext_ecpointformatlist; /* peer's list */
+ uint8_t *tlsext_ecpointformatlist; /* peer's list */
size_t tlsext_ellipticcurvelist_length;
- unsigned char *tlsext_ellipticcurvelist; /* peer's list */
+ uint16_t *tlsext_ellipticcurvelist; /* peer's list */
+
/* RFC4507 info */
unsigned char *tlsext_tick; /* Session ticket */
size_t tlsext_ticklen; /* Session ticket length */
@@ -1142,9 +1143,9 @@ struct ssl_st {
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
size_t tlsext_ecpointformatlist_length;
- unsigned char *tlsext_ecpointformatlist; /* our list */
+ uint8_t *tlsext_ecpointformatlist; /* our list */
size_t tlsext_ellipticcurvelist_length;
- unsigned char *tlsext_ellipticcurvelist; /* our list */
+ uint16_t *tlsext_ellipticcurvelist; /* our list */
/* TLS Session Ticket extension override */
TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h
index 74cacd4eec3..c425f67a5a5 100644
--- a/lib/libssl/ssl_locl.h
+++ b/lib/libssl/ssl_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_locl.h,v 1.77 2014/11/18 05:33:43 miod Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.78 2014/12/06 13:51:06 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -800,8 +800,8 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
-int tls1_ec_curve_id2nid(int curve_id);
-int tls1_ec_nid2curve_id(int nid);
+int tls1_ec_curve_id2nid(uint16_t curve_id);
+uint16_t tls1_ec_nid2curve_id(int nid);
int tls1_check_curve(SSL *s, const unsigned char *p, size_t len);
int tls1_get_shared_curve(SSL *s);
diff --git a/lib/libssl/t1_lib.c b/lib/libssl/t1_lib.c
index 5a6c0ddba0d..8a7553e3e73 100644
--- a/lib/libssl/t1_lib.c
+++ b/lib/libssl/t1_lib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: t1_lib.c,v 1.70 2014/12/06 13:28:56 jsing Exp $ */
+/* $OpenBSD: t1_lib.c,v 1.71 2014/12/06 13:51:06 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -240,45 +240,45 @@ static int nid_list[] = {
NID_brainpoolP512r1 /* brainpoolP512r1 (28) */
};
-static const unsigned char ecformats_default[] = {
+static const uint8_t ecformats_default[] = {
TLSEXT_ECPOINTFORMAT_uncompressed,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
-static const unsigned char eccurves_default[] = {
- 0,14, /* sect571r1 (14) */
- 0,13, /* sect571k1 (13) */
- 0,25, /* secp521r1 (25) */
- 0,28, /* brainpool512r1 (28) */
- 0,11, /* sect409k1 (11) */
- 0,12, /* sect409r1 (12) */
- 0,27, /* brainpoolP384r1 (27) */
- 0,24, /* secp384r1 (24) */
- 0,9, /* sect283k1 (9) */
- 0,10, /* sect283r1 (10) */
- 0,26, /* brainpoolP256r1 (26) */
- 0,22, /* secp256k1 (22) */
- 0,23, /* secp256r1 (23) */
- 0,8, /* sect239k1 (8) */
- 0,6, /* sect233k1 (6) */
- 0,7, /* sect233r1 (7) */
- 0,20, /* secp224k1 (20) */
- 0,21, /* secp224r1 (21) */
- 0,4, /* sect193r1 (4) */
- 0,5, /* sect193r2 (5) */
- 0,18, /* secp192k1 (18) */
- 0,19, /* secp192r1 (19) */
- 0,1, /* sect163k1 (1) */
- 0,2, /* sect163r1 (2) */
- 0,3, /* sect163r2 (3) */
- 0,15, /* secp160k1 (15) */
- 0,16, /* secp160r1 (16) */
- 0,17, /* secp160r2 (17) */
+static const uint16_t eccurves_default[] = {
+ 14, /* sect571r1 (14) */
+ 13, /* sect571k1 (13) */
+ 25, /* secp521r1 (25) */
+ 28, /* brainpool512r1 (28) */
+ 11, /* sect409k1 (11) */
+ 12, /* sect409r1 (12) */
+ 27, /* brainpoolP384r1 (27) */
+ 24, /* secp384r1 (24) */
+ 9, /* sect283k1 (9) */
+ 10, /* sect283r1 (10) */
+ 26, /* brainpoolP256r1 (26) */
+ 22, /* secp256k1 (22) */
+ 23, /* secp256r1 (23) */
+ 8, /* sect239k1 (8) */
+ 6, /* sect233k1 (6) */
+ 7, /* sect233r1 (7) */
+ 20, /* secp224k1 (20) */
+ 21, /* secp224r1 (21) */
+ 4, /* sect193r1 (4) */
+ 5, /* sect193r2 (5) */
+ 18, /* secp192k1 (18) */
+ 19, /* secp192r1 (19) */
+ 1, /* sect163k1 (1) */
+ 2, /* sect163r1 (2) */
+ 3, /* sect163r2 (3) */
+ 15, /* secp160k1 (15) */
+ 16, /* secp160r1 (16) */
+ 17, /* secp160r2 (17) */
};
int
-tls1_ec_curve_id2nid(int curve_id)
+tls1_ec_curve_id2nid(uint16_t curve_id)
{
/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
if ((curve_id < 1) ||
@@ -287,7 +287,7 @@ tls1_ec_curve_id2nid(int curve_id)
return nid_list[curve_id - 1];
}
-int
+uint16_t
tls1_ec_nid2curve_id(int nid)
{
/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
@@ -359,7 +359,7 @@ tls1_ec_nid2curve_id(int nid)
* exists, or the default formats if a custom list has not been specified.
*/
static void
-tls1_get_formatlist(SSL *s, int client_formats, const unsigned char **pformats,
+tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats,
size_t *pformatslen)
{
if (client_formats != 0) {
@@ -382,7 +382,7 @@ tls1_get_formatlist(SSL *s, int client_formats, const unsigned char **pformats,
* exists, or the default curves if a custom list has not been specified.
*/
static void
-tls1_get_curvelist(SSL *s, int client_curves, const unsigned char **pcurves,
+tls1_get_curvelist(SSL *s, int client_curves, const uint16_t **pcurves,
size_t *pcurveslen)
{
if (client_curves != 0) {
@@ -403,17 +403,20 @@ tls1_get_curvelist(SSL *s, int client_curves, const unsigned char **pcurves,
int
tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
{
- const unsigned char *curves;
+ const uint16_t *curves;
size_t curveslen, i;
+ uint16_t cid;
/* Only named curves are supported. */
if (len != 3 || p[0] != NAMED_CURVE_TYPE)
return (0);
+ cid = (p[1] << 8) | p[2];
+
tls1_get_curvelist(s, 0, &curves, &curveslen);
- for (i = 0; i < curveslen; i += 2, curves += 2) {
- if (p[1] == curves[0] && p[2] == curves[1])
+ for (i = 0; i < curveslen; i++) {
+ if (curves[i] == cid)
return (1);
}
return (0);
@@ -422,10 +425,9 @@ tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
int
tls1_get_shared_curve(SSL *s)
{
- const unsigned char *pref, *supp, *tsupp;
size_t preflen, supplen, i, j;
+ const uint16_t *pref, *supp;
unsigned long server_pref;
- int id;
/* Cannot do anything on the client side. */
if (s->server == 0)
@@ -436,13 +438,10 @@ tls1_get_shared_curve(SSL *s)
tls1_get_curvelist(s, (server_pref == 0), &pref, &preflen);
tls1_get_curvelist(s, (server_pref != 0), &supp, &supplen);
- for (i = 0; i < preflen; i += 2, pref += 2) {
- tsupp = supp;
- for (j = 0; j < supplen; j += 2, tsupp += 2) {
- if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) {
- id = (pref[0] << 8) | pref[1];
- return (tls1_ec_curve_id2nid(id));
- }
+ for (i = 0; i < preflen; i++) {
+ for (j = 0; j < supplen; j++) {
+ if (pref[i] == supp[j])
+ return (tls1_ec_curve_id2nid(pref[i]));
}
}
return (NID_undef);
@@ -450,7 +449,7 @@ tls1_get_shared_curve(SSL *s)
/* For an EC key set TLS ID and required compression based on parameters. */
static int
-tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, EC_KEY *ec)
+tls1_set_ec_id(uint16_t *curve_id, uint8_t *comp_id, EC_KEY *ec)
{
const EC_GROUP *grp;
const EC_METHOD *meth;
@@ -473,13 +472,10 @@ tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, EC_KEY *ec)
id = tls1_ec_nid2curve_id(nid);
/* If we have an ID set it, otherwise set arbitrary explicit curve. */
- if (id != 0) {
- curve_id[0] = 0;
- curve_id[1] = (unsigned char)id;
- } else {
- curve_id[0] = 0xff;
- curve_id[1] = is_prime ? 0x01 : 0x02;
- }
+ if (id != 0)
+ *curve_id = id;
+ else
+ *curve_id = is_prime ? 0xff01 : 0xff02;
/* Specify the compression identifier. */
if (comp_id != NULL) {
@@ -499,10 +495,11 @@ tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, EC_KEY *ec)
/* Check that an EC key is compatible with extensions. */
static int
-tls1_check_ec_key(SSL *s, unsigned char *curve_id, unsigned char *comp_id)
+tls1_check_ec_key(SSL *s, const uint16_t *curve_id, const uint8_t *comp_id)
{
- const unsigned char *curves, *formats;
size_t curveslen, formatslen, i;
+ const uint16_t *curves;
+ const uint8_t *formats;
/*
* Check point formats extension if present, otherwise everything
@@ -510,8 +507,8 @@ tls1_check_ec_key(SSL *s, unsigned char *curve_id, unsigned char *comp_id)
*/
tls1_get_formatlist(s, 1, &formats, &formatslen);
if (comp_id != NULL && formats != NULL) {
- for (i = 0; i < formatslen; i++, formats++) {
- if (*comp_id == *formats)
+ for (i = 0; i < formatslen; i++) {
+ if (formats[i] == *comp_id)
break;
}
if (i == formatslen)
@@ -522,10 +519,9 @@ tls1_check_ec_key(SSL *s, unsigned char *curve_id, unsigned char *comp_id)
* Check curve list if present, otherwise everything is supported.
*/
tls1_get_curvelist(s, 1, &curves, &curveslen);
- if (curves != NULL) {
- for (i = 0; i < curveslen; i += 2, curves += 2) {
- if (curves[0] == curve_id[0] &&
- curves[1] == curve_id[1])
+ if (curve_id != NULL && curves != NULL) {
+ for (i = 0; i < curveslen; i++) {
+ if (curves[i] == *curve_id)
break;
}
if (i == curveslen)
@@ -540,7 +536,8 @@ int
tls1_check_ec_server_key(SSL *s)
{
CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC;
- unsigned char comp_id, curve_id[2];
+ uint16_t curve_id;
+ uint8_t comp_id;
EVP_PKEY *pkey;
int rv;
@@ -548,12 +545,12 @@ tls1_check_ec_server_key(SSL *s)
return (0);
if ((pkey = X509_get_pubkey(cpk->x509)) == NULL)
return (0);
- rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec);
+ rv = tls1_set_ec_id(&curve_id, &comp_id, pkey->pkey.ec);
EVP_PKEY_free(pkey);
if (rv != 1)
return (0);
- return tls1_check_ec_key(s, curve_id, &comp_id);
+ return tls1_check_ec_key(s, &curve_id, &comp_id);
}
/* Check EC temporary key is compatible with client extensions. */
@@ -561,7 +558,7 @@ int
tls1_check_ec_tmp_key(SSL *s)
{
EC_KEY *ec = s->cert->ecdh_tmp;
- unsigned char curve_id[2];
+ uint16_t curve_id;
if (s->cert->ecdh_tmp_auto != 0) {
/* Need a shared curve. */
@@ -575,10 +572,10 @@ tls1_check_ec_tmp_key(SSL *s)
return (1);
return (0);
}
- if (tls1_set_ec_id(curve_id, NULL, ec) != 1)
+ if (tls1_set_ec_id(&curve_id, NULL, ec) != 1)
return (0);
- return tls1_check_ec_key(s, curve_id, NULL);
+ return tls1_check_ec_key(s, &curve_id, NULL);
}
/*
@@ -723,8 +720,10 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
}
if (using_ecc) {
- const unsigned char *curves, *formats;
size_t curveslen, formatslen, lenmax;
+ const uint16_t *curves;
+ const uint8_t *formats;
+ int i;
/*
* Add TLS extension ECPointFormats to the ClientHello message.
@@ -767,16 +766,16 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
}
s2n(TLSEXT_TYPE_elliptic_curves, ret);
- s2n(curveslen + 2, ret);
+ s2n((curveslen * 2) + 2, ret);
/* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
* elliptic_curve_list, but the examples use two bytes.
* http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
* resolves this to two bytes.
*/
- s2n(curveslen, ret);
- memcpy(ret, curves, curveslen);
- ret += curveslen;
+ s2n(curveslen * 2, ret);
+ for (i = 0; i < curveslen; i++)
+ s2n(curves[i], ret);
}
if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
@@ -1334,60 +1333,66 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
else if (type == TLSEXT_TYPE_ec_point_formats &&
s->version != DTLS1_VERSION) {
unsigned char *sdata = data;
- int ecpointformatlist_length;
+ size_t formatslen;
+ uint8_t *formats;
if (size < 1) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = TLS1_AD_DECODE_ERROR;
return 0;
}
- ecpointformatlist_length = *(sdata++);
-
- if (ecpointformatlist_length != size - 1) {
+ formatslen = *(sdata++);
+ if (formatslen != size - 1) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
+
if (!s->hit) {
free(s->session->tlsext_ecpointformatlist);
+ s->session->tlsext_ecpointformatlist = NULL;
s->session->tlsext_ecpointformatlist_length = 0;
- if ((s->session->tlsext_ecpointformatlist =
- malloc(ecpointformatlist_length)) == NULL) {
+
+ if ((formats = reallocarray(NULL, formatslen,
+ sizeof(uint8_t))) == NULL) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
+ memcpy(formats, sdata, formatslen);
+ s->session->tlsext_ecpointformatlist = formats;
+ s->session->tlsext_ecpointformatlist_length =
+ formatslen;
}
} else if (type == TLSEXT_TYPE_elliptic_curves &&
s->version != DTLS1_VERSION) {
unsigned char *sdata = data;
- int ellipticcurvelist_length;
+ size_t curveslen, i;
+ uint16_t *curves;
if (size < 2) {
- *al = SSL_AD_DECODE_ERROR;
+ *al = TLS1_AD_DECODE_ERROR;
return 0;
}
- ellipticcurvelist_length = (*(sdata++) << 8);
- ellipticcurvelist_length += (*(sdata++));
-
- if (ellipticcurvelist_length != size - 2 ||
- ellipticcurvelist_length < 1 ||
- ellipticcurvelist_length % 2 != 0) {
+ n2s(sdata, curveslen);
+ if (curveslen != size - 2 || curveslen % 2 != 0) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
+ curveslen /= 2;
+
if (!s->hit) {
if (s->session->tlsext_ellipticcurvelist) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
s->session->tlsext_ellipticcurvelist_length = 0;
- if ((s->session->tlsext_ellipticcurvelist =
- malloc(ellipticcurvelist_length)) == NULL) {
+ if ((curves = reallocarray(NULL, curveslen,
+ sizeof(uint16_t))) == NULL) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
- memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
+ for (i = 0; i < curveslen; i++)
+ n2s(sdata, curves[i]);
+ s->session->tlsext_ellipticcurvelist = curves;
+ s->session->tlsext_ellipticcurvelist_length = curveslen;
}
}
else if (type == TLSEXT_TYPE_session_ticket) {
@@ -1628,26 +1633,33 @@ ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
else if (type == TLSEXT_TYPE_ec_point_formats &&
s->version != DTLS1_VERSION) {
unsigned char *sdata = data;
- int ecpointformatlist_length = *(sdata++);
+ size_t formatslen;
+ uint8_t *formats;
- if (ecpointformatlist_length != size - 1 ||
- ecpointformatlist_length < 1) {
+ if (size < 1) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
+ formatslen = *(sdata++);
+ if (formatslen != size - 1) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+
if (!s->hit) {
free(s->session->tlsext_ecpointformatlist);
+ s->session->tlsext_ecpointformatlist = NULL;
s->session->tlsext_ecpointformatlist_length = 0;
- if ((s->session->tlsext_ecpointformatlist =
- malloc(ecpointformatlist_length)) == NULL) {
+ if ((formats = reallocarray(NULL, formatslen,
+ sizeof(uint8_t))) == NULL) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
+ memcpy(formats, sdata, formatslen);
+ s->session->tlsext_ecpointformatlist = formats;
s->session->tlsext_ecpointformatlist_length =
- ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist,
- sdata, ecpointformatlist_length);
+ formatslen;
}
}
else if (type == TLSEXT_TYPE_session_ticket) {