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

View File

@@ -1128,6 +1128,10 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
if (s->s3)
return s->s3->send_connection_binding;
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:
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;
ctx->max_send_fragment = larg;
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:
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);
#endif
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);
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]);
dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL);
dsa_sign= (cpk->valid_flags & CERT_PKEY_SIGN);
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);
cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);
/* 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);
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_a=0;
emask_k=0;
@@ -2174,13 +2182,16 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
*/
if (have_ecc_cert)
{
cpk = &c->pkeys[SSL_PKEY_ECC];
x = cpk->x509;
/* This call populates extension flags (ex_flags) */
x = (c->pkeys[SSL_PKEY_ECC]).x509;
X509_check_purpose(x, -1, 0);
ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
(x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1;
ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
(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_size = (ecc_pkey != NULL) ?
EVP_PKEY_bits(ecc_pkey) : 0;