From aab075e32e49adbf67c9518c715a237c8f3b0368 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sat, 12 Aug 2017 21:47:59 +0000 Subject: Convert TLS signature algorithms extension handling to the new framework. ok beck@ doug@ --- src/lib/libssl/ssl_clnt.c | 6 ++-- src/lib/libssl/ssl_locl.h | 7 +++-- src/lib/libssl/ssl_srvr.c | 8 +++--- src/lib/libssl/ssl_tlsext.c | 69 ++++++++++++++++++++++++++++++++++++++++++++- src/lib/libssl/ssl_tlsext.h | 9 +++++- src/lib/libssl/t1_lib.c | 63 +++++++++-------------------------------- 6 files changed, 99 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c index ec4a4104fc..2370ce06f7 100644 --- a/src/lib/libssl/ssl_clnt.c +++ b/src/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.16 2017/08/12 21:03:08 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.17 2017/08/12 21:47:59 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1621,9 +1621,7 @@ ssl3_get_certificate_request(SSL *s) SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } - if ((CBS_len(&sigalgs) & 1) || - !tls1_process_sigalgs(s, CBS_data(&sigalgs), - CBS_len(&sigalgs))) { + if (!tls1_process_sigalgs(s, &sigalgs)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); goto err; diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 914501213c..ddb3b30327 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.189 2017/08/12 21:03:08 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.190 2017/08/12 21:47:59 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1310,8 +1310,9 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg); void ssl_clear_hash_ctx(EVP_MD_CTX **hash); long ssl_get_algorithm2(SSL *s); -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize); -int tls12_get_req_sig_algs(SSL *s, unsigned char *p); +int tls1_process_sigalgs(SSL *s, CBS *cbs); +void tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, + size_t *sigalgs_len); int tls1_check_ec_server_key(SSL *s); int tls1_check_ec_tmp_key(SSL *s); diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index 50ce91ddd8..c43d63d991 100644 --- a/src/lib/libssl/ssl_srvr.c +++ b/src/lib/libssl/ssl_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_srvr.c,v 1.21 2017/08/12 21:03:08 jsing Exp $ */ +/* $OpenBSD: ssl_srvr.c,v 1.22 2017/08/12 21:47:59 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1577,12 +1577,12 @@ ssl3_send_certificate_request(SSL *s) unsigned char *sigalgs_data; size_t sigalgs_len; - sigalgs_len = tls12_get_req_sig_algs(s, NULL); + tls12_get_req_sig_algs(s, &sigalgs_data, &sigalgs_len); + if (!CBB_add_u16_length_prefixed(&cert_request, &sigalgs)) goto err; - if (!CBB_add_space(&sigalgs, &sigalgs_data, sigalgs_len)) + if (!CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len)) goto err; - tls12_get_req_sig_algs(s, sigalgs_data); } if (!CBB_add_u16_length_prefixed(&cert_request, &cert_auth)) diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c index 1813d46f41..9db2d1ab41 100644 --- a/src/lib/libssl/ssl_tlsext.c +++ b/src/lib/libssl/ssl_tlsext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_tlsext.c,v 1.7 2017/08/12 21:17:03 doug Exp $ */ +/* $OpenBSD: ssl_tlsext.c,v 1.8 2017/08/12 21:47:59 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -360,6 +360,64 @@ tlsext_ri_serverhello_parse(SSL *s, CBS *cbs, int *alert) return 0; } +/* + * Signature Algorithms - RFC 5246 section 7.4.1.4.1. + */ +int +tlsext_sigalgs_clienthello_needs(SSL *s) +{ + return (TLS1_get_client_version(s) >= TLS1_2_VERSION); +} + +int +tlsext_sigalgs_clienthello_build(SSL *s, CBB *cbb) +{ + unsigned char *sigalgs_data; + size_t sigalgs_len; + CBB sigalgs; + + tls12_get_req_sig_algs(s, &sigalgs_data, &sigalgs_len); + + if (!CBB_add_u16_length_prefixed(cbb, &sigalgs)) + return 0; + if (!CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +tlsext_sigalgs_clienthello_parse(SSL *s, CBS *cbs, int *alert) +{ + CBS sigalgs; + + if (!CBS_get_u16_length_prefixed(cbs, &sigalgs)) + return 0; + + return tls1_process_sigalgs(s, &sigalgs); +} + +int +tlsext_sigalgs_serverhello_needs(SSL *s) +{ + return 0; +} + +int +tlsext_sigalgs_serverhello_build(SSL *s, CBB *cbb) +{ + return 0; +} + +int +tlsext_sigalgs_serverhello_parse(SSL *s, CBS *cbs, int *alert) +{ + /* As per the RFC, servers must not send this extension. */ + return 0; +} + /* * Server Name Indication - RFC 6066, section 3. */ @@ -673,6 +731,15 @@ static struct tls_extension tls_extensions[] = { .serverhello_build = tlsext_sessionticket_serverhello_build, .serverhello_parse = tlsext_sessionticket_serverhello_parse, }, + { + .type = TLSEXT_TYPE_signature_algorithms, + .clienthello_needs = tlsext_sigalgs_clienthello_needs, + .clienthello_build = tlsext_sigalgs_clienthello_build, + .clienthello_parse = tlsext_sigalgs_clienthello_parse, + .serverhello_needs = tlsext_sigalgs_serverhello_needs, + .serverhello_build = tlsext_sigalgs_serverhello_build, + .serverhello_parse = tlsext_sigalgs_serverhello_parse, + }, }; #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h index 1e701e941a..4f8ae0cf35 100644 --- a/src/lib/libssl/ssl_tlsext.h +++ b/src/lib/libssl/ssl_tlsext.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_tlsext.h,v 1.6 2017/08/12 21:17:03 doug Exp $ */ +/* $OpenBSD: ssl_tlsext.h,v 1.7 2017/08/12 21:47:59 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -23,6 +23,13 @@ int tlsext_ri_serverhello_needs(SSL *s); int tlsext_ri_serverhello_build(SSL *s, CBB *cbb); int tlsext_ri_serverhello_parse(SSL *s, CBS *cbs, int *alert); +int tlsext_sigalgs_clienthello_needs(SSL *s); +int tlsext_sigalgs_clienthello_build(SSL *s, CBB *cbb); +int tlsext_sigalgs_clienthello_parse(SSL *s, CBS *cbs, int *alert); +int tlsext_sigalgs_serverhello_needs(SSL *s); +int tlsext_sigalgs_serverhello_build(SSL *s, CBB *cbb); +int tlsext_sigalgs_serverhello_parse(SSL *s, CBS *cbs, int *alert); + int tlsext_sni_clienthello_needs(SSL *s); int tlsext_sni_clienthello_build(SSL *s, CBB *cbb); int tlsext_sni_clienthello_parse(SSL *s, CBS *cbs, int *alert); diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index 63d401c337..e27a7d1a59 100644 --- a/src/lib/libssl/t1_lib.c +++ b/src/lib/libssl/t1_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_lib.c,v 1.129 2017/08/12 21:17:03 doug Exp $ */ +/* $OpenBSD: t1_lib.c,v 1.130 2017/08/12 21:47:59 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -654,14 +654,11 @@ static unsigned char tls12_sigalgs[] = { TLSEXT_hash_sha1, TLSEXT_signature_ecdsa, }; -int -tls12_get_req_sig_algs(SSL *s, unsigned char *p) +void +tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, size_t *sigalgs_len) { - size_t slen = sizeof(tls12_sigalgs); - - if (p) - memcpy(p, tls12_sigalgs, slen); - return (int)slen; + *sigalgs = tls12_sigalgs; + *sigalgs_len = sizeof(tls12_sigalgs); } unsigned char * @@ -690,17 +687,6 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) return NULL; ret += len; - if (TLS1_get_client_version(s) >= TLS1_2_VERSION) { - if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6) - return NULL; - - s2n(TLSEXT_TYPE_signature_algorithms, ret); - s2n(sizeof(tls12_sigalgs) + 2, ret); - s2n(sizeof(tls12_sigalgs), ret); - memcpy(ret, tls12_sigalgs, sizeof(tls12_sigalgs)); - ret += sizeof(tls12_sigalgs); - } - if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && s->version != DTLS1_VERSION) { int i; @@ -991,7 +977,6 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, unsigned short len; unsigned char *data = *p; unsigned char *end = d + n; - int sigalg_seen = 0; CBS cbs; s->internal->servername_done = 0; @@ -1026,24 +1011,7 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) return 0; - if (type == TLSEXT_TYPE_signature_algorithms) { - int dsize; - if (sigalg_seen || size < 2) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - sigalg_seen = 1; - n2s(data, dsize); - size -= 2; - if (dsize != size || dsize & 1) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - if (!tls1_process_sigalgs(s, data, dsize)) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - } else if (type == TLSEXT_TYPE_status_request && + if (type == TLSEXT_TYPE_status_request && s->version != DTLS1_VERSION) { if (size < 5) { @@ -1830,36 +1798,30 @@ tls12_get_hash(unsigned char hash_alg) /* Set preferred digest for each key type */ int -tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) +tls1_process_sigalgs(SSL *s, CBS *cbs) { - int idx; const EVP_MD *md; CERT *c = s->cert; - CBS cbs; + int idx; /* Extension ignored for inappropriate versions */ if (!SSL_USE_SIGALGS(s)) return 1; /* Should never happen */ - if (!c || dsize < 0) + if (c == NULL) return 0; - CBS_init(&cbs, data, dsize); - c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL; c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL; c->pkeys[SSL_PKEY_ECC].digest = NULL; c->pkeys[SSL_PKEY_GOST01].digest = NULL; - while (CBS_len(&cbs) > 0) { + while (CBS_len(cbs) > 0) { uint8_t hash_alg, sig_alg; - if (!CBS_get_u8(&cbs, &hash_alg) || - !CBS_get_u8(&cbs, &sig_alg)) { - /* Should never happen */ + if (!CBS_get_u8(cbs, &hash_alg) || !CBS_get_u8(cbs, &sig_alg)) return 0; - } switch (sig_alg) { case TLSEXT_signature_rsa: @@ -1888,7 +1850,8 @@ tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) } - /* Set any remaining keys to default values. NOTE: if alg is not + /* + * Set any remaining keys to default values. NOTE: if alg is not * supported it stays as NULL. */ if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) { -- cgit v1.2.3-55-g6feb