Add new "valid_flags" field to CERT_PKEY structure which determines what

the certificate can be used for (if anything). Set valid_flags field
in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
to have similar checks in it.

Add new "cert_flags" field to CERT structure and include a "strict mode".
This enforces some TLS certificate requirements (such as only permitting
certificate signature algorithms contained in the supported algorithms
extension) which some implementations ignore: this option should be used
with caution as it could cause interoperability issues.
This commit is contained in:
Dr. Stephen Henson 2012-06-28 12:45:49 +00:00
parent be681e123c
commit d61ff83be9
8 changed files with 258 additions and 27 deletions

12
CHANGES
View File

@ -4,6 +4,18 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx] Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add new "valid_flags" field to CERT_PKEY structure which determines what
the certificate can be used for (if anything). Set valid_flags field
in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
to have similar checks in it.
Add new "cert_flags" field to CERT structure and include a "strict mode".
This enforces some TLS certificate requirements (such as only permitting
certificate signature algorithms contained in the supported algorithms
extension) which some implementations ignore: this option should be used
with caution as it could cause interoperability issues.
[Steve Henson]
*) Update and tidy signature algorithm extension processing. Work out *) Update and tidy signature algorithm extension processing. Work out
shared signature algorithms based on preferences and peer algorithms shared signature algorithms based on preferences and peer algorithms
and print them out in s_client and s_server. Abort handshake if no and print them out in s_client and s_server. Abort handshake if no

View File

@ -959,6 +959,7 @@ int MAIN(int argc, char *argv[])
int badop=0,bugs=0; int badop=0,bugs=0;
int ret=1; int ret=1;
int off=0; int off=0;
int cert_flags = 0;
int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0; int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
int state=0; int state=0;
const SSL_METHOD *meth=NULL; const SSL_METHOD *meth=NULL;
@ -1396,6 +1397,8 @@ int MAIN(int argc, char *argv[])
keymatexportlen=atoi(*(++argv)); keymatexportlen=atoi(*(++argv));
if (keymatexportlen == 0) goto bad; if (keymatexportlen == 0) goto bad;
} }
else if (strcmp(*argv, "-cert_strict") == 0)
cert_flags |= SSL_CERT_FLAG_TLS_STRICT;
else else
{ {
BIO_printf(bio_err,"unknown option %s\n",*argv); BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -1614,6 +1617,7 @@ bad:
if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL); if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL);
if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
SSL_CTX_set_options(ctx,off); SSL_CTX_set_options(ctx,off);
if (cert_flags) SSL_CTX_set_cert_flags(ctx, cert_flags);
/* DTLS: partial reads end up discarding unread UDP bytes :-( /* DTLS: partial reads end up discarding unread UDP bytes :-(
* Setting read ahead solves this problem. * Setting read ahead solves this problem.
*/ */
@ -1687,6 +1691,7 @@ bad:
if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL); if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL);
if (hack) SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); if (hack) SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
SSL_CTX_set_options(ctx2,off); SSL_CTX_set_options(ctx2,off);
if (cert_flags) SSL_CTX_set_cert_flags(ctx2, cert_flags);
/* DTLS: partial reads end up discarding unread UDP bytes :-( /* DTLS: partial reads end up discarding unread UDP bytes :-(
* Setting read ahead solves this problem. * Setting read ahead solves this problem.
*/ */

View File

