[openssl] master update

bernd.edlinger at hotmail.de bernd.edlinger at hotmail.de
Thu Mar 7 21:50:01 UTC 2019


The branch master has been updated
       via  f0e4a860d0b350e10a1ee3898445cac85af8ea16 (commit)
       via  049e64cbb08df1fbf256bb79e950e8d0959de091 (commit)
       via  ac6fff700a9799c25902165e2594fd46826f3ee3 (commit)
       via  b89fdeb2f7d4471cbfd8a579945754327a4e06a8 (commit)
       via  d7f5e5ae6d53f1387a42d210806cf5e9ed0882d6 (commit)
      from  596521f48826892ddd62322726f6f2a2a52db652 (commit)


- Log -----------------------------------------------------------------
commit f0e4a860d0b350e10a1ee3898445cac85af8ea16
Author: Bernd Edlinger <bernd.edlinger at hotmail.de>
Date:   Sun Mar 3 14:25:52 2019 +0100

    Update documentation of RSA_padding_check_PKCS1_OAEP_mgf1
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    (Merged from https://github.com/openssl/openssl/pull/8365)

commit 049e64cbb08df1fbf256bb79e950e8d0959de091
Author: Bernd Edlinger <bernd.edlinger at hotmail.de>
Date:   Sun Mar 3 10:36:57 2019 +0100

    Do the error handling in pkey_rsa_decrypt in constant time
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    (Merged from https://github.com/openssl/openssl/pull/8365)

commit ac6fff700a9799c25902165e2594fd46826f3ee3
Author: Bernd Edlinger <bernd.edlinger at hotmail.de>
Date:   Sun Mar 3 00:04:11 2019 +0100

    Add a simple test for RSA_SSLV23_PADDING
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    (Merged from https://github.com/openssl/openssl/pull/8365)

commit b89fdeb2f7d4471cbfd8a579945754327a4e06a8
Author: Bernd Edlinger <bernd.edlinger at hotmail.de>
Date:   Fri Mar 1 09:27:32 2019 +0100

    Update documentation regarding required output buffer memory size
    of RSA_private_decrypt/RSA_public_encrypt.
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    (Merged from https://github.com/openssl/openssl/pull/8365)

commit d7f5e5ae6d53f1387a42d210806cf5e9ed0882d6
Author: Bernd Edlinger <bernd.edlinger at hotmail.de>
Date:   Thu Feb 28 10:08:18 2019 +0100

    Fix memory overrun in rsa padding check functions
    
    Fixes #8364 and #8357
    
    Reviewed-by: Kurt Roeckx <kurt at roeckx.be>
    (Merged from https://github.com/openssl/openssl/pull/8365)

-----------------------------------------------------------------------

Summary of changes:
 crypto/rsa/rsa_oaep.c                     | 26 +++++++-------
 crypto/rsa/rsa_pk1.c                      | 24 ++++++-------
 crypto/rsa/rsa_pmeth.c                    | 11 +++---
 crypto/rsa/rsa_ssl.c                      | 35 +++++++++---------
 doc/man3/RSA_padding_add_PKCS1_type_1.pod | 60 +++++++++++++++++++++----------
 doc/man3/RSA_public_encrypt.pod           | 38 +++++++++++++-------
 test/rsa_test.c                           | 33 ++++++++++++++++-
 7 files changed, 149 insertions(+), 78 deletions(-)

diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c
index 552b89a..8fca4fa 100644
--- a/crypto/rsa/rsa_oaep.c
+++ b/crypto/rsa/rsa_oaep.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -143,7 +143,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
      * |num| is the length of the modulus; |flen| is the length of the
      * encoded message. Therefore, for any |from| that was obtained by
      * decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
-     * num < 2 * mdlen + 2 must hold for the modulus irrespective of
+     * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective of
      * the ciphertext, see PKCS #1 v2.2, section 7.1.2.
      * This does not leak any side-channel information.
      */
@@ -179,17 +179,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
         from -= 1 & mask;
         *--em = *from & mask;
     }
-    from = em;
 
     /*
      * The first byte must be zero, however we must not leak if this is
      * true. See James H. Manger, "A Chosen Ciphertext  Attack on RSA
      * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
      */
-    good = constant_time_is_zero(from[0]);
+    good = constant_time_is_zero(em[0]);
 
-    maskedseed = from + 1;
-    maskeddb = from + 1 + mdlen;
+    maskedseed = em + 1;
+    maskeddb = em + 1 + mdlen;
 
     if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
         goto cleanup;
@@ -230,7 +229,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
     mlen = dblen - msg_index;
 
     /*
-     * For good measure, do this check in constant tine as well.
+     * For good measure, do this check in constant time as well.
      */
     good &= constant_time_ge(tlen, mlen);
 
@@ -244,15 +243,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
      * should be noted that failure is indistinguishable from normal
      * operation if |tlen| is fixed by protocol.
      */
-    tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen);
+    tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen),
+                                    dblen - mdlen - 1, tlen);
     msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
     mlen = dblen - msg_index;
-    for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) {
-        unsigned int equals = constant_time_eq(i, mlen);
+    for (mask = good, i = 0; i < tlen; i++) {
+        unsigned int equals = constant_time_eq(msg_index, dblen);
 
-        from -= dblen & equals; /* if (i == dblen) rewind   */
-        mask &= mask ^ equals;  /* if (i == dblen) mask = 0 */
-        to[i] = constant_time_select_8(mask, from[i], to[i]);
+        msg_index -= tlen & equals;  /* rewind at EOF */
+        mask &= ~equals;  /* mask = 0 at EOF */
+        to[i] = constant_time_select_8(mask, db[msg_index++], to[i]);
     }
 
     /*
diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
index cb7518e..58ac992 100644
--- a/crypto/rsa/rsa_pk1.c
+++ b/crypto/rsa/rsa_pk1.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -192,15 +192,14 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
         from -= 1 & mask;
         *--em = *from & mask;
     }
-    from = em;
 
-    good = constant_time_is_zero(from[0]);
-    good &= constant_time_eq(from[1], 2);
+    good = constant_time_is_zero(em[0]);
+    good &= constant_time_eq(em[1], 2);
 
     /* scan over padding data */
     found_zero_byte = 0;
     for (i = 2; i < num; i++) {
-        unsigned int equals0 = constant_time_is_zero(from[i]);
+        unsigned int equals0 = constant_time_is_zero(em[i]);
 
         zero_index = constant_time_select_int(~found_zero_byte & equals0,
                                               i, zero_index);
@@ -208,7 +207,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
     }
 
     /*
-     * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+     * PS must be at least 8 bytes long, and it starts two bytes into |em|.
      * If we never found a 0-byte, then |zero_index| is 0 and the check
      * also fails.
      */
@@ -236,15 +235,16 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
      * should be noted that failure is indistinguishable from normal
      * operation if |tlen| is fixed by protocol.
      */
-    tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
+    tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+                                    num - 11, tlen);
     msg_index = constant_time_select_int(good, msg_index, num - tlen);
     mlen = num - msg_index;
