summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-05-01 17:41:25 +0100
committerMatt Caswell <matt@openssl.org>2020-06-05 10:31:06 +0100
commit263ff2c9d4c88f19133d21d9956d71edd7401d54 (patch)
tree167ce57291d3476481ad230703bde7dcd1ef8f83 /ssl
parenteca471391378139f76a7d1229b6a5a1dcc4b5603 (diff)
Check that Signature Algorithms are available before using them
We should confirm that Signature Algorithms are actually available through the loaded providers before we offer or select them. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11834)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/ssl_lib.c6
-rw-r--r--ssl/ssl_local.h6
-rw-r--r--ssl/t1_lib.c149
3 files changed, 114 insertions, 47 deletions
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index cb02129d9d..c2c2388716 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3166,6 +3166,10 @@ SSL_CTX *SSL_CTX_new_with_libctx(OPENSSL_CTX *libctx, const char *propq,
/* initialize cipher/digest methods table */
if (!ssl_load_ciphers(ret))
goto err2;
+ /* initialise sig algs */
+ if (!ssl_setup_sig_algs(ret))
+ goto err2;
+
if (!SSL_CTX_set_ciphersuites(ret, OSSL_default_ciphersuites()))
goto err;
@@ -3386,6 +3390,8 @@ void SSL_CTX_free(SSL_CTX *a)
for (i = 0; i < SSL_MD_NUM_IDX; i++)
ssl_evp_md_free(a->ssl_digest_methods[i]);
+ OPENSSL_free(a->sigalg_lookup_cache);
+
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a->propq);
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 5e2379c093..d2e8e23e23 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -1157,6 +1157,9 @@ struct ssl_ctx_st {
const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX];
size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
+
+ /* Cache of all sigalgs we know and whether they are available or not */
+ struct sigalg_lookup_st *sigalg_lookup_cache;
};
typedef struct cert_pkey_st CERT_PKEY;
@@ -1776,6 +1779,8 @@ typedef struct sigalg_lookup_st {
int sigandhash;
/* Required public key curve (ECDSA only) */
int curve;
+ /* Whether this signature algorithm is actually available for use */
+ int enabled;
} SIGALG_LOOKUP;
typedef struct tls_group_info_st {
@@ -2432,6 +2437,7 @@ __owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
__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_fill_hello_random(SSL *s, int server, unsigned char *field,
size_t len, DOWNGRADE dgrd);
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 5afe53acfc..a59d992e47 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -793,97 +793,97 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
#ifndef OPENSSL_NO_EC
{"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA256, NID_X9_62_prime256v1},
+ NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1},
{"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA384, NID_secp384r1},
+ NID_ecdsa_with_SHA384, NID_secp384r1, 1},
{"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA512, NID_secp521r1},
+ NID_ecdsa_with_SHA512, NID_secp521r1, 1},
{"ed25519", TLSEXT_SIGALG_ed25519,
NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"ed448", TLSEXT_SIGALG_ed448,
NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA224, NID_undef},
+ NID_ecdsa_with_SHA224, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
- NID_ecdsa_with_SHA1, NID_undef},
+ NID_ecdsa_with_SHA1, NID_undef, 1},
#endif
{"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha256WithRSAEncryption, NID_undef},
+ NID_sha256WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha384WithRSAEncryption, NID_undef},
+ NID_sha384WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha512WithRSAEncryption, NID_undef},
+ NID_sha512WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha224WithRSAEncryption, NID_undef},
+ NID_sha224WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_sha1WithRSAEncryption, NID_undef},
+ NID_sha1WithRSAEncryption, NID_undef, 1},
#ifndef OPENSSL_NO_DSA
{NULL, TLSEXT_SIGALG_dsa_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_dsa_with_SHA256, NID_undef},
+ NID_dsa_with_SHA256, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
- NID_dsaWithSHA1, NID_undef},
+ NID_dsaWithSHA1, NID_undef, 1},
#endif
#ifndef OPENSSL_NO_GOST
{NULL, TLSEXT_SIGALG_gostr34102012_256_intrinsic,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_512_intrinsic,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
- NID_undef, NID_undef},
+ NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
NID_id_GostR3410_2001, SSL_PKEY_GOST01,
- NID_undef, NID_undef}
+ NID_undef, NID_undef, 1}
#endif
};
/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
@@ -891,7 +891,7 @@ static const SIGALG_LOOKUP legacy_rsa_sigalg = {
"rsa_pkcs1_md5_sha1", 0,
NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
EVP_PKEY_RSA, SSL_PKEY_RSA,
- NID_undef, NID_undef
+ NID_undef, NID_undef, 1
};
/*
@@ -910,16 +910,72 @@ static const uint16_t tls_default_sigalg[] = {
0, /* SSL_PKEY_ED448 */
};
+int ssl_setup_sig_algs(SSL_CTX *ctx)
+{
+ size_t i;
+ const SIGALG_LOOKUP *lu;
+ SIGALG_LOOKUP *cache
+ = OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
+ EVP_PKEY *tmpkey = EVP_PKEY_new();
+ int ret = 0;
+
+ if (cache == NULL || tmpkey == NULL)
+ goto err;
+
+ ERR_set_mark();
+ for (i = 0, lu = sigalg_lookup_tbl;
+ i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
+ EVP_PKEY_CTX *pctx;
+
+ cache[i] = *lu;
+
+ /*
+ * Check hash is available.
+ * TODO(3.0): This test is not perfect. A provider could have support
+ * for a signature scheme, but not a particular hash. However the hash
+ * could be available from some other loaded provider. In that case it
+ * could be that the signature is available, and the hash is available
+ * independently - but not as a combination. We ignore this for now.
+ */
+ if (lu->hash != NID_undef
+ && ctx->ssl_digest_methods[lu->hash_idx] == NULL) {
+ cache[i].enabled = 0;
+ continue;
+ }
+
+ if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
+ cache[i].enabled = 0;
+ continue;
+ }
+ pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, tmpkey, ctx->propq);
+ /* If unable to create pctx we assume the sig algorithm is unavailable */
+ if (pctx == NULL)
+ cache[i].enabled = 0;
+ EVP_PKEY_CTX_free(pctx);
+ }
+ ERR_pop_to_mark();
+ ctx->sigalg_lookup_cache = cache;
+ cache = NULL;
+
+ ret = 1;
+ err:
+ OPENSSL_free(cache);
+ EVP_PKEY_free(tmpkey);
+ return ret;
+}
+
/* Lookup TLS signature algorithm */
-static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
+static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL *s, uint16_t sigalg)
{
size_t i;
- const SIGALG_LOOKUP *s;
+ const SIGALG_LOOKUP *lu;
- for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
- i++, s++) {
- if (s->sigalg == sigalg)
- return s;
+ for (i = 0, lu = s->ctx->sigalg_lookup_cache;
+ /* cache should have the same number of elements as sigalg_lookup_tbl */
+ i < OSSL_NELEM(sigalg_lookup_tbl);
+ lu++, i++) {
+ if (lu->sigalg == sigalg)
+ return lu;
}
return NULL;
}
@@ -1023,7 +1079,7 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
return NULL;
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, tls_default_sigalg[idx]);
if (!tls1_lookup_md(s->ctx, lu, NULL))
return NULL;
@@ -1107,7 +1163,7 @@ int tls_check_sigalg_curve(const SSL *s, int curve)
}
for (i = 0; i < siglen; i++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, sigs[i]);
if (lu == NULL)
continue;
@@ -1187,7 +1243,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
if (pkeyid == EVP_PKEY_RSA)
pkeyid = EVP_PKEY_RSA_PSS;
}
- lu = tls1_lookup_sigalg(sig);
+ lu = tls1_lookup_sigalg(s, sig);
/*
* Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
* is consistent with signature: RSA keys can be used for RSA-PSS
@@ -1761,8 +1817,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
unsigned char sigalgstr[2];
int secbits;
- /* See if sigalgs is recognised and if hash is enabled */
- if (!tls1_lookup_md(s->ctx, lu, NULL))
+ if (lu == NULL || !lu->enabled)
return 0;
/* DSA is not allowed in TLS 1.3 */
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
@@ -1841,7 +1896,7 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i++, sigalgs++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *sigalgs);
const SSL_CERT_LOOKUP *clu;
if (lu == NULL)
@@ -1866,7 +1921,7 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
int rv = 0;
for (i = 0; i < psiglen; i++, psig++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *psig);
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
continue;
@@ -1895,7 +1950,7 @@ static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *ptmp);
/* Skip disabled hashes or signature algorithms */
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
@@ -2056,7 +2111,7 @@ int SSL_get_sigalgs(SSL *s, int idx,
*rhash = (unsigned char)((*psig >> 8) & 0xff);
if (rsig != NULL)
*rsig = (unsigned char)(*psig & 0xff);
- lu = tls1_lookup_sigalg(*psig);
+ lu = tls1_lookup_sigalg(s, *psig);
if (psign != NULL)
*psign = lu != NULL ? lu->sig : NID_undef;
if (phash != NULL)
@@ -2294,7 +2349,7 @@ static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
}
for (i = 0; i < sigalgslen; i++) {
sigalg = use_pc_sigalgs
- ? tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i])
+ ? tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i])
: s->shared_sigalgs[i];
if (sigalg != NULL && sig_nid == sigalg->sigandhash)
return 1;
@@ -2442,7 +2497,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
size_t j;
const uint16_t *p = c->conf_sigalgs;
for (j = 0; j < c->conf_sigalgslen; j++, p++) {
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p);
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *p);
if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
break;
@@ -2777,7 +2832,7 @@ static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
if (!X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
return 0;
for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
- lu = tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i]);
+ lu = tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i]);
if (lu == NULL)
continue;