mirror of
https://github.com/openssl/openssl.git
synced 2024-11-23 18:13:39 +08:00
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:
parent
1817dcaf55
commit
ee58915cfd
@ -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.
|
||||
|
3
NEWS.md
3
NEWS.md
@ -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
|
||||
-----------
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
428
ssl/t1_lib.c
428
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);
|
||||
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 */
|
||||
|
@ -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);
|
||||
|
2566
test/tls-provider.c
2566
test/tls-provider.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user