Skip to content

Commit

Permalink
Security framework.
Browse files Browse the repository at this point in the history
Security callback: selects which parameters are permitted including
sensible defaults based on bits of security.

The "parameters" which can be selected include: ciphersuites,
curves, key sizes, certificate signature algorithms, supported
signature algorithms, DH parameters, SSL/TLS version, session tickets
and compression.

In some cases prohibiting the use of a parameters will mean they are
not advertised to the peer: for example cipher suites and ECC curves.
In other cases it will abort the handshake: e.g DH parameters or the
peer key size.

Documentation to follow...
  • Loading branch information
snhenson committed Mar 28, 2014
1 parent 66f96fe commit b362cca
Show file tree
Hide file tree
Showing 16 changed files with 822 additions and 197 deletions.
14 changes: 12 additions & 2 deletions ssl/s23_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,13 @@ static int ssl23_no_ssl2_ciphers(SSL *s)
SSL_CIPHER *cipher;
STACK_OF(SSL_CIPHER) *ciphers;
int i;
ssl_set_client_disabled(s);
ciphers = SSL_get_ciphers(s);
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++)
{
cipher = sk_SSL_CIPHER_value(ciphers, i);
if (ssl_cipher_disabled(s, cipher, SSL_SECOP_CIPHER_SUPPORTED))
continue;
if (cipher->algorithm_ssl == SSL_SSLV2)
return 0;
}
Expand Down Expand Up @@ -309,6 +312,8 @@ static int ssl23_client_hello(SSL *s)

ssl2_compat = (options & SSL_OP_NO_SSLv2) ? 0 : 1;

if (ssl2_compat && !ssl_security(s, SSL_SECOP_SSL2_COMPAT, 0, 0, NULL))
ssl2_compat = 0;
if (ssl2_compat && ssl23_no_ssl2_ciphers(s))
ssl2_compat = 0;

Expand Down Expand Up @@ -533,8 +538,7 @@ static int ssl23_client_hello(SSL *s)
#ifdef OPENSSL_NO_COMP
*(p++)=1;
#else
if ((s->options & SSL_OP_NO_COMPRESSION)
|| !s->ctx->comp_methods)
if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
j=0;
else
j=sk_SSL_COMP_num(s->ctx->comp_methods);
Expand Down Expand Up @@ -750,6 +754,12 @@ static int ssl23_get_server_hello(SSL *s)
goto err;
}

if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL))
{
SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_VERSION_TOO_LOW);
goto err;
}

if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
{
/* fatal alert */
Expand Down
6 changes: 6 additions & 0 deletions ssl/s23_srvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,12 @@ int ssl23_get_client_hello(SSL *s)
}
#endif

if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL))
{
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_VERSION_TOO_LOW);
goto err;
}

if (s->state == SSL23_ST_SR_CLNT_HELLO_B)
{
/* we have SSLv3/TLSv1 in an SSLv2 header
Expand Down
6 changes: 6 additions & 0 deletions ssl/s2_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,12 @@ int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data)
ERR_clear_error(); /* but we keep s->verify_result */
s->session->verify_result = s->verify_result;

if (i > 1)
{
SSLerr(SSL_F_SSL2_SET_CERTIFICATE, i);
goto err;
}

/* server's cert for this session */
sc=ssl_sess_cert_new();
if (sc == NULL)
Expand Down
6 changes: 6 additions & 0 deletions ssl/s2_srvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,12 @@ static int request_certificate(SSL *s)

i=ssl_verify_cert_chain(s,sk);

if (i > 1)
{
SSLerr(SSL_F_REQUEST_CERTIFICATE, i);
goto msg_end;
}

if (i > 0) /* we like the packet, now check the chksum */
{
EVP_MD_CTX ctx;
Expand Down
11 changes: 9 additions & 2 deletions ssl/s3_both.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ int ssl3_setup_read_buffer(SSL *s)
len += SSL3_RT_MAX_EXTRA;
}
#ifndef OPENSSL_NO_COMP
if (!(s->options & SSL_OP_NO_COMPRESSION))
if (ssl_allow_compression(s))
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
if ((p=freelist_extract(s->ctx, 1, len)) == NULL)
Expand Down Expand Up @@ -732,7 +732,7 @@ int ssl3_setup_write_buffer(SSL *s)
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
+ headerlen + align;
#ifndef OPENSSL_NO_COMP
if (!(s->options & SSL_OP_NO_COMPRESSION))
if (ssl_allow_compression(s))
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
Expand Down Expand Up @@ -782,3 +782,10 @@ int ssl3_release_read_buffer(SSL *s)
return 1;
}

