Properly check certificate in case of export ciphers.

Reviewed-by: Matt Caswell <matt@openssl.org>
MR #588
This commit is contained in:
Kurt Roeckx 2015-04-18 12:23:12 +02:00
parent 0fb9990480
commit 26c79d5641
10 changed files with 82 additions and 32 deletions

View File

@ -237,6 +237,11 @@ void *DH_get_ex_data(DH *d, int idx)
return (CRYPTO_get_ex_data(&d->ex_data, idx)); return (CRYPTO_get_ex_data(&d->ex_data, idx));
} }
int DH_bits(const DH *dh)
{
return BN_num_bits(dh->p);
}
int DH_size(const DH *dh) int DH_size(const DH *dh)
{ {
return (BN_num_bytes(dh->p)); return (BN_num_bytes(dh->p));

View File

@ -64,6 +64,11 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/rand.h> #include <openssl/rand.h>
int RSA_bits(const RSA *r)
{
return (BN_num_bits(r->n));
}
int RSA_size(const RSA *r) int RSA_size(const RSA *r)
{ {
return (BN_num_bytes(r->n)); return (BN_num_bytes(r->n));

View File

@ -2,32 +2,38 @@
=head1 NAME =head1 NAME
DH_size - get Diffie-Hellman prime size DH_size, DH_bits - get Diffie-Hellman prime size
=head1 SYNOPSIS =head1 SYNOPSIS
#include <openssl/dh.h> #include <openssl/dh.h>
int DH_size(DH *dh); int DH_size(const DH *dh);
int DH_bits(const DH *dh);
=head1 DESCRIPTION =head1 DESCRIPTION
This function returns the Diffie-Hellman size in bytes. It can be used DH_size() returns the Diffie-Hellman prime size in bytes. It can be used
to determine how much memory must be allocated for the shared secret to determine how much memory must be allocated for the shared secret
computed by DH_compute_key(). computed by DH_compute_key().
B<dh-E<gt>p> must not be B<NULL>. DH_bits() returns the number of significant bits.
B<dh> and B<dh-E<gt>p> must not be B<NULL>.
=head1 RETURN VALUE =head1 RETURN VALUE
The size in bytes. The size.
=head1 SEE ALSO =head1 SEE ALSO
L<dh(3)|dh(3)>, L<DH_generate_key(3)|DH_generate_key(3)> L<dh(3)|dh(3)>, L<DH_generate_key(3)|DH_generate_key(3)>,
L<BN_num_bits(3)|BN_num_bits(3)>
=head1 HISTORY =head1 HISTORY
DH_size() is available in all versions of SSLeay and OpenSSL. DH_size() is available in all versions of SSLeay and OpenSSL.
DH_bits() was added in OpenSSL 1.1.0.
=cut =cut

View File

@ -2,32 +2,37 @@
=head1 NAME =head1 NAME
RSA_size - get RSA modulus size RSA_size, RSA_bits - get RSA modulus size
=head1 SYNOPSIS =head1 SYNOPSIS
#include <openssl/rsa.h> #include <openssl/rsa.h>
int RSA_size(const RSA *rsa); int RSA_size(const RSA *rsa);
int RSA_bits(const RSA *rsa);
=head1 DESCRIPTION =head1 DESCRIPTION
This function returns the RSA modulus size in bytes. It can be used to RSA_size() returns the RSA modulus size in bytes. It can be used to
determine how much memory must be allocated for an RSA encrypted determine how much memory must be allocated for an RSA encrypted
value. value.
B<rsa-E<gt>n> must not be B<NULL>. RSA_bits() returns the number of significant bits.
B<rsa> and B<rsa-E<gt>n> must not be B<NULL>.
=head1 RETURN VALUE =head1 RETURN VALUE
The size in bytes. The size.
=head1 SEE ALSO =head1 SEE ALSO
L<rsa(3)|rsa(3)> L<rsa(3)|rsa(3)>, L<BN_num_bits(3)|BN_num_bits(3)>
=head1 HISTORY =head1 HISTORY
RSA_size() is available in all versions of SSLeay and OpenSSL. RSA_size() is available in all versions of SSLeay and OpenSSL.
RSA_bits() was added in OpenSSL 1.1.0.
=cut =cut

View File

@ -12,8 +12,6 @@ dh - Diffie-Hellman key agreement
DH * DH_new(void); DH * DH_new(void);
void DH_free(DH *dh); void DH_free(DH *dh);
int DH_size(const DH *dh);
DH * DH_generate_parameters(int prime_len, int generator, DH * DH_generate_parameters(int prime_len, int generator,
void (*callback)(int, int, void *), void *cb_arg); void (*callback)(int, int, void *), void *cb_arg);
int DH_check(const DH *dh, int *codes); int DH_check(const DH *dh, int *codes);

View File

@ -26,8 +26,6 @@ rsa - RSA public key cryptosystem
int RSA_verify(int type, unsigned char *m, unsigned int m_len, int RSA_verify(int type, unsigned char *m, unsigned int m_len,
unsigned char *sigbuf, unsigned int siglen, RSA *rsa); unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
int RSA_size(const RSA *rsa);
RSA *RSA_generate_key(int num, unsigned long e, RSA *RSA_generate_key(int num, unsigned long e,
void (*callback)(int,int,void *), void *cb_arg); void (*callback)(int,int,void *), void *cb_arg);

View File

@ -200,6 +200,7 @@ DH *DH_new_method(ENGINE *engine);
DH *DH_new(void); DH *DH_new(void);
void DH_free(DH *dh); void DH_free(DH *dh);
int DH_up_ref(DH *dh); int DH_up_ref(DH *dh);
int DH_bits(const DH *dh);
int DH_size(const DH *dh); int DH_size(const DH *dh);
int DH_security_bits(const DH *dh); int DH_security_bits(const DH *dh);
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,

View File

@ -319,6 +319,7 @@ struct rsa_st {
RSA *RSA_new(void); RSA *RSA_new(void);
RSA *RSA_new_method(ENGINE *engine); RSA *RSA_new_method(ENGINE *engine);
int RSA_bits(const RSA *rsa);
int RSA_size(const RSA *rsa); int RSA_size(const RSA *rsa);
int RSA_security_bits(const RSA *rsa); int RSA_security_bits(const RSA *rsa);

View File

@ -3335,6 +3335,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
DH *dh; DH *dh;
#endif #endif
int al = SSL_AD_HANDSHAKE_FAILURE;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey; alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
alg_a = s->s3->tmp.new_cipher->algorithm_auth; alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@ -3395,17 +3396,33 @@ int ssl3_check_cert_and_algorithm(SSL *s)
} }
#endif #endif
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
if ((alg_k & SSL_kRSA) && if (alg_k & SSL_kRSA) {
!(has_bits(i, EVP_PK_RSA | EVP_PKT_ENC) || (rsa != NULL))) { if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
SSL_R_MISSING_RSA_ENCRYPTING_CERT); SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
goto f_err; SSL_R_MISSING_RSA_ENCRYPTING_CERT);
goto f_err;
} else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
goto f_err;
}
if (rsa != NULL) {
/* server key exchange is not allowed. */
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
goto f_err;
}
}
}
} }
#endif #endif
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
if ((alg_k & SSL_kDHE) && if ((alg_k & SSL_kDHE) && (dh == NULL)) {
!(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || (dh != NULL))) { al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_KEY); SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
goto f_err; goto f_err;
} else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) && } else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) &&
!has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) {
@ -3427,9 +3444,14 @@ int ssl3_check_cert_and_algorithm(SSL *s)
pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
if (alg_k & SSL_kRSA) { if (alg_k & SSL_kRSA) {
if (rsa == NULL if (rsa == NULL) {
|| RSA_size(rsa) * 8 > SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
goto f_err;
} else if (RSA_bits(rsa) >
SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
/* We have a temporary RSA key but it's too large. */
al = SSL_AD_EXPORT_RESTRICTION;
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_EXPORT_TMP_RSA_KEY); SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
goto f_err; goto f_err;
@ -3437,14 +3459,21 @@ int ssl3_check_cert_and_algorithm(SSL *s)
} else } else
#endif #endif
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { if (alg_k & SSL_kDHE) {
if (dh == NULL if (DH_bits(dh) >
|| DH_size(dh) * 8 >
SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
/* We have a temporary DH key but it's too large. */
al = SSL_AD_EXPORT_RESTRICTION;
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_EXPORT_TMP_DH_KEY); SSL_R_MISSING_EXPORT_TMP_DH_KEY);
goto f_err; goto f_err;
} }
} else if (alg_k & (SSL_kDHr | SSL_kDHd)) {
/* The cert should have had an export DH key. */
al = SSL_AD_EXPORT_RESTRICTION;
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_EXPORT_TMP_DH_KEY);
goto f_err;
} else } else
#endif #endif
{ {
@ -3455,7 +3484,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
} }
return (1); return (1);
f_err: f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); ssl3_send_alert(s, SSL3_AL_FATAL, al);
err: err:
return (0); return (0);
} }

View File

@ -4571,3 +4571,5 @@ ASN1_INTEGER_get_uint64 4929 EXIST::FUNCTION:
ASN1_INTEGER_set_uint64 4930 EXIST::FUNCTION: ASN1_INTEGER_set_uint64 4930 EXIST::FUNCTION:
PKCS5_pbe2_set_scrypt 4931 EXIST::FUNCTION: PKCS5_pbe2_set_scrypt 4931 EXIST::FUNCTION:
PKCS8_set0_pbe 4932 EXIST::FUNCTION: PKCS8_set0_pbe 4932 EXIST::FUNCTION:
DH_bits 4933 EXIST::FUNCTION:DH
RSA_bits 4934 EXIST::FUNCTION:RSA