-    for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
-        unsigned int equals = constant_time_eq(i, mlen);
+    for (mask = good, i = 0; i < tlen; i++) {
+        unsigned int equals = constant_time_eq(msg_index, num);
 
-        from -= tlen & equals;  /* if (i == mlen) rewind   */
-        mask &= mask ^ equals;  /* if (i == mlen) mask = 0 */
-        to[i] = constant_time_select_8(mask, from[i], to[i]);
+        msg_index -= tlen & equals;  /* rewind at EOF */
+        mask &= ~equals;  /* mask = 0 at EOF */
+        to[i] = constant_time_select_8(mask, em[msg_index++], to[i]);
     }
 
     OPENSSL_clear_free(em, num);
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 2295fa5..8931d7e 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include "internal/constant_time_locl.h"
+
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
@@ -340,10 +342,9 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
         ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
                                   rctx->pad_mode);
     }
-    if (ret < 0)
-        return ret;
-    *outlen = ret;
-    return 1;
+    *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+    ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
+    return ret;
 }
 
 static int check_padding_md(const EVP_MD *md, int padding)
diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c
index 563c8ba..3659d83 100644
--- a/crypto/rsa/rsa_ssl.c
+++ b/crypto/rsa/rsa_ssl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -55,7 +55,7 @@ int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
 
 /*
  * Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding
- * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also
+ * if nul delimiter is not preceded by 8 consecutive 0x03 bytes. It also
  * preserves error code reporting for backward compatibility.
  */
 int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
@@ -67,7 +67,10 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
     unsigned int good, found_zero_byte, mask, threes_in_row;
     int zero_index = 0, msg_index, mlen = -1, err;
 
