first cut at sigalg loading

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19312)
This commit is contained in:
Michael Baentsch 2022-09-26 17:32:05 +02:00 committed by Pauli
parent 1817dcaf55
commit ee58915cfd
18 changed files with 3351 additions and 192 deletions

View File

@ -30,6 +30,15 @@ OpenSSL 3.2
*Oliver Mihatsch*
* Added support for pluggable (provider-based) TLS signature algorithms.
This enables TLS 1.3 authentication operations with algorithms embedded
in providers not included by default in OpenSSL. In combination with
the already available pluggable KEM and X.509 support, this enables
for example suitable providers to deliver post-quantum or quantum-safe
cryptography to OpenSSL users.
*Michael Baentsch*
* Added support for Hybrid Public Key Encryption (HPKE) as defined
in RFC9180. HPKE is required for TLS Encrypted ClientHello (ECH),
Message Layer Security (MLS) and other IETF specifications.

View File

@ -28,6 +28,9 @@ OpenSSL 3.2
by default.
* TCP Fast Open (RFC7413) support is available on Linux, macOS, and FreeBSD
where enabled and supported.
* Full support for provider-based/pluggable signature algorithms in TLS 1.3
operations as well as X.509 data structure support. With a suitable provider
this fully enables use of post-quantum/quantum-safe cryptography.
OpenSSL 3.1
-----------

View File

@ -258,7 +258,8 @@ static const char *get_sigtype(int nid)
return "gost2012_512";
default:
return NULL;
/* Try to output provider-registered sig alg name */
return OBJ_nid2sn(nid);
}
}

View File

