]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implement encryption/decryption RSA-OAEP
authorNicolas Mora <git@babelouest.org>
Fri, 12 Feb 2021 18:59:41 +0000 (13:59 -0500)
committerDaiki Ueno <dueno@redhat.com>
Thu, 15 Feb 2024 00:13:22 +0000 (09:13 +0900)
Modified-by: Daiki Ueno <dueno@redhat.com>
14 files changed:
Makefile.in
nettle.texinfo
oaep.c [new file with mode: 0644]
oaep.h [new file with mode: 0644]
rsa-internal.h
rsa-oaep-decrypt.c [new file with mode: 0644]
rsa-oaep-encrypt.c [new file with mode: 0644]
rsa.h
testsuite/.gitignore
testsuite/Makefile.in
testsuite/rsa-oaep-encrypt-test.c [new file with mode: 0644]
testsuite/sc-rsa-oaep-encrypt-test [new file with mode: 0755]
testsuite/testutils.c
testsuite/testutils.h

index bde6cf2ae5bb4e797a1434f4f4ae67705d54e2c7..a083f7a188de489b8b17c7d4b0f036a4051b4889 100644 (file)
@@ -172,6 +172,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
                  bignum.c bignum-random.c bignum-random-prime.c \
                  sexp2bignum.c \
                  pkcs1.c pkcs1-encrypt.c pkcs1-decrypt.c \
+                 oaep.c \
                  pkcs1-sec-decrypt.c \
                  pkcs1-rsa-digest.c pkcs1-rsa-md5.c pkcs1-rsa-sha1.c \
                  pkcs1-rsa-sha256.c pkcs1-rsa-sha512.c \
@@ -186,6 +187,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
                  rsa-pss-sha256-sign-tr.c rsa-pss-sha256-verify.c \
                  rsa-pss-sha512-sign-tr.c rsa-pss-sha512-verify.c \
                  rsa-encrypt.c rsa-decrypt.c \
+                 rsa-oaep-encrypt.c rsa-oaep-decrypt.c \
                  rsa-sec-decrypt.c rsa-decrypt-tr.c \
                  rsa-keygen.c rsa-blind.c \
                  rsa2sexp.c sexp2rsa.c \
@@ -276,7 +278,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
        ctr-internal.h chacha-internal.h sha3-internal.h \
        salsa20-internal.h umac-internal.h hogweed-internal.h \
        rsa-internal.h pkcs1-internal.h dsa-internal.h eddsa-internal.h \
-       gmp-glue.h ecc-internal.h fat-setup.h \
+       gmp-glue.h ecc-internal.h fat-setup.h oaep.h \
        mini-gmp.h asm.m4 m4-utils.m4 \
        nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c
 
index 3d1626f36180add8217dfe0e72b91d9dbd91c653..25bce6fb776ae92f855e9899f30cc5d9d1410c32 100644 (file)
@@ -5134,7 +5134,7 @@ algorithm.
 
 While the above functions for the RSA signature operations use the
 @cite{PKCS#1} padding scheme, Nettle also provides the variants based on
-the PSS padding scheme, specified in @cite{RFC 3447}.  These variants
+the PSS padding scheme, specified in @cite{RFC 8017}.  These variants
 take advantage of a randomly choosen salt value, which could enhance the
 security by causing output to be different for equivalent inputs.
 However, assuming the same security level as inverting the @acronym{RSA}
@@ -5188,6 +5188,35 @@ randomized RSA blinding.
 Returns 1 on success, 0 on failure.
 @end deftypefun
 
+While the above functions for the RSA encryption operations use the
+@cite{PKCS#1} padding scheme, Nettle also provides the variants based
+on the OAEP padding scheme, specified in @cite{RFC 8017}.  These
+variants take advantage of a randomly choosen seed value, which could
+enhance the security by causing output to be different for equivalent
+inputs.
+
+Encrypting a clear text message using RSA with the OAEP padding scheme
+is done with one of the following functions:
+
+@deftypefun int rsa_oaep_sha256_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t @var{length}, const uint8_t *@var{message}, uint8_t *@var{ciphertext})
+@deftypefunx int rsa_oaep_sha384_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t @var{length}, const uint8_t *@var{message}, uint8_t *@var{ciphertext})
+@deftypefunx int rsa_oaep_sha512_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t @var{length}, const uint8_t *@var{message}, uint8_t *@var{ciphertext})
+Returns 1 on success, 0 on failure. The label is optional and if
+omitted, @var{label_length} and @var{label} can be set to 0 and
+@code{NULL} respectively.
+@end deftypefun
+
+Decrypting a cipher text message using RSA with the OAEP padding
+scheme is done with one of the following functions:
+
+@deftypefun int rsa_oaep_sha256_decrypt (const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t *@var{length}, uint8_t *@var{message}, const uint8_t *@var{ciphertext})
+@deftypefunx int rsa_oaep_sha384_decrypt (const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t *@var{length}, uint8_t *@var{message}, const uint8_t *@var{ciphertext})
+@deftypefunx int rsa_oaep_sha512_decrypt (const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{label_length}, const uint8_t *@var{label}, size_t *@var{length}, uint8_t *@var{message}, const uint8_t *@var{ciphertext})
+Returns 1 on success, 0 on failure. These function utilize randomized
+RSA blinding similarly to @code{rsa_decrypt_tr}.
+@end deftypefun
+
+
 If you need to use the @acronym{RSA} trapdoor, the private key, in a way
 that isn't supported by the above functions Nettle also includes a
 function that computes @code{x^d mod n} and nothing more, using the