-    if (flen < 10) {
+    if (tlen <= 0 || flen <= 0)
+        return -1;
+
+    if (flen > num || num < 11) {
         RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
         return -1;
     }
@@ -89,10 +92,9 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
         from -= 1 & mask;
         *--em = *from & mask;
     }
-    from = em;
 
-    good = constant_time_is_zero(from[0]);
-    good &= constant_time_eq(from[1], 2);
+    good = constant_time_is_zero(em[0]);
+    good &= constant_time_eq(em[1], 2);
     err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02);
     mask = ~good;
 
@@ -100,18 +102,18 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
     found_zero_byte = 0;
     threes_in_row = 0;
     for (i = 2; i < num; i++) {
-        unsigned int equals0 = constant_time_is_zero(from[i]);
+        unsigned int equals0 = constant_time_is_zero(em[i]);
 
         zero_index = constant_time_select_int(~found_zero_byte & equals0,
                                               i, zero_index);
         found_zero_byte |= equals0;
 
         threes_in_row += 1 & ~found_zero_byte;
-        threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3);
+        threes_in_row &= found_zero_byte | constant_time_eq(em[i], 3);
     }
 
     /*
-     * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+     * PS must be at least 8 bytes long, and it starts two bytes into |em|.
      * If we never found a 0-byte, then |zero_index| is 0 and the check
      * also fails.
      */
@@ -120,7 +122,7 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
                                    RSA_R_NULL_BEFORE_BLOCK_MISSING);
     mask = ~good;
 
-    good &= constant_time_lt(threes_in_row, 8);
+    good &= constant_time_ge(threes_in_row, 8);
     err = constant_time_select_int(mask | good, err,
                                    RSA_R_SSLV3_ROLLBACK_ATTACK);
     mask = ~good;
@@ -148,15 +150,16 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
      * should be noted that failure is indistinguishable from normal
      * operation if |tlen| is fixed by protocol.
      */
-    tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
+    tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+                                    num - 11, tlen);
     msg_index = constant_time_select_int(good, msg_index, num - tlen);
     mlen = num - msg_index;
-    for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
-        unsigned int equals = constant_time_eq(i, mlen);
+    for (mask = good, i = 0; i < tlen; i++) {
+        unsigned int equals = constant_time_eq(msg_index, num);
 
-        from -= tlen & equals;  /* if (i == mlen) rewind   */
-        mask &= mask ^ equals;  /* if (i == mlen) mask = 0 */
-        to[i] = constant_time_select_8(mask, from[i], to[i]);
+        msg_index -= tlen & equals;  /* rewind at EOF */
+        mask &= ~equals;  /* mask = 0 at EOF */
+        to[i] = constant_time_select_8(mask, em[msg_index++], to[i]);
     }
 
     OPENSSL_clear_free(em, num);
diff --git a/doc/man3/RSA_padding_add_PKCS1_type_1.pod b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
index 49340f1..685063b 100644
--- a/doc/man3/RSA_padding_add_PKCS1_type_1.pod
+++ b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
@@ -5,6 +5,7 @@
 RSA_padding_add_PKCS1_type_1, RSA_padding_check_PKCS1_type_1,
 RSA_padding_add_PKCS1_type_2, RSA_padding_check_PKCS1_type_2,
 RSA_padding_add_PKCS1_OAEP, RSA_padding_check_PKCS1_OAEP,
+RSA_padding_add_PKCS1_OAEP_mgf1, RSA_padding_check_PKCS1_OAEP_mgf1,
 RSA_padding_add_SSLv23, RSA_padding_check_SSLv23,
 RSA_padding_add_none, RSA_padding_check_none - asymmetric encryption
 padding
@@ -14,35 +15,46 @@ padding
  #include <openssl/rsa.h>
 
  int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
-                                  unsigned char *f, int fl);
+                                  const unsigned char *f, int fl);
 
  int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
-                                    unsigned char *f, int fl, int rsa_len);
+                                    const unsigned char *f, int fl, int rsa_len);
 
  int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
-                                  unsigned char *f, int fl);
+                                  const unsigned char *f, int fl);
 
  int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
-                                    unsigned char *f, int fl, int rsa_len);
+                                    const unsigned char *f, int fl, int rsa_len);
 
  int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
-                                unsigned char *f, int fl, unsigned char *p, int pl);
+                                const unsigned char *f, int fl,
+                                const unsigned char *p, int pl);
 
  int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