@ -210,7 +210,7 @@ int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
/* Modify *siginf according to alg and sig. Return 1 on success, else 0. */
static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
const ASN1_STRING *sig)
const ASN1_STRING *sig, const EVP_PKEY *pubkey)
{
int pknid, mdnid;
const EVP_MD *md;
@ -232,12 +232,20 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
case NID_undef:
/* If we have one, use a custom handler for this algorithm */
ameth = EVP_PKEY_asn1_find(NULL, pknid);
if (ameth == NULL || ameth->siginf_set == NULL
|| !ameth->siginf_set(siginf, alg, sig)) {
ERR_raise(ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET);
return 0;
if (ameth != NULL && ameth->siginf_set != NULL
&& ameth->siginf_set(siginf, alg, sig))
break;
if (pubkey != NULL) {
int secbits;
secbits = EVP_PKEY_get_security_bits(pubkey);
if (secbits != 0) {
siginf->secbits = secbits;
break;
}
}
break;
ERR_raise(ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET);
return 0;
/*
* SHA1 and MD5 are known to be broken. Reduce security bits so that
* they're no longer accepted at security level 1.
@ -288,5 +296,6 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
/* Returns 1 on success, 0 on failure */
int ossl_x509_init_sig_info(X509 *x)
{
return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature,
X509_PUBKEY_get0(x->cert_info.key));
}

View File

@ -607,6 +607,129 @@ or maximum. A -1 indicates that the group should not be used in that protocol.
=back
=head3 "TLS-SIGALG" Capability
The "TLS-SIGALG" capability can be queried by libssl to discover the list of
TLS signature algorithms that a provider can support. Each signature supported
can be used for client- or server-authentication in addition to the built-in
signature algorithms.
TLS1.3 clients can advertise the list of TLS signature algorithms they support
in the signature_algorithms extension, and TLS servers can select an algorithm
from the offered list that they also support. In this way a provider can add
to the list of signature algorithms that libssl already supports with
additional ones.
Each TLS signature algorithm that a provider supports should be described via
the callback passed in through the provider_get_capabilities function. Each
algorithm can have the following details supplied:
=over 4
=item "iana-name" (B<OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME>) <UTF8 string>
The name of the signature algorithm as given in the IANA TLS Signature Scheme
registry as "Description":
L<https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme>.
This value must be supplied.
=item "iana-code-point" (B<OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT>) <unsigned integer>
The TLS algorithm ID value as given in the IANA TLS SignatureScheme registry.
This value must be supplied.
=item "sigalg-name" (B<OSSL_CAPABILITY_TLS_SIGALG_NAME>) <UTF8 string>
A name for the full (possibly composite hash-and-signature) signature
algorithm.
The provider may, but is not obligated to, provide a signature implementation
with this name; if it doesn't, this is assumed to be a composite of a pure
signature algorithm and a hash algorithm, which must be given with the
parameters "sig-name" and "hash-name".
This value must be supplied.
=item "sigalg-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_OID>) <UTF8 string>
The OID of the "sigalg-name" algorithm in canonical numeric text form. If
this parameter is given, OBJ_create() will be used to create an OBJ and
a NID for this OID, using the "sigalg-name" parameter for its (short) name.
Otherwise, it's assumed to already exist in the object database, possibly
done by the provider with the core_obj_create() upcall.
This value is optional.
=item "sig-name" (B<OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME>) <UTF8 string>
The name of the pure signature algorithm that is part of a composite
"sigalg-name". If "sigalg-name" is implemented by the provider, this
parameter is redundant and must not be given.
This value is optional.
=item "sig-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_SIG_OID>) <UTF8 string>
The OID of the "sig-name" algorithm in canonical numeric text form. If
this parameter is given, OBJ_create() will be used to create an OBJ and
a NID for this OID, using the "sig-name" parameter for its (short) name.
Otherwise, it is assumed to already exist in the object database. This
can be done by the provider using the core_obj_create() upcall.
This value is optional.
=item "hash-name" (B<OSSL_CAPABILITY_TLS_SIGALG_HASH_NAME>) <UTF8 string>
The name of the hash algorithm that is part of a composite "sigalg-name".
If "sigalg-name" is implemented by the provider, this parameter is redundant
and must not be given.
This value is optional.
=item "hash-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_HASH_OID>) <UTF8 string>
The OID of the "hash-name" algorithm in canonical numeric text form. If
this parameter is given, OBJ_create() will be used to create an OBJ and
a NID for this OID, using the "hash-name" parameter for its (short) name.
Otherwise, it's assumed to already exist in the object database, possibly
done by the provider with the core_obj_create() upcall.
This value is optional.
=item "key-type" (B<OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE>) <UTF8 string>
The key type of the public key of applicable certificates. If this parameter
isn't present, it's assumed to be the same as "sig-name" if that's present,
otherwise "sigalg-name".
This value is optional.
=item "key-type-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID>) <UTF8 string>
The OID of the "key-type" in canonical numeric text form. If
this parameter is given, OBJ_create() will be used to create an OBJ and
a NID for this OID, using the "key-type" parameter for its (short) name.
Otherwise, it's assumed to already exist in the object database, possibly
done by the provider with the core_obj_create() upcall.
This value is optional.
=item "sec-bits" (B<OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS>) <unsigned integer>
The number of bits of security offered by keys of this algorithm. The number
of bits should be comparable with the ones given in table 2 and 3 of the NIST
SP800-57 document. This number is used to determine the security strength of
the algorithm if no digest algorithm has been registered that otherwise
defines the security strength. If the signature algorithm implements its own
digest internally, this value needs to be set to properly reflect the overall
security strength.
This value must be supplied.
=item "tls-min-tls" (B<OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS>) <integer>
=item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS>) <integer>
These parameters can be used to describe the minimum and maximum TLS
versions supported by the signature algorithm. The values equate to the
on-the-wire encoding of the various TLS versions. For example TLSv1.3 is
0x0304 (772 decimal), and TLSv1.2 is 0x0303 (771 decimal). A 0 indicates that
there is no defined minimum or maximum. A -1 indicates that the signature
algorithm should not be used in that protocol.
Presently values representing anything other than TLS1.3 mean that the
complete algorithm is ignored.
=back
=head1 NOTES
The core_obj_create() and core_obj_add_sigid() functions were not thread safe

View File