diff --git a/oaep.c b/oaep.c
new file mode 100644 (file)
index 0000000..c504fbb
--- /dev/null
+++ b/oaep.c
@@ -0,0 +1,237 @@
+/* oaep.c
+
+   PKCS#1 RSA-OAEP (RFC-8017).
+
+   Copyright (C) 2021-2024 Nicolas Mora
+   Copyright (C) 2024 Daiki Ueno
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "oaep.h"
+
+#include "gmp-glue.h"
+#include "memops.h"
+#include "memxor.h"
+#include "nettle-internal.h"
+#include "pss-mgf1.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Inputs are always cast to uint32_t values. But all values used in this
+ * function should never exceed the maximum value of a uint32_t anyway.
+ * these macros returns 1 on success, 0 on failure */
+#define NOT_EQUAL(a, b) \
+    ((0U - ((uint32_t)(a) ^ (uint32_t)(b))) >> 31)
+#define EQUAL(a, b) (IS_ZERO_SMALL ((a) ^ (b)))
+#define GREATER_OR_EQUAL(a, b) \
+    (1U - (((uint32_t)(a) - (uint32_t)(b)) >> 31))
+
+/* This is a copy of _pkcs1_sec_decrypt_variable with a slight
+ * modification for the padding format.
+ */
+static int
+_oaep_sec_decrypt_variable(size_t *length, uint8_t *message,
+                          size_t padded_message_length,
+                          const volatile uint8_t *padded_message,
+                          volatile size_t offset)
+{
+  volatile int not_found = 1;
+  volatile int ok = 1;
+  size_t buflen, msglen;
+  size_t shift, i;
+
+  /* length is discovered in a side-channel silent way.
+   * not_found goes to 0 when the terminator is found. */
+  for (i = offset; i < padded_message_length; i++)
+    {
+      not_found &= NOT_EQUAL(padded_message[i], 1);
+      offset += not_found;
+    }
+  /* check if we ran out of buffer */
+  ok &= NOT_EQUAL(not_found, 1);
+
+  /* skip terminator */
+  offset++;
+
+  /* offset can be up to padded_message_length, due to the loop above,
+   * therefore msglen can't underflow */
+  msglen = padded_message_length - offset;
+
+  /* we always fill the whole buffer but only up to
+   * padded_message_length length */
+  buflen = *length;
+  if (buflen > padded_message_length) { /* input independent branch */
+    buflen = padded_message_length;
+  }
+
+  /* if the message length is larger than the buffer we must fail */
+  ok &= GREATER_OR_EQUAL(buflen, msglen);
+
+  /* fill destination buffer fully regardless of outcome. Copies the message
+   * in a memory access independent way. The destination message buffer will
+   * be clobbered past the message length. */
+  shift = padded_message_length - buflen;
+  cnd_memcpy(ok, message, padded_message + shift, buflen);
+  offset -= shift;
+  /* In this loop, the bits of the 'offset' variable are used as shifting
+   * conditions, starting from the least significant bit. The end result is
+   * that the buffer is shifted left exactly 'offset' bytes. */
+  for (shift = 1; shift < buflen; shift <<= 1, offset >>= 1)
+    {
+      /* 'ok' is both a least significant bit mask and a condition */
+      cnd_memcpy(offset & ok, message, message + shift, buflen - shift);
+    }
+
+  /* update length only if we succeeded, otherwise leave unchanged */
+  *length = (msglen & (-(size_t) ok)) + (*length & ((size_t) ok - 1));
+
+  return ok;
+}
+
+int
+_oaep_decode_mgf1 (const uint8_t *em,
+                  size_t key_size,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t *length, uint8_t *message)
+{
+  const uint8_t *db;
+  size_t db_length;
+  const uint8_t *seed;
+  TMP_GMP_DECL(db_mask, uint8_t);
+  uint8_t seed_mask[NETTLE_MAX_HASH_DIGEST_SIZE];
+  uint8_t lhash[NETTLE_MAX_HASH_DIGEST_SIZE];
+  int ok = 1;
+
+  assert (key_size >= 2 * hash->digest_size - 2);
+
+  /* EM = 0x00 || maskedSeed || maskedDB */
+  ok &= EQUAL(*em, 0);
+  seed = em + 1;
+  db = seed + hash->digest_size;
+  db_length = key_size - hash->digest_size - 1;
+
+  TMP_GMP_ALLOC(db_mask, db_length);
+
+  /* seedMask = MGF(maskedDB, hLen) */
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, db_length, db);
+  pss_mgf1 (hash_ctx, hash, hash->digest_size, seed_mask);
+
+  /* seed = maskedSeed \xor seedMask */
+  memxor (seed_mask, seed, hash->digest_size);
+
+  /* dbMask = MGF(seed, seed - hLen - 1) */
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, hash->digest_size, seed_mask);
+  pss_mgf1 (hash_ctx, hash, db_length, db_mask);
+
+  /* DB = maskedDB \xor dbMask */
+  memxor (db_mask, db, db_length);
+
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, label_length, label);
+  hash->digest (hash_ctx, hash->digest_size, lhash);
+
+  ok &= memeql_sec (db_mask, lhash, hash->digest_size);
+
+  ok &= _oaep_sec_decrypt_variable (length, message,
+                                   db_length, db_mask,
+                                   hash->digest_size);
+
+  TMP_GMP_FREE (db_mask);
+
+  return ok;
+}
+
+int
+_oaep_encode_mgf1 (mpz_t m, size_t key_size,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t message_length, const uint8_t *message)
+{
+  TMP_GMP_DECL(em, uint8_t);
+  TMP_GMP_DECL(db_mask, uint8_t);
+  uint8_t *db;
+  size_t db_length;
+  uint8_t *seed;
+  uint8_t seed_mask[NETTLE_MAX_HASH_DIGEST_SIZE];
+
+  assert (key_size >= 2 * hash->digest_size - 2);
+
+  if (message_length > key_size - 2 * hash->digest_size - 2)
+    return 0;
+
+  TMP_GMP_ALLOC(em, key_size);
+  TMP_GMP_ALLOC(db_mask, key_size);
+
+  /* EM = 0x00 || maskedSeed || maskedDB */
+  *em = 0;
+  seed = em + 1;
+  db = seed + hash->digest_size;
+  db_length = key_size - hash->digest_size - 1;
+
+  /* DB = Hash(L) || PS || 0x01 || M */
+  memset (db, 0, db_length);
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, label_length, label);
+  hash->digest (hash_ctx, hash->digest_size, db);
+  memcpy (&db[db_length - message_length], message, message_length);
+  db[db_length - message_length - 1] = 0x01;
+
+  /* Generate seed */
+  random (random_ctx, hash->digest_size, seed);
+
+  /* dbMask = MGF(seed, k - hLen - 1) */
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, hash->digest_size, seed);
+  pss_mgf1 (hash_ctx, hash, db_length, db_mask);
+
+  /* maskedDB = DB \xor dbMask */
+  memxor (db, db_mask, db_length);
+
+  /* seedMask = MGF(maskedDB, hLen) */
+  hash->init (hash_ctx);
+  hash->update (hash_ctx, db_length, db);
+  pss_mgf1 (hash_ctx, hash, hash->digest_size, seed_mask);
+
+  /* maskedSeed = seed \xor seedMask */
+  memxor (seed, seed_mask, hash->digest_size);
+
+  nettle_mpz_set_str_256_u (m, key_size, em);
+
+  TMP_GMP_FREE (em);
+  TMP_GMP_FREE (db_mask);
+
+  return 1;
+}
diff --git a/oaep.h b/oaep.h
new file mode 100644 (file)
index 0000000..a2e179f
--- /dev/null
+++ b/oaep.h
@@ -0,0 +1,67 @@
+/* oaep.h
+
+   PKCS#1 RSA-OAEP (RFC-8017).
+
+   Copyright (C) 2021-2024 Nicolas Mora
+   Copyright (C) 2024 Daiki Ueno
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_OAEP_H_INCLUDED
+#define NETTLE_OAEP_H_INCLUDED
+
+#include "nettle-meta.h"
+#include "bignum.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define _oaep_encode_mgf1 _nettle_oaep_encode_mgf1
+#define _oaep_decode_mgf1 _nettle_oaep_decode_mgf1
+
+int
+_oaep_decode_mgf1 (const uint8_t *em, size_t key_size,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t *length, uint8_t *message);
+
+int
+_oaep_encode_mgf1 (mpz_t m, size_t key_size,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t message_length, const uint8_t *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_OAEP_H_INCLUDED */
index f66a7df049b675ac471d345d56000a2180fc31f6..fd54b9d5613c7abd7bfaee054d198e85ea9011c0 100644 (file)
@@ -35,6 +35,7 @@
 #define NETTLE_RSA_INTERNAL_H_INCLUDED
 
 #include "rsa.h"
+#include "nettle-meta.h"
 
 #define _rsa_verify _nettle_rsa_verify
 #define _rsa_verify_recover _nettle_rsa_verify_recover
@@ -44,6 +45,8 @@
 #define _rsa_sec_compute_root_itch _nettle_rsa_sec_compute_root_itch
 #define _rsa_sec_compute_root _nettle_rsa_sec_compute_root
 #define _rsa_sec_compute_root_tr _nettle_rsa_sec_compute_root_tr
+#define _rsa_oaep_encrypt _nettle_rsa_oaep_encrypt
+#define _rsa_oaep_decrypt _nettle_rsa_oaep_decrypt
 
 /* Internal functions. */
 int
@@ -85,4 +88,21 @@ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
                         void *random_ctx, nettle_random_func *random,
                         mp_limb_t *x, const mp_limb_t *m);
 
+int
+_rsa_oaep_encrypt (const struct rsa_public_key *key,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t length, const uint8_t *message,
+                  uint8_t *ciphertext);
+
+int
+_rsa_oaep_decrypt (const struct rsa_public_key *pub,
+                  const struct rsa_private_key *key,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t *length, uint8_t *message,
+                  const uint8_t *ciphertext);
+
 #endif /* NETTLE_RSA_INTERNAL_H_INCLUDED */