@ -3921,6 +3921,8 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
allow = srvr; allow = srvr;
} }
tls1_set_cert_validity(s);
for (i=0; i<sk_SSL_CIPHER_num(prio); i++) for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
{ {
c=sk_SSL_CIPHER_value(prio,i); c=sk_SSL_CIPHER_value(prio,i);

View File

@ -650,6 +650,12 @@ struct ssl_session_st
* or just freed (depending on the context's setting for freelist_max_len). */ * or just freed (depending on the context's setting for freelist_max_len). */
#define SSL_MODE_RELEASE_BUFFERS 0x00000010L #define SSL_MODE_RELEASE_BUFFERS 0x00000010L
/* Cert related flags */
/* Many implementations ignore some aspects of the TLS standards such as
* enforcing certifcate chain algorithms. When this is set we enforce them.
*/
#define SSL_CERT_FLAG_TLS_STRICT 0x00000001L
/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
* they cannot be used to clear bits. */ * they cannot be used to clear bits. */
@ -689,6 +695,15 @@ struct ssl_session_st
SSL_ctrl((ssl),SSL_CTRL_TLS_EXT_SEND_HEARTBEAT,0,NULL) SSL_ctrl((ssl),SSL_CTRL_TLS_EXT_SEND_HEARTBEAT,0,NULL)
#endif #endif
#define SSL_CTX_set_cert_flags(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
#define SSL_set_cert_flags(s,op) \
SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
#define SSL_CTX_clear_cert_flags(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
#define SSL_clear_cert_flags(s,op) \
SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) #define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
@ -1645,6 +1660,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_ECDH_AUTO 94 #define SSL_CTRL_SET_ECDH_AUTO 94
#define SSL_CTRL_SET_SIGALGS 97 #define SSL_CTRL_SET_SIGALGS 97
#define SSL_CTRL_SET_SIGALGS_LIST 98 #define SSL_CTRL_SET_SIGALGS_LIST 98
#define SSL_CTRL_CERT_FLAGS 99
#define SSL_CTRL_CLEAR_CERT_FLAGS 100
#define DTLSv1_get_timeout(ssl, arg) \ #define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)

View File

@ -334,6 +334,7 @@ CERT *ssl_cert_dup(CERT *cert)
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
} }
} }
rpk->valid_flags = 0;
if (cert->pkeys[i].authz != NULL) if (cert->pkeys[i].authz != NULL)
{ {
/* Just copy everything. */ /* Just copy everything. */
@ -376,6 +377,8 @@ CERT *ssl_cert_dup(CERT *cert)
/* Shared sigalgs also NULL */ /* Shared sigalgs also NULL */
ret->shared_sigalgs = NULL; ret->shared_sigalgs = NULL;
ret->cert_flags = cert->cert_flags;
return(ret); return(ret);
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
@ -428,6 +431,7 @@ void ssl_cert_clear_certs(CERT *c)
if (cpk->authz != NULL) if (cpk->authz != NULL)
OPENSSL_free(cpk->authz); OPENSSL_free(cpk->authz);
#endif #endif
cpk->valid_flags = 0;
} }
} }

View File