@ -540,6 +540,21 @@ extern "C" {
#define OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS "tls-min-dtls"
#define OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS "tls-max-dtls"
/* TLS-SIGALG Capability */
#define OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME "tls-sigalg-iana-name"
#define OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT "tls-sigalg-code-point"
#define OSSL_CAPABILITY_TLS_SIGALG_NAME "tls-sigalg-name"
#define OSSL_CAPABILITY_TLS_SIGALG_OID "tls-sigalg-oid"
#define OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME "tls-sigalg-sig-name"
#define OSSL_CAPABILITY_TLS_SIGALG_SIG_OID "tls-sigalg-sig-oid"
#define OSSL_CAPABILITY_TLS_SIGALG_HASH_NAME "tls-sigalg-hash-name"
#define OSSL_CAPABILITY_TLS_SIGALG_HASH_OID "tls-sigalg-hash-oid"
#define OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE "tls-sigalg-keytype"
#define OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID "tls-sigalg-keytype-oid"
#define OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS "tls-sigalg-sec-bits"
#define OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS "tls-min-tls"
#define OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS "tls-max-tls"
/*-
* storemgmt parameters
*/

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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 */

View File

@ -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;

View File

@ -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))
goto err;
/* initialise sig algs */
if (!ssl_setup_sig_algs(ret))
if (!ssl_load_ciphers(ret)) {
ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB);
goto err;
}
if (!ssl_load_groups(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;
}
/* 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

View File

@ -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);

View File

@ -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;
}

View File

@ -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) {

View File

@ -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:

View File

@ -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);
sinf->keytype = OPENSSL_strdup(p->data);
if (sinf->keytype == NULL)
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID);
if (p == NULL) {
sinf->keytype_oid = NULL;
} else if (p->data_type != OSSL_PARAM_UTF8_STRING) {
goto err;
} else {
OPENSSL_free(sinf->keytype_oid);
sinf->keytype_oid = OPENSSL_strdup(p->data);
if (sinf->keytype_oid == NULL)
goto err;
}
/* The remaining parameters below are mandatory again */
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &sinf->mintls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
if ((sinf->mintls != 0) && (sinf->mintls != -1) &&
((sinf->mintls < TLS1_3_VERSION))) {
/* ignore this sigalg as this OpenSSL doesn't know how to handle it */
ret = 1;
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &sinf->maxtls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
if ((sinf->maxtls != 0) && (sinf->maxtls != -1) &&
((sinf->maxtls < sinf->mintls))) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
if ((sinf->maxtls != 0) && (sinf->maxtls != -1) &&
((sinf->maxtls < TLS1_3_VERSION))) {
/* ignore this sigalg as this OpenSSL doesn't know how to handle it */
ret = 1;
goto err;
}
/*
* Now check that the algorithm is actually usable for our property query
* string. Regardless of the result we still return success because we have
* successfully processed this signature, even though we may decide not to
* use it.
*/
ret = 1;
ERR_set_mark();
keytype = (sinf->keytype != NULL
? sinf->keytype
: (sinf->sig_name != NULL
? sinf->sig_name
: sinf->sigalg_name));
keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, keytype, ctx->propq);
if (keymgmt != NULL) {
/*
* We have successfully fetched the algorithm - however if the provider
* doesn't match this one then we ignore it.
*
* Note: We're cheating a little here. Technically if the same algorithm
* is available from more than one provider then it is undefined which
* implementation you will get back. Theoretically this could be
* different every time...we assume here that you'll always get the
* same one back if you repeat the exact same fetch. Is this a reasonable
* assumption to make (in which case perhaps we should document this
* behaviour)?
*/
if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) {
/*
* We have a match - so we could use this signature;
* Check proper object registration first, though.
* Don't care about return value as this may have been
* done within providers or previous calls to
* add_provider_sigalgs.
*/
OBJ_create(sinf->sigalg_oid, sinf->sigalg_name, NULL);
/* sanity check: Without successful registration don't use alg */
if ((OBJ_txt2nid(sinf->sigalg_name) == NID_undef) ||
(OBJ_nid2obj(OBJ_txt2nid(sinf->sigalg_name)) == NULL)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
if (sinf->sig_name != NULL)
OBJ_create(sinf->sig_oid, sinf->sig_name, NULL);
if (sinf->keytype != NULL)
OBJ_create(sinf->keytype_oid, sinf->keytype, NULL);
if (sinf->hash_name != NULL)
OBJ_create(sinf->hash_oid, sinf->hash_name, NULL);
OBJ_add_sigid(OBJ_txt2nid(sinf->sigalg_name),
(sinf->hash_name != NULL
? OBJ_txt2nid(sinf->hash_name)
: NID_undef),
OBJ_txt2nid(keytype));
ctx->sigalg_list_len++;
sinf = NULL;
}
EVP_KEYMGMT_free(keymgmt);
}
ERR_pop_to_mark();
err:
if (sinf != NULL) {
OPENSSL_free(sinf->name);
sinf->name = NULL;
OPENSSL_free(sinf->sigalg_name);
sinf->sigalg_name = NULL;
OPENSSL_free(sinf->sigalg_oid);
sinf->sigalg_oid = NULL;
OPENSSL_free(sinf->sig_name);
sinf->sig_name = NULL;
OPENSSL_free(sinf->sig_oid);
sinf->sig_oid = NULL;
OPENSSL_free(sinf->hash_name);
sinf->hash_name = NULL;
OPENSSL_free(sinf->hash_oid);
sinf->hash_oid = NULL;
OPENSSL_free(sinf->keytype);
sinf->keytype = NULL;
OPENSSL_free(sinf->keytype_oid);
sinf->keytype_oid = NULL;
}
return ret;
}
static int discover_provider_sigalgs(OSSL_PROVIDER *provider, void *vctx)
{
struct provider_ctx_data_st pgd;
pgd.ctx = vctx;
pgd.provider = provider;
OSSL_PROVIDER_get_capabilities(provider, "TLS-SIGALG",
add_provider_sigalgs, &pgd);
/*
* Always OK, even if provider doesn't support the capability:
* Reconsider testing retval when legacy sigalgs are also loaded this way.
*/
return 1;
}
int ssl_load_sigalgs(SSL_CTX *ctx)
{
size_t i;
SSL_CERT_LOOKUP lu;
if (!OSSL_PROVIDER_do_all(ctx->libctx, discover_provider_sigalgs, ctx))
return 0;
/* now populate ctx->ssl_cert_info */
if (ctx->sigalg_list_len > 0) {
ctx->ssl_cert_info = OPENSSL_zalloc(sizeof(lu) * ctx->sigalg_list_len);
if (ctx->ssl_cert_info == NULL)
return 0;
for(i = 0; i < ctx->sigalg_list_len; i++) {
ctx->ssl_cert_info[i].nid = OBJ_txt2nid(ctx->sigalg_list[i].sigalg_name);
ctx->ssl_cert_info[i].amask = SSL_aANY;
}
}
/*
* For now, leave it at this: legacy sigalgs stay in their own
* data structures until "legacy cleanup" occurs.
*/
return 1;
}
static uint16_t tls1_group_name2id(SSL_CTX *ctx, const char *name)
{
size_t i;
@ -1153,24 +1466,36 @@ static const uint16_t tls_default_sigalg[] = {
0, /* SSL_PKEY_ED448 */
};
int ssl_setup_sig_algs(SSL_CTX *ctx)
int ssl_setup_sigalgs(SSL_CTX *ctx)
{
size_t i;
size_t i, cache_idx, sigalgs_len;
const SIGALG_LOOKUP *lu;
SIGALG_LOOKUP *cache
= OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
SIGALG_LOOKUP *cache = NULL;
uint16_t *tls12_sigalgs_list = NULL;
EVP_PKEY *tmpkey = EVP_PKEY_new();
int ret = 0;
if (ctx == NULL)
goto err;
sigalgs_len = OSSL_NELEM(sigalg_lookup_tbl) + ctx->sigalg_list_len;
cache = OPENSSL_malloc(sizeof(const SIGALG_LOOKUP) * sigalgs_len);
if (cache == NULL || tmpkey == NULL)
goto err;
tls12_sigalgs_list = OPENSSL_malloc(sizeof(uint16_t) * sigalgs_len);
if (tls12_sigalgs_list == NULL)
goto err;
ERR_set_mark();
/* First fill cache and tls12_sigalgs list from legacy algorithm list */
for (i = 0, lu = sigalg_lookup_tbl;
i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
EVP_PKEY_CTX *pctx;
cache[i] = *lu;
tls12_sigalgs_list[i] = tls12_sigalgs[i];
/*
* Check hash is available.
@ -1196,13 +1521,35 @@ int ssl_setup_sig_algs(SSL_CTX *ctx)
cache[i].enabled = 0;
EVP_PKEY_CTX_free(pctx);
}
/* Now complete cache and tls12_sigalgs list with provider sig information */
cache_idx = OSSL_NELEM(sigalg_lookup_tbl);
for (i = 0; i < ctx->sigalg_list_len; i++) {
TLS_SIGALG_INFO si = ctx->sigalg_list[i];
cache[cache_idx].name = si.name;
cache[cache_idx].sigalg = si.code_point;
tls12_sigalgs_list[cache_idx] = si.code_point;
cache[cache_idx].hash = si.hash_name?OBJ_txt2nid(si.hash_name):NID_undef;
cache[cache_idx].hash_idx = ssl_get_md_idx(cache[cache_idx].hash);
cache[cache_idx].sig = OBJ_txt2nid(si.sigalg_name);
cache[cache_idx].sig_idx = i + SSL_PKEY_NUM;
cache[cache_idx].sigandhash = OBJ_txt2nid(si.sigalg_name);
cache[cache_idx].curve = NID_undef;
/* all provided sigalgs are enabled by load */
cache[cache_idx].enabled = 1;
cache_idx++;
}
ERR_pop_to_mark();
ctx->sigalg_lookup_cache = cache;
ctx->tls12_sigalgs = tls12_sigalgs_list;
ctx->tls12_sigalgs_len = sigalgs_len;
cache = NULL;
tls12_sigalgs_list = NULL;
ret = 1;
err:
OPENSSL_free(cache);
OPENSSL_free(tls12_sigalgs_list);
EVP_PKEY_free(tmpkey);
return ret;
}
@ -1215,8 +1562,7 @@ static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL_CONNECTION *s,
const SIGALG_LOOKUP *lu;
for (i = 0, lu = SSL_CONNECTION_GET_CTX(s)->sigalg_lookup_cache;
/* cache should have the same number of elements as sigalg_lookup_tbl */
i < OSSL_NELEM(sigalg_lookup_tbl);
i < SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs_len;
lu++, i++) {
if (lu->sigalg == sigalg) {
if (!lu->enabled)
@ -1283,8 +1629,9 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL_CONNECTION *s,
size_t i;
/* Work out index corresponding to ciphersuite */
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);
for (i = 0; i < s->ssl_pkey_num; i++) {
const SSL_CERT_LOOKUP *clu
= ssl_cert_lookup_by_idx(i, SSL_CONNECTION_GET_CTX(s));
if (clu == NULL)
continue;
@ -1329,6 +1676,7 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL_CONNECTION *s,
}
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(s, tls_default_sigalg[idx]);
@ -1350,7 +1698,7 @@ int tls1_set_peer_legacy_sigalg(SSL_CONNECTION *s, const EVP_PKEY *pkey)
size_t idx;
const SIGALG_LOOKUP *lu;
if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
if (ssl_cert_lookup_by_pkey(pkey, &idx, SSL_CONNECTION_GET_CTX(s)) == NULL)
return 0;
lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
@ -1390,8 +1738,8 @@ size_t tls12_get_psigalgs(SSL_CONNECTION *s, int sent, const uint16_t **psigs)
*psigs = s->cert->conf_sigalgs;
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
return OSSL_NELEM(tls12_sigalgs);
*psigs = SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs;
return SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs_len;
}
}
@ -1408,8 +1756,8 @@ int tls_check_sigalg_curve(const SSL_CONNECTION *s, int curve)
sigs = s->cert->conf_sigalgs;
siglen = s->cert->conf_sigalgslen;
} else {
sigs = tls12_sigalgs;
siglen = OSSL_NELEM(tls12_sigalgs);
sigs = SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs;
siglen = SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs_len;
}
for (i = 0; i < siglen; i++) {
@ -1466,6 +1814,14 @@ static int sigalg_security_bits(SSL_CTX *ctx, const SIGALG_LOOKUP *lu)
else if (lu->sigalg == TLSEXT_SIGALG_ed448)
secbits = 224;
}
/*
* For provider-based sigalgs we have secbits information available
* in the (provider-loaded) sigalg_list structure
*/
if ((secbits == 0) && (lu->sig_idx >= SSL_PKEY_NUM)
&& ((lu->sig_idx - SSL_PKEY_NUM) < (int)ctx->sigalg_list_len)) {
secbits = ctx->sigalg_list[lu->sig_idx - SSL_PKEY_NUM].secbits;
}
return secbits;
}
@ -1485,9 +1841,7 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey)
int secbits = 0;
pkeyid = EVP_PKEY_get_id(pkey);
/* Should never happen */
if (pkeyid == -1)
return -1;
if (SSL_CONNECTION_IS_TLS13(s)) {
/* Disallow DSA for TLS 1.3 */
if (pkeyid == EVP_PKEY_DSA) {
@ -1499,6 +1853,14 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey)
pkeyid = EVP_PKEY_RSA_PSS;
}
lu = tls1_lookup_sigalg(s, sig);
/* if this sigalg is loaded, set so far unknown pkeyid to its sig NID */
if ((pkeyid == -1) && (lu != NULL))
pkeyid = lu->sig;
/* Should never happen */
if (pkeyid == -1)
return -1;
/*
* 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
@ -1512,7 +1874,9 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey)
return 0;
}
/* Check the sigalg is consistent with the key OID */
if (!ssl_cert_lookup_by_nid(EVP_PKEY_get_id(pkey), &cidx)
if (!ssl_cert_lookup_by_nid(
(pkeyid == EVP_PKEY_RSA_PSS) ? EVP_PKEY_get_id(pkey) : pkeyid,
&cidx, SSL_CONNECTION_GET_CTX(s))
|| lu->sig_idx != (int)cidx) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
@ -1706,9 +2070,14 @@ int tls1_set_server_sigalgs(SSL_CONNECTION *s)
OPENSSL_free(s->shared_sigalgs);
s->shared_sigalgs = NULL;
s->shared_sigalgslen = 0;
/* 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)
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));
if (s->s3.tmp.valid_flags == NULL)
return 0;
/*
* If peer sent no signature algorithms check to see if we support
* the default algorithm for each certificate type
@ -1718,7 +2087,7 @@ int tls1_set_server_sigalgs(SSL_CONNECTION *s)
const uint16_t *sent_sigs;
size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < SSL_PKEY_NUM; i++) {
for (i = 0; i < s->ssl_pkey_num; i++) {
const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i);
size_t j;
@ -2172,7 +2541,8 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL_CONNECTION *s, int op)
if (lu == NULL)
continue;
clu = ssl_cert_lookup_by_idx(lu->sig_idx);
clu = ssl_cert_lookup_by_idx(lu->sig_idx,
SSL_CONNECTION_GET_CTX(s));
if (clu == NULL)
continue;
@ -2345,7 +2715,7 @@ int tls1_process_sigalgs(SSL_CONNECTION *s)
if (!tls1_set_shared_sigalgs(s))
return 0;
for (i = 0; i < SSL_PKEY_NUM; i++)
for (i = 0; i < s->ssl_pkey_num; i++)
pvalid[i] = 0;
for (i = 0; i < s->shared_sigalgslen; i++) {
@ -2699,7 +3069,8 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
if (!x || !pk)
return 0;
if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
if (ssl_cert_lookup_by_pkey(pk, &certidx,
SSL_CONNECTION_GET_CTX(s)) == NULL)
return 0;
idx = certidx;
pvalid = s->s3.tmp.valid_flags + idx;
@ -3105,7 +3476,8 @@ static int tls12_get_cert_sigalg_idx(const SSL_CONNECTION *s,
const SIGALG_LOOKUP *lu)
{
int sig_idx = lu->sig_idx;
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx);
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx,
SSL_CONNECTION_GET_CTX(s));
/* If not recognised or not supported by cipher mask it is not suitable */
if (clu == NULL
@ -3203,7 +3575,7 @@ static int is_cert_usable(SSL_CONNECTION *s, const SIGALG_LOOKUP *sig, X509 *x,
{
size_t idx;
if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
if (ssl_cert_lookup_by_pkey(pkey, &idx, SSL_CONNECTION_GET_CTX(s)) == NULL)
return 0;
/* Check the key is consistent with the sig alg */

View File

@ -9390,6 +9390,109 @@ static int test_pluggable_group(int idx)
return testresult;
}
/*
* This function triggers encode, decode and sign functions
* of the artificial "xorhmacsig" algorithm implemented in tls-provider
* creating private key and certificate files for use in TLS testing.
*/
static int create_cert_key(int idx, char *certfilename, char *privkeyfilename)
{
EVP_PKEY_CTX * evpctx = EVP_PKEY_CTX_new_from_name(libctx,
(idx == 0) ? "xorhmacsig" : "xorhmacsha2sig", NULL);
EVP_PKEY *pkey = NULL;
X509 *x509 = X509_new();
X509_NAME *name = NULL;
BIO *keybio = NULL, *certbio = NULL;
int ret = 1;
if (!TEST_ptr(evpctx)
|| !TEST_true(EVP_PKEY_keygen_init(evpctx))
|| !TEST_true(EVP_PKEY_generate(evpctx, &pkey))
|| !TEST_ptr(pkey)
|| !TEST_ptr(x509)
|| !TEST_true(ASN1_INTEGER_set(X509_get_serialNumber(x509), 1))
|| !TEST_true(X509_gmtime_adj(X509_getm_notBefore(x509), 0))
|| !TEST_true(X509_gmtime_adj(X509_getm_notAfter(x509), 31536000L))
|| !TEST_true(X509_set_pubkey(x509, pkey))
|| !TEST_ptr(name = X509_get_subject_name(x509))
|| !TEST_true(X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
(unsigned char *)"CH", -1, -1, 0))
|| !TEST_true(X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
(unsigned char *)"test.org", -1, -1, 0))
|| !TEST_true(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"localhost", -1, -1, 0))
|| !TEST_true(X509_set_issuer_name(x509, name))
|| !TEST_true(X509_sign(x509, pkey, EVP_sha1()))
|| !TEST_ptr(keybio = BIO_new_file(privkeyfilename, "wb"))
|| !TEST_true(PEM_write_bio_PrivateKey(keybio, pkey, NULL, NULL, 0, NULL, NULL))
|| !TEST_ptr(certbio = BIO_new_file(certfilename, "wb"))
|| !TEST_true(PEM_write_bio_X509(certbio, x509)))
ret = 0;
EVP_PKEY_free(pkey);
X509_free(x509);
EVP_PKEY_CTX_free(evpctx);
BIO_free(keybio);
BIO_free(certbio);
return ret;
}
/*
* Test that signature algorithms loaded via the provider interface can
* correctly establish a TLS (1.3) connection.
* Test 0: Signature algorithm with built-in hashing functionality: "xorhmacsig"
* Test 1: Signature algorithm using external SHA2 hashing: "xorhmacsha2sig"
*/
static int test_pluggable_signature(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
OSSL_PROVIDER *tlsprov = OSSL_PROVIDER_load(libctx, "tls-provider");
OSSL_PROVIDER *defaultprov = OSSL_PROVIDER_load(libctx, "default");
char *certfilename = "tls-prov-cert.pem";
char *privkeyfilename = "tls-prov-key.pem";
/* create key and certificate for the different algorithm types */
if (!TEST_ptr(tlsprov)
|| !TEST_true(create_cert_key(idx, certfilename, privkeyfilename)))
goto end;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
TLS1_3_VERSION,
&sctx, &cctx, certfilename, privkeyfilename))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
/* This is necessary to pass minimal setup w/o other groups configured */
if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup"))
|| !TEST_true(SSL_set1_groups_list(clientssl, "xorgroup")))
goto end;
/*
* If this connection gets established, it must have been completed
* via the tls-provider-implemented "hmacsig" algorithm, testing
* both sign and verify functions during handshake.
*/
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
OSSL_PROVIDER_unload(tlsprov);
OSSL_PROVIDER_unload(defaultprov);
return testresult;
}
#endif
#ifndef OPENSSL_NO_TLS1_2
@ -10844,6 +10947,7 @@ int setup_tests(void)
#endif
#ifndef OPENSSL_NO_TLS1_3
ADD_ALL_TESTS(test_pluggable_group, 2);
ADD_ALL_TESTS(test_pluggable_signature, 2);
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_TEST(test_ssl_dup);

File diff suppressed because it is too large Load Diff