/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
return 0;
if (s->method->version == TLS_ANY_VERSION)
- s->version = TLS_MAX_VERSION;
+ s->version = TLS_MAX_VERSION_INTERNAL;
else
s->version = s->method->version;
* For Suite B ciphersuite determines curve: we already know
* these are acceptable due to previous checks.
*/
- unsigned long cid = s->s3->tmp.new_cipher->id;
+ unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return TLSEXT_curve_P_256;
*/
unsigned long dup_list = 0;
+ if (ngroups == 0) {
+ SSLerr(SSL_F_TLS1_SET_GROUPS, SSL_R_BAD_LENGTH);
+ return 0;
+ }
if ((glist = OPENSSL_malloc(ngroups * sizeof(*glist))) == NULL) {
SSLerr(SSL_F_TLS1_SET_GROUPS, ERR_R_MALLOC_FAILURE);
return 0;
return 0;
/* Check for Suite B compliance */
- if (tls1_suiteb(s) && s->s3->tmp.new_cipher != NULL) {
- unsigned long cid = s->s3->tmp.new_cipher->id;
+ if (tls1_suiteb(s) && s->s3.tmp.new_cipher != NULL) {
+ unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
if (group_id != TLSEXT_curve_P_256)
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);
- if (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) {
+ if (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) {
idx = i;
break;
}
/*
* Some GOST ciphersuites allow more than one signature algorithms
* */
- if (idx == SSL_PKEY_GOST01 && s->s3->tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
+ if (idx == SSL_PKEY_GOST01 && s->s3.tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01;
lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
return 0;
- s->s3->tmp.peer_sigalg = lu;
+ s->s3.tmp.peer_sigalg = lu;
return 1;
}
}
}
+#ifndef OPENSSL_NO_EC
+/*
+ * Called by servers only. Checks that we have a sig alg that supports the
+ * specified EC curve.
+ */
+int tls_check_sigalg_curve(const SSL *s, int curve)
+{
+ const uint16_t *sigs;
+ size_t siglen, i;
+
+ if (s->cert->conf_sigalgs) {
+ sigs = s->cert->conf_sigalgs;
+ siglen = s->cert->conf_sigalgslen;
+ } else {
+ sigs = tls12_sigalgs;
+ siglen = OSSL_NELEM(tls12_sigalgs);
+ }
+
+ for (i = 0; i < siglen; i++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);
+
+ if (lu == NULL)
+ continue;
+ if (lu->sig == EVP_PKEY_EC
+ && lu->curve != NID_undef
+ && curve == lu->curve)
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
/*
* Check signature algorithm is consistent with sent supported signature
* algorithms and if so set relevant digest and signature scheme in
const uint16_t *sent_sigs;
const EVP_MD *md = NULL;
char sigalgstr[2];
- size_t sent_sigslen, i;
+ size_t sent_sigslen, i, cidx;
int pkeyid = EVP_PKEY_id(pkey);
const SIGALG_LOOKUP *lu;
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
+ /* Check the sigalg is consistent with the key OID */
+ if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx)
+ || lu->sig_idx != (int)cidx) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+
#ifndef OPENSSL_NO_EC
if (pkeyid == EVP_PKEY_EC) {
}
}
/* Store the sigalg the peer uses */
- s->s3->tmp.peer_sigalg = lu;
+ s->s3.tmp.peer_sigalg = lu;
return 1;
}
int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
{
- if (s->s3->tmp.peer_sigalg == NULL)
+ if (s->s3.tmp.peer_sigalg == NULL)
+ return 0;
+ *pnid = s->s3.tmp.peer_sigalg->sig;
+ return 1;
+}
+
+int SSL_get_signature_type_nid(const SSL *s, int *pnid)
+{
+ if (s->s3.tmp.sigalg == NULL)
return 0;
- *pnid = s->s3->tmp.peer_sigalg->sig;
+ *pnid = s->s3.tmp.sigalg->sig;
return 1;
}
*/
int ssl_set_client_disabled(SSL *s)
{
- s->s3->tmp.mask_a = 0;
- s->s3->tmp.mask_k = 0;
- ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
- if (ssl_get_min_max_version(s, &s->s3->tmp.min_ver,
- &s->s3->tmp.max_ver) != 0)
+ s->s3.tmp.mask_a = 0;
+ s->s3.tmp.mask_k = 0;
+ ssl_set_sig_mask(&s->s3.tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
+ if (ssl_get_min_max_version(s, &s->s3.tmp.min_ver,
+ &s->s3.tmp.max_ver, NULL) != 0)
return 0;
#ifndef OPENSSL_NO_PSK
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
- s->s3->tmp.mask_a |= SSL_aPSK;
- s->s3->tmp.mask_k |= SSL_PSK;
+ s->s3.tmp.mask_a |= SSL_aPSK;
+ s->s3.tmp.mask_k |= SSL_PSK;
}
#endif /* OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
- s->s3->tmp.mask_a |= SSL_aSRP;
- s->s3->tmp.mask_k |= SSL_kSRP;
+ s->s3.tmp.mask_a |= SSL_aSRP;
+ s->s3.tmp.mask_k |= SSL_kSRP;
}
#endif
return 1;
*/
int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
- if (c->algorithm_mkey & s->s3->tmp.mask_k
- || c->algorithm_auth & s->s3->tmp.mask_a)
+ if (c->algorithm_mkey & s->s3.tmp.mask_k
+ || c->algorithm_auth & s->s3.tmp.mask_a)
return 1;
- if (s->s3->tmp.max_ver == 0)
+ if (s->s3.tmp.max_ver == 0)
return 1;
if (!SSL_IS_DTLS(s)) {
int min_tls = c->min_tls;
&& (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
min_tls = SSL3_VERSION;
- if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver))
+ if ((min_tls > s->s3.tmp.max_ver) || (c->max_tls < s->s3.tmp.min_ver))
return 1;
}
- if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
- || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
+ if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3.tmp.max_ver)
+ || DTLS_VERSION_LT(c->max_dtls, s->s3.tmp.min_ver)))
return 1;
return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
s->cert->shared_sigalgslen = 0;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
- s->s3->tmp.valid_flags[i] = 0;
+ s->s3.tmp.valid_flags[i] = 0;
/*
* If peer sent no signature algorithms check to see if we support
* the default algorithm for each certificate type
*/
- if (s->s3->tmp.peer_cert_sigalgs == NULL
- && s->s3->tmp.peer_sigalgs == NULL) {
+ if (s->s3.tmp.peer_cert_sigalgs == NULL
+ && s->s3.tmp.peer_sigalgs == NULL) {
const uint16_t *sent_sigs;
size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
/* Check default matches a type we sent */
for (j = 0; j < sent_sigslen; j++) {
if (lu->sigalg == sent_sigs[j]) {
- s->s3->tmp.valid_flags[i] = CERT_PKEY_SIGN;
+ s->s3.tmp.valid_flags[i] = CERT_PKEY_SIGN;
break;
}
}
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
return 0;
/* TODO(OpenSSL1.2) fully axe DSA/etc. in ClientHello per TLS 1.3 spec */
- if (!s->server && !SSL_IS_DTLS(s) && s->s3->tmp.min_ver >= TLS1_3_VERSION
+ if (!s->server && !SSL_IS_DTLS(s) && s->s3.tmp.min_ver >= TLS1_3_VERSION
&& (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX
|| lu->hash_idx == SSL_MD_MD5_IDX
|| lu->hash_idx == SSL_MD_SHA224_IDX))
return 0;
+
/* See if public key algorithm allowed */
if (ssl_cert_is_disabled(lu->sig_idx))
return 0;
+
+ if (lu->sig == NID_id_GostR3410_2012_256
+ || lu->sig == NID_id_GostR3410_2012_512
+ || lu->sig == NID_id_GostR3410_2001) {
+ /* We never allow GOST sig algs on the server with TLSv1.3 */
+ if (s->server && SSL_IS_TLS13(s))
+ return 0;
+ if (!s->server
+ && s->method->version == TLS_ANY_VERSION
+ && s->s3.tmp.max_ver >= TLS1_3_VERSION) {
+ int i, num;
+ STACK_OF(SSL_CIPHER) *sk;
+
+ /*
+ * We're a client that could negotiate TLSv1.3. We only allow GOST
+ * sig algs if we could negotiate TLSv1.2 or below and we have GOST
+ * ciphersuites enabled.
+ */
+
+ if (s->s3.tmp.min_ver >= TLS1_3_VERSION)
+ return 0;
+
+ sk = SSL_get_ciphers(s);
+ num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0;
+ for (i = 0; i < num; i++) {
+ const SSL_CIPHER *c;
+
+ c = sk_SSL_CIPHER_value(sk, i);
+ /* Skip disabled ciphers */
+ if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
+ continue;
+
+ if ((c->algorithm_mkey & SSL_kGOST) != 0)
+ break;
+ }
+ if (i == num)
+ return 0;
+ }
+ }
+
if (lu->hash == NID_undef)
return 1;
/* Security bits: half digest bits */
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
- allow = s->s3->tmp.peer_sigalgs;
- allowlen = s->s3->tmp.peer_sigalgslen;
+ allow = s->s3.tmp.peer_sigalgs;
+ allowlen = s->s3.tmp.peer_sigalgslen;
} else {
allow = conf;
allowlen = conflen;
- pref = s->s3->tmp.peer_sigalgs;
- preflen = s->s3->tmp.peer_sigalgslen;
+ pref = s->s3.tmp.peer_sigalgs;
+ preflen = s->s3.tmp.peer_sigalgslen;
}
nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (nmatch) {
return 0;
if (cert)
- return tls1_save_u16(pkt, &s->s3->tmp.peer_cert_sigalgs,
- &s->s3->tmp.peer_cert_sigalgslen);
+ return tls1_save_u16(pkt, &s->s3.tmp.peer_cert_sigalgs,
+ &s->s3.tmp.peer_cert_sigalgslen);
else
- return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs,
- &s->s3->tmp.peer_sigalgslen);
+ return tls1_save_u16(pkt, &s->s3.tmp.peer_sigalgs,
+ &s->s3.tmp.peer_sigalgslen);
}
int tls1_process_sigalgs(SSL *s)
{
size_t i;
- uint32_t *pvalid = s->s3->tmp.valid_flags;
+ uint32_t *pvalid = s->s3.tmp.valid_flags;
CERT *c = s->cert;
if (!tls1_set_shared_sigalgs(s))
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
- uint16_t *psig = s->s3->tmp.peer_sigalgs;
- size_t numsigalgs = s->s3->tmp.peer_sigalgslen;
+ uint16_t *psig = s->s3.tmp.peer_sigalgs;
+ size_t numsigalgs = s->s3.tmp.peer_sigalgslen;
if (psig == NULL || numsigalgs > INT_MAX)
return 0;
if (idx >= 0) {
idx = (int)(cpk - c->pkeys);
} else
cpk = c->pkeys + idx;
- pvalid = s->s3->tmp.valid_flags + idx;
+ pvalid = s->s3.tmp.valid_flags + idx;
x = cpk->x509;
pk = cpk->privatekey;
chain = cpk->chain;
if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
return 0;
idx = certidx;
- pvalid = s->s3->tmp.valid_flags + idx;
+ pvalid = s->s3.tmp.valid_flags + idx;
if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
check_flags = CERT_PKEY_STRICT_FLAGS;
if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
int default_nid;
int rsign = 0;
- if (s->s3->tmp.peer_cert_sigalgs != NULL
- || s->s3->tmp.peer_sigalgs != NULL) {
+ if (s->s3.tmp.peer_cert_sigalgs != NULL
+ || s->s3.tmp.peer_sigalgs != NULL) {
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
} else {
break;
}
if (check_type) {
- const uint8_t *ctypes = s->s3->tmp.ctype;
+ const uint8_t *ctypes = s->s3.tmp.ctype;
size_t j;
- for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) {
+ for (j = 0; j < s->s3.tmp.ctype_len; j++, ctypes++) {
if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
rv |= CERT_PKEY_CERT_TYPE;
}
- ca_dn = s->s3->tmp.peer_ca_names;
+ ca_dn = s->s3.tmp.peer_ca_names;
if (!sk_X509_NAME_num(ca_dn))
rv |= CERT_PKEY_ISSUER_NAME;
int dh_secbits = 80;
if (s->cert->dh_tmp_auto == 2)
return DH_get_1024_160();
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
- if (s->s3->tmp.new_cipher->strength_bits == 256)
+ if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
+ if (s->s3.tmp.new_cipher->strength_bits == 256)
dh_secbits = 128;
else
dh_secbits = 80;
} else {
- if (s->s3->tmp.cert == NULL)
+ if (s->s3.tmp.cert == NULL)
return NULL;
- dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey);
+ dh_secbits = EVP_PKEY_security_bits(s->s3.tmp.cert->privatekey);
}
if (dh_secbits >= 128) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx);
/* If not recognised or not supported by cipher mask it is not suitable */
- if (clu == NULL || !(clu->amask & s->s3->tmp.new_cipher->algorithm_auth))
+ if (clu == NULL
+ || (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) == 0
+ || (clu->nid == EVP_PKEY_RSA_PSS
+ && (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
return -1;
- return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
+ return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
}
/*
static int has_usable_cert(SSL *s, const SIGALG_LOOKUP *sig, int idx)
{
const SIGALG_LOOKUP *lu;
- int mdnid, pknid;
+ int mdnid, pknid, supported;
size_t i;
/* TLS 1.2 callers can override lu->sig_idx, but not TLS 1.3 callers. */
idx = sig->sig_idx;
if (!ssl_has_cert(s, idx))
return 0;
- if (s->s3->tmp.peer_cert_sigalgs != NULL) {
- for (i = 0; i < s->s3->tmp.peer_cert_sigalgslen; i++) {
- lu = tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i]);
+ if (s->s3.tmp.peer_cert_sigalgs != NULL) {
+ for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
+ lu = tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i]);
if (lu == NULL
|| !X509_get_signature_info(s->cert->pkeys[idx].x509, &mdnid,
- &pknid, NULL, NULL))
+ &pknid, NULL, NULL)
+ /*
+ * TODO this does not differentiate between the
+ * rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
+ * have a chain here that lets us look at the key OID in the
+ * signing certificate.
+ */
+ || mdnid != lu->hash
+ || pknid != lu->sig)
continue;
- /*
- * TODO this does not differentiate between the
- * rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
- * have a chain here that lets us look at the key OID in the
- * signing certificate.
- */
- if (mdnid == lu->hash && pknid == lu->sig)
- return 1;
+
+ ERR_set_mark();
+ supported = EVP_PKEY_supports_digest_nid(s->cert->pkeys[idx].privatekey,
+ mdnid);
+ if (supported == 0)
+ continue;
+ else if (supported < 0)
+ {
+ /* If it didn't report a mandatory NID, for whatever reasons,
+ * just clear the error and allow all hashes to be used. */
+ ERR_pop_to_mark();
+ }
+ return 1;
}
return 0;
}
+ supported = EVP_PKEY_supports_digest_nid(s->cert->pkeys[idx].privatekey,
+ sig->hash);
+ if (supported == 0)
+ return 0;
+ else if (supported < 0)
+ ERR_clear_error();
+
return 1;
}
const SIGALG_LOOKUP *lu = NULL;
int sig_idx = -1;
- s->s3->tmp.cert = NULL;
- s->s3->tmp.sigalg = NULL;
+ s->s3.tmp.cert = NULL;
+ s->s3.tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) {
size_t i;
}
} else {
/* If ciphersuite doesn't require a cert nothing to do */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT))
+ if (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aCERT))
return 1;
if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys))
return 1;
if (SSL_USE_SIGALGS(s)) {
size_t i;
- if (s->s3->tmp.peer_sigalgs != NULL) {
+ if (s->s3.tmp.peer_sigalgs != NULL) {
#ifndef OPENSSL_NO_EC
int curve;
if (i == s->cert->shared_sigalgslen) {
if (!fatalerrs)
return 1;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CHOOSE_SIGALG,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
}
if (sig_idx == -1)
sig_idx = lu->sig_idx;
- s->s3->tmp.cert = &s->cert->pkeys[sig_idx];
- s->cert->key = s->s3->tmp.cert;
- s->s3->tmp.sigalg = lu;
+ s->s3.tmp.cert = &s->cert->pkeys[sig_idx];
+ s->cert->key = s->s3.tmp.cert;
+ s->s3.tmp.sigalg = lu;
return 1;
}