From: Daiki Ueno <dueno(a)redhat.com>
Signed-off-by: Daiki Ueno <dueno(a)redhat.com>
---
There was an obvious buffer overrun in mgf1-test.c, which should be
fixed in this version.
---
Makefile.in | 5 +-
mgf1-sha256.c | 47 +++++++++++
mgf1-sha384.c | 47 +++++++++++
mgf1-sha512.c | 47 +++++++++++
mgf1.c | 72 +++++++++++++++++
mgf1.h | 70 ++++++++++++++++
nettle-types.h …
[View More] | 3 +
pss-sha256.c | 64 +++++++++++++++
pss-sha512.c | 90 +++++++++++++++++++++
pss.c | 195 +++++++++++++++++++++++++++++++++++++++++++++
pss.h | 105 ++++++++++++++++++++++++
testsuite/.test-rules.make | 6 ++
testsuite/Makefile.in | 4 +-
testsuite/mgf1-test.c | 23 ++++++
testsuite/pss-test.c | 35 ++++++++
15 files changed, 810 insertions(+), 3 deletions(-)
create mode 100644 mgf1-sha256.c
create mode 100644 mgf1-sha384.c
create mode 100644 mgf1-sha512.c
create mode 100644 mgf1.c
create mode 100644 mgf1.h
create mode 100644 pss-sha256.c
create mode 100644 pss-sha512.c
create mode 100644 pss.c
create mode 100644 pss.h
create mode 100644 testsuite/mgf1-test.c
create mode 100644 testsuite/pss-test.c
diff --git a/Makefile.in b/Makefile.in
index 135542f..035074c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -110,6 +110,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
md2.c md2-meta.c md4.c md4-meta.c \
md5.c md5-compress.c md5-compat.c md5-meta.c \
memeql-sec.c memxor.c memxor3.c \
+ mgf1.c mgf1-sha256.c mgf1-sha384.c mgf1-sha512.c \
nettle-meta-aeads.c nettle-meta-armors.c \
nettle-meta-ciphers.c nettle-meta-hashes.c \
pbkdf2.c pbkdf2-hmac-sha1.c pbkdf2-hmac-sha256.c \
@@ -144,6 +145,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
pkcs1.c pkcs1-encrypt.c pkcs1-decrypt.c \
pkcs1-rsa-digest.c pkcs1-rsa-md5.c pkcs1-rsa-sha1.c \
pkcs1-rsa-sha256.c pkcs1-rsa-sha512.c \
+ pss.c pss-sha256.c pss-sha512.c \
rsa.c rsa-sign.c rsa-sign-tr.c rsa-verify.c \
rsa-pkcs1-sign.c rsa-pkcs1-sign-tr.c rsa-pkcs1-verify.c \
rsa-md5-sign.c rsa-md5-sign-tr.c rsa-md5-verify.c \
@@ -194,9 +196,10 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
md2.h md4.h \
md5.h md5-compat.h \
memops.h memxor.h \
+ mgf1.h \
nettle-meta.h nettle-types.h \
pbkdf2.h \
- pgp.h pkcs1.h realloc.h ripemd160.h rsa.h \
+ pgp.h pkcs1.h pss.h realloc.h ripemd160.h rsa.h \
salsa20.h sexp.h \
serpent.h sha.h sha1.h sha2.h sha3.h twofish.h \
umac.h yarrow.h poly1305.h
diff --git a/mgf1-sha256.c b/mgf1-sha256.c
new file mode 100644
index 0000000..11e908c
--- /dev/null
+++ b/mgf1-sha256.c
@@ -0,0 +1,47 @@
+/* mgf1-sha256.c
+
+ PKCS#1 mask generation function 1, based on SHA-256.
+
+ 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 "mgf1.h"
+
+#include "nettle-meta.h"
+
+int
+mgf1_sha256(const struct sha256_ctx *hash, size_t mask_length, uint8_t *mask)
+{
+ struct sha256_ctx state;
+ return mgf1(hash, &state, &nettle_sha256, mask_length, mask);
+}
diff --git a/mgf1-sha384.c b/mgf1-sha384.c
new file mode 100644
index 0000000..5dd2b07
--- /dev/null
+++ b/mgf1-sha384.c
@@ -0,0 +1,47 @@
+/* mgf1-sha384.c
+
+ PKCS#1 mask generation function 1, based on SHA-384.
+
+ 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 "mgf1.h"
+
+#include "nettle-meta.h"
+
+int
+mgf1_sha384(const struct sha384_ctx *hash, size_t mask_length, uint8_t *mask)
+{
+ struct sha384_ctx state;
+ return mgf1(hash, &state, &nettle_sha384, mask_length, mask);
+}
diff --git a/mgf1-sha512.c b/mgf1-sha512.c
new file mode 100644
index 0000000..d1fba5f
--- /dev/null
+++ b/mgf1-sha512.c
@@ -0,0 +1,47 @@
+/* mgf1-sha512.c
+
+ PKCS#1 mask generation function 1, based on SHA-512.
+
+ 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 "mgf1.h"
+
+#include "nettle-meta.h"
+
+int
+mgf1_sha512(const struct sha512_ctx *hash, size_t mask_length, uint8_t *mask)
+{
+ struct sha512_ctx state;
+ return mgf1(hash, &state, &nettle_sha512, mask_length, mask);
+}
diff --git a/mgf1.c b/mgf1.c
new file mode 100644
index 0000000..a96b086
--- /dev/null
+++ b/mgf1.c
@@ -0,0 +1,72 @@
+/* mgf1.c
+
+ PKCS#1 mask generation function 1 (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 "mgf1.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "nettle-internal.h"
+
+#define MGF1_MIN(a,b) ((a) < (b) ? (a) : (b))
+
+int
+mgf1(void *seed, void *state, const struct nettle_hash *hash,
+ size_t mask_length, uint8_t *mask)
+{
+ TMP_DECL(h, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ size_t i, blocks;
+ uint8_t c[4], *p;
+
+ TMP_ALLOC(h, hash->digest_size);
+
+ blocks = (mask_length + hash->digest_size - 1) / hash->digest_size;
+ for (i = 0, p = mask; i < blocks; i++, p += hash->digest_size)
+ {
+ c[0] = (i >> 24) & 0xFF;
+ c[1] = (i >> 16) & 0xFF;
+ c[2] = (i >> 8) & 0xFF;
+ c[3] = i & 0xFF;
+
+ memcpy(state, seed, hash->context_size);
+ hash->update(state, 4, c);
+ hash->digest(state, hash->digest_size, h);
+ memcpy(p, h, MGF1_MIN(hash->digest_size, mask_length - (p - mask)));
+ }
+
+ return 1;
+}
diff --git a/mgf1.h b/mgf1.h
new file mode 100644
index 0000000..bbaffce
--- /dev/null
+++ b/mgf1.h
@@ -0,0 +1,70 @@
+/* mgf1.h
+
+ PKCS#1 mask generation function 1 (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_MGF1_H_INCLUDED
+#define NETTLE_MGF1_H_INCLUDED
+
+#include "nettle-meta.h"
+
+#include "sha1.h"
+#include "sha2.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define mgf1 nettle_mgf1
+#define mgf1_sha256 nettle_mgf1_sha256
+#define mgf1_sha384 nettle_mgf1_sha384
+#define mgf1_sha512 nettle_mgf1_sha512
+
+int
+mgf1(void *seed, void *state, const struct nettle_hash *hash,
+ size_t mask_length, uint8_t *mask);
+
+int
+mgf1_sha256(const struct sha256_ctx *hash, size_t mask_length, uint8_t *mask);
+
+int
+mgf1_sha384(const struct sha384_ctx *hash, size_t mask_length, uint8_t *mask);
+
+int
+mgf1_sha512(const struct sha512_ctx *hash, size_t mask_length, uint8_t *mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_MGF1_H_INCLUDED */
diff --git a/nettle-types.h b/nettle-types.h
index 475937d..b687958 100644
--- a/nettle-types.h
+++ b/nettle-types.h
@@ -103,6 +103,9 @@ typedef int nettle_armor_decode_update_func(void *ctx,
typedef int nettle_armor_decode_final_func(void *ctx);
+typedef int nettle_mgf_func(void *ctx, size_t mask_length, uint8_t *mask);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/pss-sha256.c b/pss-sha256.c
new file mode 100644
index 0000000..9c12037
--- /dev/null
+++ b/pss-sha256.c
@@ -0,0 +1,64 @@
+/* pss.c
+
+ PKCS#1 RSA-PSS padding, using SHA-256 (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.h"
+
+int
+pss_sha256_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest)
+{
+ struct sha256_ctx state;
+ return pss_encode(m, bits,
+ &state, &nettle_sha256,
+ (nettle_mgf_func *) mgf1_sha256,
+ salt_length, salt,
+ digest);
+}
+
+int
+pss_sha256_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest)
+{
+ struct sha256_ctx state;
+ return pss_verify(m, bits,
+ &state, &nettle_sha256,
+ (nettle_mgf_func *) mgf1_sha256,
+ salt_length,
+ digest);
+}
diff --git a/pss-sha512.c b/pss-sha512.c
new file mode 100644
index 0000000..e24b45d
--- /dev/null
+++ b/pss-sha512.c
@@ -0,0 +1,90 @@
+/* pss.c
+
+ PKCS#1 RSA-PSS padding, using SHA-384 and SHA-512 (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.h"
+
+int
+pss_sha384_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest)
+{
+ struct sha384_ctx state;
+ return pss_encode(m, bits,
+ &state, &nettle_sha384,
+ (nettle_mgf_func *) mgf1_sha384,
+ salt_length, salt,
+ digest);
+}
+
+int
+pss_sha384_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest)
+{
+ struct sha384_ctx state;
+ return pss_verify(m, bits,
+ &state, &nettle_sha384,
+ (nettle_mgf_func *) mgf1_sha384,
+ salt_length,
+ digest);
+}
+
+int
+pss_sha512_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest)
+{
+ struct sha512_ctx state;
+ return pss_encode(m, bits,
+ &state, &nettle_sha512,
+ (nettle_mgf_func *) mgf1_sha512,
+ salt_length, salt,
+ digest);
+}
+
+int
+pss_sha512_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest)
+{
+ struct sha512_ctx state;
+ return pss_verify(m, bits,
+ &state, &nettle_sha512,
+ (nettle_mgf_func *) mgf1_sha512,
+ salt_length,
+ digest);
+}
diff --git a/pss.c b/pss.c
new file mode 100644
index 0000000..5dd23a7
--- /dev/null
+++ b/pss.c
@@ -0,0 +1,195 @@
+/* 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 <assert.h>
+#include <string.h>
+
+#include "pss.h"
+
+#include "bignum.h"
+#include "gmp-glue.h"
+
+#include "memxor.h"
+#include "nettle-internal.h"
+
+static const uint8_t pss_masks[8] = {
+ 0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1
+};
+
+int
+pss_encode(mpz_t m, size_t bits,
+ void *state, const struct nettle_hash *hash,
+ nettle_mgf_func mgf,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest)
+{
+ TMP_GMP_DECL(em, uint8_t);
+ uint8_t pad[8];
+ size_t key_size = (bits + 7) / 8;
+ size_t j;
+
+ TMP_GMP_ALLOC(em, key_size);
+
+ if (key_size < hash->digest_size + salt_length + 2)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ /* Compute M'. */
+ hash->init(state);
+ memset(pad, 0, 8);
+ hash->update(state, 8, 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);
+
+ mgf(state, key_size - hash->digest_size - 1, em);
+
+ /* Compute maskedDB and store it in front of H in EM. */
+ for (j = 0; j < key_size - salt_length - hash->digest_size - 2; j++)
+ em[j] ^= 0;
+ 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;
+}
+
+int
+pss_verify(mpz_t m, size_t bits,
+ void *state, const struct nettle_hash *hash,
+ nettle_mgf_func mgf,
+ size_t salt_length,
+ const uint8_t *digest)
+{
+ TMP_GMP_DECL(em, uint8_t);
+ TMP_DECL(h2, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ uint8_t pad[8], *h, *db, *salt;
+ size_t key_size = (bits + 7) / 8;
+ size_t j;
+
+ /* 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);
+
+ if (key_size < hash->digest_size + salt_length + 2)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ nettle_mpz_get_str_256(key_size, em, m);
+
+ /* Check the trailer field. */
+ if (em[key_size - 1] != 0xbc)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ /* 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)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ /* Compute dbMask. */
+ hash->init(state);
+ hash->update(state, hash->digest_size, h);
+
+ db = em + key_size;
+ mgf(state, 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) {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ /* Check the octet right after PS is 0x1. */
+ if (db[j] != 0x1)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+ salt = db + j + 1;
+
+ /* Compute H'. */
+ memset(pad, 0, 8);
+ hash->init(state);
+ hash->update(state, 8, 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)
+ {
+ TMP_GMP_FREE(em);
+ return 0;
+ }
+
+ TMP_GMP_FREE(em);
+ return 1;
+}
diff --git a/pss.h b/pss.h
new file mode 100644
index 0000000..1ebe1eb
--- /dev/null
+++ b/pss.h
@@ -0,0 +1,105 @@
+/* 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-types.h"
+#include "bignum.h"
+
+#include "mgf1.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define pss_encode nettle_pss_encode
+#define pss_verify nettle_pss_verify
+#define pss_sha256_encode nettle_pss_sha256_encode
+#define pss_sha256_verify nettle_pss_sha256_verify
+#define pss_sha384_encode nettle_pss_sha384_encode
+#define pss_sha384_verify nettle_pss_sha384_verify
+#define pss_sha512_encode nettle_pss_sha512_encode
+#define pss_sha512_verify nettle_pss_sha512_verify
+
+int
+pss_encode(mpz_t m, size_t bits,
+ void *state, const struct nettle_hash *hash,
+ nettle_mgf_func mgf,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest);
+
+int
+pss_verify(mpz_t m, size_t bits,
+ void *state, const struct nettle_hash *hash,
+ nettle_mgf_func mgf,
+ size_t salt_length,
+ const uint8_t *digest);
+
+int
+pss_sha256_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest);
+
+int
+pss_sha256_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest);
+
+int
+pss_sha384_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest);
+
+int
+pss_sha384_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest);
+
+int
+pss_sha512_encode(mpz_t m, size_t bits,
+ size_t salt_length, const uint8_t *salt,
+ const uint8_t *digest);
+
+int
+pss_sha512_verify(mpz_t m, size_t bits,
+ size_t salt_length,
+ const uint8_t *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_PSS_H_INCLUDED */
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index b263e1f..2b4499f 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -157,6 +157,9 @@ yarrow-test$(EXEEXT): yarrow-test.$(OBJEXT)
pbkdf2-test$(EXEEXT): pbkdf2-test.$(OBJEXT)
$(LINK) pbkdf2-test.$(OBJEXT) $(TEST_OBJS) -o pbkdf2-test$(EXEEXT)
+mgf1-test$(EXEEXT): mgf1-test.$(OBJEXT)
+ $(LINK) mgf1-test.$(OBJEXT) $(TEST_OBJS) -o mgf1-test$(EXEEXT)
+
sexp-test$(EXEEXT): sexp-test.$(OBJEXT)
$(LINK) sexp-test.$(OBJEXT) $(TEST_OBJS) -o sexp-test$(EXEEXT)
@@ -178,6 +181,9 @@ random-prime-test$(EXEEXT): random-prime-test.$(OBJEXT)
pkcs1-test$(EXEEXT): pkcs1-test.$(OBJEXT)
$(LINK) pkcs1-test.$(OBJEXT) $(TEST_OBJS) -o pkcs1-test$(EXEEXT)
+pss-test$(EXEEXT): pss-test.$(OBJEXT)
+ $(LINK) pss-test.$(OBJEXT) $(TEST_OBJS) -o pss-test$(EXEEXT)
+
rsa-sign-tr-test$(EXEEXT): rsa-sign-tr-test.$(OBJEXT)
$(LINK) rsa-sign-tr-test.$(OBJEXT) $(TEST_OBJS) -o rsa-sign-tr-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 689d432..4a9604f 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -30,12 +30,12 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
hmac-test.c umac-test.c \
meta-hash-test.c meta-cipher-test.c\
meta-aead-test.c meta-armor-test.c \
- buffer-test.c yarrow-test.c pbkdf2-test.c
+ buffer-test.c yarrow-test.c pbkdf2-test.c mgf1-test.c
TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
rsa2sexp-test.c sexp2rsa-test.c \
bignum-test.c random-prime-test.c \
- pkcs1-test.c rsa-sign-tr-test.c \
+ pkcs1-test.c pss-test.c rsa-sign-tr-test.c \
rsa-test.c rsa-encrypt-test.c rsa-keygen-test.c \
dsa-test.c dsa-keygen-test.c \
curve25519-dh-test.c \
diff --git a/testsuite/mgf1-test.c b/testsuite/mgf1-test.c
new file mode 100644
index 0000000..967be07
--- /dev/null
+++ b/testsuite/mgf1-test.c
@@ -0,0 +1,23 @@
+#include "testutils.h"
+#include "mgf1.h"
+
+void
+test_main(void)
+{
+ struct sha256_ctx hash;
+ struct tstring *expected;
+ uint8_t mask[120];
+ int ret;
+
+ expected = SHEX("cf2db1ac9867debdf8ce91f99f141e5544bf26ca36b3fd4f8e4035"
+ "eec42cab0d46c386ebccef82ba0bb0b095aaa5548b03cdff695187"
+ "1c6fb505af68af688332f885d324a47d2145a3d8392c37978d7dc9"
+ "84c95728950c4cf3de6becc59e60ea506951bd40e6de3863095064"
+ "3ab2edbb47dc66cb54beb2d1");
+
+ sha256_init(&hash);
+ sha256_update(&hash, 3, "abc");
+ ret = mgf1_sha256(&hash, 120, mask);
+ ASSERT(ret == 1);
+ ASSERT(MEMEQ (120, mask, expected->data));
+}
diff --git a/testsuite/pss-test.c b/testsuite/pss-test.c
new file mode 100644
index 0000000..2d53e03
--- /dev/null
+++ b/testsuite/pss-test.c
@@ -0,0 +1,35 @@
+#include "testutils.h"
+
+#include "pss.h"
+
+void
+test_main(void)
+{
+ struct tstring *salt;
+ struct tstring *digest;
+ mpz_t m;
+ mpz_t expected;
+ int ret;
+
+ mpz_init(m);
+ mpz_init(expected);
+
+ salt = SHEX("11223344556677889900");
+ /* From sha256-test.c */
+ digest = SHEX("ba7816bf8f01cfea 414140de5dae2223"
+ "b00361a396177a9c b410ff61f20015ad");
+ ret = pss_sha256_encode(m, 1024, salt->length, salt->data, digest->data);
+ ASSERT(ret == 1);
+
+ mpz_set_str(expected,
+ "76b9a52705c8382c5367732f993184eff340b6305c9f73e7e308c8"
+ "004fcc15cbbaab01e976bae4b774628595379a2d448a36b3ea6fa8"
+ "353b97eeea7bdac93b4b7807ac98cd4b3bebfb31f3718e1dd3625f"
+ "227fbb8696606498e7070e21c3cbbd7386ea20eb81ac7927e0c6d1"
+ "d7788826a63af767f301bcc05dd65b00da862cbc", 16);
+
+ ASSERT(mpz_cmp(m, expected) == 0);
+
+ ret = pss_sha256_verify(m, 1024, salt->length, digest->data);
+ ASSERT(ret == 1);
+}
--
2.9.3
[View Less]
Hi,
The attached patch set introduces new APIs to access the TLS 1.0 and
1.2 PRFs as well as the HKDF (rfc5869) function used in TLS 1.3.
There are few other updates to .gitlab-ci.yml (to use a more recent
asan and ubsan versions), and a comment in .bootstrap for the
testsuite/.test-rules.make which I always seem to forget and spend an
hour figuring out what is going on. Ideally .test-rules.make should
depend on Makefile.in so that one wouldn't need to manually run test-
rules.
I'd also …
[View More]suggest to rename the .bootstrap to bootstrap.sh as the latter
is quite a convention to find in projects (.bootstrap is not even
listed in ls).
regards,
Nikos
[View Less]
GMP's mpn_mul_n must never take overlapping source and
destination buffers as the implementation makes a few
passes over source while updating destination at each
pass:
```
https://gmplib.org/manual/Low_002dlevel-Functions.html#Low_002dlevel-Functi…
Function: void mpn_mul_n (mp_limb_t *rp,
const mp_limb_t *s1p,
const mp_limb_t *s2p,
mp_size_t n)
Multiply {s1p, n} and {s2p, n}, and write the 2*n-limb …
[View More]result to rp.
The destination has to have space for 2*n limbs,
even if the product’s most significant limb is zero.
No overlap is permitted between the destination and
either source.
```
Violation of this invariant make nettle to compute
curve25519 incorrectly at least on sparc and hppa
architectures, see https://bugs.gentoo.org/613418
for some details.
The overlap happens in `ecc-add-eh.c` where layout
of local GMP variables on scratch space is the
following:
```
|x1|y1|z1|........|B|
|x3|y3|z3|...
```
x1/x3, y1/y3, z1/z3 pairs share the same memory region.
Overlap happens at a call of
```
ecc_modp_mul (ecc, y3, B, z1);
```
which is basically
```
mpn_mul_n (y3, B, z1, m->size),
```
Note how y3 overwrites z1. This is scary type of aliasing.
The bug manifested in testsuite failure in nettle and gnutls.
I've trailed the bug down to faulty function by adding printf()
and comparing exact output of scratch space on x86 versus sparc.
`mpn_mul_n` on the same source numbers produces different results.
This change does not fix the underlying overlap but exposes the
problem on all architectures and crashes the testsuitewith asset().
Reported-by: Matt Turner
Bug: https://bugs.gentoo.org/613418
Signed-off-by: Sergei Trofimovich <slyfox(a)gentoo.org>
---
ecc-mod-arith.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/ecc-mod-arith.c b/ecc-mod-arith.c
index f2e47f67..735b1238 100644
--- a/ecc-mod-arith.c
+++ b/ecc-mod-arith.c
@@ -109,11 +109,23 @@ ecc_mod_submul_1 (const struct ecc_modulo *m, mp_limb_t *rp,
assert (hi == 0);
}
+static int no_overlap(const mp_limb_t * a, size_t la,
+ const mp_limb_t * b, size_t lb)
+{
+ if (a < b)
+ return (size_t)(b - a) >= la;
+ /* a >= b */
+ return (size_t)(a - b) >= lb;
+}
+
/* NOTE: mul and sqr needs 2*m->size limbs at rp */
void
ecc_mod_mul (const struct ecc_modulo *m, mp_limb_t *rp,
const mp_limb_t *ap, const mp_limb_t *bp)
{
+ /* NOTE: mpn_mul_n does not work correctly when source and destination overlap */
+ assert (no_overlap (rp, 2 * m->size, ap, m->size));
+ assert (no_overlap (rp, 2 * m->size, bp, m->size));
mpn_mul_n (rp, ap, bp, m->size);
m->reduce (m, rp);
}
--
2.13.3
[View Less]