diff --git a/rsa-oaep-decrypt.c b/rsa-oaep-decrypt.c
new file mode 100644 (file)
index 0000000..4006a02
--- /dev/null
@@ -0,0 +1,133 @@
+/* rsa-oaep-decrypt.c
+
+   The RSA publickey algorithm. OAEP decryption.
+
+   Copyright (C) 2021-2024 Nicolas Mora
+   Copyright (C) 2024 Daiki Ueno
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rsa.h"
+
+#include "gmp-glue.h"
+#include "nettle-internal.h"
+#include "oaep.h"
+#include "rsa-internal.h"
+
+int
+_rsa_oaep_decrypt (const struct rsa_public_key *pub,
+                  const struct rsa_private_key *key,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t *length, uint8_t *message,
+                  const uint8_t *ciphertext)
+{
+  TMP_GMP_DECL (m, mp_limb_t);
+  TMP_GMP_DECL (em, uint8_t);
+  int res;
+
+  TMP_GMP_ALLOC (m, mpz_size (pub->n));
+  TMP_GMP_ALLOC (em, key->size);
+
+  mpn_set_base256 (m, mpz_size (pub->n), ciphertext, pub->size);
+
+  /* Check that input is in range. */
+  if (mpn_cmp (m, mpz_limbs_read (pub->n), mpz_size (pub->n)) >= 0)
+    {
+      TMP_GMP_FREE (em);
+      TMP_GMP_FREE (m);
+      return 0;
+    }
+
+  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, m);
+
+  mpn_get_base256 (em, key->size, m, mpz_size (pub->n));
+
+  res &= _oaep_decode_mgf1 (em, key->size, hash_ctx, hash, label_length, label,
+                           length, message);
+
+  TMP_GMP_FREE (em);
+  TMP_GMP_FREE (m);
+  return res;
+}
+
+int
+rsa_oaep_sha256_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext)
+{
+  struct sha256_ctx ctx;
+
+  sha256_init (&ctx);
+
+  return _rsa_oaep_decrypt (pub, key, random_ctx, random,
+                           &ctx, &nettle_sha256, label_length, label,
+                           length, message, ciphertext);
+}
+
+int
+rsa_oaep_sha384_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext)
+{
+  struct sha384_ctx ctx;
+
+  sha384_init (&ctx);
+
+  return _rsa_oaep_decrypt (pub, key, random_ctx, random,
+                           &ctx, &nettle_sha384, label_length, label,
+                           length, message, ciphertext);
+}
+
+int
+rsa_oaep_sha512_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext)
+{
+  struct sha512_ctx ctx;
+
+  sha512_init (&ctx);
+
+  return _rsa_oaep_decrypt (pub, key, random_ctx, random,
+                           &ctx, &nettle_sha512, label_length, label,
+                           length, message, ciphertext);
+}
diff --git a/rsa-oaep-encrypt.c b/rsa-oaep-encrypt.c
new file mode 100644 (file)
index 0000000..488821f
--- /dev/null
@@ -0,0 +1,128 @@
+/* rsa-oaep-encrypt.c
+
+   The RSA publickey algorithm. OAEP encryption.
+
+   Copyright (C) 2021-2024 Nicolas Mora
+   Copyright (C) 2024 Daiki Ueno
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rsa.h"
+
+#include "nettle-internal.h"
+#include "oaep.h"
+#include "rsa-internal.h"
+
+int
+_rsa_oaep_encrypt (const struct rsa_public_key *key,
+                  void *random_ctx, nettle_random_func *random,
+                  void *hash_ctx, const struct nettle_hash *hash,
+                  size_t label_length, const uint8_t *label,
+                  size_t length, const uint8_t *message,
+                  uint8_t *ciphertext)
+{
+  mpz_t gibberish;
+
+  mpz_init (gibberish);
+
+  if (_oaep_encode_mgf1 (gibberish, key->size,
+                        random_ctx, random,
+                        hash_ctx, hash,
+                        label_length, label,
+                        length, message))
+    {
+      mpz_powm (gibberish, gibberish, key->e, key->n);
+      nettle_mpz_get_str_256 (key->size, ciphertext, gibberish);
+      mpz_clear (gibberish);
+      return 1;
+    }
+
+  mpz_clear (gibberish);
+  return 0;
+}
+
+int
+rsa_oaep_sha256_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t *message,
+                        uint8_t *ciphertext)
+{
+  struct sha256_ctx ctx;
+
+  sha256_init (&ctx);
+
+  return _rsa_oaep_encrypt (key,
+                           random_ctx, random,
+                           &ctx, &nettle_sha256,
+                           label_length, label,
+                           length, message,
+                           ciphertext);
+}
+
+int
+rsa_oaep_sha384_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t *message,
+                        uint8_t *ciphertext)
+{
+  struct sha384_ctx ctx;
+
+  sha384_init (&ctx);
+
+  return _rsa_oaep_encrypt (key,
+                           random_ctx, random,
+                           &ctx, &nettle_sha384,
+                           label_length, label,
+                           length, message,
+                           ciphertext);
+}
+
+int
+rsa_oaep_sha512_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t *message,
+                        uint8_t *ciphertext)
+{
+  struct sha512_ctx ctx;
+
+  sha512_init (&ctx);
+
+  return _rsa_oaep_encrypt (key,
+                           random_ctx, random,
+                           &ctx, &nettle_sha512,
+                           label_length, label,
+                           length, message,
+                           ciphertext);
+}
diff --git a/rsa.h b/rsa.h
index 2dd35a2d34edb53b05635d5712fcf14557373fea..054b318c4cb40d06ad19d8840d0fd8c8ed9273cc 100644 (file)
--- a/rsa.h
+++ b/rsa.h
@@ -88,6 +88,12 @@ extern "C" {
 #define rsa_encrypt nettle_rsa_encrypt
 #define rsa_decrypt nettle_rsa_decrypt
 #define rsa_decrypt_tr nettle_rsa_decrypt_tr
+#define rsa_oaep_sha256_encrypt nettle_rsa_oaep_sha256_encrypt
+#define rsa_oaep_sha256_decrypt nettle_rsa_oaep_sha256_decrypt
+#define rsa_oaep_sha384_encrypt nettle_rsa_oaep_sha384_encrypt
+#define rsa_oaep_sha384_decrypt nettle_rsa_oaep_sha384_decrypt
+#define rsa_oaep_sha512_encrypt nettle_rsa_oaep_sha512_encrypt
+#define rsa_oaep_sha512_decrypt nettle_rsa_oaep_sha512_decrypt
 #define rsa_sec_decrypt nettle_rsa_sec_decrypt
 #define rsa_compute_root nettle_rsa_compute_root
 #define rsa_compute_root_tr nettle_rsa_compute_root_tr
@@ -389,8 +395,6 @@ rsa_pss_sha512_verify_digest(const struct rsa_public_key *key,
 
 
 /* RSA encryption, using PKCS#1 */
-/* These functions uses the v1.5 padding. What should the v2 (OAEP)
- * functions be called? */
 
 /* Returns 1 on success, 0 on failure, which happens if the
  * message is too long for the key. */
@@ -428,6 +432,53 @@ rsa_sec_decrypt(const struct rsa_public_key *pub,
                size_t length, uint8_t *message,
                const mpz_t gibberish);
 