int ssl_allow_compression(SSL *s)
{
if (s->options & SSL_OP_NO_COMPRESSION)
return 0;
return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL);
}

28 changes: 24 additions & 4 deletions ssl/s3_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ int ssl3_connect(SSL *s)
ret = -1;
goto end;
}

if (!ssl_security(s, SSL_SECOP_VERSION, 0,
s->version, NULL))
{
SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW);
return -1;
}

/* s->version=SSL3_VERSION; */
s->type=SSL_ST_CONNECT;
Expand Down Expand Up @@ -871,8 +878,7 @@ int ssl3_client_hello(SSL *s)
*(p++)=1;
#else

if ((s->options & SSL_OP_NO_COMPRESSION)
|| !s->ctx->comp_methods)
if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
j=0;
else
j=sk_SSL_COMP_num(s->ctx->comp_methods);
Expand Down Expand Up @@ -1079,7 +1085,7 @@ int ssl3_get_server_hello(SSL *s)
/* If it is a disabled cipher we didn't send it in client hello,
* so return an error.
*/
if (ssl_cipher_disabled(s, c))
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK))
{
al=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
Expand Down Expand Up @@ -1148,7 +1154,7 @@ int ssl3_get_server_hello(SSL *s)
}
if (j == 0)
comp=NULL;
else if (s->options & SSL_OP_NO_COMPRESSION)
else if (!ssl_allow_compression(s))
{
al=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
Expand Down Expand Up @@ -1290,6 +1296,12 @@ int ssl3_get_server_certificate(SSL *s)
goto f_err;
}
ERR_clear_error(); /* but we keep s->verify_result */
if (i > 1)
{
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, i);
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}

sc=ssl_sess_cert_new();
if (sc == NULL) goto err;
Expand Down Expand Up @@ -1709,6 +1721,14 @@ int ssl3_get_key_exchange(SSL *s)
p+=i;
n-=param_len;

if (!ssl_security(s, SSL_SECOP_TMP_DH,
DH_security_bits(dh), 0, dh))
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL);
goto f_err;
}

#ifndef OPENSSL_NO_RSA
if (alg_a & SSL_aRSA)
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
Expand Down
80 changes: 36 additions & 44 deletions ssl/s3_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -3228,6 +3228,12 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return(ret);
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
DH_security_bits(dh), 0, dh))
{
SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL);
return(ret);
}
if ((dh = DHparams_dup(dh)) == NULL)
{
SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
Expand Down Expand Up @@ -3415,17 +3421,17 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)

case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(s->cert,
return ssl_cert_set1_chain(s, NULL,
(STACK_OF (X509) *)parg);
else
return ssl_cert_set0_chain(s->cert,
return ssl_cert_set0_chain(s, NULL,
(STACK_OF (X509) *)parg);

case SSL_CTRL_CHAIN_CERT:
if (larg)
return ssl_cert_add1_chain_cert(s->cert, (X509 *)parg);
return ssl_cert_add1_chain_cert(s, NULL, (X509 *)parg);
else
return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
return ssl_cert_add0_chain_cert(s, NULL, (X509 *)parg);

case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = s->cert->key->chain;
Expand Down Expand Up @@ -3533,7 +3539,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return ssl3_set_req_cert_type(s->cert, parg, larg);

case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg);
return ssl_build_cert_chain(s, NULL, larg);

case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
Expand Down Expand Up @@ -3736,6 +3742,12 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
DH *new=NULL,*dh;

dh=(DH *)parg;
if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
DH_security_bits(dh), 0, dh))
{
SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL);
return 0;
}
if ((new=DHparams_dup(dh)) == NULL)
{
SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB);
Expand Down Expand Up @@ -3911,7 +3923,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return ssl3_set_req_cert_type(ctx->cert, parg, larg);

case SSL_CTRL_BUILD_CERT_CHAIN:
return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg);
return ssl_build_cert_chain(NULL, ctx, larg);

