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 \
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 \
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
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}
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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
#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
#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
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 */
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
#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
/* 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. */
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
/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
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 \
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 \
--- /dev/null
+#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 ();
+}
--- /dev/null
+#! /bin/sh
+
+srcdir=`dirname $0`
+. "${srcdir}/sc-valgrind.sh"
+
+with_valgrind ./rsa-oaep-encrypt-test
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,
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,