summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-03-31 14:36:46 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-05-29 08:23:33 +0200
commitce703b76b5526815fc58f055bde16347a0ae931e (patch)
treec639ee91fe2b5688267040a22be990a49568be34
parente29327ac05a54bcd9085da5be4c5609f689ed08a (diff)
downloadgnutls-ce703b76b5526815fc58f055bde16347a0ae931e.tar.gz
build: import files from Nettle for RSA-PSS
Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--configure.ac8
-rw-r--r--lib/nettle/Makefile.am7
-rw-r--r--lib/nettle/int/pss-mgf1.c71
-rw-r--r--lib/nettle/int/pss-mgf1.h81
-rw-r--r--lib/nettle/int/pss.c200
-rw-r--r--lib/nettle/int/pss.h65
-rw-r--r--lib/nettle/int/rsa-pss-sha256-sign-tr.c64
-rw-r--r--lib/nettle/int/rsa-pss-sha256-verify.c60
-rw-r--r--lib/nettle/int/rsa-pss-sha512-sign-tr.c87
-rw-r--r--lib/nettle/int/rsa-pss-sha512-verify.c79
-rw-r--r--lib/nettle/int/rsa-pss.c15
-rw-r--r--lib/nettle/int/rsa-pss.h53
12 files changed, 790 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index e4f963a31f..10d26204b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -509,6 +509,14 @@ if test "$enable_non_suiteb" = "yes";then
fi
AM_CONDITIONAL(ENABLE_NON_SUITEB_CURVES, test "$enable_non_suiteb" = "yes")
+dnl nettle_rsa_pss_* are only available in the development version of nettle
+AC_CHECK_LIB(hogweed, nettle_rsa_pss_sha256_verify_digest, have_nettle_rsa_pss=yes, have_nettle_rsa_pss=no, [$HOGWEED_LIBS])
+
+if test "$have_nettle_rsa_pss" = "yes";then
+ AC_DEFINE([HAVE_NETTLE_RSA_PSS], 1, [Have nettle_rsa_pss_*])
+fi
+AM_CONDITIONAL(HAVE_NETTLE_RSA_PSS, test "$have_nettle_rsa_pss" = "yes")
+
AC_MSG_CHECKING([whether to build libdane])
AC_ARG_ENABLE(libdane,
AS_HELP_STRING([--disable-libdane],
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index 1cc251c84e..ea62926e72 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -56,3 +56,10 @@ if ENABLE_FIPS140
libcrypto_la_SOURCES += rnd-fips.c int/drbg-aes-self-test.c \
int/drbg-aes.c int/drbg-aes.h
endif
+
+if !HAVE_NETTLE_RSA_PSS
+libcrypto_la_SOURCES += int/pss-mgf1.c int/pss-mgf1.h int/pss.c int/pss.h \
+ int/rsa-pss.c int/rsa-pss.h \
+ int/rsa-pss-sha256-sign-tr.c int/rsa-pss-sha256-verify.c \
+ int/rsa-pss-sha512-sign-tr.c int/rsa-pss-sha512-verify.c
+endif
diff --git a/lib/nettle/int/pss-mgf1.c b/lib/nettle/int/pss-mgf1.c
new file mode 100644
index 0000000000..54d9cf1561
--- /dev/null
+++ b/lib/nettle/int/pss-mgf1.c
@@ -0,0 +1,71 @@
+/* pss-mgf1.c
+
+ PKCS#1 mask generation function 1, used in RSA-PSS (RFC-3447).
+
+ Copyright (C) 2017 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 "pss-mgf1.h"
+
+#include <string.h>
+
+#include <nettle/macros.h>
+
+void
+pss_mgf1(const void *seed, const struct nettle_hash *hash,
+ size_t length, uint8_t *mask)
+{
+ TMP_DECL(h, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
+ size_t i;
+ uint8_t c[4];
+
+ TMP_ALLOC(h, hash->digest_size);
+ TMP_ALLOC(state, hash->context_size);
+
+ for (i = 0; 1;
+ i++, mask += hash->digest_size, length -= hash->digest_size)
+ {
+ WRITE_UINT32(c, i);
+
+ memcpy(state, seed, hash->context_size);
+ hash->update(state, 4, c);
+
+ if (length <= hash->digest_size)
+ {
+ hash->digest(state, length, mask);
+ return;
+ }
+ hash->digest(state, hash->digest_size, mask);
+ }
+}
diff --git a/lib/nettle/int/pss-mgf1.h b/lib/nettle/int/pss-mgf1.h
new file mode 100644
index 0000000000..ab301e169f
--- /dev/null
+++ b/lib/nettle/int/pss-mgf1.h
@@ -0,0 +1,81 @@
+/* pss-mgf1.h
+
+ PKCS#1 mask generation function 1, used in RSA-PSS (RFC-3447).
+
+ Copyright (C) 2017 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_PSS_MGF1_H_INCLUDED
+#define NETTLE_PSS_MGF1_H_INCLUDED
+
+#include <nettle/nettle-meta.h>
+
+#include <nettle/sha1.h>
+#include <nettle/sha2.h>
+
+#include <alloca.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Temporary allocation, for systems that don't support alloca. Note
+ * that the allocation requests should always be reasonably small, so
+ * that they can fit on the stack. For non-alloca systems, we use a
+ * fix maximum size, and abort if we ever need anything larger. */
+
+#if HAVE_ALLOCA
+# define TMP_DECL(name, type, max) type *name
+# define TMP_ALLOC(name, size) (name = alloca(sizeof (*name) * (size)))
+#else /* !HAVE_ALLOCA */
+# define TMP_DECL(name, type, max) type name[max]
+# define TMP_ALLOC(name, size) \
+ do { if ((size) > (sizeof(name) / sizeof(name[0]))) abort(); } while (0)
+#endif
+
+/* Arbitrary limits which apply to systems that don't have alloca */
+#define NETTLE_MAX_HASH_BLOCK_SIZE 128
+#define NETTLE_MAX_HASH_DIGEST_SIZE 64
+#define NETTLE_MAX_HASH_CONTEXT_SIZE (sizeof(struct sha3_224_ctx))
+#define NETTLE_MAX_SEXP_ASSOC 17
+#define NETTLE_MAX_CIPHER_BLOCK_SIZE 32
+
+/* Namespace mangling */
+#define pss_mgf1 nettle_pss_mgf1
+
+void
+pss_mgf1(const void *seed, const struct nettle_hash *hash,
+ size_t length, uint8_t *mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_PSS_MGF1_H_INCLUDED */
diff --git a/lib/nettle/int/pss.c b/lib/nettle/int/pss.c
new file mode 100644
index 0000000000..ce2e72f662
--- /dev/null
+++ b/lib/nettle/int/pss.c
@@ -0,0 +1,200 @@
+/* pss.c
+
+ PKCS#1 RSA-PSS padding (RFC-3447).
+
+ Copyright (C) 2017 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 <string.h>
+
+#include "pss.h"
+#include "pss-mgf1.h"
+
+#include <nettle/bignum.h>
+
+#include <gnutls/gnutls.h>
+
+#define TMP_GMP_DECL(name, type) type *name
+#define TMP_GMP_ALLOC(name, size) do { \
+ (name) = gnutls_malloc(sizeof (*name) * (size)); \
+ } while (0)
+#define TMP_GMP_FREE(name) (gnutls_free(name))
+
+#include <nettle/memxor.h>
+
+/* Masks to clear the leftmost N bits. */
+static const uint8_t pss_masks[8] = {
+ 0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1
+};
+
+static const uint8_t pss_pad[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+/* Format the PKCS#1 PSS padding for given salt and digest, using
+ * pss_mgf1() as the mask generation function.
+ *
+ * The encoded messsage is stored in M, and the consistency can be
+ * checked with pss_verify_mgf1(), which takes the encoded message,
+ * the length of salt, and the digest. */
+int
+pss_encode_mgf1(mpz_t m, size_t bits,
+ const struct nettle_hash *hash,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest)
+{
+ TMP_GMP_DECL(em, uint8_t);
+ TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
+ size_t key_size = (bits + 7) / 8;
+ size_t j;
+
+ TMP_GMP_ALLOC(em, key_size);
+ TMP_ALLOC(state, hash->context_size);
+
+ if (key_size < hash->digest_size + salt_length + 2)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ /* Compute M'. */
+ hash->init(state);
+ hash->update(state, sizeof(pss_pad), pss_pad);
+ hash->update(state, hash->digest_size, digest);
+ hash->update(state, salt_length, salt);
+
+ /* Store H in EM, right after maskedDB. */
+ hash->digest(state, hash->digest_size, em + key_size - hash->digest_size - 1);
+
+ /* Compute dbMask. */
+ hash->init(state);
+ hash->update(state, hash->digest_size, em + key_size - hash->digest_size - 1);
+
+ pss_mgf1(state, hash, key_size - hash->digest_size - 1, em);
+
+ /* Compute maskedDB and store it in front of H in EM. */
+ j = key_size - salt_length - hash->digest_size - 2;
+
+ em[j++] ^= 1;
+ memxor(em + j, salt, salt_length);
+ j += salt_length;
+
+ /* Store the trailer field following H. */
+ j += hash->digest_size;
+ em[j] = 0xbc;
+
+ /* Clear the leftmost 8 * emLen - emBits of the leftmost octet in EM. */
+ *em &= pss_masks[(8 * key_size - bits)];
+
+ nettle_mpz_set_str_256_u(m, key_size, em);
+ TMP_GMP_FREE(em);
+ return 1;
+}
+
+/* Check the consistency of given PKCS#1 PSS encoded message, created
+ * with pss_encode_mgf1().
+ *
+ * Returns 1 if the encoded message is consistent, 0 if it is
+ * inconsistent. */
+int
+pss_verify_mgf1(const mpz_t m, size_t bits,
+ const struct nettle_hash *hash,
+ size_t salt_length,
+ const uint8_t *digest)
+{
+ TMP_GMP_DECL(em, uint8_t);
+ TMP_DECL(h2, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
+ uint8_t *h, *db, *salt;
+ size_t key_size = (bits + 7) / 8;
+ size_t j;
+ int ret = 0;
+
+ /* Allocate twice the key size to store the intermediate data DB
+ * following the EM value. */
+ TMP_GMP_ALLOC(em, key_size * 2);
+
+ TMP_ALLOC(h2, hash->digest_size);
+ TMP_ALLOC(state, hash->context_size);
+
+ if (key_size < hash->digest_size + salt_length + 2)
+ goto cleanup;
+
+ nettle_mpz_get_str_256(key_size, em, m);
+
+ /* Check the trailer field. */
+ if (em[key_size - 1] != 0xbc)
+ goto cleanup;
+
+ /* Extract H. */
+ h = em + (key_size - hash->digest_size - 1);
+
+ /* Check if the leftmost 8 * emLen - emBits bits of the leftmost
+ * octet of EM are all equal to zero. */
+ if ((*em & ~pss_masks[(8 * key_size - bits)]) != 0)
+ goto cleanup;
+
+ /* Compute dbMask. */
+ hash->init(state);
+ hash->update(state, hash->digest_size, h);
+
+ db = em + key_size;
+ pss_mgf1(state, hash, key_size - hash->digest_size - 1, db);
+
+ /* Compute DB. */
+ memxor(db, em, key_size - hash->digest_size - 1);
+
+ *db &= pss_masks[(8 * key_size - bits)];
+ for (j = 0; j < key_size - salt_length - hash->digest_size - 2; j++)
+ if (db[j] != 0)
+ goto cleanup;
+
+ /* Check the octet right after PS is 0x1. */
+ if (db[j] != 0x1)
+ goto cleanup;
+ salt = db + j + 1;
+
+ /* Compute H'. */
+ hash->init(state);
+ hash->update(state, sizeof(pss_pad), pss_pad);
+ hash->update(state, hash->digest_size, digest);
+ hash->update(state, salt_length, salt);
+ hash->digest(state, hash->digest_size, h2);
+
+ /* Check if H' = H. */
+ if (memcmp(h2, h, hash->digest_size) != 0)
+ goto cleanup;
+
+ ret = 1;
+ cleanup:
+ TMP_GMP_FREE(em);
+ return ret;
+}
diff --git a/lib/nettle/int/pss.h b/lib/nettle/int/pss.h
new file mode 100644
index 0000000000..4d1bf75f4f
--- /dev/null
+++ b/lib/nettle/int/pss.h
@@ -0,0 +1,65 @@
+/* pss.h
+
+ PKCS#1 RSA-PSS (RFC-3447).
+
+ Copyright (C) 2017 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_PSS_H_INCLUDED
+#define NETTLE_PSS_H_INCLUDED
+
+#include <nettle/nettle-types.h>
+#include <nettle/bignum.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define pss_encode_mgf1 nettle_pss_encode_mgf1
+#define pss_verify_mgf1 nettle_pss_verify_mgf1
+
+int
+pss_encode_mgf1(mpz_t m, size_t bits,
+ const struct nettle_hash *hash,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest);
+
+int
+pss_verify_mgf1(const mpz_t m, size_t bits,
+ const struct nettle_hash *hash,
+ size_t salt_length,
+ const uint8_t *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_PSS_H_INCLUDED */
diff --git a/lib/nettle/int/rsa-pss-sha256-sign-tr.c b/lib/nettle/int/rsa-pss-sha256-sign-tr.c
new file mode 100644
index 0000000000..c3f54dd47f
--- /dev/null
+++ b/lib/nettle/int/rsa-pss-sha256-sign-tr.c
@@ -0,0 +1,64 @@
+/* rsa-pss-sha256-sign-tr.c
+
+ Signatures using RSA and SHA-256, with PSS padding.
+
+ Copyright (C) 2017 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-pss.h"
+
+#include <nettle/bignum.h>
+#include "pss.h"
+
+int
+rsa_pss_sha256_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s)
+{
+ mpz_t m;
+ int res;
+
+ mpz_init (m);
+
+ res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha256,
+ salt_length, salt, digest)
+ && rsa_compute_root_tr (pub, key,
+ random_ctx, random,
+ s, m));
+
+ mpz_clear (m);
+ return res;
+}
diff --git a/lib/nettle/int/rsa-pss-sha256-verify.c b/lib/nettle/int/rsa-pss-sha256-verify.c
new file mode 100644
index 0000000000..5a117533b6
--- /dev/null
+++ b/lib/nettle/int/rsa-pss-sha256-verify.c
@@ -0,0 +1,60 @@
+/* rsa-pss-sha256-verify.c
+
+ Verifying signatures created with RSA and SHA-256, with PSS padding.
+
+ Copyright (C) 2017 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-pss.h"
+
+#include <nettle/bignum.h>
+#include "pss.h"
+
+int
+rsa_pss_sha256_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature)
+{
+ int res;
+ mpz_t m;
+
+ mpz_init (m);
+
+ res = (_rsa_verify_recover(key, m, signature) &&
+ pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha256,
+ salt_length, digest));
+
+ mpz_clear (m);
+ return res;
+}
diff --git a/lib/nettle/int/rsa-pss-sha512-sign-tr.c b/lib/nettle/int/rsa-pss-sha512-sign-tr.c
new file mode 100644
index 0000000000..6781ead22b
--- /dev/null
+++ b/lib/nettle/int/rsa-pss-sha512-sign-tr.c
@@ -0,0 +1,87 @@
+/* rsa-pss-sha512-sign-tr.c
+
+ Signatures using RSA and SHA-384/SHA-512, with PSS padding.
+
+ Copyright (C) 2017 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-pss.h"
+
+#include <nettle/bignum.h>
+#include "pss.h"
+
+int
+rsa_pss_sha384_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s)
+{
+ mpz_t m;
+ int res;
+
+ mpz_init (m);
+
+ res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha384,
+ salt_length, salt, digest)
+ && rsa_compute_root_tr (pub, key,
+ random_ctx, random,
+ s, m));
+
+ mpz_clear (m);
+ return res;
+}
+
+int
+rsa_pss_sha512_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s)
+{
+ mpz_t m;
+ int res;
+
+ mpz_init (m);
+
+ res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha512,
+ salt_length, salt, digest)
+ && rsa_compute_root_tr (pub, key,
+ random_ctx, random,
+ s, m));
+
+ mpz_clear (m);
+ return res;
+}
diff --git a/lib/nettle/int/rsa-pss-sha512-verify.c b/lib/nettle/int/rsa-pss-sha512-verify.c
new file mode 100644
index 0000000000..2380ba381d
--- /dev/null
+++ b/lib/nettle/int/rsa-pss-sha512-verify.c
@@ -0,0 +1,79 @@
+/* rsa-pss-sha512-verify.c
+
+ Verifying signatures created with RSA and SHA-384/SHA-512, with PSS padding.
+
+ Copyright (C) 2017 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-pss.h"
+
+#include <nettle/bignum.h>
+#include "pss.h"
+
+int
+rsa_pss_sha384_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature)
+{
+ int res;
+ mpz_t m;
+
+ mpz_init (m);
+
+ res = (_rsa_verify_recover(key, m, signature) &&
+ pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha384,
+ salt_length, digest));
+
+ mpz_clear (m);
+ return res;
+}
+
+int
+rsa_pss_sha512_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature)
+{
+ int res;
+ mpz_t m;
+
+ mpz_init (m);
+
+ res = (_rsa_verify_recover(key, m, signature) &&
+ pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha512,
+ salt_length, digest));
+
+ mpz_clear (m);
+ return res;
+}
diff --git a/lib/nettle/int/rsa-pss.c b/lib/nettle/int/rsa-pss.c
new file mode 100644
index 0000000000..76dd3441e3
--- /dev/null
+++ b/lib/nettle/int/rsa-pss.c
@@ -0,0 +1,15 @@
+#include "rsa-pss.h"
+
+int
+_rsa_verify_recover(const struct rsa_public_key *key,
+ mpz_t m,
+ const mpz_t s)
+{
+ if ( (mpz_sgn(s) <= 0)
+ || (mpz_cmp(s, key->n) >= 0) )
+ return 0;
+
+ mpz_powm(m, s, key->e, key->n);
+
+ return 1;
+}
diff --git a/lib/nettle/int/rsa-pss.h b/lib/nettle/int/rsa-pss.h
new file mode 100644
index 0000000000..8705e0912e
--- /dev/null
+++ b/lib/nettle/int/rsa-pss.h
@@ -0,0 +1,53 @@
+#ifndef RSA_PSS_H_INCLUDED
+#define RSA_PSS_H_INCLUDED
+
+#include <nettle/rsa.h>
+
+int
+rsa_pss_sha256_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s);
+
+int
+rsa_pss_sha256_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature);
+
+int
+rsa_pss_sha384_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s);
+
+int
+rsa_pss_sha384_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature);
+
+int
+rsa_pss_sha512_sign_digest_tr(const struct rsa_public_key *pub,
+ const struct rsa_private_key *key,
+ void *random_ctx, nettle_random_func *random,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest,
+ mpz_t s);
+
+int
+rsa_pss_sha512_verify_digest(const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature);
+
+int
+_rsa_verify_recover(const struct rsa_public_key *key,
+ mpz_t m,
+ const mpz_t s);
+
+#endif