-                                  unsigned char *f, int fl, int rsa_len,
-                                  unsigned char *p, int pl);
+                                  const unsigned char *f, int fl, int rsa_len,
+                                  const unsigned char *p, int pl);
+
+ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+                                     const unsigned char *f, int fl,
+                                     const unsigned char *p, int pl,
+                                     const EVP_MD *md, const EVP_MD *mgf1md);
+
+ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+                                       const unsigned char *f, int fl, int rsa_len,
+                                       const unsigned char *p, int pl,
+                                       const EVP_MD *md, const EVP_MD *mgf1md);
 
  int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
-                            unsigned char *f, int fl);
+                            const unsigned char *f, int fl);
 
  int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
-                              unsigned char *f, int fl, int rsa_len);
+                              const unsigned char *f, int fl, int rsa_len);
 
  int RSA_padding_add_none(unsigned char *to, int tlen,
-                          unsigned char *f, int fl);
+                          const unsigned char *f, int fl);
 
  int RSA_padding_check_none(unsigned char *to, int tlen,
-                            unsigned char *f, int fl, int rsa_len);
+                            const unsigned char *f, int fl, int rsa_len);
 
 =head1 DESCRIPTION
 
@@ -98,6 +110,10 @@ at B<to>.
 For RSA_padding_xxx_OAEP(), B<p> points to the encoding parameter
 of length B<pl>. B<p> may be B<NULL> if B<pl> is 0.
 
+For RSA_padding_xxx_OAEP_mgf1(), B<md> points to the md hash,
+if B<md> is B<NULL> that means md=sha1, and B<mgf1md> points to
+the mgf1 hash, if B<mgf1md> is B<NULL> that means mgf1md=md.
+
 =head1 RETURN VALUES
 
 The RSA_padding_add_xxx() functions return 1 on success, 0 on error.
@@ -107,15 +123,21 @@ L<ERR_get_error(3)>.
 
 =head1 WARNING
 
-The RSA_padding_check_PKCS1_type_2() padding check leaks timing
+The result of RSA_padding_check_PKCS1_type_2() is a very sensitive
 information which can potentially be used to mount a Bleichenbacher
 padding oracle attack. This is an inherent weakness in the PKCS #1
-v1.5 padding design. Prefer PKCS1_OAEP padding. Otherwise it can
-be recommended to pass zero-padded B<f>, so that B<fl> equals to
-B<rsa_len>, and if fixed by protocol, B<tlen> being set to the
-expected length. In such case leakage would be minimal, it would
-take attacker's ability to observe memory access pattern with byte
-granilarity as it occurs, post-factum timing analysis won't do.
+v1.5 padding design. Prefer PKCS1_OAEP padding. If that is not
+possible, the result of RSA_padding_check_PKCS1_type_2() should be
+checked in constant time if it matches the expected length of the
+plaintext and additionally some application specific consistency
+checks on the plaintext need to be performed in constant time.
+If the plaintext is rejected it must be kept secret which of the
+checks caused the application to reject the message.
+Do not remove the zero-padding from the decrypted raw RSA data
+which was computed by RSA_private_decrypt() with B<RSA_NO_PADDING>,
+as this would create a small timing side channel which could be
+used to mount a Bleichenbacher attack against any padding mode
+including PKCS1_OAEP.
 
 =head1 SEE ALSO
 
@@ -125,7 +147,7 @@ L<RSA_sign(3)>, L<RSA_verify(3)>
 
 =head1 COPYRIGHT
 
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/doc/man3/RSA_public_encrypt.pod b/doc/man3/RSA_public_encrypt.pod
index 4e3c119..9c75944 100644
--- a/doc/man3/RSA_public_encrypt.pod
+++ b/doc/man3/RSA_public_encrypt.pod
@@ -8,10 +8,10 @@ RSA_public_encrypt, RSA_private_decrypt - RSA public key cryptography
 
  #include <openssl/rsa.h>
 