case SSL_CTRL_SET_VERIFY_CERT_STORE:
return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
Expand Down Expand Up @@ -3948,17 +3960,17 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)

case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(ctx->cert,
return ssl_cert_set1_chain(NULL, ctx,
(STACK_OF (X509) *)parg);
else
return ssl_cert_set0_chain(ctx->cert,
return ssl_cert_set0_chain(NULL, ctx,
(STACK_OF (X509) *)parg);

case SSL_CTRL_CHAIN_CERT:
if (larg)
return ssl_cert_add1_chain_cert(ctx->cert, (X509 *)parg);
return ssl_cert_add1_chain_cert(NULL, ctx, (X509 *)parg);
else
return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
return ssl_cert_add0_chain_cert(NULL, ctx, (X509 *)parg);

case SSL_CTRL_GET_CHAIN_CERTS:
*(STACK_OF(X509) **)parg = ctx->cert->key->chain;
Expand Down Expand Up @@ -4203,6 +4215,10 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
ii=sk_SSL_CIPHER_find(allow,c);
if (ii >= 0)
{
/* Check security callback permits this cipher */
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, c))
continue;
#if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_TLSEXT)
if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA) && s->s3->is_probably_safari)
{
Expand All @@ -4220,43 +4236,19 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
{
int ret=0;
const unsigned char *sig;
size_t i, siglen;
int have_rsa_sign = 0, have_dsa_sign = 0;
#ifndef OPENSSL_NO_ECDSA
int have_ecdsa_sign = 0;
#endif
int nostrict = 1;
unsigned long alg_k;
unsigned long alg_k, alg_a = 0;

/* If we have custom certificate types set, use them */
if (s->cert->ctypes)
{
memcpy(p, s->cert->ctypes, s->cert->ctype_num);
return (int)s->cert->ctype_num;
}
/* get configured sigalgs */
siglen = tls12_get_psigalgs(s, &sig);
/* Get mask of algorithms disabled by signature list */
ssl_set_sig_mask(&alg_a, s, SSL_SECOP_SIGALG_MASK);
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
nostrict = 0;
for (i = 0; i < siglen; i+=2, sig+=2)
{
switch(sig[1])
{
case TLSEXT_signature_rsa:
have_rsa_sign = 1;
break;

case TLSEXT_signature_dsa:
have_dsa_sign = 1;
break;
#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
have_ecdsa_sign = 1;
break;
#endif
}
}

alg_k = s->s3->tmp.new_cipher->algorithm_mkey;

Expand All @@ -4279,11 +4271,11 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
/* Since this refers to a certificate signed with an RSA
* algorithm, only check for rsa signing in strict mode.
*/
if (nostrict || have_rsa_sign)
if (nostrict || !(alg_a & SSL_aRSA))
p[ret++]=SSL3_CT_RSA_FIXED_DH;
# endif
# ifndef OPENSSL_NO_DSA
if (nostrict || have_dsa_sign)
if (nostrict || !(alg_a & SSL_aDSS))
p[ret++]=SSL3_CT_DSS_FIXED_DH;
# endif
}
Expand All @@ -4299,19 +4291,19 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
}
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_RSA
if (have_rsa_sign)
if (!(alg_a & SSL_aRSA))
p[ret++]=SSL3_CT_RSA_SIGN;
#endif
#ifndef OPENSSL_NO_DSA
if (have_dsa_sign)
if (!(alg_a & SSL_aDSS))
p[ret++]=SSL3_CT_DSS_SIGN;
#endif
#ifndef OPENSSL_NO_ECDH
if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->version >= TLS1_VERSION))
{
if (nostrict || have_rsa_sign)
if (nostrict || !(alg_a & SSL_aRSA))
p[ret++]=TLS_CT_RSA_FIXED_ECDH;
if (nostrict || have_ecdsa_sign)
if (nostrict || !(alg_a & SSL_aECDSA))
p[ret++]=TLS_CT_ECDSA_FIXED_ECDH;
}
#endif
Expand All @@ -4322,7 +4314,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
*/
if (s->version >= TLS1_VERSION)
{
if (have_ecdsa_sign)
if (!(alg_a & SSL_aECDSA))
p[ret++]=TLS_CT_ECDSA_SIGN;
}
#endif
Expand Down

0 comments on commit b362cca

Please sign in to comment.