From 703bcee021790d33e07809c9b07fd51d2b4b5474 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 14 Dec 2016 14:31:21 +0000 Subject: [PATCH] Convert Sigalgs processing to use ints In TLSv1.2 an individual sig alg is represented by 1 byte for the hash and 1 byte for the signature. In TLSv1.3 each sig alg is represented by two bytes, where the two bytes together represent a single hash and signature combination. This converts the internal representation of sigalgs to use a single int for the pair, rather than a pair of bytes. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/2157) --- ssl/ssl_cert.c | 11 +- ssl/ssl_locl.h | 40 ++++-- ssl/statem/extensions_clnt.c | 2 +- ssl/statem/extensions_srvr.c | 6 +- ssl/statem/statem_clnt.c | 14 +- ssl/statem/statem_lib.c | 7 +- ssl/statem/statem_srvr.c | 3 +- ssl/t1_lib.c | 256 +++++++++++++++++++++-------------- 8 files changed, 214 insertions(+), 125 deletions(-) diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 9668976324..bbb6932210 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -141,20 +141,23 @@ CERT *ssl_cert_dup(CERT *cert) /* Configured sigalgs copied across */ if (cert->conf_sigalgs) { - ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); + ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen + * sizeof(*cert->conf_sigalgs)); if (ret->conf_sigalgs == NULL) goto err; - memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen); + memcpy(ret->conf_sigalgs, cert->conf_sigalgs, + cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs)); ret->conf_sigalgslen = cert->conf_sigalgslen; } else ret->conf_sigalgs = NULL; if (cert->client_sigalgs) { - ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); + ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen + * sizeof(*cert->client_sigalgs)); if (ret->client_sigalgs == NULL) goto err; memcpy(ret->client_sigalgs, cert->client_sigalgs, - cert->client_sigalgslen); + cert->client_sigalgslen * sizeof(*cert->client_sigalgs)); ret->client_sigalgslen = cert->client_sigalgslen; } else ret->client_sigalgs = NULL; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 02666f063f..9f974efbe0 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1243,7 +1243,7 @@ typedef struct ssl3_state_st { * algorithms extension for server or as part of a certificate * request for client. */ - unsigned char *peer_sigalgs; + unsigned int *peer_sigalgs; /* Size of above array */ size_t peer_sigalgslen; /* Digest peer uses for signing */ @@ -1512,7 +1512,7 @@ typedef struct cert_st { * the client hello as the supported signature algorithms extension. For * servers it represents the signature algorithms we are willing to use. */ - unsigned char *conf_sigalgs; + unsigned int *conf_sigalgs; /* Size of above array */ size_t conf_sigalgslen; /* @@ -1522,7 +1522,7 @@ typedef struct cert_st { * represents the signature algortithms we are willing to use for client * authentication. */ - unsigned char *client_sigalgs; + unsigned int *client_sigalgs; /* Size of above array */ size_t client_sigalgslen; /* @@ -1683,6 +1683,30 @@ typedef enum tlsext_index_en { */ #define TLSEXT_STATUSTYPE_nothing -1 +/* Sigalgs values */ +#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256 0x0403 +#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384 0x0503 +#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603 +#define TLSEXT_SIGALG_ecdsa_sha1 0x0203 +#define TLSEXT_SIGALG_rsa_pss_sha256 0x0804 +#define TLSEXT_SIGALG_rsa_pss_sha384 0x0805 +#define TLSEXT_SIGALG_rsa_pss_sha512 0x0806 +#define TLSEXT_SIGALG_rsa_pkcs1_sha256 0x0401 +#define TLSEXT_SIGALG_rsa_pkcs1_sha384 0x0501 +#define TLSEXT_SIGALG_rsa_pkcs1_sha512 0x0601 +#define TLSEXT_SIGALG_rsa_pkcs1_sha1 0x0201 +#define TLSEXT_SIGALG_dsa_sha256 0x0402 +#define TLSEXT_SIGALG_dsa_sha384 0x0502 +#define TLSEXT_SIGALG_dsa_sha512 0x0602 +#define TLSEXT_SIGALG_dsa_sha1 0x0202 +#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee +#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef +#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded + +/* A dummy signature value not valid for TLSv1.2 signature algs */ +#define TLSEXT_signature_rsa_pss 0x0101 + + #define MAX_COMPRESSIONS_SIZE 255 typedef struct { @@ -2152,12 +2176,12 @@ __owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md); void ssl_clear_hash_ctx(EVP_MD_CTX **hash); __owur long ssl_get_algorithm2(SSL *s); __owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt, - const unsigned char *psig, size_t psiglen); -__owur int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize); + const unsigned int *psig, size_t psiglen); +__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt); __owur int tls1_process_sigalgs(SSL *s); -__owur size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs); -__owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, - const unsigned char *sig, EVP_PKEY *pkey); +__owur size_t tls12_get_psigalgs(SSL *s, const unsigned int **psigs); +__owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, unsigned int sig, + EVP_PKEY *pkey); void ssl_set_client_disabled(SSL *s); __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op); diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index be0c979eb9..18f5ca3d1b 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -226,7 +226,7 @@ int tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx, int *al) { size_t salglen; - const unsigned char *salg; + const unsigned int *salg; if (!SSL_CLIENT_USE_SIGALGS(s)) return 1; diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index c868bb9e2c..d58eedda3a 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -204,15 +204,13 @@ int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) - || (PACKET_remaining(&supported_sig_algs) % 2) != 0 || PACKET_remaining(&supported_sig_algs) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } - if (!s->hit && !tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs), - PACKET_remaining(&supported_sig_algs))) { - *al = TLS1_AD_INTERNAL_ERROR; + if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) { + *al = TLS1_AD_DECODE_ERROR; return 0; } diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index ff57e9217a..432dc915b7 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1880,14 +1880,15 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) } if (SSL_USE_SIGALGS(s)) { - const unsigned char *sigalgs; + unsigned int sigalg; int rv; - if (!PACKET_get_bytes(pkt, &sigalgs, 2)) { + + if (!PACKET_get_net_2(pkt, &sigalg)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto err; } - rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey); + rv = tls12_check_peer_sigalg(&md, s, sigalg, pkey); if (rv == -1) { al = SSL_AD_INTERNAL_ERROR; goto err; @@ -2026,8 +2027,9 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) s->s3->tmp.ctype[i] = data[i]; if (SSL_USE_SIGALGS(s)) { - if (!PACKET_get_net_2(pkt, &list_len) - || !PACKET_get_bytes(pkt, &data, list_len)) { + PACKET sigalgs; + + if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); @@ -2039,7 +2041,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) s->s3->tmp.md[i] = NULL; s->s3->tmp.valid_flags[i] = 0; } - if ((list_len & 1) || !tls1_save_sigalgs(s, data, list_len)) { + if (!tls1_save_sigalgs(s, &sigalgs)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_SIGNATURE_ALGORITHMS_ERROR); diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 827de4be34..4353202e39 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -238,7 +238,7 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt) MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) { EVP_PKEY *pkey = NULL; - const unsigned char *sig, *data; + const unsigned char *data; #ifndef OPENSSL_NO_GOST unsigned char *gost_data = NULL; #endif @@ -284,12 +284,13 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) { if (SSL_USE_SIGALGS(s)) { int rv; + unsigned int sigalg; - if (!PACKET_get_bytes(pkt, &sig, 2)) { + if (!PACKET_get_net_2(pkt, &sigalg)) { al = SSL_AD_DECODE_ERROR; goto f_err; } - rv = tls12_check_peer_sigalg(&md, s, sig, pkey); + rv = tls12_check_peer_sigalg(&md, s, sigalg, pkey); if (rv == -1) { goto f_err; } else if (rv == 0) { diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index d08ed6f77b..12eb6aeb42 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2292,8 +2292,9 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } if (SSL_USE_SIGALGS(s)) { - const unsigned char *psigs; + const unsigned int *psigs; size_t nl = tls12_get_psigalgs(s, &psigs); + if (!WPACKET_start_sub_packet_u16(pkt) || !tls12_copy_sigalgs(s, pkt, psigs, nl) || !WPACKET_close(pkt)) { diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index ec8b9687bb..1ca2b61bec 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -719,55 +719,86 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) #endif /* OPENSSL_NO_EC */ -/* - * List of supported signature algorithms and hashes. Should make this - * customisable at some point, for now include everything we support. - */ - -#ifdef OPENSSL_NO_RSA -# define tlsext_sigalg_rsa(md) /* */ -#else -# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa, -#endif - -#ifdef OPENSSL_NO_DSA -# define tlsext_sigalg_dsa(md) /* */ -#else -# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa, +/* Default sigalg schemes */ +static const unsigned int tls12_sigalgs[] = { +#ifndef OPENSSL_NO_EC + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + TLSEXT_SIGALG_ecdsa_secp384r1_sha384, + TLSEXT_SIGALG_ecdsa_secp521r1_sha512, #endif -#ifdef OPENSSL_NO_EC -# define tlsext_sigalg_ecdsa(md)/* */ -#else -# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa, -#endif + TLSEXT_SIGALG_rsa_pkcs1_sha256, + TLSEXT_SIGALG_rsa_pkcs1_sha384, + TLSEXT_SIGALG_rsa_pkcs1_sha512, -#define tlsext_sigalg(md) \ - tlsext_sigalg_rsa(md) \ - tlsext_sigalg_dsa(md) \ - tlsext_sigalg_ecdsa(md) - -static const unsigned char tls12_sigalgs[] = { - tlsext_sigalg(TLSEXT_hash_sha512) - tlsext_sigalg(TLSEXT_hash_sha384) - tlsext_sigalg(TLSEXT_hash_sha256) - tlsext_sigalg(TLSEXT_hash_sha224) - tlsext_sigalg(TLSEXT_hash_sha1) -#ifndef OPENSSL_NO_GOST - TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001, - TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256, - TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512 -#endif + TLSEXT_SIGALG_dsa_sha256, + TLSEXT_SIGALG_dsa_sha384, + TLSEXT_SIGALG_dsa_sha512 }; #ifndef OPENSSL_NO_EC -static const unsigned char suiteb_sigalgs[] = { - tlsext_sigalg_ecdsa(TLSEXT_hash_sha256) - tlsext_sigalg_ecdsa(TLSEXT_hash_sha384) +static const unsigned int suiteb_sigalgs[] = { + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + TLSEXT_SIGALG_ecdsa_secp384r1_sha384 }; #endif -size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) +typedef struct sigalg_lookup_st { + unsigned int sigalg; + unsigned int hash; + unsigned int sig; +} SIGALG_LOOKUP; + +SIGALG_LOOKUP sigalg_lookup_tbl[] = { + {TLSEXT_SIGALG_ecdsa_secp256r1_sha256, TLSEXT_hash_sha256, TLSEXT_signature_ecdsa}, + {TLSEXT_SIGALG_ecdsa_secp384r1_sha384, TLSEXT_hash_sha384, TLSEXT_signature_ecdsa}, + {TLSEXT_SIGALG_ecdsa_secp521r1_sha512, TLSEXT_hash_sha512, TLSEXT_signature_ecdsa}, + {TLSEXT_SIGALG_ecdsa_sha1, TLSEXT_hash_sha1, TLSEXT_signature_ecdsa}, + {TLSEXT_SIGALG_rsa_pss_sha256, TLSEXT_hash_sha256, TLSEXT_signature_rsa_pss}, + {TLSEXT_SIGALG_rsa_pss_sha384, TLSEXT_hash_sha384, TLSEXT_signature_rsa_pss}, + {TLSEXT_SIGALG_rsa_pss_sha512, TLSEXT_hash_sha512, TLSEXT_signature_rsa_pss}, + {TLSEXT_SIGALG_rsa_pkcs1_sha256, TLSEXT_hash_sha256, TLSEXT_signature_rsa}, + {TLSEXT_SIGALG_rsa_pkcs1_sha384, TLSEXT_hash_sha384, TLSEXT_signature_rsa}, + {TLSEXT_SIGALG_rsa_pkcs1_sha512, TLSEXT_hash_sha512, TLSEXT_signature_rsa}, + {TLSEXT_SIGALG_rsa_pkcs1_sha1, TLSEXT_hash_sha1, TLSEXT_signature_rsa}, + {TLSEXT_SIGALG_dsa_sha256, TLSEXT_hash_sha256, TLSEXT_signature_dsa}, + {TLSEXT_SIGALG_dsa_sha384, TLSEXT_hash_sha384, TLSEXT_signature_dsa}, + {TLSEXT_SIGALG_dsa_sha512, TLSEXT_hash_sha512, TLSEXT_signature_dsa}, + {TLSEXT_SIGALG_dsa_sha1, TLSEXT_hash_sha1, TLSEXT_signature_dsa}, + {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256}, + {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512}, + {TLSEXT_SIGALG_gostr34102001_gostr3411, TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001} +}; + +static unsigned int tls_sigalg_get_hash(unsigned int sigalg) +{ + size_t i; + SIGALG_LOOKUP *curr; + + for (i = 0, curr = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, curr++) { + if (curr->sigalg == sigalg) + return curr->hash; + } + + return 0; +} + +static unsigned int tls_sigalg_get_sig(unsigned int sigalg) +{ + size_t i; + SIGALG_LOOKUP *curr; + + for (i = 0, curr = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, curr++) { + if (curr->sigalg == sigalg) + return curr->sig; + } + + return 0; +} + +size_t tls12_get_psigalgs(SSL *s, const unsigned int **psigs) { /* * If Suite B mode use Suite B sigalgs only, ignore any other @@ -797,7 +828,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) return s->cert->conf_sigalgslen; } else { *psigs = tls12_sigalgs; - return sizeof(tls12_sigalgs); + return OSSL_NELEM(tls12_sigalgs); } } @@ -805,17 +836,18 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) * Check signature algorithm is consistent with sent supported signature * algorithms and if so return relevant digest. */ -int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, - const unsigned char *sig, EVP_PKEY *pkey) +int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, unsigned int sig, + EVP_PKEY *pkey) { - const unsigned char *sent_sigs; + const unsigned int *sent_sigs; + char sigalgstr[2]; size_t sent_sigslen, i; int sigalg = tls12_get_sigid(pkey); /* Should never happen */ if (sigalg == -1) return -1; /* Check key type is consistent with signature */ - if (sigalg != (int)sig[1]) { + if ((unsigned int)sigalg != tls_sigalg_get_sig(sig)) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); return 0; } @@ -834,13 +866,13 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, if (curve_id[0]) return 0; if (curve_id[1] == TLSEXT_curve_P_256) { - if (sig[0] != TLSEXT_hash_sha256) { + if (tls_sigalg_get_hash(sig) != TLSEXT_hash_sha256) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_ILLEGAL_SUITEB_DIGEST); return 0; } } else if (curve_id[1] == TLSEXT_curve_P_384) { - if (sig[0] != TLSEXT_hash_sha384) { + if (tls_sigalg_get_hash(sig) != TLSEXT_hash_sha384) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_ILLEGAL_SUITEB_DIGEST); return 0; @@ -854,25 +886,31 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, /* Check signature matches a type we sent */ sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); - for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { - if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1]) + for (i = 0; i < sent_sigslen; i ++, sent_sigs++) { + if (sig == *sent_sigs) break; } /* Allow fallback to SHA1 if not strict mode */ if (i == sent_sigslen - && (sig[0] != TLSEXT_hash_sha1 + && (tls_sigalg_get_hash(sig) != TLSEXT_hash_sha1 || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); return 0; } - *pmd = tls12_get_hash(sig[0]); + *pmd = tls12_get_hash(tls_sigalg_get_hash(sig)); if (*pmd == NULL) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST); return 0; } - /* Make sure security callback allows algorithm */ + /* + * Make sure security callback allows algorithm. For historical reasons we + * have to pass the sigalg as a two byte char array. + */ + sigalgstr[0] = (sig >> 8) & 0xff; + sigalgstr[1] = sig & 0xff; if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK, - EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), (void *)sig)) { + EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), + (void *)sigalgstr)) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); return 0; } @@ -1411,18 +1449,20 @@ static int tls12_get_pkey_idx(unsigned char sig_alg) /* Convert TLS 1.2 signature algorithm extension values into NIDs */ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, - int *psignhash_nid, const unsigned char *data) + int *psignhash_nid, unsigned int data) { int sign_nid = NID_undef, hash_nid = NID_undef; if (!phash_nid && !psign_nid && !psignhash_nid) return; if (phash_nid || psignhash_nid) { - hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md)); + hash_nid = tls12_find_nid(tls_sigalg_get_hash(data), tls12_md, + OSSL_NELEM(tls12_md)); if (phash_nid) *phash_nid = hash_nid; } if (psign_nid || psignhash_nid) { - sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig)); + sign_nid = tls12_find_nid(tls_sigalg_get_sig(data), tls12_sig, + OSSL_NELEM(tls12_sig)); if (psign_nid) *psign_nid = sign_nid; } @@ -1434,17 +1474,22 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, } /* Check to see if a signature algorithm is allowed */ -static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp) +static int tls12_sigalg_allowed(SSL *s, int op, unsigned int ptmp) { /* See if we have an entry in the hash table and it is enabled */ - const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]); + const tls12_hash_info *hinf + = tls12_get_hash_info(tls_sigalg_get_hash(ptmp)); + unsigned char sigalgstr[2]; + if (hinf == NULL || ssl_md(hinf->md_idx) == NULL) return 0; /* See if public key algorithm allowed */ - if (tls12_get_pkey_idx(ptmp[1]) == -1) + if (tls12_get_pkey_idx(tls_sigalg_get_sig(ptmp)) == -1) return 0; /* Finally see if security callback allows it */ - return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp); + sigalgstr[0] = (ptmp >> 8) & 0xff; + sigalgstr[1] = ptmp & 0xff; + return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)sigalgstr); } /* @@ -1455,7 +1500,7 @@ static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp) void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op) { - const unsigned char *sigalgs; + const unsigned int *sigalgs; size_t i, sigalgslen; int have_rsa = 0, have_dsa = 0, have_ecdsa = 0; /* @@ -1464,23 +1509,23 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op) * down calls to security callback only check if we have to. */ sigalgslen = tls12_get_psigalgs(s, &sigalgs); - for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { - switch (sigalgs[1]) { + for (i = 0; i < sigalgslen; i ++, sigalgs++) { + switch (tls_sigalg_get_sig(*sigalgs)) { #ifndef OPENSSL_NO_RSA case TLSEXT_signature_rsa: - if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs)) + if (!have_rsa && tls12_sigalg_allowed(s, op, *sigalgs)) have_rsa = 1; break; #endif #ifndef OPENSSL_NO_DSA case TLSEXT_signature_dsa: - if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs)) + if (!have_dsa && tls12_sigalg_allowed(s, op, *sigalgs)) have_dsa = 1; break; #endif #ifndef OPENSSL_NO_EC case TLSEXT_signature_ecdsa: - if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs)) + if (!have_ecdsa && tls12_sigalg_allowed(s, op, *sigalgs)) have_ecdsa = 1; break; #endif @@ -1495,14 +1540,13 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op) } int tls12_copy_sigalgs(SSL *s, WPACKET *pkt, - const unsigned char *psig, size_t psiglen) + const unsigned int *psig, size_t psiglen) { size_t i; - for (i = 0; i < psiglen; i += 2, psig += 2) { - if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) { - if (!WPACKET_put_bytes_u8(pkt, psig[0]) - || !WPACKET_put_bytes_u8(pkt, psig[1])) + for (i = 0; i < psiglen; i++, psig++) { + if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, *psig)) { + if (!WPACKET_put_bytes_u16(pkt, *psig)) return 0; } } @@ -1511,24 +1555,24 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt, /* Given preference and allowed sigalgs set shared sigalgs */ static size_t tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig, - const unsigned char *pref, size_t preflen, - const unsigned char *allow, size_t allowlen) + const unsigned int *pref, size_t preflen, + const unsigned int *allow, size_t allowlen) { - const unsigned char *ptmp, *atmp; + const unsigned int *ptmp, *atmp; size_t i, j, nmatch = 0; - for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) { + for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) { /* Skip disabled hashes or signature algorithms */ - if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp)) + if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, *ptmp)) continue; - for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) { - if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) { + for (j = 0, atmp = allow; j < allowlen; j++, atmp++) { + if (*ptmp == *atmp) { nmatch++; if (shsig) { - shsig->rhash = ptmp[0]; - shsig->rsign = ptmp[1]; + shsig->rhash = tls_sigalg_get_hash(*ptmp); + shsig->rsign = tls_sigalg_get_sig(*ptmp); tls1_lookup_sigalg(&shsig->hash_nid, &shsig->sign_nid, - &shsig->signandhash_nid, ptmp); + &shsig->signandhash_nid, *ptmp); shsig++; } break; @@ -1541,7 +1585,7 @@ static size_t tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig, /* Set shared signature algorithms for SSL structures */ static int tls1_set_shared_sigalgs(SSL *s) { - const unsigned char *pref, *allow, *conf; + const unsigned int *pref, *allow, *conf; size_t preflen, allowlen, conflen; size_t nmatch; TLS_SIGALGS *salgs = NULL; @@ -1587,9 +1631,11 @@ static int tls1_set_shared_sigalgs(SSL *s) /* Set preferred digest for each key type */ -int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize) +int tls1_save_sigalgs(SSL *s, PACKET *pkt) { CERT *c = s->cert; + size_t size, i; + /* Extension ignored for inappropriate versions */ if (!SSL_USE_SIGALGS(s)) return 1; @@ -1597,12 +1643,26 @@ int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize) if (!c) return 0; + size = PACKET_remaining(pkt); + + /* Invalid data length */ + if ((size & 1) != 0) + return 0; + + size >>= 1; + OPENSSL_free(s->s3->tmp.peer_sigalgs); - s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize); + s->s3->tmp.peer_sigalgs = OPENSSL_malloc(size * sizeof(unsigned int)); if (s->s3->tmp.peer_sigalgs == NULL) return 0; - s->s3->tmp.peer_sigalgslen = dsize; - memcpy(s->s3->tmp.peer_sigalgs, data, dsize); + s->s3->tmp.peer_sigalgslen = size; + for (i = 0; i < size && PACKET_get_net_2(pkt, &s->s3->tmp.peer_sigalgs[i]); + i++) + continue; + + if (i != size) + return 0; + return 1; } @@ -1673,20 +1733,19 @@ int SSL_get_sigalgs(SSL *s, int idx, int *psign, int *phash, int *psignhash, unsigned char *rsig, unsigned char *rhash) { - const unsigned char *psig = s->s3->tmp.peer_sigalgs; - size_t numsigalgs = s->s3->tmp.peer_sigalgslen / 2; + unsigned int *psig = s->s3->tmp.peer_sigalgs; + size_t numsigalgs = s->s3->tmp.peer_sigalgslen; if (psig == NULL || numsigalgs > INT_MAX) return 0; if (idx >= 0) { - idx <<= 1; - if (idx >= (int)s->s3->tmp.peer_sigalgslen) + if (idx >= (int)numsigalgs) return 0; psig += idx; if (rhash) - *rhash = psig[0]; + *rhash = tls_sigalg_get_hash(*psig); if (rsig) - *rsig = psig[1]; - tls1_lookup_sigalg(phash, psign, psignhash, psig); + *rsig = tls_sigalg_get_sig(*psig); + tls1_lookup_sigalg(phash, psign, psignhash, *psig); } return (int)numsigalgs; } @@ -1789,12 +1848,12 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client) int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client) { - unsigned char *sigalgs, *sptr; + unsigned int *sigalgs, *sptr; int rhash, rsign; size_t i; if (salglen & 1) return 0; - sigalgs = OPENSSL_malloc(salglen); + sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs)); if (sigalgs == NULL) return 0; for (i = 0, sptr = sigalgs; i < salglen; i += 2) { @@ -1974,9 +2033,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, */ if (default_nid > 0 && c->conf_sigalgs) { size_t j; - const unsigned char *p = c->conf_sigalgs; - for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) { - if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign) + const unsigned int *p = c->conf_sigalgs; + for (j = 0; j < c->conf_sigalgslen; j++, p++) { + if (tls_sigalg_get_hash(*p) == TLSEXT_hash_sha1 + && tls_sigalg_get_sig(*p) == rsign) break; } if (j == c->conf_sigalgslen) { -- 2.25.1