+/* RSA encryption, using OAEP */
+
+int
+rsa_oaep_sha256_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t * message,
+                        uint8_t *ciphertext);
+
+int
+rsa_oaep_sha256_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext);
+
+int
+rsa_oaep_sha384_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t * message,
+                        uint8_t *ciphertext);
+
+int
+rsa_oaep_sha384_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext);
+
+int
+rsa_oaep_sha512_encrypt (const struct rsa_public_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t length, const uint8_t *message,
+                        uint8_t *ciphertext);
+
+int
+rsa_oaep_sha512_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext);
+
 /* Compute x, the e:th root of m. Calling it with x == m is allowed.
    It is required that 0 <= m < n. */
 void
index f237815237f0bf8cdbdff13088b54127f0e251cd..9cc90985004ed1d6c4318865f240e3598e7969d1 100644 (file)
@@ -76,6 +76,7 @@
 /rsa-compute-root-test
 /rsa-encrypt-test
 /rsa-keygen-test
+/rsa-oaep-encrypt-test
 /rsa-pss-sign-tr-test
 /rsa-sign-tr-test
 /rsa-test
index c4513005642a258ce613cbe45694edb417e0f76a..bd63052479233c21dd706d77606a3d5cecb13b99 100644 (file)
@@ -43,6 +43,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
                     pss-test.c rsa-sign-tr-test.c \
                     pss-mgf1-test.c rsa-pss-sign-tr-test.c \
                     rsa-test.c rsa-encrypt-test.c rsa-keygen-test.c \
+                    rsa-oaep-encrypt-test.c \
                     rsa-sec-decrypt-test.c \
                     rsa-compute-root-test.c \
                     dsa-test.c dsa-keygen-test.c \
@@ -67,6 +68,7 @@ TS_C = $(TS_NETTLE) @IF_HOGWEED@ $(TS_HOGWEED)
 TS_CXX = @IF_CXX@ $(CXX_SOURCES:.cxx=$(EXEEXT))
 TARGETS = $(TS_C) $(TS_CXX)
 TS_SC_HOGWEED = sc-pkcs1-sec-decrypt-test sc-rsa-sec-decrypt-test \
+       sc-rsa-oaep-encrypt-test \
        sc-ecdsa-sign-test sc-curve25519-dh-test sc-curve448-dh-test \
        sc-ed25519-test sc-ed448-test
 TS_SC = sc-cnd-memcpy-test sc-gcm-test sc-memeql-test \