@ -1128,6 +1128,10 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
if (s->s3) if (s->s3)
return s->s3->send_connection_binding; return s->s3->send_connection_binding;
else return 0; else return 0;
case SSL_CTRL_CERT_FLAGS:
return(s->cert->cert_flags|=larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
return(s->cert->cert_flags &=~larg);
default: default:
return(s->method->ssl_ctrl(s,cmd,larg,parg)); return(s->method->ssl_ctrl(s,cmd,larg,parg));
} }
@ -1225,6 +1229,10 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
return 0; return 0;
ctx->max_send_fragment = larg; ctx->max_send_fragment = larg;
return 1; return 1;
case SSL_CTRL_CERT_FLAGS:
return(ctx->cert->cert_flags|=larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
return(ctx->cert->cert_flags &=~larg);
default: default:
return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
} }
@ -2078,21 +2086,21 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
#endif #endif
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); rsa_enc= cpk->valid_flags;
rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl); rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);
rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); rsa_sign= (cpk->valid_flags & CERT_PKEY_SIGN);
cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]);
dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); dsa_sign= (cpk->valid_flags & CERT_PKEY_SIGN);
cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); cpk= &(c->pkeys[SSL_PKEY_DH_RSA]);
dh_rsa= (cpk->x509 != NULL && cpk->privatekey != NULL); dh_rsa= cpk->valid_flags;
dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_DH_DSA]); cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);
/* FIX THIS EAY EAY EAY */ /* FIX THIS EAY EAY EAY */
dh_dsa= (cpk->x509 != NULL && cpk->privatekey != NULL); dh_dsa= cpk->valid_flags;
dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_ECC]); cpk= &(c->pkeys[SSL_PKEY_ECC]);
have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL); have_ecc_cert= cpk->valid_flags;
mask_k=0; mask_k=0;
mask_a=0; mask_a=0;
emask_k=0; emask_k=0;
@ -2174,13 +2182,16 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
*/ */
if (have_ecc_cert) if (have_ecc_cert)
{ {
cpk = &c->pkeys[SSL_PKEY_ECC];
x = cpk->x509;
/* This call populates extension flags (ex_flags) */ /* This call populates extension flags (ex_flags) */
x = (c->pkeys[SSL_PKEY_ECC]).x509;
X509_check_purpose(x, -1, 0); X509_check_purpose(x, -1, 0);
ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
(x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1; (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1;
ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
(x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
if (!(cpk->valid_flags & CERT_PKEY_SIGN))
ecdsa_ok = 0;
ecc_pkey = X509_get_pubkey(x); ecc_pkey = X509_get_pubkey(x);
ecc_pkey_size = (ecc_pkey != NULL) ? ecc_pkey_size = (ecc_pkey != NULL) ?
EVP_PKEY_bits(ecc_pkey) : 0; EVP_PKEY_bits(ecc_pkey) : 0;

View File

@ -466,6 +466,14 @@
#define NAMED_CURVE_TYPE 3 #define NAMED_CURVE_TYPE 3
#endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_NO_EC */
/* Values for valid_flags in CERT_PKEY structure */
/* Certificate inconsistent with session, key missing etc */
#define CERT_PKEY_INVALID 0x0
/* Certificate can be used with this sesstion */
#define CERT_PKEY_VALID 0x1
/* Certificate can also be used for signing */
#define CERT_PKEY_SIGN 0x2
typedef struct cert_pkey_st typedef struct cert_pkey_st
{ {
X509 *x509; X509 *x509;
@ -483,6 +491,11 @@ typedef struct cert_pkey_st
unsigned char *authz; unsigned char *authz;
size_t authz_length; size_t authz_length;
#endif #endif
/* Set if CERT_PKEY can be used with current SSL session: e.g.
* appropriate curve, signature algorithms etc. If zero it can't be
* used at all.
*/
int valid_flags;
} CERT_PKEY; } CERT_PKEY;
typedef struct cert_st typedef struct cert_st
@ -514,7 +527,8 @@ typedef struct cert_st
/* Select ECDH parameters automatically */ /* Select ECDH parameters automatically */
int ecdh_tmp_auto; int ecdh_tmp_auto;
#endif #endif
/* Flags related to certificates */
unsigned int cert_flags;
CERT_PKEY pkeys[SSL_PKEY_NUM]; CERT_PKEY pkeys[SSL_PKEY_NUM];
/* signature algorithms peer reports: e.g. supported signature /* signature algorithms peer reports: e.g. supported signature
@ -1178,6 +1192,9 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg);
int tls1_set_sigalgs_list(CERT *c, const char *str); int tls1_set_sigalgs_list(CERT *c, const char *str);
int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen); int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen);
int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx);
void tls1_set_cert_validity(SSL *s);
#endif #endif
EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ; EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;

View File

@ -539,24 +539,38 @@ static int tls1_check_ec_key(SSL *s,
} }
return 1; return 1;
} }
/* Check EC server key is compatible with client extensions */
int tls1_check_ec_server_key(SSL *s) /* Check cert parameters compatible with extensions: currently just checks
* EC certificates have compatible curves and compression.
*/
static int tls1_check_cert_param(SSL *s, X509 *x)
{ {
int rv;
CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC;
EVP_PKEY *pkey;
unsigned char comp_id, curve_id[2]; unsigned char comp_id, curve_id[2];
if (!cpk->x509 || !cpk->privatekey) EVP_PKEY *pkey;
return 0; int rv;
pkey = X509_get_pubkey(cpk->x509); pkey = X509_get_pubkey(x);
if (!pkey) if (!pkey)
return 0; return 0;
/* If not EC nothing to do */
if (pkey->type != EVP_PKEY_EC)
{
EVP_PKEY_free(pkey);
return 1;
}
rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec); rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
if (!rv) if (!rv)
return 0; return 0;
return tls1_check_ec_key(s, curve_id, &comp_id); return tls1_check_ec_key(s, curve_id, &comp_id);
} }
/* Check EC server key is compatible with client extensions */
int tls1_check_ec_server_key(SSL *s)
{
CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC;
if (!cpk->x509 || !cpk->privatekey)
return 0;
return tls1_check_cert_param(s, cpk->x509);
}
/* Check EC temporary key is compatible with client extensions */ /* Check EC temporary key is compatible with client extensions */
int tls1_check_ec_tmp_key(SSL *s) int tls1_check_ec_tmp_key(SSL *s)
{ {
@ -3050,24 +3064,30 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
} }
} }
/* Set any remaining keys to default values. NOTE: if alg is not /* In strict mode leave unset digests as NULL to indicate we can't
* supported it stays as NULL. * use the certificate for signing.
*/ */
if (!(s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT))
{
/* Set any remaining keys to default values. NOTE: if alg is
* not supported it stays as NULL.
*/
#ifndef OPENSSL_NO_DSA #ifndef OPENSSL_NO_DSA
if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest) if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
#endif #endif
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
{ {
c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1(); c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1(); c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
} }
#endif #endif
#ifndef OPENSSL_NO_ECDSA #ifndef OPENSSL_NO_ECDSA
if (!c->pkeys[SSL_PKEY_ECC].digest) if (!c->pkeys[SSL_PKEY_ECC].digest)
c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
#endif #endif
}
return 1; return 1;
} }
@ -3360,4 +3380,147 @@ int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen)
return 0; return 0;
} }
static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid)
{
int sig_nid;
size_t i;
if (default_nid == -1)
return 1;
sig_nid = X509_get_signature_nid(x);
if (default_nid)
return sig_nid == default_nid ? 1 : 0;
for (i = 0; i < c->shared_sigalgslen; i++)
if (sig_nid == c->shared_sigalgs[i].signandhash_nid)
return 1;
return 0;
}
/* Check certificate chain is consistent with TLS extensions and is
* usable by server.
*/
int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx)
{
int i;
int rv = CERT_PKEY_INVALID;
CERT_PKEY *cpk = NULL;
CERT *c = s->cert;
if (idx != -1)
{
cpk = c->pkeys + idx;
x = cpk->x509;
pk = cpk->privatekey;
chain = cpk->chain;
/* If no cert or key, forget it */
if (!x || !pk)
goto end;
}
else
{
idx = ssl_cert_type(x, pk);
if (idx == -1)
goto end;
}
/* Check all signature algorithms are consistent with
* signature algorithms extension if TLS 1.2 or later
* and strict mode.
*/
if (TLS1_get_version(s) >= TLS1_2_VERSION
&& c->cert_flags & SSL_CERT_FLAG_TLS_STRICT)
{
int default_nid;
unsigned char rsign = 0;
if (c->peer_sigalgs)
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
else
{
switch(idx)
{
case SSL_PKEY_RSA_ENC:
case SSL_PKEY_RSA_SIGN:
case SSL_PKEY_DH_RSA:
rsign = TLSEXT_signature_rsa;
default_nid = NID_sha1WithRSAEncryption;
break;
case SSL_PKEY_DSA_SIGN:
case SSL_PKEY_DH_DSA:
rsign = TLSEXT_signature_dsa;
default_nid = NID_dsaWithSHA1;
break;
case SSL_PKEY_ECC:
rsign = TLSEXT_signature_ecdsa;
default_nid = NID_ecdsa_with_SHA1;
break;
default:
default_nid = -1;
break;
}
}
/* If peer sent no signature algorithms extension and we
* have set preferred signature algorithms check we support
* sha1.
*/
if (default_nid > 0 && c->conf_sigalgs)
{
size_t j;
const unsigned char *p = c->conf_sigalgs;
for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2)
{
if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign)
break;
}
if (j == c->conf_sigalgslen)
goto end;
}
/* Check signature algorithm of each cert in chain */
if (!tls1_check_sig_alg(c, x, default_nid))
goto end;
for (i = 0; i < sk_X509_num(chain); i++)
{
if (!tls1_check_sig_alg(c, sk_X509_value(chain, i),
default_nid))
goto end;
}
}
/* Check cert parameters are consistent */
if (!tls1_check_cert_param(s, x))
goto end;
/* In strict mode check rest of chain too */
if (c->cert_flags & SSL_CERT_FLAG_TLS_STRICT)
{
for (i = 0; i < sk_X509_num(chain); i++)
{
if (!tls1_check_cert_param(s, sk_X509_value(chain, i)))
goto end;
}
}
rv = CERT_PKEY_VALID;
end:
if (cpk)
{
if (rv && cpk->digest)
rv |= CERT_PKEY_SIGN;
cpk->valid_flags = rv;
}
return rv;
}
/* Set validity of certificates in an SSL structure */
void tls1_set_cert_validity(SSL *s)
{
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_RSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_DSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
}
#endif #endif