- int RSA_public_encrypt(int flen, unsigned char *from,
+ int RSA_public_encrypt(int flen, const unsigned char *from,
                         unsigned char *to, RSA *rsa, int padding);
 
- int RSA_private_decrypt(int flen, unsigned char *from,
+ int RSA_private_decrypt(int flen, const unsigned char *from,
                          unsigned char *to, RSA *rsa, int padding);
 
 =head1 DESCRIPTION
@@ -27,6 +27,8 @@ B<padding> denotes one of the following modes:
 =item RSA_PKCS1_PADDING
 
 PKCS #1 v1.5 padding. This currently is the most widely used mode.
+However, it is highly recommended to use RSA_PKCS1_OAEP_PADDING in
+new applications. SEE WARNING BELOW.
 
 =item RSA_PKCS1_OAEP_PADDING
 
@@ -46,23 +48,35 @@ Encrypting user data directly with RSA is insecure.
 
 =back
 
-B<flen> must be less than RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5
-based padding modes, less than RSA_size(B<rsa>) - 41 for
+B<flen> must not be more than RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5
+based padding modes, not more than RSA_size(B<rsa>) - 42 for
 RSA_PKCS1_OAEP_PADDING and exactly RSA_size(B<rsa>) for RSA_NO_PADDING.
-The random number generator must be seeded prior to calling
-RSA_public_encrypt().
+When a padding mode other than RSA_NO_PADDING is in use, then
+RSA_public_encrypt() will include some random bytes into the ciphertext
+and therefore the ciphertext will be different each time, even if the
+plaintext and the public key are exactly identical.
+The returned ciphertext in B<to> will always be zero padded to exactly
+RSA_size(B<rsa>) bytes.
+B<to> and B<from> may overlap.
 
 RSA_private_decrypt() decrypts the B<flen> bytes at B<from> using the
-private key B<rsa> and stores the plaintext in B<to>. B<to> must point
-to a memory section large enough to hold the decrypted data (which is
-smaller than RSA_size(B<rsa>)). B<padding> is the padding mode that
-was used to encrypt the data.
+private key B<rsa> and stores the plaintext in B<to>. B<flen> should
+be equal to RSA_size(B<rsa>) but may be smaller, when leading zero
+bytes are in the ciphertext. Those are not important and may be removed,
+but RSA_public_encrypt() does not do that. B<to> must point
+to a memory section large enough to hold the maximal possible decrypted
+data (which is equal to RSA_size(B<rsa>) for RSA_NO_PADDING,
+RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5 based padding modes and
+RSA_size(B<rsa>) - 42 for RSA_PKCS1_OAEP_PADDING).
+B<padding> is the padding mode that was used to encrypt the data.
+B<to> and B<from> may overlap.
 
 =head1 RETURN VALUES
 
 RSA_public_encrypt() returns the size of the encrypted data (i.e.,
 RSA_size(B<rsa>)). RSA_private_decrypt() returns the size of the
-recovered plaintext.
+recovered plaintext. A return value of 0 is not an error and
+means only that the plaintext was empty.
 
 On error, -1 is returned; the error codes can be
 obtained by L<ERR_get_error(3)>.
@@ -85,7 +99,7 @@ L<RSA_size(3)>
 
 =head1 COPYRIGHT
 
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/test/rsa_test.c b/test/rsa_test.c
index cd9ca7f..b351ceb 100644
--- a/test/rsa_test.c
+++ b/test/rsa_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -268,6 +268,36 @@ err:
     return ret;
 }
 
+static int test_rsa_sslv23(int idx)
+{
+    int ret = 0;
+    RSA *key;
+    unsigned char ptext[256];
+    unsigned char ctext[256];
+    static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
+    unsigned char ctext_ex[256];
+    int plen;
+    int clen = 0;
+    int num;
+
+    plen = sizeof(ptext_ex) - 1;
+    clen = rsa_setkey(&key, ctext_ex, idx);
+
+    num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
+                             RSA_SSLV23_PADDING);
+    if (!TEST_int_eq(num, clen))
+        goto err;
+
+    num = RSA_private_decrypt(num, ctext, ptext, key, RSA_SSLV23_PADDING);
+    if (!TEST_mem_eq(ptext, num, ptext_ex, plen))
+        goto err;
+
+    ret = 1;
+err:
+    RSA_free(key);
+    return ret;
+}
+
 static int test_rsa_oaep(int idx)
 {
     int ret = 0;
@@ -391,6 +421,7 @@ err:
 int setup_tests(void)
 {
     ADD_ALL_TESTS(test_rsa_pkcs1, 3);
+    ADD_ALL_TESTS(test_rsa_sslv23, 3);
     ADD_ALL_TESTS(test_rsa_oaep, 3);
     ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases));
     return 1;


More information about the openssl-commits mailing list