diff --git a/testsuite/rsa-oaep-encrypt-test.c b/testsuite/rsa-oaep-encrypt-test.c
new file mode 100644 (file)
index 0000000..3d9808a
--- /dev/null
@@ -0,0 +1,535 @@
+#include "testutils.h"
+#include "knuth-lfib.h"
+#include "nettle-meta.h"
+#include "rsa-internal.h"
+#include "sha1.h"
+
+#define MARK_MPZ_LIMBS_UNDEFINED(x) \
+  mark_bytes_undefined (mpz_size (x) * sizeof (mp_limb_t), mpz_limbs_read (x))
+
+#define MARK_MPZ_LIMBS_DEFINED(x) \
+  mark_bytes_defined (mpz_size (x) * sizeof (mp_limb_t), mpz_limbs_read (x))
+
+typedef int (*test_rsa_oaep_encrypt_func) (const struct rsa_public_key *key,
+                                          void *random_ctx,
+                                          nettle_random_func *random,
+                                          size_t label_length,
+                                          const uint8_t *label,
+                                          size_t length,
+                                          const uint8_t *message,
+                                          uint8_t *ciphertext);
+
+typedef int (*test_rsa_oaep_decrypt_func) (const struct rsa_public_key *pub,
+                                          const struct rsa_private_key *key,
+                                          void *random_ctx,
+                                          nettle_random_func *random,
+                                          size_t label_length,
+                                          const uint8_t *label,
+                                          size_t *length,
+                                          uint8_t *message,
+                                          const uint8_t *ciphertext);
+
+static int
+rsa_decrypt_for_test(test_rsa_oaep_decrypt_func decrypt_func,
+                    const struct rsa_public_key *pub,
+                     const struct rsa_private_key *key,
+                     void *random_ctx, nettle_random_func *random,
+                    size_t label_length, const uint8_t *label,
+                     size_t *length, uint8_t *message,
+                     const uint8_t *ciphertext)
+{
+  int ret;
+
+  /* Makes valgrind trigger on any branches depending on the input
+     data. Except that (i) we have to allow rsa_sec_compute_root_tr to
+     check that p and q are odd, (ii) mpn_sec_div_r may leak
+     information about the most significant bits of p and q, due to
+     normalization check and table lookup in invert_limb, and (iii)
+     mpn_sec_powm may leak information about the least significant
+     bits of p and q, due to table lookup in binvert_limb. */
+  mark_bytes_undefined (*length, message);
+  MARK_MPZ_LIMBS_UNDEFINED(key->a);
+  MARK_MPZ_LIMBS_UNDEFINED(key->b);
+  MARK_MPZ_LIMBS_UNDEFINED(key->c);
+  mark_bytes_undefined ((mpz_size (key->p) - 3) * sizeof(mp_limb_t),
+                       mpz_limbs_read (key->p) + 1);
+  mark_bytes_undefined((mpz_size (key->q) - 3) * sizeof(mp_limb_t),
+                      mpz_limbs_read (key->q) + 1);
+
+  ret = decrypt_func (pub, key, random_ctx, random, label_length, label,
+                     length, message, ciphertext);
+
+  mark_bytes_defined (sizeof(*length), length);
+  mark_bytes_defined (*length, message);
+  mark_bytes_defined (sizeof(ret), &ret);
+  MARK_MPZ_LIMBS_DEFINED(key->a);
+  MARK_MPZ_LIMBS_DEFINED(key->b);
+  MARK_MPZ_LIMBS_DEFINED(key->c);
+  MARK_MPZ_LIMBS_DEFINED(key->p);
+  MARK_MPZ_LIMBS_DEFINED(key->q);
+
+  return ret;
+}
+
+static void
+test_rsa_oaep_encrypt_decrypt (struct rsa_public_key *pub,
+                              struct rsa_private_key *key,
+                              test_rsa_oaep_encrypt_func encrypt_func,
+                              test_rsa_oaep_decrypt_func decrypt_func,
+                              size_t label_length, const uint8_t *label,
+                              size_t length, const uint8_t *message)
+{
+  uint8_t *ciphertext;
+  uint8_t *decrypted;
+  size_t decrypted_length;
+  uint8_t after;
+  struct knuth_lfib_ctx lfib;
+
+  knuth_lfib_init(&lfib, 1111);
+
+  ciphertext = xalloc (key->size + 1);
+  knuth_lfib_random (&lfib, key->size + 1, ciphertext);
+  after = ciphertext[key->size];
+
+  ASSERT (encrypt_func (pub,
+                       &lfib, (nettle_random_func *) knuth_lfib_random,
+                       label_length, label,
+                       length, message,
+                       ciphertext));
+  ASSERT (ciphertext[key->size] == after);
+
+  if (verbose)
+    {
+      fprintf (stderr, "encrypted: ");
+      print_hex (key->size, ciphertext);
+      fprintf (stderr, "\n");
+    }
+
+  decrypted = xalloc (length + 1);
+
+  knuth_lfib_random (&lfib, length + 1, decrypted);
+  after = decrypted[length];
+
+  /* Test short buffer */
+  decrypted_length = length - 1;
+  ASSERT (!rsa_decrypt_for_test (decrypt_func,
+                                pub, key,
+                                &lfib, (nettle_random_func *) knuth_lfib_random,
+                                label_length, label,
+                                &decrypted_length, decrypted,
+                                ciphertext));
+
+  decrypted_length = length;
+  ASSERT (rsa_decrypt_for_test (decrypt_func,
+                               pub, key,
+                               &lfib, (nettle_random_func *) knuth_lfib_random,
+                               label_length, label,
+                               &decrypted_length, decrypted,
+                               ciphertext));
+  ASSERT (decrypted_length == length);
+  ASSERT (MEMEQ (length, message, decrypted));
+  ASSERT (decrypted[length] == after);
+
+  free (decrypted);
+  free (ciphertext);
+}
+
+static void
+test_encrypt_decrypt (void)
+{
+  struct rsa_public_key pub;
+  struct rsa_private_key key;
+
+  const unsigned char msg[] = "Squemish ossifrage";
+  size_t msg_length = LLENGTH(msg);
+  const unsigned char label[] = "This is a magic label";
+  size_t label_length = LLENGTH(label);
+
+  rsa_private_key_init(&key);
+  rsa_public_key_init(&pub);
+
+  test_rsa_set_key_2(&pub, &key);
+
+  /* Test without label */
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha256_encrypt,
+                                rsa_oaep_sha256_decrypt,
+                                0, NULL,
+                                msg_length, msg);
+
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha384_encrypt,
+                                rsa_oaep_sha384_decrypt,
+                                0, NULL,
+                                msg_length, msg);
+
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha512_encrypt,
+                                rsa_oaep_sha512_decrypt,
+                                0, NULL,
+                                msg_length, msg);
+
+  /* Test with label */
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha256_encrypt,
+                                rsa_oaep_sha256_decrypt,
+                                label_length, label,
+                                msg_length, msg);
+
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha384_encrypt,
+                                rsa_oaep_sha384_decrypt,
+                                label_length, label,
+                                msg_length, msg);
+
+  test_rsa_oaep_encrypt_decrypt (&pub, &key,
+                                rsa_oaep_sha512_encrypt,
+                                rsa_oaep_sha512_decrypt,
+                                label_length, label,
+                                msg_length, msg);
+
+  rsa_public_key_clear (&pub);
+  rsa_private_key_clear (&key);
+}
+
+static int
+rsa_oaep_sha1_encrypt (const struct rsa_public_key *key,
+                      void *random_ctx, nettle_random_func *random,
+                      size_t label_length, const uint8_t *label,
+                      size_t length, const uint8_t *message,
+                      uint8_t *ciphertext)
+{
+  struct sha1_ctx ctx;
+
+  sha1_init (&ctx);
+
+  return _rsa_oaep_encrypt (key,
+                           random_ctx, random,
+                           &ctx, &nettle_sha1,
+                           label_length, label,
+                           length, message,
+                           ciphertext);
+}
+
+static int
+rsa_oaep_sha1_decrypt (const struct rsa_public_key *pub,
+                        const struct rsa_private_key *key,
+                        void *random_ctx, nettle_random_func *random,
+                        size_t label_length, const uint8_t *label,
+                        size_t *length, uint8_t *message,
+                        const uint8_t *ciphertext)
+{
+  struct sha1_ctx ctx;
+
+  sha1_init (&ctx);
+
+  return _rsa_oaep_decrypt (pub, key, random_ctx, random,
+                           &ctx, &nettle_sha1, label_length, label,
+                           length, message, ciphertext);
+}
+
+static void
+random_from_seed (struct tstring *seed, size_t n, uint8_t *dst)
+{
+  ASSERT (n <= seed->length);
+  memcpy (dst, seed->data, n);
+}
+
+static void
+test_rsa_oaep_encrypt_decrypt_kat (struct rsa_public_key *pub,
+                                  struct rsa_private_key *key,
+                                  test_rsa_oaep_encrypt_func encrypt_func,
+                                  test_rsa_oaep_decrypt_func decrypt_func,
+                                  void *random_ctx, nettle_random_func *random,
+                                  size_t label_length, const uint8_t *label,
+                                  size_t length, const uint8_t *message,
+                                  const uint8_t *expected)
+{
+  uint8_t *ciphertext;
+  uint8_t *decrypted;
+  size_t decrypted_length;
+  uint8_t after;
+  /* For blinding at decryption */
+  struct knuth_lfib_ctx lfib;
+
+  knuth_lfib_init(&lfib, 1111);
+
+  ciphertext = xalloc (key->size + 1);
+  knuth_lfib_random (&lfib, key->size + 1, ciphertext);
+  after = ciphertext[key->size];
+
+  ASSERT (encrypt_func (pub,
+                       random_ctx, random,
+                       label_length, label,
+                       length, message,
+                       ciphertext));
+  ASSERT (MEMEQ (key->size, ciphertext, expected));
+  ASSERT (ciphertext[key->size] == after);
+
+  decrypted = xalloc (length + 1);
+  knuth_lfib_random (&lfib, length + 1, decrypted);
+  after = decrypted[length];
+
+  decrypted_length = length;
+
+  ASSERT (rsa_decrypt_for_test (decrypt_func,
+                               pub, key,
+                               &lfib, (nettle_random_func *) knuth_lfib_random,
+                               label_length, label,
+                               &decrypted_length, decrypted,
+                               ciphertext));
+  ASSERT (decrypted_length == length);
+  ASSERT (MEMEQ (length, message, decrypted));
+  ASSERT (decrypted[length] == after);
+
+  free (decrypted);
+  free (ciphertext);
+}
+
+/* The below are known answer tests constructed using the draft
+ * version of PKCS #1 2.1 test vectors from RSA Laboratories:
+ *
+ * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip
+ *
+ * While the original zip file is no longer accessible, a copy is
+ * kept in the python-cryptography repository, under the following license:
+ * https://github.com/pyca/cryptography/tree/49bf4e408cd2f93276687f451dd28982e5d501e0/vectors/cryptography_vectors/asymmetric/RSA/pkcs-1v2-1d2-vec
+ */
+
+/*
+ * Copyright (c) Individual contributors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above copyright notice,
+ *        this list of conditions and the following disclaimer.
+ *
+ *     2. Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ *     3. Neither the name of PyCA Cryptography nor the names of its contributors
+ *        may be used to endorse or promote products derived from this software
+ *        without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static void
+test_rsa_oaep_set_key(struct rsa_public_key *pub,
+                     struct rsa_private_key *key)
+{
+  mpz_set_str(pub->n,
+             "a8b3b284af8eb50b" "387034a860f146c4" "919f318763cd6c55"
+             "98c8ae4811a1e0ab" "c4c7e0b082d693a5" "e7fced675cf46685"
+             "12772c0cbc64a742" "c6c630f533c8cc72" "f62ae833c40bf258"
+             "42e984bb78bdbf97" "c0107d55bdb662f5" "c4e0fab9845cb514"
+             "8ef7392dd3aaff93" "ae1e6b667bb3d424" "7616d4f5ba10d4cf"
+             "d226de88d39f16fb", 16);
+  mpz_set_str(pub->e, "010001", 16);
+
+  ASSERT (rsa_public_key_prepare(pub));
+
+  /* d is not used */
+#if 0
+  mpz_set_str(key->d,
+             "53339cfdb79fc846" "6a655c7316aca85c" "55fd8f6dd898fdaf"
+             "119517ef4f52e8fd" "8e258df93fee180f" "a0e4ab29693cd83b"
+             "152a553d4ac4d181" "2b8b9fa5af0e7f55" "fe7304df41570926"
+             "f3311f15c4d65a73" "2c483116ee3d3d2d" "0af3549ad9bf7cbf"
+             "b78ad884f84d5beb" "04724dc7369b31de" "f37d0cf539e9cfcd"
+             "d3de653729ead5d1" , 16);
+#endif
+
+  mpz_set_str(key->p,
+             "d32737e7267ffe13" "41b2d5c0d150a81b" "586fb3132bed2f8d"
+             "5262864a9cb9f30a" "f38be448598d413a" "172efb802c21acf1"
+             "c11c520c2f26a471" "dcad212eac7ca39d", 16);
+
+  mpz_set_str(key->q,
+             "cc8853d1d54da630" "fac004f471f281c7" "b8982d8224a490ed"
+             "beb33d3e3d5cc93c" "4765703d1dd79164" "2f1f116a0dd852be"
+             "2419b2af72bfe9a0" "30e860b0288b5d77", 16);
+
+  mpz_set_str(key->a,
+             "0e12bf1718e9cef5" "599ba1c3882fe804" "6a90874eefce8f2c"
+             "cc20e4f2741fb0a3" "3a3848aec9c9305f" "becbd2d76819967d"
+             "4671acc6431e4037" "968db37878e695c1", 16);
+
+  mpz_set_str(key->b,
+             "95297b0f95a2fa67" "d00707d609dfd4fc" "05c89dafc2ef6d6e"
+             "a55bec771ea33373" "4d9251e79082ecda" "866efef13c459e1a"
+             "631386b7e354c899" "f5f112ca85d71583", 16);
+
+  mpz_set_str(key->c,
+             "4f456c502493bdc0" "ed2ab756a3a6ed4d" "67352a697d4216e9"
+             "3212b127a63d5411" "ce6fa98d5dbefd73" "263e372814274381"
+             "8166ed7dd63687dd" "2a8ca1d2f4fbd8e1", 16);
+
+  ASSERT (rsa_private_key_prepare(key));
+  ASSERT (pub->size == key->size);
+}
+
+static void
+test_encrypt (void)
+{
+  struct rsa_public_key pub;
+  struct rsa_private_key key;
+
+  struct tstring *seed;
+  struct tstring *msg;
+  struct tstring *ciphertext;
+
+  rsa_private_key_init(&key);
+  rsa_public_key_init(&pub);
+
+  /* Test vector from RSA labs */
+  test_rsa_oaep_set_key(&pub, &key);
+
+  /* Example 1.1 */
+  msg = tstring_hex ("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34");
+  seed = tstring_hex ("18b776ea21069d69776a33e96bad48e1dda0a5ef");
+  ciphertext = tstring_hex ("354fe67b4a126d5d" "35fe36c777791a3f"
+                           "7ba13def484e2d39" "08aff722fad468fb"
+                           "21696de95d0be911" "c2d3174f8afcc201"
+                           "035f7b6d8e69402d" "e5451618c21a535f"
+                           "a9d7bfc5b8dd9fc2" "43f8cf927db31322"
+                           "d6e881eaa91a9961" "70e657a05a266426"
+                           "d98c88003f8477c1" "227094a0d9fa1e8c"
+                           "4024309ce1ecccb5" "210035d47ac72e8a");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  /* Example 1.2 */
+  msg = tstring_hex ("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5");
+  seed = tstring_hex ("0cc742ce4a9b7f32f951bcb251efd925fe4fe35f");
+  ciphertext = tstring_hex ("640db1acc58e0568" "fe5407e5f9b701df"
+                           "f8c3c91e716c536f" "c7fcec6cb5b71c11"
+                           "65988d4a279e1577" "d730fc7a29932e3f"
+                           "00c81515236d8d8e" "31017a7a09df4352"
+                           "d904cdeb79aa583a" "dcc31ea698a4c052"
+                           "83daba9089be5491" "f67c1a4ee48dc74b"
+                           "bbe6643aef846679" "b4cb395a352d5ed1"
+                           "15912df696ffe070" "2932946d71492b44");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  /* Example 1.3 */
+  msg = tstring_hex ("d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051");
+  seed = tstring_hex ("2514df4695755a67b288eaf4905c36eec66fd2fd");
+  ciphertext = tstring_hex ("423736ed035f6026" "af276c35c0b3741b"
+                           "365e5f76ca091b4e" "8c29e2f0befee603"
+                           "595aa8322d602d2e" "625e95eb81b2f1c9"
+                           "724e822eca76db86" "18cf09c5343503a4"
+                           "360835b5903bc637" "e3879fb05e0ef326"
+                           "85d5aec5067cd7cc" "96fe4b2670b6eac3"
+                           "066b1fcf5686b685" "89aafb7d629b02d8"
+                           "f8625ca3833624d4" "800fb081b1cf94eb");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  /* Example 1.4 */
+  msg = tstring_hex ("52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85");
+  seed = tstring_hex ("c4435a3e1a18a68b6820436290a37cefb85db3fb");
+  ciphertext = tstring_hex ("45ead4ca551e662c" "9800f1aca8283b05"
+                           "25e6abae30be4b4a" "ba762fa40fd3d38e"
+                           "22abefc69794f6eb" "bbc05ddbb1121624"
+                           "7d2f412fd0fba87c" "6e3acd888813646f"
+                           "d0e48e785204f9c3" "f73d6d8239562722"
+                           "dddd8771fec48b83" "a31ee6f592c4cfd4"
+                           "bc88174f3b13a112" "aae3b9f7b80e0fc6"
+                           "f7255ba880dc7d80" "21e22ad6a85f0755");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  /* Example 1.5 */
+  msg = tstring_hex ("8da89fd9e5f974a29feffb462b49180f6cf9e802");
+  seed = tstring_hex ("b318c42df3be0f83fea823f5a7b47ed5e425a3b5");
+  ciphertext = tstring_hex ("36f6e34d94a8d34d" "aacba33a2139d00a"
+                           "d85a9345a86051e7" "3071620056b920e2"
+                           "19005855a213a0f2" "3897cdcd731b4525"
+                           "7c777fe908202bef" "dd0b58386b1244ea"
+                           "0cf539a05d5d1032" "9da44e13030fd760"
+                           "dcd644cfef2094d1" "910d3f433e1c7c6d"
+                           "d18bc1f2df7f643d" "662fb9dd37ead905"
+                           "9190f4fa66ca39e8" "69c4eb449cbdc439");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  /* Example 1.6 */
+  msg = tstring_hex ("26521050844271");
+  seed = tstring_hex ("e4ec0982c2336f3a677f6a356174eb0ce887abc2");
+  ciphertext = tstring_hex ("42cee2617b1ecea4" "db3f4829386fbd61"
+                           "dafbf038e180d837" "c96366df24c097b4"
+                           "ab0fac6bdf590d82" "1c9f10642e681ad0"
+                           "5b8d78b378c0f46c" "e2fad63f74e0ad3d"
+                           "f06b075d7eb5f563" "6f8d403b9059ca76"
+                           "1b5c62bb52aa4500" "2ea70baace08ded2"
+                           "43b9d8cbd62a68ad" "e265832b56564e43"
+                           "a6fa42ed199a0997" "69742df1539e8255");
+  ASSERT (ciphertext->length == key.size);
+
+  test_rsa_oaep_encrypt_decrypt_kat (&pub, &key,
+                                    rsa_oaep_sha1_encrypt,
+                                    rsa_oaep_sha1_decrypt,
+                                    seed, (nettle_random_func *) random_from_seed,
+                                    0, NULL,
+                                    msg->length, msg->data,
+                                    ciphertext->data);
+
+  rsa_public_key_clear (&pub);
+  rsa_private_key_clear (&key);
+}
+
+void
+test_main (void)
+{
+  test_encrypt_decrypt ();
+  test_encrypt ();
+}
diff --git a/testsuite/sc-rsa-oaep-encrypt-test b/testsuite/sc-rsa-oaep-encrypt-test
new file mode 100755 (executable)
index 0000000..a414b07
--- /dev/null
@@ -0,0 +1,6 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+. "${srcdir}/sc-valgrind.sh"
+
+with_valgrind ./rsa-oaep-encrypt-test
index 4c9e4768cf50d6a8c18ea79d03e747c65b4907da..6fc8a8b824367ad5353ac6a52678de45f3781eb7 100644 (file)
@@ -1516,6 +1516,191 @@ test_rsa_set_key_1(struct rsa_public_key *pub,
   ASSERT (pub->size == key->size);
 }
 
