diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s3_lib.c | 8 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 80 | ||||
-rw-r--r-- | ssl/ssl_cert_table.h | 2 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 17 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 46 | ||||
-rw-r--r-- | ssl/ssl_local.h | 67 | ||||
-rw-r--r-- | ssl/ssl_rsa.c | 22 | ||||
-rw-r--r-- | ssl/statem/statem_clnt.c | 18 | ||||
-rw-r--r-- | ssl/statem/statem_lib.c | 7 | ||||
-rw-r--r-- | ssl/t1_lib.c | 428 |
10 files changed, 597 insertions, 98 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index e7078efa6c..17e318b857 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3366,6 +3366,7 @@ void ssl3_free(SSL *s) OPENSSL_clear_free(sc->s3.tmp.pms, sc->s3.tmp.pmslen); OPENSSL_free(sc->s3.tmp.peer_sigalgs); OPENSSL_free(sc->s3.tmp.peer_cert_sigalgs); + OPENSSL_free(sc->s3.tmp.valid_flags); ssl3_free_digest_list(sc); OPENSSL_free(sc->s3.alpn_selected); OPENSSL_free(sc->s3.alpn_proposed); @@ -3390,6 +3391,7 @@ int ssl3_clear(SSL *s) OPENSSL_clear_free(sc->s3.tmp.pms, sc->s3.tmp.pmslen); OPENSSL_free(sc->s3.tmp.peer_sigalgs); OPENSSL_free(sc->s3.tmp.peer_cert_sigalgs); + OPENSSL_free(sc->s3.tmp.valid_flags); EVP_PKEY_free(sc->s3.tmp.pkey); EVP_PKEY_free(sc->s3.peer_tmp); @@ -4244,7 +4246,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *cl if (SSL_CONNECTION_IS_TLS13(s)) { #ifndef OPENSSL_NO_PSK - int j; + size_t j; /* * If we allow "old" style PSK callbacks, and we have no certificate (so @@ -4254,8 +4256,8 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *cl * that. */ if (s->psk_server_callback != NULL) { - for (j = 0; j < SSL_PKEY_NUM && !ssl_has_cert(s, j); j++); - if (j == SSL_PKEY_NUM) { + for (j = 0; j < s->ssl_pkey_num && !ssl_has_cert(s, j); j++); + if (j == s->ssl_pkey_num) { /* There are no certificates */ prefer_sha256 = 1; } diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 320f6d322e..1c4f452997 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -58,13 +58,25 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void) return ssl_x509_store_ctx_idx; } -CERT *ssl_cert_new(void) +CERT *ssl_cert_new(size_t ssl_pkey_num) { - CERT *ret = OPENSSL_zalloc(sizeof(*ret)); + CERT *ret = NULL; + + /* Should never happen */ + if (!ossl_assert(ssl_pkey_num >= SSL_PKEY_NUM)) + return NULL; + ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) return NULL; + ret->ssl_pkey_num = ssl_pkey_num; + ret->pkeys = OPENSSL_zalloc(ret->ssl_pkey_num * sizeof(CERT_PKEY)); + if (ret->pkeys == NULL) { + OPENSSL_free(ret); + return NULL; + } + ret->key = &(ret->pkeys[SSL_PKEY_RSA]); ret->references = 1; ret->sec_cb = ssl_security_default_callback; @@ -73,6 +85,7 @@ CERT *ssl_cert_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); + OPENSSL_free(ret->pkeys); OPENSSL_free(ret); return NULL; } @@ -83,7 +96,7 @@ CERT *ssl_cert_new(void) CERT *ssl_cert_dup(CERT *cert) { CERT *ret = OPENSSL_zalloc(sizeof(*ret)); - int i; + size_t i; #ifndef OPENSSL_NO_COMP_ALG int j; #endif @@ -91,6 +104,11 @@ CERT *ssl_cert_dup(CERT *cert) if (ret == NULL) return NULL; + ret->ssl_pkey_num = cert->ssl_pkey_num; + ret->pkeys = OPENSSL_zalloc(ret->ssl_pkey_num * sizeof(CERT_PKEY)); + if (ret->pkeys == NULL) + return NULL; + ret->references = 1; ret->key = &ret->pkeys[cert->key - cert->pkeys]; ret->lock = CRYPTO_THREAD_lock_new(); @@ -108,7 +126,7 @@ CERT *ssl_cert_dup(CERT *cert) ret->dh_tmp_cb = cert->dh_tmp_cb; ret->dh_tmp_auto = cert->dh_tmp_auto; - for (i = 0; i < SSL_PKEY_NUM; i++) { + for (i = 0; i < ret->ssl_pkey_num; i++) { CERT_PKEY *cpk = cert->pkeys + i; CERT_PKEY *rpk = ret->pkeys + i; @@ -217,14 +235,14 @@ CERT *ssl_cert_dup(CERT *cert) void ssl_cert_clear_certs(CERT *c) { - int i; + size_t i; #ifndef OPENSSL_NO_COMP_ALG int j; #endif if (c == NULL) return; - for (i = 0; i < SSL_PKEY_NUM; i++) { + for (i = 0; i < c->ssl_pkey_num; i++) { CERT_PKEY *cpk = c->pkeys + i; X509_free(cpk->x509); cpk->x509 = NULL; @@ -269,6 +287,7 @@ void ssl_cert_free(CERT *c) #ifndef OPENSSL_NO_PSK OPENSSL_free(c->psk_identity_hint); #endif + OPENSSL_free(c->pkeys); CRYPTO_THREAD_lock_free(c->lock); OPENSSL_free(c); } @@ -297,6 +316,7 @@ int ssl_cert_set0_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) int ssl_cert_set1_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) { STACK_OF(X509) *dchain; + if (!chain) return ssl_cert_set0_chain(s, ctx, NULL); dchain = X509_chain_up_ref(chain); @@ -313,6 +333,7 @@ int ssl_cert_add0_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x) { int r; CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key; + if (!cpk) return 0; r = ssl_security_cert(s, ctx, x, 0, 0); @@ -337,10 +358,11 @@ int ssl_cert_add1_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x) int ssl_cert_select_current(CERT *c, X509 *x) { - int i; + size_t i; + if (x == NULL) return 0; - for (i = 0; i < SSL_PKEY_NUM; i++) { + for (i = 0; i < c->ssl_pkey_num; i++) { CERT_PKEY *cpk = c->pkeys + i; if (cpk->x509 == x && cpk->privatekey) { c->key = cpk; @@ -348,7 +370,7 @@ int ssl_cert_select_current(CERT *c, X509 *x) } } - for (i = 0; i < SSL_PKEY_NUM; i++) { + for (i = 0; i < c->ssl_pkey_num; i++) { CERT_PKEY *cpk = c->pkeys + i; if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) { c->key = cpk; @@ -360,18 +382,19 @@ int ssl_cert_select_current(CERT *c, X509 *x) int ssl_cert_set_current(CERT *c, long op) { - int i, idx; + size_t i, idx; + if (!c) return 0; if (op == SSL_CERT_SET_FIRST) idx = 0; else if (op == SSL_CERT_SET_NEXT) { - idx = (int)(c->key - c->pkeys + 1); - if (idx >= SSL_PKEY_NUM) + idx = (size_t)(c->key - c->pkeys + 1); + if (idx >= c->ssl_pkey_num) return 0; } else return 0; - for (i = idx; i < SSL_PKEY_NUM; i++) { + for (i = idx; i < c->ssl_pkey_num; i++) { CERT_PKEY *cpk = c->pkeys + i; if (cpk->x509 && cpk->privatekey) { c->key = cpk; @@ -1156,7 +1179,7 @@ int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other) ctx->cert->sec_ex); } -int ssl_cert_lookup_by_nid(int nid, size_t *pidx) +int ssl_cert_lookup_by_nid(int nid, size_t *pidx, SSL_CTX *ctx) { size_t i; @@ -1166,16 +1189,22 @@ int ssl_cert_lookup_by_nid(int nid, size_t *pidx) return 1; } } - + for (i = 0; i < ctx->sigalg_list_len; i++) { + if (ctx->ssl_cert_info[i].nid == nid) { + *pidx = SSL_PKEY_NUM + i; + return 1; + } + } return 0; } -const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx) +SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx, SSL_CTX *ctx) { size_t i; + /* check classic pk types */ for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) { - const SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i]; + SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i]; if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid)) || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) { @@ -1184,13 +1213,26 @@ const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx) return tmp_lu; } } + /* check provider-loaded pk types */ + for (i = 0; ctx->sigalg_list_len; i++) { + SSL_CERT_LOOKUP *tmp_lu = &(ctx->ssl_cert_info[i]); + + if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid)) + || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) { + if (pidx != NULL) + *pidx = SSL_PKEY_NUM + i; + return &ctx->ssl_cert_info[i]; + } + } return NULL; } -const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx) +SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx, SSL_CTX *ctx) { - if (idx >= OSSL_NELEM(ssl_cert_info)) + if (idx >= (OSSL_NELEM(ssl_cert_info) + ctx->sigalg_list_len)) return NULL; + else if (idx >= (OSSL_NELEM(ssl_cert_info))) + return &(ctx->ssl_cert_info[idx - SSL_PKEY_NUM]); return &ssl_cert_info[idx]; } diff --git a/ssl/ssl_cert_table.h b/ssl/ssl_cert_table.h index f66c5fe390..e70d9d624e 100644 --- a/ssl/ssl_cert_table.h +++ b/ssl/ssl_cert_table.h @@ -10,7 +10,7 @@ /* * Certificate table information. NB: table entries must match SSL_PKEY indices */ -static const SSL_CERT_LOOKUP ssl_cert_info [] = { +static SSL_CERT_LOOKUP ssl_cert_info [] = { {EVP_PKEY_RSA, SSL_aRSA}, /* SSL_PKEY_RSA */ {EVP_PKEY_RSA_PSS, SSL_aRSA}, /* SSL_PKEY_RSA_PSS_SIGN */ {EVP_PKEY_DSA, SSL_aDSS}, /* SSL_PKEY_DSA_SIGN */ diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 0ea998d383..a2b12a8811 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -2155,6 +2155,16 @@ int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) return ssl_cipher_table_auth[i].nid; } +int ssl_get_md_idx(int md_nid) { + int i; + + for(i = 0; i < SSL_MD_NUM_IDX; i++) { + if (md_nid == ssl_cipher_table_mac[i].nid) + return i; + } + return -1; +} + const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c) { int idx = c->algorithm2 & SSL_HANDSHAKE_MAC_MASK; @@ -2223,8 +2233,13 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead, int ssl_cert_is_disabled(SSL_CTX *ctx, size_t idx) { - const SSL_CERT_LOOKUP *cl = ssl_cert_lookup_by_idx(idx); + SSL_CERT_LOOKUP *cl; + + /* A provider-loaded key type is always enabled */ + if (idx >= SSL_PKEY_NUM) + return 0; + cl = ssl_cert_lookup_by_idx(idx, ctx); if (cl == NULL || (cl->amask & ctx->disabled_auth_mask) != 0) return 1; return 0; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index a2e2666962..1b2c527eb0 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -890,6 +890,7 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) goto sslerr; #endif + s->ssl_pkey_num = SSL_PKEY_NUM + ctx->sigalg_list_len; return ssl; cerr: ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB); @@ -1432,6 +1433,7 @@ void ossl_ssl_connection_free(SSL *ssl) s->wbio = NULL; BIO_free_all(s->rbio); s->rbio = NULL; + OPENSSL_free(s->s3.tmp.valid_flags); } void SSL_set0_rbio(SSL *s, BIO *rbio) @@ -3778,10 +3780,6 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, ret->session_timeout = meth->get_timeout(); ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; ret->verify_mode = SSL_VERIFY_NONE; - if ((ret->cert = ssl_cert_new()) == NULL) { - ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); - goto err; - } ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); if (ret->sessions == NULL) { @@ -3802,20 +3800,38 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq, #endif /* initialize cipher/digest methods table */ - if (!ssl_load_ciphers(ret)) + if (!ssl_load_ciphers(ret)) { + ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); goto err; - /* initialise sig algs */ - if (!ssl_setup_sig_algs(ret)) + } + + if (!ssl_load_groups(ret)) { + ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); + goto err; + } + + /* load provider sigalgs */ + if (!ssl_load_sigalgs(ret)) { + ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); goto err; + } - if (!ssl_load_groups(ret)) + /* initialise sig algs */ + if (!ssl_setup_sigalgs(ret)) { + ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); goto err; + } if (!SSL_CTX_set_ciphersuites(ret, OSSL_default_ciphersuites())) { ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); goto err; } + if ((ret->cert = ssl_cert_new(SSL_PKEY_NUM + ret->sigalg_list_len)) == NULL) { + ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); + goto err; + } + if (!ssl_create_cipher_list(ret, ret->tls13_ciphersuites, &ret->cipher_list, &ret->cipher_list_by_id, @@ -4057,8 +4073,22 @@ void SSL_CTX_free(SSL_CTX *a) OPENSSL_free(a->group_list[j].algorithm); } OPENSSL_free(a->group_list); + for (j = 0; j < a->sigalg_list_len; j++) { + OPENSSL_free(a->sigalg_list[j].name); + OPENSSL_free(a->sigalg_list[j].sigalg_name); + OPENSSL_free(a->sigalg_list[j].sigalg_oid); + OPENSSL_free(a->sigalg_list[j].sig_name); + OPENSSL_free(a->sigalg_list[j].sig_oid); + OPENSSL_free(a->sigalg_list[j].hash_name); + OPENSSL_free(a->sigalg_list[j].hash_oid); + OPENSSL_free(a->sigalg_list[j].keytype); + OPENSSL_free(a->sigalg_list[j].keytype_oid); + } + OPENSSL_free(a->sigalg_list); + OPENSSL_free(a->ssl_cert_info); OPENSSL_free(a->sigalg_lookup_cache); + OPENSSL_free(a->tls12_sigalgs); CRYPTO_THREAD_lock_free(a->lock); #ifdef TSAN_REQUIRES_LOCKING diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index e82564daf6..87fb1fd7cf 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -755,6 +755,31 @@ typedef struct tls_group_info_st { char is_kem; /* Mode for this Group: 0 is KEX, 1 is KEM */ } TLS_GROUP_INFO; +typedef struct tls_sigalg_info_st { + char *name; /* name as in IANA TLS specs */ + uint16_t code_point; /* IANA-specified code point of sigalg-name */ + char *sigalg_name; /* (combined) sigalg name */ + char *sigalg_oid; /* (combined) sigalg OID */ + char *sig_name; /* pure signature algorithm name */ + char *sig_oid; /* pure signature algorithm OID */ + char *hash_name; /* hash algorithm name */ + char *hash_oid; /* hash algorithm OID */ + char *keytype; /* keytype name */ + char *keytype_oid; /* keytype OID */ + unsigned int secbits; /* Bits of security (from SP800-57) */ + int mintls; /* Minimum TLS version, -1 unsupported */ + int maxtls; /* Maximum TLS version (or 0 for undefined) */ +} TLS_SIGALG_INFO; + +/* + * Structure containing table entry of certificate info corresponding to + * CERT_PKEY entries + */ +typedef struct { + int nid; /* NID of public key algorithm */ + uint32_t amask; /* authmask corresponding to key type */ +} SSL_CERT_LOOKUP; + /* flags values */ # define TLS_GROUP_TYPE 0x0000000FU /* Mask for group type */ # define TLS_GROUP_CURVE_PRIME 0x00000001U @@ -901,6 +926,7 @@ struct ssl_ctx_st { size_t max_cert_list; struct cert_st /* CERT */ *cert; + SSL_CERT_LOOKUP *ssl_cert_info; int read_ahead; /* callback that allows applications to peek at protocol messages */ @@ -1120,13 +1146,20 @@ struct ssl_ctx_st { const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]; size_t ssl_mac_secret_size[SSL_MD_NUM_IDX]; + size_t tls12_sigalgs_len; /* Cache of all sigalgs we know and whether they are available or not */ struct sigalg_lookup_st *sigalg_lookup_cache; + /* List of all sigalgs (code points) available, incl. from providers */ + uint16_t *tls12_sigalgs; TLS_GROUP_INFO *group_list; size_t group_list_len; size_t group_list_max_len; + TLS_SIGALG_INFO *sigalg_list; + size_t sigalg_list_len; + size_t sigalg_list_max_len; + /* masks of disabled algorithms */ uint32_t disabled_enc_mask; uint32_t disabled_mac_mask; @@ -1210,6 +1243,8 @@ struct ssl_connection_st { size_t init_num; /* amount read/written */ size_t init_off; /* amount read/written */ + size_t ssl_pkey_num; + struct { long flags; unsigned char server_random[SSL3_RANDOM_SIZE]; @@ -1244,6 +1279,7 @@ struct ssl_connection_st { int total_renegotiations; int num_renegotiations; int in_read_app_data; + struct { /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ unsigned char finish_md[EVP_MAX_MD_SIZE * 2]; @@ -1307,7 +1343,7 @@ struct ssl_connection_st { * SSL session: e.g. appropriate curve, signature algorithms etc. * If zero it can't be used at all. */ - uint32_t valid_flags[SSL_PKEY_NUM]; + uint32_t *valid_flags; /* * For servers the following masks are for the key and auth algorithms * that are supported by the certs below. For clients they are masks of @@ -1794,15 +1830,6 @@ typedef struct sigalg_lookup_st { int enabled; } SIGALG_LOOKUP; -/* - * Structure containing table entry of certificate info corresponding to - * CERT_PKEY entries - */ -typedef struct { - int nid; /* NID of public key algorithm */ - uint32_t amask; /* authmask corresponding to key type */ -} SSL_CERT_LOOKUP; - /* DTLS structures */ # ifndef OPENSSL_NO_SCTP @@ -2000,7 +2027,8 @@ typedef struct cert_st { int dh_tmp_auto; /* Flags related to certificates */ uint32_t cert_flags; - CERT_PKEY pkeys[SSL_PKEY_NUM]; + CERT_PKEY *pkeys; + size_t ssl_pkey_num; /* Custom certificate types sent in certificate request message. */ uint8_t *ctype; size_t ctype_len; @@ -2355,7 +2383,7 @@ const char *ssl_protocol_to_string(int version); /* Returns true if certificate and private key for 'idx' are present */ static ossl_inline int ssl_has_cert(const SSL_CONNECTION *s, int idx) { - if (idx < 0 || idx >= SSL_PKEY_NUM) + if (idx < 0 || idx >= (int)s->ssl_pkey_num) return 0; return s->cert->pkeys[idx].x509 != NULL && s->cert->pkeys[idx].privatekey != NULL; @@ -2381,7 +2409,7 @@ __owur int ossl_ssl_connection_reset(SSL *ssl); __owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes); __owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written); int ssl_clear_bad_session(SSL_CONNECTION *s); -__owur CERT *ssl_cert_new(void); +__owur CERT *ssl_cert_new(size_t ssl_pkey_num); __owur CERT *ssl_cert_dup(CERT *cert); void ssl_cert_clear_certs(CERT *c); void ssl_cert_free(CERT *c); @@ -2444,10 +2472,11 @@ __owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other); int ssl_get_security_level_bits(const SSL *s, const SSL_CTX *ctx, int *levelp); -__owur int ssl_cert_lookup_by_nid(int nid, size_t *pidx); -__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, - size_t *pidx); -__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx); +__owur int ssl_cert_lookup_by_nid(int nid, size_t *pidx, SSL_CTX *ctx); +__owur SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, + size_t *pidx, + SSL_CTX *ctx); +__owur SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx, SSL_CTX *ctx); int ssl_undefined_function(SSL *s); __owur int ssl_undefined_void_function(void); @@ -2460,8 +2489,9 @@ __owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL_CONNECTION *sc); __owur int ssl_x509err2alert(int type); void ssl_sort_cipher_list(void); int ssl_load_ciphers(SSL_CTX *ctx); -__owur int ssl_setup_sig_algs(SSL_CTX *ctx); +__owur int ssl_setup_sigalgs(SSL_CTX *ctx); int ssl_load_groups(SSL_CTX *ctx); +int ssl_load_sigalgs(SSL_CTX *ctx); __owur int ssl_fill_hello_random(SSL_CONNECTION *s, int server, unsigned char *field, size_t len, DOWNGRADE dgrd); @@ -2750,6 +2780,7 @@ __owur int ssl_handshake_hash(SSL_CONNECTION *s, unsigned char *out, size_t outlen, size_t *hashlen); __owur const EVP_MD *ssl_md(SSL_CTX *ctx, int idx); +int ssl_get_md_idx(int md_nid); __owur const EVP_MD *ssl_handshake_md(SSL_CONNECTION *s); __owur const EVP_MD *ssl_prf_md(SSL_CONNECTION *s); diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 76466b55b9..3d4ad85a62 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -17,8 +17,8 @@ #include <openssl/x509v3.h> #include <openssl/pem.h> -static int ssl_set_cert(CERT *c, X509 *x509); -static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); +static int ssl_set_cert(CERT *c, X509 *x509, SSL_CTX *ctx); +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey, SSL_CTX *ctx); #define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ | SSL_EXT_CLIENT_HELLO \ @@ -47,7 +47,7 @@ int SSL_use_certificate(SSL *ssl, X509 *x) return 0; } - return ssl_set_cert(sc->cert, x); + return ssl_set_cert(sc->cert, x, SSL_CONNECTION_GET_CTX(sc)); } int SSL_use_certificate_file(SSL *ssl, const char *file, int type) @@ -128,11 +128,11 @@ int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) return ret; } -static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey, SSL_CTX *ctx) { size_t i; - if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + if (ssl_cert_lookup_by_pkey(pkey, &i, ctx) == NULL) { ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return 0; } @@ -160,7 +160,7 @@ int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } - ret = ssl_set_pkey(sc->cert, pkey); + ret = ssl_set_pkey(sc->cert, pkey, SSL_CONNECTION_GET_CTX(sc)); return ret; } @@ -243,10 +243,10 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) ERR_raise(ERR_LIB_SSL, rv); return 0; } - return ssl_set_cert(ctx->cert, x); + return ssl_set_cert(ctx->cert, x, ctx); } -static int ssl_set_cert(CERT *c, X509 *x) +static int ssl_set_cert(CERT *c, X509 *x, SSL_CTX *ctx) { EVP_PKEY *pkey; size_t i; @@ -257,7 +257,7 @@ static int ssl_set_cert(CERT *c, X509 *x) return 0; } - if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + if (ssl_cert_lookup_by_pkey(pkey, &i, ctx) == NULL) { ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return 0; } @@ -371,7 +371,7 @@ int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } - return ssl_set_pkey(ctx->cert, pkey); + return ssl_set_pkey(ctx->cert, pkey, ctx); } int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) @@ -1010,7 +1010,7 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr goto out; } } - if (ssl_cert_lookup_by_pkey(pubkey, &i) == NULL) { + if (ssl_cert_lookup_by_pkey(pubkey, &i, ctx) == NULL) { ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto out; } diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index f1ed43abd3..e5b036390a 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1988,7 +1988,8 @@ WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s, return WORK_ERROR; } - if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) { + if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx, + SSL_CONNECTION_GET_CTX(s))) == NULL) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return WORK_ERROR; } @@ -2434,11 +2435,15 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL_CONNECTION *s, PACKET *pkt) MSG_PROCESS_RETURN tls_process_certificate_request(SSL_CONNECTION *s, PACKET *pkt) { - size_t i; - /* Clear certificate validity flags */ - for (i = 0; i < SSL_PKEY_NUM; i++) - s->s3.tmp.valid_flags[i] = 0; + if (s->s3.tmp.valid_flags != NULL) + memset(s->s3.tmp.valid_flags, 0, s->ssl_pkey_num * sizeof(uint32_t)); + else + s->s3.tmp.valid_flags = OPENSSL_zalloc(s->ssl_pkey_num * sizeof(uint32_t)); + + /* Give up for good if allocation didn't work */ + if (s->s3.tmp.valid_flags == NULL) + return 0; if (SSL_CONNECTION_IS_TLS13(s)) { PACKET reqctx, extensions; @@ -3768,7 +3773,8 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s) return 1; /* This is the passed certificate */ - clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx); + clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx, + SSL_CONNECTION_GET_CTX(s)); /* Check certificate is recognised and suitable for cipher */ if (clu == NULL || (alg_a & clu->amask) == 0) { diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index ebedbeefbb..1bc01e1d25 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -468,7 +468,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL_CONNECTION *s, PACKET *pkt) goto err; } - if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) { + if (ssl_cert_lookup_by_pkey(pkey, NULL, sctx) == NULL) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); goto err; @@ -1602,7 +1602,7 @@ static int ssl_method_error(const SSL_CONNECTION *s, const SSL_METHOD *method) */ static int is_tls13_capable(const SSL_CONNECTION *s) { - int i; + size_t i; int curve; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); @@ -1625,7 +1625,8 @@ static int is_tls13_capable(const SSL_CONNECTION *s) if (s->psk_find_session_cb != NULL || s->cert->cert_cb != NULL) return 1; - for (i = 0; i < SSL_PKEY_NUM; i++) { + /* All provider-based sig algs are required to support at least TLS1.3 */ + for (i = 0; i < s->ssl_pkey_num; i++) { /* Skip over certs disallowed for TLSv1.3 */ switch (i) { case SSL_PKEY_DSA_SIGN: diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 25aaa9b56d..5622532314 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -222,7 +222,7 @@ static const uint16_t suiteb_curves[] = { OSSL_TLS_GROUP_ID_secp384r1, }; -struct provider_group_data_st { +struct provider_ctx_data_st { SSL_CTX *ctx; OSSL_PROVIDER *provider; }; @@ -231,7 +231,7 @@ struct provider_group_data_st { static OSSL_CALLBACK add_provider_groups; static int add_provider_groups(const OSSL_PARAM params[], void *data) { - struct provider_group_data_st *pgd = data; + struct provider_ctx_data_st *pgd = data; SSL_CTX *ctx = pgd->ctx; OSSL_PROVIDER *provider = pgd->provider; const OSSL_PARAM *p; @@ -375,7 +375,7 @@ static int add_provider_groups(const OSSL_PARAM params[], void *data) static int discover_provider_groups(OSSL_PROVIDER *provider, void *vctx) { - struct provider_group_data_st pgd; + struct provider_ctx_data_st pgd; pgd.ctx = vctx; pgd.provider = provider; @@ -417,6 +417,319 @@ int ssl_load_groups(SSL_CTX *ctx) return 1; } +#define TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE 10 +static OSSL_CALLBACK add_provider_sigalgs; +static int add_provider_sigalgs(const OSSL_PARAM params[], void *data) +{ + struct provider_ctx_data_st *pgd = data; + SSL_CTX *ctx = pgd->ctx; + OSSL_PROVIDER *provider = pgd->provider; + const OSSL_PARAM *p; + TLS_SIGALG_INFO *sinf = NULL; + EVP_KEYMGMT *keymgmt; + const char *keytype; + unsigned int code_point = 0; + int ret = 0; + + if (ctx->sigalg_list_max_len == ctx->sigalg_list_len) { + TLS_SIGALG_INFO *tmp = NULL; + + if (ctx->sigalg_list_max_len == 0) + tmp = OPENSSL_malloc(sizeof(TLS_SIGALG_INFO) + * TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE); + else + tmp = OPENSSL_realloc(ctx->sigalg_list, + (ctx->sigalg_list_max_len + + TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE) + * sizeof(TLS_SIGALG_INFO)); + if (tmp == NULL) + return 0; + ctx->sigalg_list = tmp; + memset(tmp + ctx->sigalg_list_max_len, 0, + sizeof(TLS_SIGALG_INFO) * TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE); + ctx->sigalg_list_max_len += TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE; + } + + sinf = &ctx->sigalg_list[ctx->sigalg_list_len]; + + /* First, mandatory parameters */ + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_NAME); + if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) { + ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + goto err; + } + OPENSSL_free(sinf->sigalg_name); + sinf->sigalg_name = OPENSSL_strdup(p->data); + if (sinf->sigalg_name == NULL) + goto err; + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME); + if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) { + ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + goto err; + } + OPENSSL_free(sinf->name); + sinf->name = OPENSSL_strdup(p->data); + if (sinf->name == NULL) + goto err; + + p = OSSL_PARAM_locate_const(params, + OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT); + if (p == NULL + || !OSSL_PARAM_get_uint(p, &code_point) + || code_point > UINT16_MAX) { + ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + goto err; + } + sinf->code_point = (uint16_t)code_point; + + p = OSSL_PARAM_locate_const(params, + OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS); + if (p == NULL || !OSSL_PARAM_get_uint(p, &sinf->secbits)) { + ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + goto err; + } + + /* Now, optional parameters */ + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_OID); + if (p == NULL) { + sinf->sigalg_oid = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->sigalg_oid); + sinf->sigalg_oid = OPENSSL_strdup(p->data); + if (sinf->sigalg_oid == NULL) + goto err; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME); + if (p == NULL) { + sinf->sig_name = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->sig_name); + sinf->sig_name = OPENSSL_strdup(p->data); + if (sinf->sig_name == NULL) + goto err; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_SIG_OID); + if (p == NULL) { + sinf->sig_oid = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->sig_oid); + sinf->sig_oid = OPENSSL_strdup(p->data); + if (sinf->sig_oid == NULL) + goto err; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_HASH_NAME); + if (p == NULL) { + sinf->hash_name = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->hash_name); + sinf->hash_name = OPENSSL_strdup(p->data); + if (sinf->hash_name == NULL) + goto err; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_HASH_OID); + if (p == NULL) { + sinf->hash_oid = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->hash_oid); + sinf->hash_oid = OPENSSL_strdup(p->data); + if (sinf->hash_oid == NULL) + goto err; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE); + if (p == NULL) { + sinf->keytype = NULL; + } else if (p->data_type != OSSL_PARAM_UTF8_STRING) { + goto err; + } else { + OPENSSL_free(sinf->keytype); |