提交 2ea80354 编写于 作者: D Dr. Stephen Henson

Add three Suite B modes to TLS code, supporting RFC6460.

上级 5833e4f5
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx] Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) New Suite B modes for TLS code. These use and enforce the requirements
of RFC6460: restrict ciphersuites, only permit Suite B algorithms and
only use Suite B curves. The Suite B modes can be set by using the
strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring.
[Steve Henson]
*) New chain verification flags for Suite B levels of security. Check *) New chain verification flags for Suite B levels of security. Check
algorithms are acceptable when flags are set in X509_verify_cert. algorithms are acceptable when flags are set in X509_verify_cert.
[Steve Henson] [Steve Henson]
......
...@@ -2623,8 +2623,8 @@ static int init_ssl_connection(SSL *con) ...@@ -2623,8 +2623,8 @@ static int init_ssl_connection(SSL *con)
BIO_printf(bio_err,"verify error:%s\n", BIO_printf(bio_err,"verify error:%s\n",
X509_verify_cert_error_string(verify_error)); X509_verify_cert_error_string(verify_error));
} }
else /* Always print any error messages */
ERR_print_errors(bio_err); ERR_print_errors(bio_err);
return(0); return(0);
} }
......
...@@ -367,6 +367,12 @@ static int ssl23_client_hello(SSL *s) ...@@ -367,6 +367,12 @@ static int ssl23_client_hello(SSL *s)
version_major = TLS1_2_VERSION_MAJOR; version_major = TLS1_2_VERSION_MAJOR;
version_minor = TLS1_2_VERSION_MINOR; version_minor = TLS1_2_VERSION_MINOR;
} }
else if (tls1_suiteb(s))
{
SSLerr(SSL_F_SSL23_CLIENT_HELLO,
SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
return -1;
}
else if (version == TLS1_1_VERSION) else if (version == TLS1_1_VERSION)
{ {
version_major = TLS1_1_VERSION_MAJOR; version_major = TLS1_1_VERSION_MAJOR;
......
...@@ -425,6 +425,13 @@ int ssl23_get_client_hello(SSL *s) ...@@ -425,6 +425,13 @@ int ssl23_get_client_hello(SSL *s)
} }
} }
if (s->version < TLS1_2_VERSION && tls1_suiteb(s))
{
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
goto err;
}
#ifdef OPENSSL_FIPS #ifdef OPENSSL_FIPS
if (FIPS_mode() && (s->version < TLS1_VERSION)) if (FIPS_mode() && (s->version < TLS1_VERSION))
{ {
......
...@@ -3154,8 +3154,9 @@ err: ...@@ -3154,8 +3154,9 @@ err:
} }
/* Check a certificate can be used for client authentication. Currently /* Check a certificate can be used for client authentication. Currently
* check cert exists, if we have a suitable digest for TLS 1.2 and if * check cert exists, if we have a suitable digest for TLS 1.2 if
* static DH client certificates can be used. * static DH client certificates can be used and optionally checks
* suitability for Suite B.
*/ */
static int ssl3_check_client_certificate(SSL *s) static int ssl3_check_client_certificate(SSL *s)
{ {
...@@ -3165,6 +3166,12 @@ static int ssl3_check_client_certificate(SSL *s) ...@@ -3165,6 +3166,12 @@ static int ssl3_check_client_certificate(SSL *s)
/* If no suitable signature algorithm can't use certificate */ /* If no suitable signature algorithm can't use certificate */
if (TLS1_get_version(s) >= TLS1_2_VERSION && !s->cert->key->digest) if (TLS1_get_version(s) >= TLS1_2_VERSION && !s->cert->key->digest)
return 0; return 0;
/* If strict mode check suitability of chain before using it.
* This also adjusts suite B digest if necessary.
*/
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
!tls1_check_chain(s, NULL, NULL, NULL, -2))
return 0;
alg_k=s->s3->tmp.new_cipher->algorithm_mkey; alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
/* See if we can use client certificate for fixed DH */ /* See if we can use client certificate for fixed DH */
if (alg_k & (SSL_kDHr|SSL_kDHd)) if (alg_k & (SSL_kDHr|SSL_kDHd))
......
...@@ -3966,7 +3966,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, ...@@ -3966,7 +3966,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
} }
#endif #endif
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s))
{ {
prio = srvr; prio = srvr;
allow = clnt; allow = clnt;
...@@ -4040,7 +4040,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, ...@@ -4040,7 +4040,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
/* if we are considering an ECC cipher suite that uses /* if we are considering an ECC cipher suite that uses
* an ephemeral EC key check it */ * an ephemeral EC key check it */
if (alg_k & SSL_kEECDH) if (alg_k & SSL_kEECDH)
ok = ok && tls1_check_ec_tmp_key(s); ok = ok && tls1_check_ec_tmp_key(s, c->id);
#endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_NO_EC */
#endif /* OPENSSL_NO_TLSEXT */ #endif /* OPENSSL_NO_TLSEXT */
...@@ -4059,7 +4059,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p) ...@@ -4059,7 +4059,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
{ {
int ret=0; int ret=0;
const unsigned char *sig; const unsigned char *sig;
size_t siglen; size_t i, siglen;
int have_rsa_sign = 0, have_dsa_sign = 0, have_ecdsa_sign = 0; int have_rsa_sign = 0, have_dsa_sign = 0, have_ecdsa_sign = 0;
int nostrict = 1; int nostrict = 1;
unsigned long alg_k; unsigned long alg_k;
...@@ -4070,48 +4070,27 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p) ...@@ -4070,48 +4070,27 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
memcpy(p, s->cert->ctypes, s->cert->ctype_num); memcpy(p, s->cert->ctypes, s->cert->ctype_num);
return (int)s->cert->ctype_num; return (int)s->cert->ctype_num;
} }
/* Else see if we have any signature algorithms configured */ /* get configured sigalgs */
if (s->cert->client_sigalgs) siglen = tls12_get_psigalgs(s, &sig);
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
nostrict = 0;
for (i = 0; i < siglen; i+=2, sig+=2)
{ {
sig = s->cert->client_sigalgs; switch(sig[1])
siglen = s->cert->client_sigalgslen;
}
else
{
sig = s->cert->conf_sigalgs;
siglen = s->cert->conf_sigalgslen;
}
/* If we have sigalgs work out if we can sign with RSA, DSA, ECDSA */
if (sig)
{
size_t i;
if (s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT)
nostrict = 0;
for (i = 0; i < siglen; i+=2, sig+=2)
{ {
switch(sig[1]) case TLSEXT_signature_rsa:
{ have_rsa_sign = 1;
case TLSEXT_signature_rsa: break;
have_rsa_sign = 1;
break;
case TLSEXT_signature_dsa: case TLSEXT_signature_dsa:
have_dsa_sign = 1; have_dsa_sign = 1;
break; break;
case TLSEXT_signature_ecdsa: case TLSEXT_signature_ecdsa:
have_ecdsa_sign = 1; have_ecdsa_sign = 1;
break; break;
}
} }
} }
/* Otherwise allow anything */
else
{
have_rsa_sign = 1;
have_dsa_sign = 1;
have_ecdsa_sign = 1;
}
alg_k = s->s3->tmp.new_cipher->algorithm_mkey; alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
......
...@@ -1704,8 +1704,8 @@ int ssl3_send_server_key_exchange(SSL *s) ...@@ -1704,8 +1704,8 @@ int ssl3_send_server_key_exchange(SSL *s)
ecdhp=cert->ecdh_tmp; ecdhp=cert->ecdh_tmp;
if (s->cert->ecdh_tmp_auto) if (s->cert->ecdh_tmp_auto)
{ {
/* Get NID of first shared curve */ /* Get NID of appropriate shared curve */
int nid = tls1_shared_curve(s, 0); int nid = tls1_shared_curve(s, -2);
if (nid != NID_undef) if (nid != NID_undef)
ecdhp = EC_KEY_new_by_curve_name(nid); ecdhp = EC_KEY_new_by_curve_name(nid);
} }
......
...@@ -654,7 +654,16 @@ struct ssl_session_st ...@@ -654,7 +654,16 @@ struct ssl_session_st
/* Many implementations ignore some aspects of the TLS standards such as /* Many implementations ignore some aspects of the TLS standards such as
* enforcing certifcate chain algorithms. When this is set we enforce them. * enforcing certifcate chain algorithms. When this is set we enforce them.
*/ */
#define SSL_CERT_FLAG_TLS_STRICT 0x00000001L #define SSL_CERT_FLAG_TLS_STRICT 0x00000001L
/* Suite B modes, takes same values as certificate verify flags */
#define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000
/* Suite B 192 bit only mode */
#define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000
/* Suite B 128 bit mode allowing 192 bit algorithms */
#define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000
/* Flags for building certificate chains */ /* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */ /* Treat any existing certificates as untrusted CAs */
...@@ -681,6 +690,8 @@ struct ssl_session_st ...@@ -681,6 +690,8 @@ struct ssl_session_st
#define CERT_PKEY_ISSUER_NAME 0x200 #define CERT_PKEY_ISSUER_NAME 0x200
/* Cert type matches client types (always set for server cert) */ /* Cert type matches client types (always set for server cert) */
#define CERT_PKEY_CERT_TYPE 0x400 #define CERT_PKEY_CERT_TYPE 0x400
/* Cert chain suitable to Suite B */
#define CERT_PKEY_SUITEB 0x800
/* 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. */
...@@ -2579,6 +2590,7 @@ void ERR_load_SSL_strings(void); ...@@ -2579,6 +2590,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_HTTPS_PROXY_REQUEST 155 #define SSL_R_HTTPS_PROXY_REQUEST 155
#define SSL_R_HTTP_REQUEST 156 #define SSL_R_HTTP_REQUEST 156
#define SSL_R_ILLEGAL_PADDING 283 #define SSL_R_ILLEGAL_PADDING 283
#define SSL_R_ILLEGAL_SUITEB_DIGEST 380
#define SSL_R_INCONSISTENT_COMPRESSION 340 #define SSL_R_INCONSISTENT_COMPRESSION 340
#define SSL_R_INVALID_AUDIT_PROOF 371 #define SSL_R_INVALID_AUDIT_PROOF 371
#define SSL_R_INVALID_AUTHZ_DATA 374 #define SSL_R_INVALID_AUTHZ_DATA 374
...@@ -2653,6 +2665,7 @@ void ERR_load_SSL_strings(void); ...@@ -2653,6 +2665,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_NULL_SSL_METHOD_PASSED 196 #define SSL_R_NULL_SSL_METHOD_PASSED 196
#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
#define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 #define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
#define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE 379
#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297
#define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG 327 #define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG 327
#define SSL_R_PACKET_LENGTH_TOO_LONG 198 #define SSL_R_PACKET_LENGTH_TOO_LONG 198
......
...@@ -692,6 +692,8 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) ...@@ -692,6 +692,8 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk)
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
return(0); return(0);
} }
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
#if 0 #if 0
if (SSL_get_verify_depth(s) >= 0) if (SSL_get_verify_depth(s) >= 0)
X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
...@@ -1151,6 +1153,8 @@ int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) ...@@ -1151,6 +1153,8 @@ int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags)
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB); SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
return 0; return 0;
} }
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(&xs_ctx, c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
i = X509_verify_cert(&xs_ctx); i = X509_verify_cert(&xs_ctx);
if (i > 0) if (i > 0)
......
...@@ -1347,10 +1347,49 @@ static int ssl_cipher_process_rulestr(const char *rule_str, ...@@ -1347,10 +1347,49 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
return(retval); return(retval);
} }
static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
const char **prule_str)
{
unsigned int suiteb_flags = 0;
if (!strcmp(*prule_str, "SUITEB128"))
suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS;
else if (!strcmp(*prule_str, "SUITEB128ONLY"))
suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS_ONLY;
else if (!strcmp(*prule_str, "SUITEB192"))
suiteb_flags = SSL_CERT_FLAG_SUITEB_192_LOS;
if (suiteb_flags)
{
c->cert_flags &= ~SSL_CERT_FLAG_SUITEB_128_LOS;
c->cert_flags |= suiteb_flags;
}
else
suiteb_flags = c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS;
if (!suiteb_flags)
return 1;
/* Check version */
switch(suiteb_flags)
{
case SSL_CERT_FLAG_SUITEB_128_LOS:
*prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384";
break;
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256";
break;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384";
break;
}
return 1;
}
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) **cipher_list, STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id, STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str) const char *rule_str, CERT *c)
{ {
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl; unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl;
...@@ -1365,6 +1404,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, ...@@ -1365,6 +1404,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL) if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
return NULL; return NULL;
if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
return NULL;
/* /*
* To reduce the work to do we only want to process the compiled * To reduce the work to do we only want to process the compiled
* in algorithms, so we first get the mask of disabled ciphers. * in algorithms, so we first get the mask of disabled ciphers.
......
...@@ -398,6 +398,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= ...@@ -398,6 +398,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST) ,"https proxy request"}, {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST) ,"https proxy request"},
{ERR_REASON(SSL_R_HTTP_REQUEST) ,"http request"}, {ERR_REASON(SSL_R_HTTP_REQUEST) ,"http request"},
{ERR_REASON(SSL_R_ILLEGAL_PADDING) ,"illegal padding"}, {ERR_REASON(SSL_R_ILLEGAL_PADDING) ,"illegal padding"},
{ERR_REASON(SSL_R_ILLEGAL_SUITEB_DIGEST) ,"illegal Suite B digest"},
{ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"}, {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},
{ERR_REASON(SSL_R_INVALID_AUDIT_PROOF) ,"invalid audit proof"}, {ERR_REASON(SSL_R_INVALID_AUDIT_PROOF) ,"invalid audit proof"},
{ERR_REASON(SSL_R_INVALID_AUTHZ_DATA) ,"invalid authz data"}, {ERR_REASON(SSL_R_INVALID_AUTHZ_DATA) ,"invalid authz data"},
...@@ -472,6 +473,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= ...@@ -472,6 +473,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"}, {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
{ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"}, {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
{ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"}, {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"},
{ERR_REASON(SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE),"only TLS 1.2 allowed in Suite B mode"},
{ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"}, {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
{ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"}, {ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"},
{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"}, {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
......
...@@ -263,7 +263,7 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth) ...@@ -263,7 +263,7 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth)
sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
&(ctx->cipher_list_by_id), &(ctx->cipher_list_by_id),
meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ctx->cert);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
{ {
SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
...@@ -1333,7 +1333,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) ...@@ -1333,7 +1333,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
STACK_OF(SSL_CIPHER) *sk; STACK_OF(SSL_CIPHER) *sk;
sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list,
&ctx->cipher_list_by_id,str); &ctx->cipher_list_by_id,str, ctx->cert);
/* ssl_create_cipher_list may return an empty stack if it /* ssl_create_cipher_list may return an empty stack if it
* was unable to find a cipher matching the given rule string * was unable to find a cipher matching the given rule string
* (for example if the rule string specifies a cipher which * (for example if the rule string specifies a cipher which
...@@ -1357,7 +1357,7 @@ int SSL_set_cipher_list(SSL *s,const char *str) ...@@ -1357,7 +1357,7 @@ int SSL_set_cipher_list(SSL *s,const char *str)
STACK_OF(SSL_CIPHER) *sk; STACK_OF(SSL_CIPHER) *sk;
sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list,
&s->cipher_list_by_id,str); &s->cipher_list_by_id,str, s->cert);
/* see comment in SSL_CTX_set_cipher_list */ /* see comment in SSL_CTX_set_cipher_list */
if (sk == NULL) if (sk == NULL)
return 0; return 0;
...@@ -1787,7 +1787,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ...@@ -1787,7 +1787,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ssl_create_cipher_list(ret->method, ssl_create_cipher_list(ret->method,
&ret->cipher_list,&ret->cipher_list_by_id, &ret->cipher_list,&ret->cipher_list_by_id,
meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ret->cert);
if (ret->cipher_list == NULL if (ret->cipher_list == NULL
|| sk_SSL_CIPHER_num(ret->cipher_list) <= 0) || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
{ {
......
...@@ -489,6 +489,11 @@ typedef struct cert_pkey_st ...@@ -489,6 +489,11 @@ typedef struct cert_pkey_st
*/ */
int valid_flags; int valid_flags;
} CERT_PKEY; } CERT_PKEY;
/* Retrieve Suite B flags */
#define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS)
/* Uses to check strict mode: suite B modes are always strict */
#define SSL_CERT_FLAGS_CHECK_TLS_STRICT \
(SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT)
typedef struct cert_st typedef struct cert_st
{ {
...@@ -910,7 +915,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, ...@@ -910,7 +915,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
STACK_OF(SSL_CIPHER) **pref, STACK_OF(SSL_CIPHER) **pref,
STACK_OF(SSL_CIPHER) **sorted, STACK_OF(SSL_CIPHER) **sorted,
const char *rule_str); const char *rule_str, CERT *c);
void ssl_update_cache(SSL *s, int mode); void ssl_update_cache(SSL *s, int mode);
int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc, int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp); const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
...@@ -1184,7 +1189,7 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen, ...@@ -1184,7 +1189,7 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen,
int *curves, size_t ncurves); int *curves, size_t ncurves);
int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, int tls1_set_curves_list(unsigned char **pext, size_t *pextlen,
const char *str); const char *str);
int tls1_check_ec_tmp_key(SSL *s); int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
#endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_TLSEXT #ifndef OPENSSL_NO_TLSEXT
......
...@@ -241,6 +241,12 @@ static const unsigned char eccurves_default[] = ...@@ -241,6 +241,12 @@ static const unsigned char eccurves_default[] =
0,17, /* secp160r2 (17) */ 0,17, /* secp160r2 (17) */
}; };
static const unsigned char suiteb_curves[] =
{
0, TLSEXT_curve_P_256,
0, TLSEXT_curve_P_384
};
int tls1_ec_curve_id2nid(int curve_id) int tls1_ec_curve_id2nid(int curve_id)
{ {
/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
...@@ -320,13 +326,29 @@ static void tls1_get_curvelist(SSL *s, int sess, ...@@ -320,13 +326,29 @@ static void tls1_get_curvelist(SSL *s, int sess,
{ {
*pcurves = s->session->tlsext_ellipticcurvelist; *pcurves = s->session->tlsext_ellipticcurvelist;
*pcurveslen = s->session->tlsext_ellipticcurvelist_length; *pcurveslen = s->session->tlsext_ellipticcurvelist_length;
return;
} }
else /* For Suite B mode only include P-256, P-384 */
switch (tls1_suiteb(s))
{ {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*pcurves = suiteb_curves;
*pcurveslen = sizeof(suiteb_curves);
break;
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*pcurves = suiteb_curves;
*pcurveslen = 2;
break;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*pcurves = suiteb_curves + 2;
*pcurveslen = 2;
break;
default:
*pcurves = s->tlsext_ellipticcurvelist; *pcurves = s->tlsext_ellipticcurvelist;
*pcurveslen = s->tlsext_ellipticcurvelist_length; *pcurveslen = s->tlsext_ellipticcurvelist_length;
} }
/* If not set use default: for now static structure */
if (!*pcurves) if (!*pcurves)
{ {
*pcurves = eccurves_default; *pcurves = eccurves_default;
...@@ -338,8 +360,28 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) ...@@ -338,8 +360,28 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
{ {
const unsigned char *curves; const unsigned char *curves;
size_t curveslen, i; size_t curveslen, i;
unsigned int suiteb_flags = tls1_suiteb(s);
if (len != 3 || p[0] != NAMED_CURVE_TYPE) if (len != 3 || p[0] != NAMED_CURVE_TYPE)
return 0; return 0;
/* Check curve matches Suite B preferences */
if (suiteb_flags)
{
unsigned long cid = s->s3->tmp.new_cipher->id;
if (p[1])
return 0;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
{
if (p[2] != TLSEXT_curve_P_256)
return 0;
}
else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
{
if (p[2] != TLSEXT_curve_P_384)
return 0;
}
else /* Should never happen */
return 0;
}
tls1_get_curvelist(s, 0, &curves, &curveslen); tls1_get_curvelist(s, 0, &curves, &curveslen);
for (i = 0; i < curveslen; i += 2, curves += 2) for (i = 0; i < curveslen; i += 2, curves += 2)
{ {
...@@ -350,7 +392,8 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) ...@@ -350,7 +392,8 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
} }
/* Return nth shared curve. If nmatch == -1 return number of /* Return nth shared curve. If nmatch == -1 return number of
* matches. * matches. For nmatch == -2 return the NID of the curve to use for
* an EC tmp key.
*/ */
int tls1_shared_curve(SSL *s, int nmatch) int tls1_shared_curve(SSL *s, int nmatch)
...@@ -361,6 +404,25 @@ int tls1_shared_curve(SSL *s, int nmatch) ...@@ -361,6 +404,25 @@ int tls1_shared_curve(SSL *s, int nmatch)
/* Can't do anything on client side */ /* Can't do anything on client side */
if (s->server == 0) if (s->server == 0)
return -1; return -1;
if (nmatch == -2)
{
if (tls1_suiteb(s))
{
/* 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;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return NID_X9_62_prime256v1; /* P-256 */
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
return NID_secp384r1; /* P-384 */
/* Should never happen */
return NID_undef;
}
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
&supp, &supplen); &supp, &supplen);
tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
...@@ -540,6 +602,8 @@ static int tls1_check_ec_key(SSL *s, ...@@ -540,6 +602,8 @@ static int tls1_check_ec_key(SSL *s,
if (i == plen) if (i == plen)
return 0; return 0;
} }
if (!curve_id)
return 1;
/* Check curve is consistent with client and server preferences */ /* Check curve is consistent with client and server preferences */
for (j = 0; j <= 1; j++) for (j = 0; j <= 1; j++)
{ {
...@@ -551,6 +615,9 @@ static int tls1_check_ec_key(SSL *s, ...@@ -551,6 +615,9 @@ static int tls1_check_ec_key(SSL *s,
} }
if (i == plen) if (i == plen)
return 0; return 0;
/* For clients can only check sent curve list */
if (!s->server)
return 1;
} }
return 1; return 1;
} }
...@@ -558,7 +625,7 @@ static int tls1_check_ec_key(SSL *s, ...@@ -558,7 +625,7 @@ static int tls1_check_ec_key(SSL *s,
/* Check cert parameters compatible with extensions: currently just checks /* Check cert parameters compatible with extensions: currently just checks
* EC certificates have compatible curves and compression. * EC certificates have compatible curves and compression.
*/ */
static int tls1_check_cert_param(SSL *s, X509 *x) static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
{ {
unsigned char comp_id, curve_id[2]; unsigned char comp_id, curve_id[2];
EVP_PKEY *pkey; EVP_PKEY *pkey;
...@@ -576,13 +643,82 @@ static int tls1_check_cert_param(SSL *s, X509 *x) ...@@ -576,13 +643,82 @@ static int tls1_check_cert_param(SSL *s, X509 *x)
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); /* Can't check curve_id for client certs as we don't have a
* supported curves extension.
*/
rv = tls1_check_ec_key(s, s->server ? curve_id : NULL, &comp_id);
if (!rv)
return 0;
/* Special case for suite B. We *MUST* sign using SHA256+P-256 or
* SHA384+P-384, adjust digest if necessary.
*/
if (set_ee_md && tls1_suiteb(s))
{
int check_md;
size_t i;
CERT *c = s->cert;
if (curve_id[0])
return 0;
/* Check to see we have necessary signing algorithm */
if (curve_id[1] == TLSEXT_curve_P_256)
check_md = NID_ecdsa_with_SHA256;
else if (curve_id[1] == TLSEXT_curve_P_384)
check_md = NID_ecdsa_with_SHA384;
else
return 0; /* Should never happen */
for (i = 0; i < c->shared_sigalgslen; i++)
if (check_md == c->shared_sigalgs[i].signandhash_nid)
break;
if (i == c->shared_sigalgslen)
return 0;
if (set_ee_md == 2)
{
if (check_md == NID_ecdsa_with_SHA256)
c->pkeys[SSL_PKEY_ECC].digest = EVP_sha256();
else
c->pkeys[SSL_PKEY_ECC].digest = EVP_sha384();
}
}
return rv;
} }
/* 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, unsigned long cid)
{ {
unsigned char curve_id[2]; unsigned char curve_id[2];
EC_KEY *ec = s->cert->ecdh_tmp; EC_KEY *ec = s->cert->ecdh_tmp;
/* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384,
* no other curves permitted.
*/
if (tls1_suiteb(s))
{
/* Curve to check determined by ciphersuite */
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
curve_id[1] = TLSEXT_curve_P_256;
else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
curve_id[1] = TLSEXT_curve_P_384;
else
return 0;
curve_id[0] = 0;
/* Check this curve is acceptable */
if (!tls1_check_ec_key(s, curve_id, NULL))
return 0;
/* If auto or setting curve from callback assume OK */
if (s->cert->ecdh_tmp_auto || s->cert->ecdh_tmp_cb)
return 1;
/* Otherwise check curve is acceptable */
else
{
unsigned char curve_tmp[2];
if (!ec)
return 0;
if (!tls1_set_ec_id(curve_tmp, NULL, ec))
return 0;
if (!curve_tmp[0] || curve_tmp[1] == curve_id[1])
return 1;
return 0;
}
}
if (s->cert->ecdh_tmp_auto) if (s->cert->ecdh_tmp_auto)
{ {
/* Need a shared curve */ /* Need a shared curve */
...@@ -655,8 +791,31 @@ static unsigned char tls12_sigalgs[] = { ...@@ -655,8 +791,31 @@ static unsigned char tls12_sigalgs[] = {
#endif #endif
}; };
static unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
{ {
/* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
switch (tls1_suiteb(s))
{
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
return sizeof(suiteb_sigalgs);
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*psigs = suiteb_sigalgs;
return 2;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*psigs = suiteb_sigalgs + 2;
return 2;
}
/* If server use client authentication sigalgs if not NULL */ /* If server use client authentication sigalgs if not NULL */
if (s->server && s->cert->client_sigalgs) if (s->server && s->cert->client_sigalgs)
{ {
...@@ -698,6 +857,44 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, ...@@ -698,6 +857,44 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE); SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
return 0; return 0;
} }
if (pkey->type == EVP_PKEY_EC)
{
unsigned char curve_id[2], comp_id;
/* Check compression and curve matches extensions */
if (!tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec))
return 0;
if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id))
return 0;
/* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */
if (tls1_suiteb(s))
{
if (curve_id[0])
return 0;
if (curve_id[1] == TLSEXT_curve_P_256)
{
if (sig[0] != TLSEXT_hash_sha256)
{
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_ILLEGAL_SUITEB_DIGEST);
return 0;
}
}
else if (curve_id[1] == TLSEXT_curve_P_384)
{
if (sig[0] != TLSEXT_hash_sha384)
{
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_ILLEGAL_SUITEB_DIGEST);
return 0;
}
}
else
return 0;
}
}
else if (tls1_suiteb(s))
return 0;
/* Check signature matches a type we sent */ /* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
for (i = 0; i < sent_sigslen; i+=2, sent_sigs+=2) for (i = 0; i < sent_sigslen; i+=2, sent_sigs+=2)
...@@ -706,7 +903,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, ...@@ -706,7 +903,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
break; break;
} }
/* Allow fallback to SHA1 if not strict mode */ /* Allow fallback to SHA1 if not strict mode */
if (i == sent_sigslen && (sig[0] != TLSEXT_hash_sha1 || s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT)) if (i == sent_sigslen && (sig[0] != TLSEXT_hash_sha1 || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT))
{ {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE); SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
return 0; return 0;
...@@ -3123,27 +3320,21 @@ static int tls1_set_shared_sigalgs(SSL *s) ...@@ -3123,27 +3320,21 @@ static int tls1_set_shared_sigalgs(SSL *s)
size_t nmatch; size_t nmatch;
TLS_SIGALGS *salgs = NULL; TLS_SIGALGS *salgs = NULL;
CERT *c = s->cert; CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
/* If client use client signature algorithms if not NULL */ /* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs) if (!s->server && c->client_sigalgs && !is_suiteb)
{ {
conf = c->client_sigalgs; conf = c->client_sigalgs;
conflen = c->client_sigalgslen; conflen = c->client_sigalgslen;
} }
else if (c->conf_sigalgs) else if (c->conf_sigalgs && !is_suiteb)
{ {
conf = c->conf_sigalgs; conf = c->conf_sigalgs;
conflen = c->conf_sigalgslen; conflen = c->conf_sigalgslen;
} }
else else
{ conflen = tls12_get_psigalgs(s, &conf);
conf = tls12_sigalgs; if(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb)
conflen = sizeof(tls12_sigalgs);
#ifdef OPENSSL_FIPS
if (FIPS_mode())
conflen -= 2;
#endif
}
if(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
{ {
pref = conf; pref = conf;
preflen = conflen; preflen = conflen;
...@@ -3214,7 +3405,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) ...@@ -3214,7 +3405,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
/* In strict mode leave unset digests as NULL to indicate we can't /* In strict mode leave unset digests as NULL to indicate we can't
* use the certificate for signing. * use the certificate for signing.
*/ */
if (!(s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT)) if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT))
{ {
/* Set any remaining keys to default values. NOTE: if alg is /* Set any remaining keys to default values. NOTE: if alg is
* not supported it stays as NULL. * not supported it stays as NULL.
...@@ -3588,14 +3779,22 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, ...@@ -3588,14 +3779,22 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int check_flags = 0, strict_mode; int check_flags = 0, strict_mode;
CERT_PKEY *cpk = NULL; CERT_PKEY *cpk = NULL;
CERT *c = s->cert; CERT *c = s->cert;
/* idx != -1 means checking server chains */ unsigned int suiteb_flags = tls1_suiteb(s);
/* idx == -1 means checking server chains */
if (idx != -1) if (idx != -1)
{ {
cpk = c->pkeys + idx; /* idx == -2 means checking client certificate chains */
if (idx == -2)
{
cpk = c->key;
idx = cpk - c->pkeys;
}
else
cpk = c->pkeys + idx;
x = cpk->x509; x = cpk->x509;
pk = cpk->privatekey; pk = cpk->privatekey;
chain = cpk->chain; chain = cpk->chain;
strict_mode = c->cert_flags & SSL_CERT_FLAG_TLS_STRICT; strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
/* If no cert or key, forget it */ /* If no cert or key, forget it */
if (!x || !pk) if (!x || !pk)
goto end; goto end;
...@@ -3608,13 +3807,27 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, ...@@ -3608,13 +3807,27 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
if (idx == -1) if (idx == -1)
goto end; goto end;
cpk = c->pkeys + idx; cpk = c->pkeys + idx;
if (c->cert_flags & SSL_CERT_FLAG_TLS_STRICT) if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
check_flags = CERT_PKEY_STRICT_FLAGS; check_flags = CERT_PKEY_STRICT_FLAGS;
else else
check_flags = CERT_PKEY_VALID_FLAGS; check_flags = CERT_PKEY_VALID_FLAGS;
strict_mode = 1; strict_mode = 1;
} }
if (suiteb_flags)
{
int ok;
if (check_flags)
check_flags |= CERT_PKEY_SUITEB;
ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
if (ok != X509_V_OK)
{
if (check_flags)
rv |= CERT_PKEY_SUITEB;
else
goto end;
}
}
/* Check all signature algorithms are consistent with /* Check all signature algorithms are consistent with
* signature algorithms extension if TLS 1.2 or later * signature algorithms extension if TLS 1.2 or later
...@@ -3702,8 +3915,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, ...@@ -3702,8 +3915,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
else if(check_flags) else if(check_flags)
rv |= CERT_PKEY_EE_SIGNATURE|CERT_PKEY_CA_SIGNATURE; rv |= CERT_PKEY_EE_SIGNATURE|CERT_PKEY_CA_SIGNATURE;
skip_sigs: skip_sigs:
/* Check cert parameters are consistent: server certs only */ /* Check cert parameters are consistent */
if (!s->server || tls1_check_cert_param(s, x)) if (tls1_check_cert_param(s, x, check_flags ? 1 : 2))
rv |= CERT_PKEY_EE_PARAM; rv |= CERT_PKEY_EE_PARAM;
else if (!check_flags) else if (!check_flags)
goto end; goto end;
...@@ -3715,7 +3928,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, ...@@ -3715,7 +3928,8 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
rv |= CERT_PKEY_CA_PARAM; rv |= CERT_PKEY_CA_PARAM;
for (i = 0; i < sk_X509_num(chain); i++) for (i = 0; i < sk_X509_num(chain); i++)
{ {
if (!tls1_check_cert_param(s, sk_X509_value(chain, i))) X509 *ca = sk_X509_value(chain, i);
if (!tls1_check_cert_param(s, ca, 0))
{ {
if (check_flags) if (check_flags)
{ {
...@@ -3832,7 +4046,11 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, ...@@ -3832,7 +4046,11 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
if (rv & CERT_PKEY_VALID) if (rv & CERT_PKEY_VALID)
cpk->valid_flags = rv; cpk->valid_flags = rv;
else else
cpk->valid_flags = 0; {
/* Preserve explicit sign flag, clear rest */
cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN;
return 0;
}
} }
return rv; return rv;
} }
......
...@@ -285,6 +285,11 @@ extern "C" { ...@@ -285,6 +285,11 @@ extern "C" {
/* Flag set for unrecognised algorithms */ /* Flag set for unrecognised algorithms */
#define TLSEXT_nid_unknown 0x1000000 #define TLSEXT_nid_unknown 0x1000000
/* ECC curves */
#define TLSEXT_curve_P_256 23
#define TLSEXT_curve_P_384 24
#ifndef OPENSSL_NO_TLSEXT #ifndef OPENSSL_NO_TLSEXT
#define TLSEXT_MAXLEN_host_name 255 #define TLSEXT_MAXLEN_host_name 255
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册