+void
+test_rsa_set_key_2(struct rsa_public_key *pub,
+                  struct rsa_private_key *key)
+{
+  /* Initialize key pair for test programs */
+  /* 2048-bit key, generated by
+   *
+   *   certtool --generate-privkey --key-type=rsa --bits=2048 --outfile -
+   *
+   * Public Key Info:
+   *         Public Key Algorithm: RSA
+   *         Key Security Level: Medium (2048 bits)
+   *
+   * modulus:
+   *         00:dd:ef:1d:66:d5:f0:b3:56:9b:da:2a:59:c7:96:e6
+   *         7a:c9:c8:13:61:89:da:f1:5a:01:65:61:ac:fb:53:1a
+   *         09:49:41:dd:fd:db:6e:68:c4:3a:8a:61:46:c3:ea:8b
+   *         34:5f:e1:f6:60:91:9b:09:ae:8e:8c:ad:fa:99:ef:2a
+   *         b5:7d:32:ad:cc:2d:4f:3f:df:21:42:b7:ce:6e:ab:ca
+   *         eb:a4:93:97:8f:55:c4:8f:19:de:dd:ea:0a:83:10:3c
+   *         8c:5f:f5:ce:01:7f:32:3d:d6:f8:82:f2:2d:3f:8f:20
+   *         6a:02:68:a9:8b:0d:12:99:93:67:f9:1c:23:ae:5f:0d
+   *         df:ec:2b:5d:78:c8:14:ac:6b:e9:2a:f7:aa:3e:cd:a1
+   *         c8:c8:3e:11:24:50:eb:68:34:4c:0c:c1:2a:be:13:95
+   *         ee:a0:73:dd:09:f2:38:5c:58:a7:dc:60:30:90:c9:a4
+   *         1b:19:ed:51:5c:15:51:54:cd:8a:92:10:76:d4:19:88
+   *         f8:93:ff:8d:08:a2:46:0f:59:af:c1:3d:4e:24:b5:e5
+   *         8a:8e:44:10:85:74:8d:06:64:72:b2:f7:c5:6c:75:09
+   *         fa:bc:9d:73:5d:14:c5:a6:81:f5:2e:8a:2d:a9:aa:c1
+   *         43:b9:07:cf:77:90:7a:28:c5:41:53:51:d1:b3:6a:e2
+   *         7b:
+   *
+   * public exponent:
+   *         01:00:01:
+   *
+   * private exponent:
+   *         73:2e:6f:66:f8:af:d4:93:a5:8d:63:9f:76:cb:a5:50
+   *         a2:ba:b8:fc:4d:4c:99:28:2a:43:50:9f:33:4c:9c:dd
+   *         a6:ec:8d:66:fb:e4:60:71:3f:24:a4:79:d2:a2:3e:9e
+   *         ef:08:5a:13:22:5e:81:76:db:ba:bd:6c:ab:49:8a:33
+   *         e9:07:4d:56:03:49:f7:0f:39:b6:e3:a8:3a:9d:e4:51
+   *         c9:f7:63:98:5b:5e:09:1a:d7:24:fb:1b:7b:8c:08:b0
+   *         9d:f8:f7:72:a5:6e:10:d4:29:e3:e4:06:81:cf:29:76
+   *         7b:4b:90:7a:7f:4d:60:f1:34:eb:ff:a3:b1:12:da:22
+   *         9e:87:c0:77:22:38:03:4b:80:ab:0c:8a:07:14:c3:c0
+   *         08:9e:2c:13:9f:74:f4:19:86:51:61:67:b0:ce:bc:7b
+   *         8f:81:18:8e:3c:8e:e7:e5:d4:e9:ed:49:b8:0b:21:b1
+   *         2a:82:0f:7b:4d:8d:e4:f7:bc:8a:6c:c9:20:8c:4b:ba
+   *         1e:67:43:9e:58:a4:e4:20:c6:4b:22:05:9d:33:d3:11
+   *         92:f2:94:88:d8:fb:c9:53:8f:9c:52:4e:d3:66:f3:2b
+   *         8c:3b:56:a7:4c:25:10:44:a0:62:79:4d:44:fb:9d:0e
+   *         35:8b:92:b0:49:af:5d:a4:00:36:44:3c:e7:31:9d:f9
+   *
+   *
+   * prime1:
+   *         00:ed:6b:29:25:c1:4f:9c:df:08:4b:c1:43:e3:e6:f3
+   *         d6:6e:1e:2d:46:d6:eb:97:aa:c7:c9:32:5e:0a:6b:39
+   *         ac:be:2a:49:98:f6:c3:c8:d0:08:33:5b:75:62:f7:d9
+   *         7e:87:d6:90:2d:9d:ce:94:be:2b:ed:8e:aa:85:29:86
+   *         d9:bc:c0:10:2e:95:30:cc:3f:72:75:81:d1:60:f6:89
+   *         86:f7:42:dc:29:8f:dc:d7:15:e8:99:1a:1d:12:92:89
+   *         88:95:47:3e:25:c5:f4:e5:c4:82:87:32:d3:d7:a8:ce
+   *         d9:77:2c:fc:87:bb:d9:f9:e6:a4:ec:1e:c8:a9:7b:0b
+   *         35:
+   *
+   * prime2:
+   *         00:ef:4d:b5:f6:53:12:9a:4e:3c:3f:56:ff:25:86:44
+   *         0e:b1:b7:81:c4:0e:31:40:90:e7:91:d7:e7:80:8e:8a
+   *         cc:99:1a:1b:0b:5d:9b:9b:00:81:fa:36:95:02:6a:44
+   *         16:6e:67:64:db:ba:35:9b:5b:1c:e7:96:ac:2a:e3:c8
+   *         7a:a9:de:1d:e4:75:54:cf:73:c9:76:92:2f:03:8b:ef
+   *         a4:dc:5c:4d:54:2a:cc:f6:c3:cd:a7:0e:84:ce:33:96
+   *         9b:99:68:e5:a9:cf:80:5b:df:2b:5a:a4:02:b2:d5:65
+   *         a7:b8:d0:33:c8:23:ed:89:d1:44:7b:d1:94:99:9f:3c
+   *         ef:
+   *
+   * coefficient:
+   *         5c:ba:5a:d7:98:43:ab:ac:a0:d2:9c:1f:ab:3d:5e:a0
+   *         54:c9:6e:54:19:9b:ff:9c:dc:05:75:93:97:3a:88:e9
+   *         bb:1f:79:05:03:79:9b:b7:ac:07:71:bf:b0:a7:12:fc
+   *         22:6c:38:04:40:2f:b9:0d:2d:0a:f3:b8:2e:88:3e:ab
+   *         d8:ee:30:5c:fb:dc:59:0e:d9:9f:96:cd:4a:4a:12:88
+   *         aa:c9:f0:03:e2:01:df:5d:0e:ec:e6:ac:0b:f1:81:b8
+   *         85:9b:f7:69:b6:c8:e4:54:d8:02:5b:58:b4:c2:45:02
+   *         b7:65:d4:5c:dc:aa:b6:47:6e:dd:1f:72:46:6c:27:22
+   *
+   *
+   * exp1:
+   *         41:78:03:68:bd:dd:ce:4c:52:65:51:6d:ff:32:78:9a
+   *         f0:d2:b1:79:8f:5a:78:00:48:07:5b:34:43:7b:3d:f4
+   *         3c:9c:3c:9f:49:ac:c3:7b:5a:47:8f:38:d7:89:b1:18
+   *         0b:2d:47:a4:cc:97:62:bc:ee:30:1b:df:39:c9:31:be
+   *         69:26:2d:50:2b:23:c1:ae:dd:49:39:fb:1a:d9:e1:22
+   *         ae:9c:69:49:ac:ba:21:35:91:66:66:a5:0d:b2:0a:ea
+   *         f6:ff:26:4c:14:42:6b:f9:bc:64:bb:c7:5e:f8:d5:d1
+   *         71:e3:9d:df:70:15:b3:ab:be:5e:be:3e:67:3d:de:e1
+   *
+   *
+   * exp2:
+   *         63:00:4a:5c:5a:e7:e2:50:a5:9a:2a:ba:a9:e2:8f:3b
+   *         69:08:9b:35:ea:0d:34:41:fe:9b:96:af:de:be:99:eb
+   *         a5:17:68:c2:dd:fa:27:39:21:8c:cb:92:00:0a:c8:9a
+   *         63:18:81:60:69:fc:0d:86:b7:41:94:53:2b:f7:4a:94
+   *         7c:bc:38:af:b0:5e:e2:e8:6b:1b:93:c4:c1:79:de:2d
+   *         dd:40:8e:79:58:af:ad:13:3a:7c:77:84:37:ee:9d:cb
+   *         47:bf:5e:ec:4e:bd:32:c4:f4:21:ae:a2:b3:2b:97:bf
+   *         b8:b4:e2:07:55:dd:ca:db:79:b2:a3:f5:0f:4d:12:9f
+   */
+
+  mpz_set_str(pub->n,
+             "00ddef1d66d5f0b3" "569bda2a59c796e6" "7ac9c8136189daf1"
+             "5a016561acfb531a" "094941ddfddb6e68" "c43a8a6146c3ea8b"
+             "345fe1f660919b09" "ae8e8cadfa99ef2a" "b57d32adcc2d4f3f"
+             "df2142b7ce6eabca" "eba493978f55c48f" "19deddea0a83103c"
+             "8c5ff5ce017f323d" "d6f882f22d3f8f20" "6a0268a98b0d1299"
+             "9367f91c23ae5f0d" "dfec2b5d78c814ac" "6be92af7aa3ecda1"
+             "c8c83e112450eb68" "344c0cc12abe1395" "eea073dd09f2385c"
+             "58a7dc603090c9a4" "1b19ed515c155154" "cd8a921076d41988"
+             "f893ff8d08a2460f" "59afc13d4e24b5e5" "8a8e441085748d06"
+             "6472b2f7c56c7509" "fabc9d735d14c5a6" "81f52e8a2da9aac1"
+             "43b907cf77907a28" "c5415351d1b36ae2" "7b", 16);
+  mpz_set_str(pub->e, "010001", 16);
+
+  ASSERT (rsa_public_key_prepare(pub));
+
+  /* d is not used */
+#if 0
+  mpz_set_str(key->d,
+             "732e6f66f8afd493" "a58d639f76cba550" "a2bab8fc4d4c9928"
+             "2a43509f334c9cdd" "a6ec8d66fbe46071" "3f24a479d2a23e9e"
+             "ef085a13225e8176" "dbbabd6cab498a33" "e9074d560349f70f"
+             "39b6e3a83a9de451" "c9f763985b5e091a" "d724fb1b7b8c08b0"
+             "9df8f772a56e10d4" "29e3e40681cf2976" "7b4b907a7f4d60f1"
+             "34ebffa3b112da22" "9e87c0772238034b" "80ab0c8a0714c3c0"
+             "089e2c139f74f419" "86516167b0cebc7b" "8f81188e3c8ee7e5"
+             "d4e9ed49b80b21b1" "2a820f7b4d8de4f7" "bc8a6cc9208c4bba"
+             "1e67439e58a4e420" "c64b22059d33d311" "92f29488d8fbc953"
+             "8f9c524ed366f32b" "8c3b56a74c251044" "a062794d44fb9d0e"
+             "358b92b049af5da4" "0036443ce7319df9" , 16);
+#endif
+
+  mpz_set_str(key->p,
+             "00ed6b2925c14f9c" "df084bc143e3e6f3" "d66e1e2d46d6eb97"
+             "aac7c9325e0a6b39" "acbe2a4998f6c3c8" "d008335b7562f7d9"
+             "7e87d6902d9dce94" "be2bed8eaa852986" "d9bcc0102e9530cc"
+             "3f727581d160f689" "86f742dc298fdcd7" "15e8991a1d129289"
+             "8895473e25c5f4e5" "c4828732d3d7a8ce" "d9772cfc87bbd9f9"
+             "e6a4ec1ec8a97b0b" "35", 16);
+
+  mpz_set_str(key->q,
+             "00ef4db5f653129a" "4e3c3f56ff258644" "0eb1b781c40e3140"
+             "90e791d7e7808e8a" "cc991a1b0b5d9b9b" "0081fa3695026a44"
+             "166e6764dbba359b" "5b1ce796ac2ae3c8" "7aa9de1de47554cf"
+             "73c976922f038bef" "a4dc5c4d542accf6" "c3cda70e84ce3396"
+             "9b9968e5a9cf805b" "df2b5aa402b2d565" "a7b8d033c823ed89"
+             "d1447bd194999f3c" "ef", 16);
+
+  mpz_set_str(key->a,
+             "41780368bdddce4c" "5265516dff32789a" "f0d2b1798f5a7800"
+             "48075b34437b3df4" "3c9c3c9f49acc37b" "5a478f38d789b118"
+             "0b2d47a4cc9762bc" "ee301bdf39c931be" "69262d502b23c1ae"
+             "dd4939fb1ad9e122" "ae9c6949acba2135" "916666a50db20aea"
+             "f6ff264c14426bf9" "bc64bbc75ef8d5d1" "71e39ddf7015b3ab"
+             "be5ebe3e673ddee1", 16);
+
+  mpz_set_str(key->b,
+             "63004a5c5ae7e250" "a59a2abaa9e28f3b" "69089b35ea0d3441"
+             "fe9b96afdebe99eb" "a51768c2ddfa2739" "218ccb92000ac89a"
+             "6318816069fc0d86" "b74194532bf74a94" "7cbc38afb05ee2e8"
+             "6b1b93c4c179de2d" "dd408e7958afad13" "3a7c778437ee9dcb"
+             "47bf5eec4ebd32c4" "f421aea2b32b97bf" "b8b4e20755ddcadb"
+             "79b2a3f50f4d129f", 16);
+
+  mpz_set_str(key->c,
+             "5cba5ad79843abac" "a0d29c1fab3d5ea0" "54c96e54199bff9c"
+             "dc057593973a88e9" "bb1f790503799bb7" "ac0771bfb0a712fc"
+             "226c3804402fb90d" "2d0af3b82e883eab" "d8ee305cfbdc590e"
+             "d99f96cd4a4a1288" "aac9f003e201df5d" "0eece6ac0bf181b8"
+             "859bf769b6c8e454" "d8025b58b4c24502" "b765d45cdcaab647"
+             "6edd1f72466c2722", 16);
+
+  ASSERT (rsa_private_key_prepare(key));
+  ASSERT (pub->size == key->size);
+}
+
 void
 test_rsa_md5(struct rsa_public_key *pub,
             struct rsa_private_key *key,
index 97710fc93817bfebdbdd8c235dfb3a5c7778e0a8..c0366541d0a447cd2ddf532726350ff78b72cdfd 100644 (file)
@@ -227,6 +227,10 @@ void
 test_rsa_set_key_1(struct rsa_public_key *pub,
                   struct rsa_private_key *key);
 
+void
+test_rsa_set_key_2(struct rsa_public_key *pub,
+                  struct rsa_private_key *key);
+
 void
 test_rsa_md5(struct rsa_public_key *pub,
             struct rsa_private_key *key,