/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
+#include "internal/nelem.h"
#include "ssl_locl.h"
#include <openssl/ct.h>
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls13_alert_code,
- tls1_export_keying_material,
+ tls13_export_keying_material,
SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
ssl3_set_handshake_header,
tls_close_construct_packet,
int tls1_new(SSL *s)
{
if (!ssl3_new(s))
- return (0);
- s->method->ssl_clear(s);
- return (1);
+ return 0;
+ if (!s->method->ssl_clear(s))
+ return 0;
+
+ return 1;
}
void tls1_free(SSL *s)
ssl3_free(s);
}
-void tls1_clear(SSL *s)
+int tls1_clear(SSL *s)
{
- ssl3_clear(s);
+ if (!ssl3_clear(s))
+ return 0;
+
if (s->method->version == TLS_ANY_VERSION)
s->version = TLS_MAX_VERSION;
else
s->version = s->method->version;
+
+ return 1;
}
#ifndef OPENSSL_NO_EC
{NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */
{NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */
{NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */
- {NID_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */
+ {EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */
};
static const unsigned char ecformats_default[] = {
return rv;
}
-# ifndef OPENSSL_NO_EC
/*
* tls1_check_ec_tmp_key - Check EC temporary key compatibility
* @s: SSL connection
return 1;
return 0;
}
-# endif /* OPENSSL_NO_EC */
#else
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
+ TLSEXT_SIGALG_ed25519,
#endif
TLSEXT_SIGALG_rsa_pss_sha256,
TLSEXT_SIGALG_rsa_pkcs1_sha512,
#ifndef OPENSSL_NO_EC
+ TLSEXT_SIGALG_ecdsa_sha224,
TLSEXT_SIGALG_ecdsa_sha1,
#endif
+ TLSEXT_SIGALG_rsa_pkcs1_sha224,
TLSEXT_SIGALG_rsa_pkcs1_sha1,
#ifndef OPENSSL_NO_DSA
+ TLSEXT_SIGALG_dsa_sha224,
TLSEXT_SIGALG_dsa_sha1,
TLSEXT_SIGALG_dsa_sha256,
{"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA512, NID_secp521r1},
+ {"ed25519", TLSEXT_SIGALG_ed25519,
+ NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
+ NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_ecdsa_sha224,
+ NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
+ NID_ecdsa_with_SHA224, NID_undef},
{NULL, TLSEXT_SIGALG_ecdsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA1, NID_undef},
{"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha512WithRSAEncryption, NID_undef},
+ {"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
+ NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_sha224WithRSAEncryption, NID_undef},
{"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha1WithRSAEncryption, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_dsa_sha224,
+ NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
+ NID_undef, NID_undef},
{NULL, TLSEXT_SIGALG_dsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_dsaWithSHA1, NID_undef},
*/
static const uint16_t tls_default_sigalg[] = {
TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */
+ 0, /* SSL_PKEY_RSA_PSS_SIGN */
TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */
TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */
TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */
TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */
- TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 /* SSL_PKEY_GOST12_512 */
+ TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, /* SSL_PKEY_GOST12_512 */
+ 0 /* SSL_PKEY_ED25519 */
};
/* Lookup TLS signature algorithm */
}
return NULL;
}
+/* Lookup hash: return 0 if invalid or not enabled */
+int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
+{
+ const EVP_MD *md;
+ if (lu == NULL)
+ return 0;
+ /* lu->hash == NID_undef means no associated digest */
+ if (lu->hash == NID_undef) {
+ md = NULL;
+ } else {
+ md = ssl_md(lu->hash_idx);
+ if (md == NULL)
+ return 0;
+ }
+ if (pmd)
+ *pmd = md;
+ return 1;
+}
+
/*
* Return a signature algorithm for TLS < 1.2 where the signature type
* is fixed by the certificate type.
*/
static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
{
+ if (idx == -1) {
+ if (s->server) {
+ 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);
+
+ if (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) {
+ idx = i;
+ break;
+ }
+ }
+ } else {
+ idx = s->cert->key - s->cert->pkeys;
+ }
+ }
if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
return NULL;
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
- if (lu == NULL || ssl_md(lu->hash_idx) == NULL) {
+ if (!tls1_lookup_md(lu, NULL))
return NULL;
- }
return lu;
}
return &legacy_rsa_sigalg;
/* Set peer sigalg based key type */
int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey)
{
- int idx = ssl_cert_type(NULL, pkey);
+ size_t idx;
+ const SIGALG_LOOKUP *lu;
- const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, idx);
+ if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
+ return 0;
+ lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
return 0;
s->s3->tmp.peer_sigalg = lu;
return 1;
}
-static int tls_sigalg_get_sig(uint16_t sigalg)
-{
- const SIGALG_LOOKUP *r = tls1_lookup_sigalg(sigalg);
-
- return r != NULL ? r->sig : 0;
-}
-
size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
{
/*
}
lu = tls1_lookup_sigalg(sig);
/*
- * Check sigalgs is known and key type is consistent with signature:
- * RSA keys can be used for RSA-PSS
+ * 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
*/
- if (lu == NULL || (pkeyid != lu->sig
+ if (lu == NULL
+ || (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
+ || (pkeyid != lu->sig
&& (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
if (SSL_IS_TLS13(s)) {
+ if (EC_KEY_get_conv_form(ec) != POINT_CONVERSION_UNCOMPRESSED) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_ILLEGAL_POINT_COMPRESSION);
+ return 0;
+ }
/* For TLS 1.3 check curve matches signature algorithm */
-
if (lu->curve != NID_undef && curve != lu->curve) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
- md = ssl_md(lu->hash_idx);
- if (md == NULL) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
- return 0;
+ if (!tls1_lookup_md(lu, &md)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
+ return 0;
}
- /*
- * Make sure security callback allows algorithm. For historical reasons we
- * have to pass the sigalg as a two byte char array.
- */
- sigalgstr[0] = (sig >> 8) & 0xff;
- sigalgstr[1] = sig & 0xff;
- if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
- EVP_MD_size(md) * 4, EVP_MD_type(md),
- (void *)sigalgstr)) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
- return 0;
+ if (md != NULL) {
+ /*
+ * Make sure security callback allows algorithm. For historical
+ * reasons we have to pass the sigalg as a two byte char array.
+ */
+ sigalgstr[0] = (sig >> 8) & 0xff;
+ sigalgstr[1] = sig & 0xff;
+ if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
+ EVP_MD_size(md) * 4, EVP_MD_type(md),
+ (void *)sigalgstr)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
}
/* Store the sigalg the peer uses */
s->s3->tmp.peer_sigalg = lu;
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);
- ssl_get_client_min_max_version(s, &s->s3->tmp.min_ver, &s->s3->tmp.max_ver);
+ ssl_get_min_max_version(s, &s->s3->tmp.min_ver, &s->s3->tmp.max_ver);
#ifndef OPENSSL_NO_PSK
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
* @s: SSL connection that you want to use the cipher on
* @c: cipher to check
* @op: Security check that you want to do
+ * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3
*
* Returns 1 when it's disabled, 0 when enabled.
*/
-int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
+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)
return 1;
if (s->s3->tmp.max_ver == 0)
return 1;
- if (!SSL_IS_DTLS(s) && ((c->min_tls > s->s3->tmp.max_ver)
- || (c->max_tls < s->s3->tmp.min_ver)))
- return 1;
+ if (!SSL_IS_DTLS(s)) {
+ int min_tls = c->min_tls;
+
+ /*
+ * For historical reasons we will allow ECHDE to be selected by a server
+ * in SSLv3 if we are a client
+ */
+ if (min_tls == TLS1_VERSION && ecdhe
+ && (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))
+ 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)))
return 1;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
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_sigalgs == NULL) {
+ const uint16_t *sent_sigs;
+ size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
- if (s->s3->tmp.peer_sigalgs == NULL)
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i);
+ size_t j;
+
+ if (lu == NULL)
+ continue;
+ /* 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;
+ break;
+ }
+ }
+ }
return 1;
+ }
if (!tls1_process_sigalgs(s)) {
SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
}
if (s->cert->shared_sigalgs != NULL)
return 1;
- /* Fatal error is no shared signature algorithms */
+ /* Fatal error if no shared signature algorithms */
SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
- al = SSL_AD_ILLEGAL_PARAMETER;
+ al = SSL_AD_HANDSHAKE_FAILURE;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
+ slen -= p - sdec;
OPENSSL_free(sdec);
if (sess) {
+ /* Some additional consistency checks */
+ if (slen != 0 || sess->session_id_length != 0) {
+ SSL_SESSION_free(sess);
+ return TICKET_NO_DECRYPT;
+ }
/*
* The session ID, if non-empty, is used by some clients to detect
* that the ticket has been accepted. So we copy it to the session
return ret;
}
-static int tls12_get_pkey_idx(int sig_nid)
-{
- switch (sig_nid) {
-#ifndef OPENSSL_NO_RSA
- case EVP_PKEY_RSA:
- return SSL_PKEY_RSA;
- /*
- * For now return RSA key for PSS. When we support PSS only keys
- * this will need to be updated.
- */
- case EVP_PKEY_RSA_PSS:
- return SSL_PKEY_RSA;
-#endif
-#ifndef OPENSSL_NO_DSA
- case EVP_PKEY_DSA:
- return SSL_PKEY_DSA_SIGN;
-#endif
-#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- return SSL_PKEY_ECC;
-#endif
-#ifndef OPENSSL_NO_GOST
- case NID_id_GostR3410_2001:
- return SSL_PKEY_GOST01;
-
- case NID_id_GostR3410_2012_256:
- return SSL_PKEY_GOST12_256;
-
- case NID_id_GostR3410_2012_512:
- return SSL_PKEY_GOST12_512;
-#endif
- }
- return -1;
-}
-
/* Check to see if a signature algorithm is allowed */
-static int tls12_sigalg_allowed(SSL *s, int op, uint16_t ptmp)
+static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
{
- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(ptmp);
unsigned char sigalgstr[2];
int secbits;
/* See if sigalgs is recognised and if hash is enabled */
- if (lu == NULL || ssl_md(lu->hash_idx) == NULL)
+ if (!tls1_lookup_md(lu, NULL))
+ return 0;
+ /* DSA is not allowed in TLS 1.3 */
+ 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
+ && (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 (tls12_get_pkey_idx(lu->sig) == -1)
+ if (ssl_cert_is_disabled(lu->sig_idx))
return 0;
+ if (lu->hash == NID_undef)
+ return 1;
/* Security bits: half digest bits */
secbits = EVP_MD_size(ssl_md(lu->hash_idx)) * 4;
/* Finally see if security callback allows it */
- sigalgstr[0] = (ptmp >> 8) & 0xff;
- sigalgstr[1] = ptmp & 0xff;
+ sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
+ sigalgstr[1] = lu->sigalg & 0xff;
return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
}
{
const uint16_t *sigalgs;
size_t i, sigalgslen;
- int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
+ uint32_t disabled_mask = SSL_aRSA | SSL_aDSS | SSL_aECDSA;
/*
- * Now go through all signature algorithms seeing if we support any for
- * RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2. To keep
- * down calls to security callback only check if we have to.
+ * Go through all signature algorithms seeing if we support any
+ * in disabled_mask.
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i ++, sigalgs++) {
- switch (tls_sigalg_get_sig(*sigalgs)) {
-#ifndef OPENSSL_NO_RSA
- /* Any RSA-PSS signature algorithms also mean we allow RSA */
- case EVP_PKEY_RSA_PSS:
- case EVP_PKEY_RSA:
- if (!have_rsa && tls12_sigalg_allowed(s, op, *sigalgs))
- have_rsa = 1;
- break;
-#endif
-#ifndef OPENSSL_NO_DSA
- case EVP_PKEY_DSA:
- if (!have_dsa && tls12_sigalg_allowed(s, op, *sigalgs))
- have_dsa = 1;
- break;
-#endif
-#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- if (!have_ecdsa && tls12_sigalg_allowed(s, op, *sigalgs))
- have_ecdsa = 1;
- break;
-#endif
- }
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
+ const SSL_CERT_LOOKUP *clu;
+
+ if (lu == NULL)
+ continue;
+
+ clu = ssl_cert_lookup_by_idx(lu->sig_idx);
+
+ /* If algorithm is disabled see if we can enable it */
+ if ((clu->amask & disabled_mask) != 0
+ && tls12_sigalg_allowed(s, op, lu))
+ disabled_mask &= ~clu->amask;
}
- if (!have_rsa)
- *pmask_a |= SSL_aRSA;
- if (!have_dsa)
- *pmask_a |= SSL_aDSS;
- if (!have_ecdsa)
- *pmask_a |= SSL_aECDSA;
+ *pmask_a |= disabled_mask;
}
int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
const uint16_t *psig, size_t psiglen)
{
size_t i;
+ int rv = 0;
for (i = 0; i < psiglen; i++, psig++) {
- if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, *psig)) {
- if (!WPACKET_put_bytes_u16(pkt, *psig))
- return 0;
- }
- }
- return 1;
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
+
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
+ continue;
+ if (!WPACKET_put_bytes_u16(pkt, *psig))
+ return 0;
+ /*
+ * If TLS 1.3 must have at least one valid TLS 1.3 message
+ * signing algorithm: i.e. neither RSA nor SHA1/SHA224
+ */
+ if (rv == 0 && (!SSL_IS_TLS13(s)
+ || (lu->sig != EVP_PKEY_RSA
+ && lu->hash != NID_sha1
+ && lu->hash != NID_sha224)))
+ rv = 1;
+ }
+ if (rv == 0)
+ SSLerr(SSL_F_TLS12_COPY_SIGALGS, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ return rv;
}
/* Given preference and allowed sigalgs set shared sigalgs */
const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp);
+
/* Skip disabled hashes or signature algorithms */
- if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, *ptmp))
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
continue;
for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
if (*ptmp == *atmp) {
nmatch++;
- if (shsig) {
- *shsig = tls1_lookup_sigalg(*ptmp);
- shsig++;
- }
+ if (shsig)
+ *shsig++ = lu;
break;
}
}
size = PACKET_remaining(pkt);
/* Invalid data length */
- if ((size & 1) != 0)
+ if (size == 0 || (size & 1) != 0)
return 0;
size >>= 1;
if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA)
continue;
/* If not disabled indicate we can explicitly sign */
- if (pvalid[idx] == 0 && tls12_get_pkey_idx(sigptr->sig) != -1)
- pvalid[sigptr->sig_idx] = CERT_PKEY_EXPLICIT_SIGN;
+ if (pvalid[idx] == 0 && !ssl_cert_is_disabled(idx))
+ pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
}
return 1;
}
get_sigorhash(&sig_alg, &hash_alg, p);
}
- if (sig_alg == NID_undef || hash_alg == NID_undef)
+ if (sig_alg == NID_undef || (p != NULL && hash_alg == NID_undef))
return 0;
for (i = 0; i < sarg->sigalgcnt; i += 2) {
* attempting to use them.
*/
-/* Flags which need to be set for a certificate when stict mode not set */
+/* Flags which need to be set for a certificate when strict mode not set */
#define CERT_PKEY_VALID_FLAGS \
(CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
if (!x || !pk)
goto end;
} else {
+ size_t certidx;
+
if (!x || !pk)
return 0;
- idx = ssl_cert_type(x, pk);
- if (idx == -1)
+
+ if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
return 0;
+ idx = certidx;
pvalid = s->s3->tmp.valid_flags + idx;
if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
break;
}
if (check_type) {
- const unsigned char *ctypes;
- int ctypelen;
- if (c->ctypes) {
- ctypes = c->ctypes;
- ctypelen = (int)c->ctype_num;
- } else {
- ctypes = (unsigned char *)s->s3->tmp.ctype;
- ctypelen = s->s3->tmp.ctype_num;
- }
- for (i = 0; i < ctypelen; i++) {
- if (ctypes[i] == check_type) {
+ const uint8_t *ctypes = s->s3->tmp.ctype;
+ size_t j;
+
+ for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) {
+ if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
}
}
if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
goto end;
- } else
+ } else {
rv |= CERT_PKEY_CERT_TYPE;
+ }
- ca_dn = s->s3->tmp.ca_names;
+ ca_dn = s->s3->tmp.peer_ca_names;
if (!sk_X509_NAME_num(ca_dn))
rv |= CERT_PKEY_ISSUER_NAME;
end:
- if (TLS1_get_version(s) >= TLS1_2_VERSION) {
- if (*pvalid & CERT_PKEY_EXPLICIT_SIGN)
- rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
- } else
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN);
+ else
rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
/*
* chain is invalid.
*/
if (!check_flags) {
- if (rv & CERT_PKEY_VALID)
+ if (rv & CERT_PKEY_VALID) {
*pvalid = rv;
- else {
- /* Preserve explicit sign flag, clear rest */
- *pvalid &= CERT_PKEY_EXPLICIT_SIGN;
+ } else {
+ /* Preserve sign and explicit sign flag, clear rest */
+ *pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
return 0;
}
}
void tls1_set_cert_validity(SSL *s)
{
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_PSS_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED25519);
}
-/* User level utiity function to check a chain is suitable */
+/* User level utility function to check a chain is suitable */
int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
{
return tls1_check_chain(s, x, pk, chain, -1);
static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
/* Lookup signature algorithm digest */
- int secbits = -1, md_nid = NID_undef, sig_nid;
+ int secbits, nid, pknid;
/* Don't check signature if self signed */
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
return 1;
- sig_nid = X509_get_signature_nid(x);
- if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) {
- const EVP_MD *md;
- if (md_nid && (md = EVP_get_digestbynid(md_nid)))
- secbits = EVP_MD_size(md) * 4;
- }
+ if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL))
+ secbits = -1;
+ /* If digest NID not defined use signature NID */
+ if (nid == NID_undef)
+ nid = pknid;
if (s)
- return ssl_security(s, op, secbits, md_nid, x);
+ return ssl_security(s, op, secbits, nid, x);
else
- return ssl_ctx_security(ctx, op, secbits, md_nid, x);
+ return ssl_ctx_security(ctx, op, secbits, nid, x);
}
int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee)
}
/*
- * Check security of a chain, if sk includes the end entity certificate then
- * x is NULL. If vfy is 1 then we are verifying a peer chain and not sending
+ * Check security of a chain, if |sk| includes the end entity certificate then
+ * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending
* one to the peer. Return values: 1 if ok otherwise error code to use
*/
return 1;
}
+/*
+ * For TLS 1.2 servers check if we have a certificate which can be used
+ * with the signature algorithm "lu" and return index of certificate.
+ */
+
+static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
+{
+ int sig_idx = lu->sig_idx;
+ 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))
+ return -1;
+
+ /* If PSS and we have no PSS cert use RSA */
+ if (sig_idx == SSL_PKEY_RSA_PSS_SIGN && !ssl_has_cert(s, sig_idx))
+ sig_idx = SSL_PKEY_RSA;
+
+ return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
+}
+
/*
* Choose an appropriate signature algorithm based on available certificates
* Sets chosen certificate and signature algorithm.
*/
int tls_choose_sigalg(SSL *s, int *al)
{
- int idx = -1;
const SIGALG_LOOKUP *lu = NULL;
+ int sig_idx = -1;
s->s3->tmp.cert = NULL;
s->s3->tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) {
size_t i;
#ifndef OPENSSL_NO_EC
- int curve = -1;
+ int curve = -1, skip_ec = 0;
#endif
- /* Look for a certificate matching shared sigaglgs */
+ /* Look for a certificate matching shared sigalgs */
for (i = 0; i < s->cert->shared_sigalgslen; i++) {
lu = s->cert->shared_sigalgs[i];
- /* Skip DSA and RSA if not PSS */
- if (lu->sig == EVP_PKEY_DSA || lu->sig == EVP_PKEY_RSA)
+ /* Skip SHA1, SHA224, DSA and RSA if not PSS */
+ if (lu->hash == NID_sha1
+ || lu->hash == NID_sha224
+ || lu->sig == EVP_PKEY_DSA
+ || lu->sig == EVP_PKEY_RSA)
continue;
- if (ssl_md(lu->hash_idx) == NULL)
+ if (!tls1_lookup_md(lu, NULL))
continue;
- idx = lu->sig_idx;
- if (!ssl_has_cert(s, idx))
+ if (!ssl_has_cert(s, lu->sig_idx)) {
+ if (lu->sig_idx != SSL_PKEY_RSA_PSS_SIGN
+ || !ssl_has_cert(s, SSL_PKEY_RSA))
continue;
+ sig_idx = SSL_PKEY_RSA;
+ }
if (lu->sig == EVP_PKEY_EC) {
#ifndef OPENSSL_NO_EC
if (curve == -1) {
- EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[idx].privatekey);
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ if (EC_KEY_get_conv_form(ec)
+ != POINT_CONVERSION_UNCOMPRESSED)
+ skip_ec = 1;
}
- if (lu->curve != NID_undef && curve != lu->curve)
+ if (skip_ec || (lu->curve != NID_undef && curve != lu->curve))
continue;
#else
continue;
return 0;
}
} else {
- if (s->server) {
- /* Find index corresponding to ciphersuite */
- idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
- /* If no certificate for ciphersuite return */
- if (idx == -1)
- return 1;
- if (idx == SSL_PKEY_GOST_EC) {
- /* Work out which GOST certificate is avaiable */
- if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
- idx = SSL_PKEY_GOST12_512;
- } else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
- idx = SSL_PKEY_GOST12_256;
- } else if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
- idx = SSL_PKEY_GOST01;
- } else {
- if (al == NULL)
- return 1;
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else if (!ssl_has_cert(s, idx)) {
- if (al == NULL)
- return 1;
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else {
- /* Find index for client certificate */
- idx = s->cert->key - s->cert->pkeys;
- if (!ssl_has_cert(s, idx))
+ /* If ciphersuite doesn't require a cert nothing to do */
+ 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)) {
if (s->s3->tmp.peer_sigalgs != NULL) {
size_t i;
+#ifndef OPENSSL_NO_EC
+ int curve;
+
+ /* For Suite B need to match signature algorithm to curve */
+ if (tls1_suiteb(s)) {
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
+ curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ } else {
+ curve = -1;
+ }
+#endif
/*
* Find highest preference signature algorithm matching
*/
for (i = 0; i < s->cert->shared_sigalgslen; i++) {
lu = s->cert->shared_sigalgs[i];
- if (lu->sig_idx == idx)
- break;
- if (idx == SSL_PKEY_RSA && lu->sig == EVP_PKEY_RSA_PSS)
+
+ if (s->server) {
+ if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
+ continue;
+ } else {
+ int cc_idx = s->cert->key - s->cert->pkeys;
+
+ sig_idx = lu->sig_idx;
+ if (cc_idx != sig_idx) {
+ if (sig_idx != SSL_PKEY_RSA_PSS_SIGN
+ || cc_idx != SSL_PKEY_RSA)
+ continue;
+ sig_idx = SSL_PKEY_RSA;
+ }
+ }
+#ifndef OPENSSL_NO_EC
+ if (curve == -1 || lu->curve == curve)
+#endif
break;
}
if (i == s->cert->shared_sigalgslen) {
const uint16_t *sent_sigs;
size_t sent_sigslen, i;
- if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
+ if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR;
if (al == NULL)
return 1;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
- *al = SSL_AD_HANDSHAKE_FAILURE;
+ *al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
}
} else {
- if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
+ if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR;
}
}
}
- if (idx == -1) {
- if (al != NULL) {
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
- }
- return 0;
- }
- s->s3->tmp.cert = &s->cert->pkeys[idx];
+ 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;
return 1;