Properly check certificate in case of export ciphers.
authorKurt Roeckx <kurt@roeckx.be>
Sat, 18 Apr 2015 10:23:12 +0000 (12:23 +0200)
committerKurt Roeckx <kurt@roeckx.be>
Mon, 8 Jun 2015 22:46:59 +0000 (00:46 +0200)
Reviewed-by: Matt Caswell <matt@openssl.org>
MR #588

crypto/dh/dh_lib.c
crypto/rsa/rsa_crpt.c
doc/crypto/DH_size.pod
doc/crypto/RSA_size.pod
doc/crypto/dh.pod
doc/crypto/rsa.pod
include/openssl/dh.h
include/openssl/rsa.h
ssl/s3_clnt.c
util/libeay.num

index 4a37adc9f8208eb7eb7298ff2871f8c3d9e1e165..cce2514bbfca272bacdd50e620f1ffe09a06a315 100644 (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)
 {
     return (BN_num_bytes(dh->p));
 int DH_size(const DH *dh)
 {
     return (BN_num_bytes(dh->p));
index 5220b7d068fc13b1e181ec8b49a98d28cc6d38c8..3c4fd67714567a8c76fdb9dfc9af2160612b2967 100644 (file)
 #include <openssl/rsa.h>
 #include <openssl/rand.h>
 
 #include <openssl/rsa.h>
 #include <openssl/rand.h>
 
+int RSA_bits(const RSA *r)
+{
+    return (BN_num_bits(r->n));
+}
+
 int RSA_size(const RSA *r)
 {
     return (BN_num_bytes(r->n));
 int RSA_size(const RSA *r)
 {
     return (BN_num_bytes(r->n));
index 97f26fda7855e8e865e9e9d7893a4d3d15d7f124..e73f32589a0ca36fef8e2d068f86230b66d297c2 100644 (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
 computed by DH_compute_key().
 
 to determine how much memory must be allocated for the shared secret
 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
 
 DH_size() is available in all versions of SSLeay and OpenSSL.
 
 =head1 HISTORY
 
 DH_size() is available in all versions of SSLeay and OpenSSL.
+DH_bits() was added in OpenSSL 1.1.0.
 
 =cut
 
 =cut
index 5b7f835f95d6dc01ecb6c5419761985d6eded98d..f68d5e8e3c1782b8c1568bb1e8b308b340970f3a 100644 (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
 value.
 
 determine how much memory must be allocated for an RSA encrypted
 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
 
 RSA_size() is available in all versions of SSLeay and OpenSSL.
 
 =head1 HISTORY
 
 RSA_size() is available in all versions of SSLeay and OpenSSL.
+RSA_bits() was added in OpenSSL 1.1.0.
 
 =cut
 
 =cut
index c3ccd062078304ad6f237417dae48047bfe0c4f8..1c8a327458a54bbb5588b0fed10b073e58f420a1 100644 (file)
@@ -12,8 +12,6 @@ dh - Diffie-Hellman key agreement
  DH *  DH_new(void);
  void  DH_free(DH *dh);
 
  DH *  DH_new(void);
  void  DH_free(DH *dh);
 
- int   DH_size(const DH *dh);
-
  DH *  DH_generate_parameters(int prime_len, int generator,
                void (*callback)(int, int, void *), void *cb_arg);
  int   DH_check(const DH *dh, int *codes);
  DH *  DH_generate_parameters(int prime_len, int generator,
                void (*callback)(int, int, void *), void *cb_arg);
  int   DH_check(const DH *dh, int *codes);
index 45ac53ffc1472fcbc5fdb14487dc823f7a72b51f..743334ff79891c8a3cdae25b9ee826a7c340b0cc 100644 (file)
@@ -26,8 +26,6 @@ rsa - RSA public key cryptosystem
  int RSA_verify(int type, unsigned char *m, unsigned int m_len,
     unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
 
  int RSA_verify(int type, unsigned char *m, unsigned int m_len,
     unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
 
- int RSA_size(const RSA *rsa);
-
  RSA *RSA_generate_key(int num, unsigned long e,
     void (*callback)(int,int,void *), void *cb_arg);
 
  RSA *RSA_generate_key(int num, unsigned long e,
     void (*callback)(int,int,void *), void *cb_arg);
 
index 2d7c739eca980f8fb176deaf1b160315ceef3a36..e0f4b57349ec410d8799515a8a8cde894e8fcb82 100644 (file)
@@ -200,6 +200,7 @@ DH *DH_new_method(ENGINE *engine);
 DH *DH_new(void);
 void DH_free(DH *dh);
 int DH_up_ref(DH *dh);
 DH *DH_new(void);
 void DH_free(DH *dh);
 int DH_up_ref(DH *dh);
+int DH_bits(const DH *dh);
 int DH_size(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_size(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,
index 9ba64970b650947746367080d660b47db062c316..727b9df4c48102a7ab41361cc6cac863d8f4c2d1 100644 (file)
@@ -319,6 +319,7 @@ struct rsa_st {
 
 RSA *RSA_new(void);
 RSA *RSA_new_method(ENGINE *engine);
 
 RSA *RSA_new(void);
 RSA *RSA_new_method(ENGINE *engine);
+int RSA_bits(const RSA *rsa);
 int RSA_size(const RSA *rsa);
 int RSA_security_bits(const RSA *rsa);
 
 int RSA_size(const RSA *rsa);
 int RSA_security_bits(const RSA *rsa);
 
index 632d743871d3944f7295794b4bc5235902c99287..2f7b093c3dd2cdf42da4bf5e89c690c5532d5b37 100644 (file)
@@ -3335,6 +3335,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 #ifndef OPENSSL_NO_DH
     DH *dh;
 #endif
 #ifndef OPENSSL_NO_DH
     DH *dh;
 #endif
+    int al = SSL_AD_HANDSHAKE_FAILURE;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@@ -3395,17 +3396,33 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
 #endif
 #ifndef OPENSSL_NO_RSA
     }
 #endif
 #ifndef OPENSSL_NO_RSA
-    if ((alg_k & SSL_kRSA) &&
-        !(has_bits(i, EVP_PK_RSA | EVP_PKT_ENC) || (rsa != NULL))) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-               SSL_R_MISSING_RSA_ENCRYPTING_CERT);
-        goto f_err;
+    if (alg_k & SSL_kRSA) {
+        if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
+            !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;
+        } 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
 #ifndef OPENSSL_NO_DH
     }
 #endif
 #ifndef OPENSSL_NO_DH
-    if ((alg_k & SSL_kDHE) &&
-        !(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || (dh != NULL))) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_KEY);
+    if ((alg_k & SSL_kDHE) && (dh == NULL)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
         goto f_err;
     } else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) &&
                !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) {
         goto f_err;
     } else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) &&
                !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)) {
 #ifndef OPENSSL_NO_RSA
         if (alg_k & SSL_kRSA) {
         pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
 #ifndef OPENSSL_NO_RSA
         if (alg_k & SSL_kRSA) {
-            if (rsa == NULL
-                || RSA_size(rsa) * 8 >
+            if (rsa == NULL) {
+                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,
                        SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
                 goto f_err;
                 SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
                        SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
                 goto f_err;
@@ -3437,14 +3459,21 @@ int ssl3_check_cert_and_algorithm(SSL *s)
         } else
 #endif
 #ifndef OPENSSL_NO_DH
         } else
 #endif
 #ifndef OPENSSL_NO_DH
-        if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
-            if (dh == NULL
-                || DH_size(dh) * 8 >
+        if (alg_k & SSL_kDHE) {
+            if (DH_bits(dh) >
                 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,
                        SSL_R_MISSING_EXPORT_TMP_DH_KEY);
                 goto f_err;
             }
                 SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
                        SSL_R_MISSING_EXPORT_TMP_DH_KEY);
                 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
 #endif
         {
         } else
 #endif
         {
@@ -3455,7 +3484,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
     return (1);
  f_err:
     }
     return (1);
  f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
     return (0);
 }
  err:
     return (0);
 }
index c297ef789dd7f3b1bba61f93170479ebb14da6db..edeb50d34f5cfd7927f7ca0d5565ad6b59a02582 100755 (executable)
@@ -4571,3 +4571,5 @@ ASN1_INTEGER_get_uint64                 4929      EXIST::FUNCTION:
 ASN1_INTEGER_set_uint64                 4930   EXIST::FUNCTION:
 PKCS5_pbe2_set_scrypt                   4931   EXIST::FUNCTION:
 PKCS8_set0_pbe                          4932   EXIST::FUNCTION:
 ASN1_INTEGER_set_uint64                 4930   EXIST::FUNCTION:
 PKCS5_pbe2_set_scrypt                   4931   EXIST::FUNCTION:
 PKCS8_set0_pbe                          4932   EXIST::FUNCTION:
+DH_bits                                 4933   EXIST::FUNCTION:DH
+RSA_bits                                4934   EXIST::FUNCTION:RSA