summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2017-10-23 22:25:58 +0200
committerNiels Möller <nisse@lysator.liu.se>2017-10-23 22:25:58 +0200
commit61460b2e8edda447a40fb1264cb1327114ea61d3 (patch)
tree206ba0138631e83f9cfdeab9f5458c286a71801d
parent54e1450a0ebdd24cdf6234741e5275bb3d83ebda (diff)
parentf1366bc97b8cd93f4797ee42fcfafd5584d038df (diff)
downloadnettle-61460b2e8edda447a40fb1264cb1327114ea61d3.tar.gz
Merge remote-tracking branch 'origin/master' into api-opaque
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml47
-rw-r--r--CONTRIBUTING.md21
-rw-r--r--ChangeLog214
-rw-r--r--Makefile.in27
-rw-r--r--README2
-rw-r--r--aclocal.m42
-rw-r--r--aes-set-key-internal.c2
-rw-r--r--arm/ecc-521-modp.asm2
-rw-r--r--base16-decode.c10
-rw-r--r--base16-encode.c4
-rw-r--r--base16-meta.c4
-rw-r--r--base16.h8
-rw-r--r--base64-decode.c6
-rw-r--r--base64-encode.c18
-rw-r--r--base64.h20
-rw-r--r--base64url-encode.c2
-rw-r--r--cfb.c165
-rw-r--r--cfb.h87
-rw-r--r--config.make.in2
-rw-r--r--configure.ac15
-rw-r--r--ecc-add-eh.c4
-rw-r--r--ecc-mod-inv.c1
-rw-r--r--ecc-mod.c8
-rw-r--r--ecc.h4
-rw-r--r--eccdata.c23
-rw-r--r--ecdsa-verify.c4
-rw-r--r--examples/base16dec.c2
-rw-r--r--examples/base16enc.c2
-rw-r--r--examples/base64dec.c2
-rw-r--r--examples/base64enc.c2
-rw-r--r--examples/hogweed-benchmark.c5
-rw-r--r--examples/nettle-benchmark.c4
-rw-r--r--examples/nettle-openssl.c274
-rw-r--r--fat-arm.c2
-rw-r--r--hkdf.c84
-rw-r--r--hkdf.h67
-rw-r--r--mini-gmp.c360
-rw-r--r--mini-gmp.h6
-rw-r--r--misc/plan.html62
-rw-r--r--nettle-internal.h2
-rw-r--r--nettle-types.h6
-rw-r--r--nettle.texinfo192
-rw-r--r--pgp-encode.c10
-rw-r--r--pss-mgf1.c73
-rw-r--r--pss-mgf1.h58
-rw-r--r--pss.c198
-rw-r--r--pss.h65
-rw-r--r--rsa-pss-sha256-sign-tr.c64
-rw-r--r--rsa-pss-sha256-verify.c60
-rw-r--r--rsa-pss-sha512-sign-tr.c87
-rw-r--r--rsa-pss-sha512-verify.c79
-rw-r--r--rsa-verify.c14
-rw-r--r--rsa.h55
-rw-r--r--sexp-transport-format.c9
-rw-r--r--sexp-transport.c2
-rw-r--r--testsuite/.gitignore25
-rw-r--r--testsuite/.test-rules.make15
-rw-r--r--testsuite/Makefile.in18
-rw-r--r--testsuite/base64-test.c20
-rw-r--r--testsuite/cfb-test.c287
-rw-r--r--testsuite/dlopen-test.c1
-rw-r--r--testsuite/ecc-mul-a-test.c2
-rw-r--r--testsuite/ecc-mul-g-test.c2
-rw-r--r--testsuite/hkdf-test.c143
-rw-r--r--testsuite/meta-hash-test.c10
-rw-r--r--testsuite/pss-mgf1-test.c36
-rw-r--r--testsuite/pss-test.c86
-rw-r--r--testsuite/rsa-pss-sign-tr-test.c356
-rw-r--r--testsuite/test-rules.stamp1
-rw-r--r--testsuite/testutils.c183
-rw-r--r--testsuite/testutils.h30
-rw-r--r--tools/input.c2
-rw-r--r--tools/nettle-hash.c6
-rw-r--r--tools/nettle-pbkdf2.c8
-rw-r--r--tools/output.c6
-rw-r--r--tools/pkcs1-conv.c13
77 files changed, 3299 insertions, 500 deletions
diff --git a/.gitignore b/.gitignore
index 1f3b92b9..830ba678 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,7 @@ core
/ecc-384.h
/ecc-521.h
/ecc-25519.h
+/version.h
/nettle.aux
/nettle.cp
/nettle.cps
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f8394163..6cfc1dcb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,27 +4,40 @@ before_script:
- yum install -y git make autoconf libtool automake gettext-devel glibc-devel gcc valgrind libasan-static libgcc.i686 glibc-devel.i686
# See http://doc.gitlab.com/ce/ci/yaml/ for documentation.
-Build and Check (x86-64):
+build/x86-64:
script:
- yum install -y gmp-devel
- ./.bootstrap &&
- ./configure --disable-documentation && make -j4 &&
+ ./configure --enable-fat --disable-documentation && make -j4 &&
make check -j4
tags:
- shared
except:
- tags
-Build and Check (x86):
+build/x86:
script:
- yum install -y gmp-devel.i686
- ./.bootstrap &&
- PKG_CONFIG_PATH="/usr/lib/pkgconfig/" CFLAGS="-O2 -g -m32" LDFLAGS="-m32" ./configure --build=i686-redhat-linux --disable-documentation && make -j4 &&
+ PKG_CONFIG_PATH="/usr/lib/pkgconfig/" CFLAGS="-O2 -g -m32" LDFLAGS="-m32" ./configure --build=i686-redhat-linux --enable-fat --disable-documentation && make -j4 &&
make check -j4
tags:
- shared
except:
- tags
-Build and Check with mini-gmp:
+build/aarch64:
+ before_script:
+ - /bin/true
+ script:
+ - ./.bootstrap &&
+ ./configure --enable-fat --disable-documentation && make -j4 &&
+ make check -j4
+ tags:
+ - aarch64
+ only:
+ - branches@gnutls/nettle
+ except:
+ - tags
+build/mini-gmp:
script:
- ./.bootstrap &&
./configure --disable-documentation --enable-mini-gmp && make -j4 &&
@@ -33,8 +46,8 @@ Build and Check with mini-gmp:
- shared
except:
- tags
-Build and Check with ubsan:
- image: fedora:24
+build/ubsan:
+ image: fedora:26
script:
- yum install -y gmp-devel libubsan-static libubsan
- ./.bootstrap &&
@@ -44,7 +57,8 @@ Build and Check with ubsan:
- shared
except:
- tags
-Build and Check with asan:
+build/asan:
+ image: fedora:26
script:
- yum install -y gmp-devel
- ./.bootstrap &&
@@ -54,3 +68,20 @@ Build and Check with asan:
- shared
except:
- tags
+build/static-analyzers:
+ image: fedora:26
+ script:
+ - yum install -y gmp-devel clang compiler-rt cppcheck clang-analyzer
+ - ./.bootstrap
+ - scan-build ./configure --disable-documentation
+ - scan-build --status-bugs -o scan-build-lib make -j$(nproc)
+ tags:
+ - shared
+ except:
+ - tags
+ artifacts:
+ expire_in: 1 week
+ when: on_failure
+ paths:
+ - scan-build-lib/*
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..92200abc
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,21 @@
+# nettle -- Information about our contribution rules
+
+# Test suite:
+
+ New functionality should be accompanied by a test case which verifies
+its correctness, on successful use of the new functionality, as well as on
+failure cases. The nettle test suite is run on "make check".
+
+# Continuous Integration (CI)
+
+We utilize a continuous integration systems, using gitlab-ci.
+
+This is run on a repository mirror at:
+https://gitlab.com/gnutls/nettle
+
+# Sending patches
+
+Please do not utilize the gitlab web interfaces. They are not
+being followed on. Please send your patches to nettle-bugs@lists.lysator.liu.se
+
+
diff --git a/ChangeLog b/ChangeLog
index cf37b0b1..0b98d741 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,6 +44,220 @@
(nettle_hashes): ... old name.
(nettle_get_hashes): New function.
+2017-10-16 Niels Möller <nisse@lysator.liu.se>
+
+ CFB support, contributed by Dmitry Eremin-Solenikov.
+ * cfb.c (cfb_encrypt, cfb_decrypt): New file, new functions.
+ * cfb.h: New header file.
+ (CFB_CTX, CFB_SET_IV, CFB_ENCRYPT, CFB_DECRYPT): New macros.
+ * Makefile.in (nettle_SOURCES): Add cfb.c.
+ (HEADERS): Add cfb.h.
+ * testsuite/cfb-test.c: New test case.
+ * testsuite/testutils.c (test_cipher_cfb): New function.
+ * nettle.texinfo (CFB): Documentation.
+
+2017-10-16 Niels Möller <nisse@lysator.liu.se>
+
+ * aclocal.m4 (GMP_PROG_CC_FOR_BUILD): Add -g when compiling with
+ gcc.
+
+2017-09-24 Niels Möller <nisse@lysator.liu.se>
+
+ * tools/pkcs1-conv.c (base64_decode_in_place): New helper
+ function.
+ (decode_base64): Use it.
+
+ * sexp-transport-format.c (base64_encode_in_place): New helper
+ function.
+ (sexp_transport_vformat): Use it.
+
+ * testsuite/base64-test.c (test_fuzz_once): Update to use char
+ type where appropriate.
+ (test_main): Use helper functions base64_encode_in_place and
+ base64_decode_in_place (copied to this file).
+
+ * testsuite/testutils.c (tstring_data): Use uint8_t for data
+ argument.
+ * testsuite/testutils.h (SDATA): Use US macro to cast data
+ argument.
+
+2017-09-14 Niels Möller <nisse@lysator.liu.se>
+
+ * hkdf.c: Delete unneeded includes. Use Nettle licensing notice.
+ * hkdf.h: Include only nettle-types.h, not nettle-meta.h.
+
+ * ecc-mod.c (ecc_mod): Workaround to silence a false positive from
+ the clang static analyzer.
+
+2017-09-12 Niels Möller <nisse@lysator.liu.se>
+
+ * testsuite/testutils.h (mpn_zero_p): Avoid redefining mpn_zero_p
+ when building with mini-gmp. Since the mini-gmp update, this
+ function is defined by mini-gmp, causing link errors if nettle is
+ configured with --enable-mini-gmp --disable-shared. Reported by
+ Tim Rühsen.
+
+2017-09-09 Daiki Ueno <dueno@redhat.com>
+
+ * testsuite/ecc-mul-g-test.c (test_main): Fixed mpn_cmp call.
+ * testsuite/ecc-mul-a-test.c (test_main): Likewise.
+ * eccdata.c (ecc_point_out): Write to given stream, instead of
+ stderr.
+ * eccdata.c (output_curve): In curve448, the bit size of the order
+ is slightly smaller than the one of p's. Adjust ecc_Bmodq_shifted
+ accordingly.
+
+2017-09-09 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c: Updated mini-gmp from the gmp repository, latest
+ change from 2017-07-23.
+ * mini-gmp.h: Likewise.
+
+2017-09-06 Niels Möller <nisse@lysator.liu.se>
+
+ * hkdf.c (hkdf_expand): Eliminate a (signed) ssize_t variable, use
+ break rather than return at loop termination.
+
+2017-09-06 Niels Möller <nisse@lysator.liu.se>
+
+ HKDF implementation, contributed by Nikos Mavrogiannopoulos.
+ * hkdf.c (hkdf_extract, hkdf_expand): New file, new functions.
+ * hkdf.h: New file.
+ * Makefile.in (nettle_SOURCES): Add hkdf.c.
+ (HEADERS): Add hkdf.h.
+ * testsuite/hkdf-test.c: Tests for hkdf-sha256 and hkdf-sha1.
+ * testsuite/Makefile.in (TS_NETTLE_SOURCES): Added hkdf-test.c.
+ * nettle.texinfo (Key derivation functions): Document HKDF.
+
+2017-09-04 Andreas Schneider <asn@samba.org>
+
+ * fat-arm.c: Add missing define for _GNU_SOURCE.
+
+2017-08-27 Niels Möller <nisse@lysator.liu.se>
+
+ * configure.ac (GMP_NUMB_BITS): Set to dummy value "n/a" in
+ mini-gmp builds.
+ (NUMB_BITS): New substituted variable which always holds the
+ configured value.
+ * Makefile.in (GMP_NUMB_BITS): Renamed variable...
+ (NUMB_BITS): ...new name
+ * config.make.in: Update corresponding substitution.
+
+2017-08-26 Niels Möller <nisse@lysator.liu.se>
+
+ * ecc-mod-inv.c (ecc_mod_inv): Add missing assert. Fixes a
+ "dead increment" warning from the clang static analyzer.
+
+2017-08-26 Niels Möller <nisse@lysator.liu.se>
+
+ * examples/nettle-openssl.c (struct openssl_cipher_ctx): New
+ struct. Use everywhere, instead of typing EVP_CIPHER_CTX pointers
+ directly.
+
+ * configure.ac: Update openssl-related tests. Checks for
+ cipher-specific headers are replaced by a check for openssl/evp.h,
+ and the check for the BF_ecb_encrypt function is replaced by a
+ check for EVP_CIPHER_CTX_new.
+
+2017-08-03 Daniel P. Berrange <berrange@redhat.com>
+
+ * examples/nettle-openssl.c: Rewritten to use openssl's EVP APIs.
+ The older cipher-specific functions always use openssl's generic
+ software implementation, while the EVP functions enables
+ platform-specific code, e.g., using the x86 AES-NI instructions.
+ (nettle_openssl_init): New function.
+
+2017-07-18 Niels Möller <nisse@lysator.liu.se>
+
+ * ecc-add-eh.c (ecc_add_eh): Fix in-place operation by reordering
+ two multiplies. Previously, in-place operation resulted in an
+ invalid call to mpn_mul with overlapping operands. Reported by
+ Sergei Trofimovich.
+
+2017-06-09 Niels Möller <nisse@lysator.liu.se>
+
+ * pss.c (pss_verify_mgf1): Check for m being too large, fixing an
+ assertion failure for certain invalid signatures. Based on a patch
+ contributed by Daiki Ueno.
+
+ * testsuite/rsa-pss-sign-tr-test.c (test_main): Add test case
+ contributed by Daiki Ueno. Problem originally found by oss-fuzz,
+ see https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2132.
+ That problem report is currently embargoed, but will hopefully be
+ public in a month or two.
+
+2017-05-23 Niels Möller <nisse@lysator.liu.se>
+
+ Rework the previous change, which had the unintended effect of
+ always regenerating .test-rules.make after ./configure is run.
+ * testsuite/Makefile.in (test-rules.stamp): New stamp file target,
+ depend on Makefile.in, and run $(MAKE) test-rules.
+ (.test-rules.make): Add a level of indirection, by depending on
+ test-rules.stamp.
+
+2017-05-20 Niels Möller <nisse@lysator.liu.se>
+
+ * testsuite/Makefile.in (test-rules): Use $(srddir)/-prefix for
+ .test-rules.make target, and change dependency from Makefile.in to
+ Makefile.
+
+2017-05-17 Nikos Mavrogiannopoulos <nmav@redhat.com>
+
+ * testsuite/Makefile.in: Ensure .test-rules.make is regenerated
+ when Makefile.in is modified.
+
+2017-04-09 Niels Möller <nisse@lysator.liu.se>
+
+ * testsuite/dlopen-test.c (main): Call dlclose, to fix memory leak
+ on success.
+
+ * testsuite/pss-test.c: Delete magic to let valgrind to check if
+ pss_encode_mgf1 is side-channel silent with respect to the salt
+ and digest inputs. It turns out that the most significant bits of
+ the padded bignum, and hence its size, depends on these inputs.
+ Which results in a data-dependent branch in the normalization code
+ of at the end of gmp's mpz_import.
+
+2017-04-04 Niels Möller <nisse@lysator.liu.se>
+
+ * pss.c (pss_verify_mgf1): Use const for input mpz_t argument.
+ (pss_encode_mgf1): Avoid unnecessary memset and xor operations.
+
+ Merged RSA-PSS support, contributed by Daiki Ueno.
+ * pss-mgf1.h, pss.h: New header files.
+ * pss-mgf1.c (pss_mgf1): New file and function.
+ * pss.c (pss_encode_mgf1, pss_verify_mgf1): New file and
+ functions.
+ * rsa-verify.c (_rsa_verify_recover): New function.
+ * rsa-pss-sha256-sign-tr.c: (rsa_pss_sha256_sign_digest_tr): New
+ file and function.
+ * rsa-pss-sha256-verify.c (rsa_pss_sha256_verify_digest): New
+ file and function.
+ * rsa-pss-sha512-sign-tr.c (rsa_pss_sha384_sign_digest_tr)
+ (rsa_pss_sha512_sign_digest_tr): New file and functions.
+ * rsa-pss-sha512-verify.c (rsa_pss_sha384_verify_digest)
+ (rsa_pss_sha512_verify_digest): New file and functions.
+ * rsa.h: Prototypes for new functions.
+ * testsuite/rsa-pss-sign-tr-test.c: New test case.
+ * testsuite/pss-test.c: New test case.
+ * testsuite/pss-mgf1-test.c: New test case.
+ * Makefile.in, testsuite/Makefile.in: Added new files.
+ * nettle.texinfo: Documentation of rsa-pss functions.
+
+2017-03-20 Niels Möller <nisse@lysator.liu.se>
+
+ * nettle-internal.h (NETTLE_MAX_HASH_CONTEXT_SIZE): New constant.
+ * testsuite/meta-hash-test.c (test_main): Add sanity check for
+ NETTLE_MAX_HASH_CONTEXT_SIZE.
+
+ * tools/nettle-hash.c (list_algorithms): Also display the internal
+ context size.
+
+2017-01-03 Nikos Mavrogiannopoulos <nmav@redhat.com>
+
+ * ecdsa-verify.c (ecdsa_verify): Eliminated memory leak on error
+ path.
+
2016-10-10 Niels Möller <nisse@lysator.liu.se>
* write-be32.c (_nettle_write_be32): Use const for source argument.
diff --git a/Makefile.in b/Makefile.in
index 52886622..6a0c13ec 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -91,7 +91,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
camellia256-set-decrypt-key.c \
camellia256-meta.c \
cast128.c cast128-meta.c cbc.c \
- ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c \
+ ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
chacha-set-key.c chacha-set-nonce.c \
@@ -106,7 +106,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
gosthash94.c gosthash94-meta.c \
hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
- knuth-lfib.c \
+ knuth-lfib.c hkdf.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 \
@@ -145,12 +145,15 @@ 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-mgf1.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 \
rsa-sha1-sign.c rsa-sha1-sign-tr.c rsa-sha1-verify.c \
rsa-sha256-sign.c rsa-sha256-sign-tr.c rsa-sha256-verify.c \
rsa-sha512-sign.c rsa-sha512-sign-tr.c rsa-sha512-verify.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-decrypt-tr.c \
rsa-keygen.c rsa-blind.c \
rsa2sexp.c sexp2rsa.c \
@@ -186,18 +189,18 @@ OPT_SOURCES = fat-x86_64.c fat-arm.c mini-gmp.c
HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
base16.h base64.h bignum.h buffer.h camellia.h cast128.h \
- cbc.h ccm.h chacha.h chacha-poly1305.h ctr.h \
+ cbc.h ccm.h cfb.h chacha.h chacha-poly1305.h ctr.h \
curve25519.h des.h des-compat.h dsa.h dsa-compat.h eax.h \
ecc-curve.h ecc.h ecdsa.h eddsa.h \
gcm.h gosthash94.h hmac.h \
- knuth-lfib.h \
+ knuth-lfib.h hkdf.h \
macros.h \
md2.h md4.h \
md5.h md5-compat.h \
memops.h memxor.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 pss-mgf1.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
@@ -218,7 +221,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
libnettle.map.in libhogweed.map.in \
config.guess config.sub install-sh texinfo.tex \
config.h.in config.m4.in config.make.in Makefile.in \
- README AUTHORS COPYING.LESSERv3 COPYINGv2 COPYINGv3 \
+ README CONTRIBUTING.md AUTHORS COPYING.LESSERv3 COPYINGv2 COPYINGv3 \
INSTALL NEWS TODO ChangeLog \
nettle.pc.in hogweed.pc.in \
$(des_headers) descore.README \
@@ -324,7 +327,7 @@ des.$(OBJEXT): des.c des.h $(des_headers)
# k = 7, c = 6, 320 entries, ~15 KB
# k = 9, c = 7, 512 entries, ~24 KB
ecc-192.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 192 7 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 192 7 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some possible choices for 224:
# k = 18, c = 4, 64 entries, ~4 KB
# k = 24, c = 6, 128 entries, ~8 KB
@@ -332,7 +335,7 @@ ecc-192.h: eccdata.stamp
# k = 8, c = 6, 320 entries, ~20 KB
# k = 10, c = 7, 512 entries, ~32 KB
ecc-224.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 224 12 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 224 12 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some possible choices for 256:
# k = 20, c = 4, 64 entries, ~4 KB
# k = 27, c = 6, 128 entries, ~8 KB
@@ -340,7 +343,7 @@ ecc-224.h: eccdata.stamp
# k = 9, c = 6, 320 entries, ~20 KB
# k = 12, c = 7, 512 entries, ~32 KB
ecc-256.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 256 14 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 256 14 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some possible choices for 384:
# k = 31, c = 4, 64 entries, ~6 KB
# k = 41, c = 6, 128 entries, ~12 KB
@@ -348,7 +351,7 @@ ecc-256.h: eccdata.stamp
# k = 14, c = 6, 320 entries, ~30 KB
# k = 18, c = 7, 512 entries, ~48 KB
ecc-384.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 384 41 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 384 41 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some possible choices for 521:
# k = 42, c = 4, 64 entries, ~9 KB
# k = 56, c = 6, 128 entries, ~18 KB
@@ -356,10 +359,10 @@ ecc-384.h: eccdata.stamp
# k = 19, c = 6, 320 entries, ~44 KB
# k = 24, c = 7, 512 entries, ~70 KB
ecc-521.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 521 56 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 521 56 6 $(NUMB_BITS) > $@T && mv $@T $@
ecc-25519.h: eccdata.stamp
- ./eccdata$(EXEEXT_FOR_BUILD) 255 14 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@
+ ./eccdata$(EXEEXT_FOR_BUILD) 255 14 6 $(NUMB_BITS) > $@T && mv $@T $@
eccdata.stamp: eccdata.c
$(MAKE) eccdata$(EXEEXT_FOR_BUILD)
diff --git a/README b/README
index ca873a3f..8355739b 100644
--- a/README
+++ b/README
@@ -42,6 +42,8 @@ Read the manual. Mail me if you have any questions or suggestions.
You may want to subscribe to the nettle-bugs mailing list. See
<URL: http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs>.
+See CONTRIBUTING.md for information on contibuting patches.
+
Happy hacking,
/Niels Möller <nisse@lysator.liu.se>
diff --git a/aclocal.m4 b/aclocal.m4
index debcf9c7..783dbc49 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -526,7 +526,7 @@ else
fi
fi
if test "$CC_FOR_BUILD" = gcc ; then
- CC_FOR_BUILD="$CC_FOR_BUILD -O"
+ CC_FOR_BUILD="$CC_FOR_BUILD -O -g"
fi
fi
diff --git a/aes-set-key-internal.c b/aes-set-key-internal.c
index 9b515bfd..88728d85 100644
--- a/aes-set-key-internal.c
+++ b/aes-set-key-internal.c
@@ -39,6 +39,7 @@
#endif
#include "aes-internal.h"
+#include <assert.h>
#include "macros.h"
void
@@ -52,6 +53,7 @@ _aes_set_key(unsigned nr, unsigned nk,
unsigned lastkey, i;
uint32_t t;
+ assert(nk != 0);
lastkey = (AES_BLOCK_SIZE/4) * (nr + 1);
for (i=0, rp = rcon; i<nk; i++)
diff --git a/arm/ecc-521-modp.asm b/arm/ecc-521-modp.asm
index c311a891..3fba2396 100644
--- a/arm/ecc-521-modp.asm
+++ b/arm/ecc-521-modp.asm
@@ -91,7 +91,7 @@ PROLOGUE(nettle_ecc_521_modp)
adcs F0, F0, F3, lsr #9
C Copy low 9 bits to H, then shift right including carry
and H, F0, T0
- rrx F0, F0
+ mov F0, F0, rrx
lsr F0, F0, #8
C Add in F1 = rp[33], with weight 2^1056 = 2^14
adds F0, F0, F1, lsl #14
diff --git a/base16-decode.c b/base16-decode.c
index 28acc404..fc331236 100644
--- a/base16-decode.c
+++ b/base16-decode.c
@@ -66,14 +66,16 @@ hex_decode_table[0x80] =
int
base16_decode_single(struct base16_decode_ctx *ctx,
uint8_t *dst,
- uint8_t src)
+ char src)
{
+ /* Avoid signed char for indexing. */
+ unsigned char usrc = src;
int digit;
- if (src >= 0x80)
+ if (usrc >= 0x80)
return -1;
- digit = hex_decode_table[src];
+ digit = hex_decode_table[usrc];
switch (digit)
{
case -1:
@@ -104,7 +106,7 @@ base16_decode_update(struct base16_decode_ctx *ctx,
size_t *dst_length,
uint8_t *dst,
size_t src_length,
- const uint8_t *src)
+ const char *src)
{
size_t done;
size_t i;
diff --git a/base16-encode.c b/base16-encode.c
index 297491ad..9c7f0b1e 100644
--- a/base16-encode.c
+++ b/base16-encode.c
@@ -45,7 +45,7 @@ hex_digits[16] = "0123456789abcdef";
/* Encodes a single byte. Always stores two digits in dst[0] and dst[1]. */
void
-base16_encode_single(uint8_t *dst,
+base16_encode_single(char *dst,
uint8_t src)
{
dst[0] = DIGIT(src/0x10);
@@ -54,7 +54,7 @@ base16_encode_single(uint8_t *dst,
/* Always stores BASE16_ENCODE_LENGTH(length) digits in dst. */
void
-base16_encode_update(uint8_t *dst,
+base16_encode_update(char *dst,
size_t length,
const uint8_t *src)
{
diff --git a/base16-meta.c b/base16-meta.c
index a2a10906..a7789c50 100644
--- a/base16-meta.c
+++ b/base16-meta.c
@@ -59,7 +59,7 @@ base16_encode_init(void *ctx UNUSED)
static nettle_armor_encode_update_func base16_encode_update_wrapper;
static size_t
-base16_encode_update_wrapper(void *ctx UNUSED, uint8_t *dst,
+base16_encode_update_wrapper(void *ctx UNUSED, char *dst,
size_t length, const uint8_t *src)
{
base16_encode_update(dst, length, src);
@@ -71,7 +71,7 @@ base16_encode_update_wrapper(void *ctx UNUSED, uint8_t *dst,
static nettle_armor_encode_final_func base16_encode_final;
static size_t
-base16_encode_final(void *ctx UNUSED, uint8_t *dst UNUSED)
+base16_encode_final(void *ctx UNUSED, char *dst UNUSED)
{
return 0;
}
diff --git a/base16.h b/base16.h
index 2579c0ef..755e6ed3 100644
--- a/base16.h
+++ b/base16.h
@@ -56,12 +56,12 @@ extern "C" {
/* Encodes a single byte. Always stores two digits in dst[0] and dst[1]. */
void
-base16_encode_single(uint8_t *dst,
+base16_encode_single(char *dst,
uint8_t src);
/* Always stores BASE16_ENCODE_LENGTH(length) digits in dst. */
void
-base16_encode_update(uint8_t *dst,
+base16_encode_update(char *dst,
size_t length,
const uint8_t *src);
@@ -86,7 +86,7 @@ base16_decode_init(struct base16_decode_ctx *ctx);
int
base16_decode_single(struct base16_decode_ctx *ctx,
uint8_t *dst,
- uint8_t src);
+ char src);
/* Returns 1 on success, 0 on error. DST should point to an area of
* size at least BASE16_DECODE_LENGTH(length). The amount of data
@@ -97,7 +97,7 @@ base16_decode_update(struct base16_decode_ctx *ctx,
size_t *dst_length,
uint8_t *dst,
size_t src_length,
- const uint8_t *src);
+ const char *src);
/* Returns 1 on success. */
int
diff --git a/base64-decode.c b/base64-decode.c
index 337ea395..b993117a 100644
--- a/base64-decode.c
+++ b/base64-decode.c
@@ -73,9 +73,9 @@ base64_decode_init(struct base64_decode_ctx *ctx)
int
base64_decode_single(struct base64_decode_ctx *ctx,
uint8_t *dst,
- uint8_t src)
+ char src)
{
- int data = ctx->table[src];
+ int data = ctx->table[(uint8_t) src];
switch(data)
{
@@ -122,7 +122,7 @@ base64_decode_update(struct base64_decode_ctx *ctx,
size_t *dst_length,
uint8_t *dst,
size_t src_length,
- const uint8_t *src)
+ const char *src)
{
size_t done;
size_t i;
diff --git a/base64-encode.c b/base64-encode.c
index f23115a9..42fa016d 100644
--- a/base64-encode.c
+++ b/base64-encode.c
@@ -41,11 +41,11 @@
#define ENCODE(alphabet,x) ((alphabet)[0x3F & (x)])
static void
-encode_raw(const uint8_t *alphabet,
- uint8_t *dst, size_t length, const uint8_t *src)
+encode_raw(const char *alphabet,
+ char *dst, size_t length, const uint8_t *src)
{
const uint8_t *in = src + length;
- uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
+ char *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
unsigned left_over = length % 3;
@@ -83,19 +83,19 @@ encode_raw(const uint8_t *alphabet,
assert(out == dst);
}
-static const uint8_t base64_encode_table[64] =
+static const char base64_encode_table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
void
-base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src)
+base64_encode_raw(char *dst, size_t length, const uint8_t *src)
{
encode_raw(base64_encode_table, dst, length, src);
}
void
-base64_encode_group(uint8_t *dst, uint32_t group)
+base64_encode_group(char *dst, uint32_t group)
{
*dst++ = ENCODE(base64_encode_table, (group >> 18));
*dst++ = ENCODE(base64_encode_table, (group >> 12));
@@ -113,7 +113,7 @@ base64_encode_init(struct base64_encode_ctx *ctx)
/* Encodes a single byte. */
size_t
base64_encode_single(struct base64_encode_ctx *ctx,
- uint8_t *dst,
+ char *dst,
uint8_t src)
{
unsigned done = 0;
@@ -138,7 +138,7 @@ base64_encode_single(struct base64_encode_ctx *ctx,
* area of size at least BASE64_ENCODE_LENGTH(length). */
size_t
base64_encode_update(struct base64_encode_ctx *ctx,
- uint8_t *dst,
+ char *dst,
size_t length,
const uint8_t *src)
{
@@ -181,7 +181,7 @@ base64_encode_update(struct base64_encode_ctx *ctx,
* BASE64_ENCODE_FINAL_SIZE */
size_t
base64_encode_final(struct base64_encode_ctx *ctx,
- uint8_t *dst)
+ char *dst)
{
unsigned done = 0;
unsigned bits = ctx->bits;
diff --git a/base64.h b/base64.h
index 79194bd4..8e69adb1 100644
--- a/base64.h
+++ b/base64.h
@@ -73,7 +73,7 @@ extern "C" {
struct base64_encode_ctx
{
- const uint8_t *alphabet; /* Alphabet to use for encoding */
+ const char *alphabet; /* Alphabet to use for encoding */
unsigned short word; /* Leftover bits */
unsigned char bits; /* Number of bits, always 0, 2, or 4. */
};
@@ -89,14 +89,14 @@ base64url_encode_init(struct base64_encode_ctx *ctx);
/* Encodes a single byte. Returns amount of output (always 1 or 2). */
size_t
base64_encode_single(struct base64_encode_ctx *ctx,
- uint8_t *dst,
+ char *dst,
uint8_t src);
/* Returns the number of output characters. DST should point to an
* area of size at least BASE64_ENCODE_LENGTH(length). */
size_t
base64_encode_update(struct base64_encode_ctx *ctx,
- uint8_t *dst,
+ char *dst,
size_t length,
const uint8_t *src);
@@ -104,18 +104,20 @@ base64_encode_update(struct base64_encode_ctx *ctx,
* BASE64_ENCODE_FINAL_LENGTH */
size_t
base64_encode_final(struct base64_encode_ctx *ctx,
- uint8_t *dst);
+ char *dst);
/* Lower level functions */
/* Encodes a string in one go, including any padding at the end.
* Generates exactly BASE64_ENCODE_RAW_LENGTH(length) bytes of output.
- * Supports overlapped operation, if src <= dst. */
+ * Supports overlapped operation, if src <= dst. FIXME: Use of overlap
+ * is deprecated, if needed there should be a separate public fucntion
+ * to do that.*/
void
-base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src);
+base64_encode_raw(char *dst, size_t length, const uint8_t *src);
void
-base64_encode_group(uint8_t *dst, uint32_t group);
+base64_encode_group(char *dst, uint32_t group);
/* Base64 decoding */
@@ -147,7 +149,7 @@ base64url_decode_init(struct base64_decode_ctx *ctx);
int
base64_decode_single(struct base64_decode_ctx *ctx,
uint8_t *dst,
- uint8_t src);
+ char src);
/* Returns 1 on success, 0 on error. DST should point to an area of
* size at least BASE64_DECODE_LENGTH(length). The amount of data
@@ -157,7 +159,7 @@ base64_decode_update(struct base64_decode_ctx *ctx,
size_t *dst_length,
uint8_t *dst,
size_t src_length,
- const uint8_t *src);
+ const char *src);
/* Returns 1 on success. */
int
diff --git a/base64url-encode.c b/base64url-encode.c
index 6af33fb8..d30044ea 100644
--- a/base64url-encode.c
+++ b/base64url-encode.c
@@ -38,7 +38,7 @@
void
base64url_encode_init(struct base64_encode_ctx *ctx)
{
- static const uint8_t base64url_encode_table[64] =
+ static const char base64url_encode_table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-_";
diff --git a/cfb.c b/cfb.c
new file mode 100644
index 00000000..82cf18f4
--- /dev/null
+++ b/cfb.c
@@ -0,0 +1,165 @@
+/* cfb.c
+
+ Cipher feedback mode.
+
+ Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov
+ Copyright (C) 2001, 2011 Niels Möller
+
+ 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 <stdlib.h>
+#include <string.h>
+
+#include "cfb.h"
+
+#include "memxor.h"
+#include "nettle-internal.h"
+
+void
+cfb_encrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src)
+{
+ uint8_t *p;
+ TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
+
+ TMP_ALLOC(buffer, block_size);
+
+ if (src != dst)
+ {
+ for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
+ {
+ f(ctx, block_size, dst, p);
+ memxor(dst, src, block_size);
+ }
+ }
+ else
+ {
+ for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
+ {
+ f(ctx, block_size, buffer, p);
+ memxor(dst, buffer, block_size);
+ }
+ }
+
+ if (p != iv)
+ memcpy(iv, p, block_size);
+
+ if (length)
+ {
+ f(ctx, block_size, buffer, iv);
+ memxor3(dst, buffer, src, length);
+ /* We do not care about updating IV here. This is the last call in
+ * message sequence and one has to set IV afterwards anyway */
+ }
+}
+
+/* Don't allocate any more space than this on the stack */
+#define CFB_BUFFER_LIMIT 512
+
+void
+cfb_decrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src)
+{
+ if (src != dst)
+ {
+ size_t left = length % block_size;
+
+ length -= left;
+ if (length > 0)
+ {
+ /* Decrypt in ECB mode */
+ f(ctx, block_size, dst, iv);
+ f(ctx, length - block_size, dst + block_size, src);
+ memcpy(iv, src + length - block_size, block_size);
+ memxor(dst, src, length);
+ }
+
+ if (left > 0)
+ {
+ TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
+ TMP_ALLOC(buffer, block_size);
+
+ f(ctx, block_size, buffer, iv);
+ memxor3(dst + length, src + length, buffer, left);
+ }
+ }
+ else
+ {
+ /* For in-place CFB, we decrypt into a temporary buffer of size
+ * at most CFB_BUFFER_LIMIT, and process that amount of data at
+ * a time. */
+
+ /* NOTE: We assume that block_size <= CFB_BUFFER_LIMIT */
+
+ TMP_DECL(buffer, uint8_t, CFB_BUFFER_LIMIT);
+ TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
+
+ size_t buffer_size;
+ size_t left;
+
+ buffer_size = CFB_BUFFER_LIMIT - (CFB_BUFFER_LIMIT % block_size);
+
+ TMP_ALLOC(buffer, buffer_size);
+ TMP_ALLOC(initial_iv, block_size);
+
+ left = length % block_size;
+ length -= left;
+
+ while (length > 0)
+ {
+ size_t part = length > buffer_size ? buffer_size : length;
+
+ /* length is greater that zero and is divided by block_size, so it is
+ * not less than block_size. So does part */
+
+ f(ctx, block_size, buffer, iv);
+ f(ctx, part - block_size, buffer + block_size, src);
+ memcpy(iv, src + part - block_size, block_size);
+ memxor(dst, buffer, part);
+
+ length -= part;
+ src += part;
+ dst += part;
+ }
+
+ if (left > 0)
+ {
+ f(ctx, block_size, buffer, iv);
+ memxor(dst, buffer, left);
+ }
+ }
+}
diff --git a/cfb.h b/cfb.h
new file mode 100644
index 00000000..16660df9
--- /dev/null
+++ b/cfb.h
@@ -0,0 +1,87 @@
+/* cfb.h
+
+ Cipher feedback mode.
+
+ Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov
+ Copyright (C) 2001 Niels Möller
+
+ 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_CFB_H_INCLUDED
+#define NETTLE_CFB_H_INCLUDED
+
+#include "nettle-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name mangling */
+#define cfb_encrypt nettle_cfb_encrypt
+#define cfb_decrypt nettle_cfb_decrypt
+
+void
+cfb_encrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src);
+
+void
+cfb_decrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src);
+
+#define CFB_CTX(type, size) \
+{ type ctx; uint8_t iv[size]; }
+
+#define CFB_SET_IV(ctx, data) \
+memcpy((ctx)->iv, (data), sizeof((ctx)->iv))
+
+/* NOTE: Avoid using NULL, as we don't include anything defining it. */
+#define CFB_ENCRYPT(self, f, length, dst, src) \
+ (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0)) \
+ : cfb_encrypt((void *) &(self)->ctx, \
+ (nettle_cipher_func *) (f), \
+ sizeof((self)->iv), (self)->iv, \
+ (length), (dst), (src)))
+
+#define CFB_DECRYPT(self, f, length, dst, src) \
+ (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0)) \
+ : cfb_decrypt((void *) &(self)->ctx, \
+ (nettle_cipher_func *) (f), \
+ sizeof((self)->iv), (self)->iv, \
+ (length), (dst), (src)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_CFB_H_INCLUDED */
diff --git a/config.make.in b/config.make.in
index 2981379a..af2068ce 100644
--- a/config.make.in
+++ b/config.make.in
@@ -46,7 +46,7 @@ LIBHOGWEED_FORLINK = @LIBHOGWEED_FORLINK@
LIBHOGWEED_LIBS = @LIBHOGWEED_LIBS@
LIBHOGWEED_LINK = @LIBHOGWEED_LINK@
-GMP_NUMB_BITS = @GMP_NUMB_BITS@
+NUMB_BITS = @NUMB_BITS@
AR = @AR@
ARFLAGS = cru
diff --git a/configure.ac b/configure.ac
index 1d1951b5..45ef50e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -185,7 +185,7 @@ AC_HEADER_TIME
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(size_t)
-AC_CHECK_HEADERS([openssl/blowfish.h openssl/des.h openssl/cast.h openssl/aes.h openssl/ecdsa.h],,
+AC_CHECK_HEADERS([openssl/evp.h openssl/ecdsa.h],,
[enable_openssl=no
break])
@@ -268,7 +268,16 @@ if test "x$enable_public_key" = "xyes" ; then
fi
fi
-GMP_NUMB_BITS="$nettle_cv_gmp_numb_bits"
+# Substituted in Makefile, passed on to the eccdata command.
+NUMB_BITS="$nettle_cv_gmp_numb_bits"
+AC_SUBST([NUMB_BITS])
+
+# Substituted in version.h, used only with mini-gmp.
+if test "x$enable_mini_gmp" = "xyes" ; then
+ GMP_NUMB_BITS="$NUMB_BITS"
+else
+ GMP_NUMB_BITS="n/a"
+fi
AC_SUBST([GMP_NUMB_BITS])
# Figure out ABI. Currently, configurable only by setting CFLAGS.
@@ -876,7 +885,7 @@ OPENSSL_LIBFLAGS=''
# Check for openssl's libcrypto (used only for benchmarking)
if test x$enable_openssl = xyes ; then
- AC_CHECK_LIB(crypto, BF_ecb_encrypt,
+ AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_new,
[OPENSSL_LIBFLAGS='-lcrypto'],
[enable_openssl=no])
fi
diff --git a/ecc-add-eh.c b/ecc-add-eh.c
index a16be4cb..c07ff49a 100644
--- a/ecc-add-eh.c
+++ b/ecc-add-eh.c
@@ -98,8 +98,8 @@ ecc_add_eh (const struct ecc_curve *ecc,
ecc_modp_mul (ecc, x3, B, z1);
/* y3 */
- ecc_modp_mul (ecc, B, F, C); /* ! */
- ecc_modp_mul (ecc, y3, B, z1);
+ ecc_modp_mul (ecc, B, F, z1); /* ! */
+ ecc_modp_mul (ecc, y3, B, C); /* Clobbers z1 in case r == p. */
/* z3 */
ecc_modp_mul (ecc, B, F, G);
diff --git a/ecc-mod-inv.c b/ecc-mod-inv.c
index f65c9da4..8cfd2e3b 100644
--- a/ecc-mod-inv.c
+++ b/ecc-mod-inv.c
@@ -145,6 +145,7 @@ ecc_mod_inv (const struct ecc_modulo *m,
cnd_swap (swap, up, vp, n);
cy = cnd_sub_n (odd, up, vp, n);
cy -= cnd_add_n (cy, up, m->m, n);
+ assert (cy == 0);
cy = mpn_rshift (ap, ap, n, 1);
assert (cy == 0);
diff --git a/ecc-mod.c b/ecc-mod.c
index 5fee4c68..4e77f0c0 100644
--- a/ecc-mod.c
+++ b/ecc-mod.c
@@ -51,7 +51,7 @@ ecc_mod (const struct ecc_modulo *m, mp_limb_t *rp)
mp_size_t i;
unsigned shift;
- assert (sn > 0);
+ assert (bn < mn);
/* FIXME: Could use mpn_addmul_2. */
/* Eliminate sn limbs at a time */
@@ -72,6 +72,12 @@ ecc_mod (const struct ecc_modulo *m, mp_limb_t *rp)
}
else
{
+ /* The loop below always runs at least once. But the analyzer
+ doesn't realize that, and complains about hi being used later
+ on without a well defined value. */
+#ifdef __clang_analyzer__
+ hi = 0;
+#endif
while (rn >= 2 * mn - bn)
{
rn -= sn;
diff --git a/ecc.h b/ecc.h
index c67ccdc3..93fc9e87 100644
--- a/ecc.h
+++ b/ecc.h
@@ -121,8 +121,8 @@ ecc_point_mul_g (struct ecc_point *r, const struct ecc_scalar *n);
/* Points on a curve are represented as arrays of mp_limb_t, with
curve-specific representation. For the secp curves, we use Jacobian
- coordinates (possibly in Montgomery for for mod multiplication).
- For curve25519 we use homogeneous coordiantes on an equivalent
+ coordinates (possibly in Montgomery form for mod multiplication).
+ For curve25519 we use homogeneous coordinates on an equivalent
Edwards curve. The suffix "_h" denotes this internal
representation.
diff --git a/eccdata.c b/eccdata.c
index 9533d783..97a61941 100644
--- a/eccdata.c
+++ b/eccdata.c
@@ -694,11 +694,11 @@ ecc_point_out (FILE *f, const struct ecc_point *p)
fprintf (f, "zero");
else
{
- fprintf (stderr, "(");
- mpz_out_str (stderr, 16, p->x);
- fprintf (stderr, ",\n ");
- mpz_out_str (stderr, 16, (p)->y);
- fprintf (stderr, ")");
+ fprintf (f, "(");
+ mpz_out_str (f, 16, p->x);
+ fprintf (f, ",\n ");
+ mpz_out_str (f, 16, (p)->y);
+ fprintf (f, ")");
}
}
#define ASSERT_EQUAL(p, q) do { \
@@ -1014,16 +1014,19 @@ output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb)
exit (EXIT_FAILURE);
}
}
+ }
+ else
+ printf ("#define ecc_Bmodp_shifted ecc_Bmodp\n");
+
+ if (bits < limb_size * bits_per_limb)
+ {
mpz_set_ui (t, 0);
- mpz_setbit (t, ecc->bit_size);
+ mpz_setbit (t, bits);
mpz_sub (t, t, ecc->q);
output_bignum ("ecc_Bmodq_shifted", t, limb_size, bits_per_limb);
}
else
- {
- printf ("#define ecc_Bmodp_shifted ecc_Bmodp\n");
- printf ("#define ecc_Bmodq_shifted ecc_Bmodq\n");
- }
+ printf ("#define ecc_Bmodq_shifted ecc_Bmodq\n");
mpz_add_ui (t, ecc->p, 1);
mpz_fdiv_q_2exp (t, t, 1);
diff --git a/ecdsa-verify.c b/ecdsa-verify.c
index 05c174ec..ab8e19f3 100644
--- a/ecdsa-verify.c
+++ b/ecdsa-verify.c
@@ -52,7 +52,7 @@ ecdsa_verify (const struct ecc_point *pub,
/* For ECC_MUL_A_WBITS == 0, at most 1512 bytes. With
ECC_MUL_A_WBITS == 4, currently needs 67 * ecc->size, at most
4824 bytes. Don't use stack allocation for this. */
- mp_limb_t *scratch = gmp_alloc_limbs (itch);
+ mp_limb_t *scratch;
int res;
#define rp scratch
@@ -62,6 +62,8 @@ ecdsa_verify (const struct ecc_point *pub,
if (mpz_sgn (signature->r) <= 0 || mpz_size (signature->r) > size
|| mpz_sgn (signature->s) <= 0 || mpz_size (signature->s) > size)
return 0;
+
+ scratch = gmp_alloc_limbs (itch);
mpz_limbs_copy (rp, signature->r, size);
mpz_limbs_copy (sp, signature->s, size);
diff --git a/examples/base16dec.c b/examples/base16dec.c
index 70714567..1185b3e1 100644
--- a/examples/base16dec.c
+++ b/examples/base16dec.c
@@ -58,7 +58,7 @@ int
main(int argc UNUSED, char **argv UNUSED)
{
/* "buffer" will hold the bytes from disk: */
- uint8_t * buffer = xalloc (CHUNK_SIZE);
+ char * buffer = xalloc (CHUNK_SIZE);
/* "result" will hold bytes before output: */
uint8_t * result = xalloc (DECODED_SIZE);
diff --git a/examples/base16enc.c b/examples/base16enc.c
index 02e4f280..6ac08e1d 100644
--- a/examples/base16enc.c
+++ b/examples/base16enc.c
@@ -70,7 +70,7 @@ main(int argc UNUSED, char **argv UNUSED)
/* "buffer" will hold the bytes from disk: */
uint8_t buffer[CHUNK_SIZE];
/* "result" will hold bytes before output: */
- uint8_t result[ENCODED_SIZE + 1];
+ char result[ENCODED_SIZE + 1];
unsigned nbytes; /* Number of bytes read from stdin */
int encoded_bytes; /* Total number of bytes encoded per iteration */
diff --git a/examples/base64dec.c b/examples/base64dec.c
index 624de628..d05d924a 100644
--- a/examples/base64dec.c
+++ b/examples/base64dec.c
@@ -58,7 +58,7 @@ int
main(int argc UNUSED, char **argv UNUSED)
{
/* "buffer" will hold the bytes from disk: */
- uint8_t * buffer = xalloc (CHUNK_SIZE);
+ char * buffer = xalloc (CHUNK_SIZE);
/* "result" will hold bytes before output: */
uint8_t * result = xalloc (DECODED_SIZE);
diff --git a/examples/base64enc.c b/examples/base64enc.c
index f8ba829b..cc6010cc 100644
--- a/examples/base64enc.c
+++ b/examples/base64enc.c
@@ -72,7 +72,7 @@ main(int argc UNUSED, char **argv UNUSED)
/* "buffer" will hold the bytes from disk: */
uint8_t buffer[CHUNK_SIZE];
/* "result" is the result vector: */
- uint8_t result[ENCODED_SIZE + BASE64_ENCODE_FINAL_LENGTH + 1];
+ char result[ENCODED_SIZE + BASE64_ENCODE_FINAL_LENGTH + 1];
unsigned nbytes; /* Number of bytes read from stdin */
int encoded_bytes; /* total number of bytes encoded per iteration */
nbytes = fread(buffer,1,CHUNK_SIZE,stdin);
diff --git a/examples/hogweed-benchmark.c b/examples/hogweed-benchmark.c
index 3fabe207..ebce9034 100644
--- a/examples/hogweed-benchmark.c
+++ b/examples/hogweed-benchmark.c
@@ -612,7 +612,10 @@ bench_openssl_ecdsa_init (unsigned size)
/* This curve isn't supported in this build of openssl */
if (ctx->key == NULL)
- return NULL;
+ {
+ free(ctx);
+ return NULL;
+ }
if (!EC_KEY_generate_key( ctx->key))
die ("Openssl EC_KEY_generate_key failed.\n");
diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c
index c00486cc..11f62709 100644
--- a/examples/nettle-benchmark.c
+++ b/examples/nettle-benchmark.c
@@ -723,6 +723,10 @@ main(int argc, char **argv)
int c;
const char *alg;
+#if WITH_OPENSSL
+ nettle_openssl_init();
+#endif
+
const struct nettle_hash *hashes[] =
{
&nettle_md2, &nettle_md4, &nettle_md5,
diff --git a/examples/nettle-openssl.c b/examples/nettle-openssl.c
index 86c5321c..b549ba54 100644
--- a/examples/nettle-openssl.c
+++ b/examples/nettle-openssl.c
@@ -2,7 +2,8 @@
Glue that's used only by the benchmark, and subject to change.
- Copyright (C) 2002 Niels Möller
+ Copyright (C) 2002, 2017 Niels Möller
+ Copyright (C) 2017 Red Hat, Inc.
This file is part of GNU Nettle.
@@ -45,17 +46,69 @@
#include <assert.h>
-#include <openssl/aes.h>
-#include <openssl/blowfish.h>
-#include <openssl/des.h>
-#include <openssl/cast.h>
-#include <openssl/rc4.h>
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include "nettle-internal.h"
+/* We use Openssl's EVP api for all openssl ciphers. This API selects
+ platform-specific implementations if appropriate, e.g., using x86
+ AES-NI instructions. */
+struct openssl_cipher_ctx {
+ EVP_CIPHER_CTX *evp;
+};
+
+void
+nettle_openssl_init(void)
+{
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#if OPENSSL_VERSION_NUMBER >= 0x1010000
+ CONF_modules_load_file(NULL, NULL, 0);
+#else
+ OPENSSL_config(NULL);
+#endif
+}
+
+static void
+openssl_evp_set_encrypt_key(void *p, const uint8_t *key,
+ const EVP_CIPHER *cipher)
+{
+ struct openssl_cipher_ctx *ctx = p;
+ ctx->evp = EVP_CIPHER_CTX_new();
+ assert(EVP_EncryptInit_ex(ctx->evp, cipher, NULL, key, NULL) == 1);
+ EVP_CIPHER_CTX_set_padding(ctx->evp, 0);
+}
+static void
+openssl_evp_set_decrypt_key(void *p, const uint8_t *key,
+ const EVP_CIPHER *cipher)
+{
+ struct openssl_cipher_ctx *ctx = p;
+ ctx->evp = EVP_CIPHER_CTX_new();
+ assert(EVP_DecryptInit_ex(ctx->evp, cipher, NULL, key, NULL) == 1);
+ EVP_CIPHER_CTX_set_padding(ctx->evp, 0);
+}
+
+static void
+openssl_evp_encrypt(const void *p, size_t length,
+ uint8_t *dst, const uint8_t *src)
+{
+ const struct openssl_cipher_ctx *ctx = p;
+ int len;
+ assert(EVP_EncryptUpdate(ctx->evp, dst, &len, src, length) == 1);
+}
+static void
+openssl_evp_decrypt(const void *p, size_t length,
+ uint8_t *dst, const uint8_t *src)
+{
+ const struct openssl_cipher_ctx *ctx = p;
+ int len;
+ assert(EVP_DecryptUpdate(ctx->evp, dst, &len, src, length) == 1);
+}
/* AES */
static nettle_set_key_func openssl_aes128_set_encrypt_key;
@@ -64,273 +117,152 @@ static nettle_set_key_func openssl_aes192_set_encrypt_key;
static nettle_set_key_func openssl_aes192_set_decrypt_key;
static nettle_set_key_func openssl_aes256_set_encrypt_key;
static nettle_set_key_func openssl_aes256_set_decrypt_key;
+
static void
openssl_aes128_set_encrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_encrypt_key(key, 128, ctx);
+ openssl_evp_set_encrypt_key(ctx, key, EVP_aes_128_ecb());
}
static void
openssl_aes128_set_decrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_decrypt_key(key, 128, ctx);
+ openssl_evp_set_decrypt_key(ctx, key, EVP_aes_128_ecb());
}
static void
openssl_aes192_set_encrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_encrypt_key(key, 192, ctx);
+ openssl_evp_set_encrypt_key(ctx, key, EVP_aes_192_ecb());
}
static void
openssl_aes192_set_decrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_decrypt_key(key, 192, ctx);
+ openssl_evp_set_decrypt_key(ctx, key, EVP_aes_192_ecb());
}
static void
openssl_aes256_set_encrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_encrypt_key(key, 256, ctx);
+ openssl_evp_set_encrypt_key(ctx, key, EVP_aes_256_ecb());
}
static void
openssl_aes256_set_decrypt_key(void *ctx, const uint8_t *key)
{
- AES_set_decrypt_key(key, 256, ctx);
-}
-
-static nettle_cipher_func openssl_aes_encrypt;
-static void
-openssl_aes_encrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
-{
- assert (!(length % AES_BLOCK_SIZE));
- while (length)
- {
- AES_ecb_encrypt(src, dst, ctx, AES_ENCRYPT);
- length -= AES_BLOCK_SIZE;
- dst += AES_BLOCK_SIZE;
- src += AES_BLOCK_SIZE;
- }
-}
-
-static nettle_cipher_func openssl_aes_decrypt;
-static void
-openssl_aes_decrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
-{
- assert (!(length % AES_BLOCK_SIZE));
- while (length)
- {
- AES_ecb_encrypt(src, dst, ctx, AES_DECRYPT);
- length -= AES_BLOCK_SIZE;
- dst += AES_BLOCK_SIZE;
- src += AES_BLOCK_SIZE;
- }
+ openssl_evp_set_decrypt_key(ctx, key, EVP_aes_256_ecb());
}
const struct nettle_cipher
nettle_openssl_aes128 = {
- "openssl aes128", sizeof(AES_KEY),
+ "openssl aes128", sizeof(struct openssl_cipher_ctx),
16, 16,
openssl_aes128_set_encrypt_key, openssl_aes128_set_decrypt_key,
- openssl_aes_encrypt, openssl_aes_decrypt
+ openssl_evp_encrypt, openssl_evp_decrypt
};
const struct nettle_cipher
nettle_openssl_aes192 = {
- "openssl aes192", sizeof(AES_KEY),
- /* Claim no block size, so that the benchmark doesn't try CBC mode
- * (as openssl cipher + nettle cbc is somewhat pointless to
- * benchmark). */
+ "openssl aes192", sizeof(struct openssl_cipher_ctx),
16, 24,
openssl_aes192_set_encrypt_key, openssl_aes192_set_decrypt_key,
- openssl_aes_encrypt, openssl_aes_decrypt
+ openssl_evp_encrypt, openssl_evp_decrypt
};
const struct nettle_cipher
nettle_openssl_aes256 = {
- "openssl aes256", sizeof(AES_KEY),
- /* Claim no block size, so that the benchmark doesn't try CBC mode
- * (as openssl cipher + nettle cbc is somewhat pointless to
- * benchmark). */
+ "openssl aes256", sizeof(struct openssl_cipher_ctx),
16, 32,
openssl_aes256_set_encrypt_key, openssl_aes256_set_decrypt_key,
- openssl_aes_encrypt, openssl_aes_decrypt
+ openssl_evp_encrypt, openssl_evp_decrypt
};
/* Arcfour */
-static nettle_set_key_func openssl_arcfour128_set_key;
static void
-openssl_arcfour128_set_key(void *ctx, const uint8_t *key)
+openssl_arcfour128_set_encrypt_key(void *ctx, const uint8_t *key)
{
- RC4_set_key(ctx, 16, key);
+ openssl_evp_set_encrypt_key(ctx, key, EVP_rc4());
}
-static nettle_crypt_func openssl_arcfour_crypt;
static void
-openssl_arcfour_crypt(void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_arcfour128_set_decrypt_key(void *ctx, const uint8_t *key)
{
- RC4(ctx, length, src, dst);
+ openssl_evp_set_decrypt_key(ctx, key, EVP_rc4());
}
const struct nettle_aead
nettle_openssl_arcfour128 = {
- "openssl arcfour128", sizeof(RC4_KEY),
+ "openssl arcfour128", sizeof(struct openssl_cipher_ctx),
1, 16, 0, 0,
- openssl_arcfour128_set_key,
- openssl_arcfour128_set_key,
+ openssl_arcfour128_set_encrypt_key,
+ openssl_arcfour128_set_decrypt_key,
NULL, NULL,
- openssl_arcfour_crypt,
- openssl_arcfour_crypt,
+ (nettle_crypt_func *)openssl_evp_encrypt,
+ (nettle_crypt_func *)openssl_evp_decrypt,
NULL,
};
/* Blowfish */
-static nettle_set_key_func openssl_bf128_set_key;
-static void
-openssl_bf128_set_key(void *ctx, const uint8_t *key)
-{
- BF_set_key(ctx, 16, key);
-}
-
-static nettle_cipher_func openssl_bf_encrypt;
static void
-openssl_bf_encrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_bf128_set_encrypt_key(void *ctx, const uint8_t *key)
{
- assert (!(length % BF_BLOCK));
- while (length)
- {
- BF_ecb_encrypt(src, dst, ctx, BF_ENCRYPT);
- length -= BF_BLOCK;
- dst += BF_BLOCK;
- src += BF_BLOCK;
- }
+ openssl_evp_set_encrypt_key(ctx, key, EVP_bf_ecb());
}
-static nettle_cipher_func openssl_bf_decrypt;
static void
-openssl_bf_decrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_bf128_set_decrypt_key(void *ctx, const uint8_t *key)
{
- assert (!(length % BF_BLOCK));
- while (length)
- {
- BF_ecb_encrypt(src, dst, ctx, BF_DECRYPT);
- length -= BF_BLOCK;
- dst += BF_BLOCK;
- src += BF_BLOCK;
- }
+ openssl_evp_set_decrypt_key(ctx, key, EVP_bf_ecb());
}
const struct nettle_cipher
nettle_openssl_blowfish128 = {
- "openssl bf128", sizeof(BF_KEY),
+ "openssl bf128", sizeof(struct openssl_cipher_ctx),
8, 16,
- openssl_bf128_set_key, openssl_bf128_set_key,
- openssl_bf_encrypt, openssl_bf_decrypt
+ openssl_bf128_set_encrypt_key, openssl_bf128_set_decrypt_key,
+ openssl_evp_encrypt, openssl_evp_decrypt
};
/* DES */
-static nettle_set_key_func openssl_des_set_key;
static void
-openssl_des_set_key(void *ctx, const uint8_t *key)
+openssl_des_set_encrypt_key(void *ctx, const uint8_t *key)
{
- /* Not sure what "unchecked" means. We want to ignore parity bits,
- but it would still make sense to check for weak keys. */
- /* Explicit cast used as I don't want to care about openssl's broken
- array typedefs DES_cblock and const_DES_cblock. */
- DES_set_key_unchecked( (void *) key, ctx);
+ openssl_evp_set_encrypt_key(ctx, key, EVP_des_ecb());
}
-#define DES_BLOCK_SIZE 8
-
-static nettle_cipher_func openssl_des_encrypt;
-static void
-openssl_des_encrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
-{
- assert (!(length % DES_BLOCK_SIZE));
- while (length)
- {
- DES_ecb_encrypt((void *) src, (void *) dst,
- (void *) ctx, DES_ENCRYPT);
- length -= DES_BLOCK_SIZE;
- dst += DES_BLOCK_SIZE;
- src += DES_BLOCK_SIZE;
- }
-}
-
-static nettle_cipher_func openssl_des_decrypt;
static void
-openssl_des_decrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_des_set_decrypt_key(void *ctx, const uint8_t *key)
{
- assert (!(length % DES_BLOCK_SIZE));
- while (length)
- {
- DES_ecb_encrypt((void *) src, (void *) dst,
- (void *) ctx, DES_DECRYPT);
- length -= DES_BLOCK_SIZE;
- dst += DES_BLOCK_SIZE;
- src += DES_BLOCK_SIZE;
- }
+ openssl_evp_set_decrypt_key(ctx, key, EVP_des_ecb());
}
const struct nettle_cipher
nettle_openssl_des = {
- "openssl des", sizeof(DES_key_schedule),
+ "openssl des", sizeof(struct openssl_cipher_ctx),
8, 8,
- openssl_des_set_key, openssl_des_set_key,
- openssl_des_encrypt, openssl_des_decrypt
+ openssl_des_set_encrypt_key, openssl_des_set_decrypt_key,
+ openssl_evp_encrypt, openssl_evp_decrypt
};
/* Cast128 */
-static nettle_set_key_func openssl_cast128_set_key;
-static void
-openssl_cast128_set_key(void *ctx, const uint8_t *key)
-{
- CAST_set_key(ctx, 16, key);
-}
-
-static nettle_cipher_func openssl_cast_encrypt;
static void
-openssl_cast_encrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_cast128_set_encrypt_key(void *ctx, const uint8_t *key)
{
- assert (!(length % CAST_BLOCK));
- while (length)
- {
- CAST_ecb_encrypt(src, dst, ctx, CAST_ENCRYPT);
- length -= CAST_BLOCK;
- dst += CAST_BLOCK;
- src += CAST_BLOCK;
- }
+ openssl_evp_set_encrypt_key(ctx, key, EVP_cast5_ecb());
}
-static nettle_cipher_func openssl_cast_decrypt;
static void
-openssl_cast_decrypt(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
+openssl_cast128_set_decrypt_key(void *ctx, const uint8_t *key)
{
- assert (!(length % CAST_BLOCK));
- while (length)
- {
- CAST_ecb_encrypt(src, dst, ctx, CAST_DECRYPT);
- length -= CAST_BLOCK;
- dst += CAST_BLOCK;
- src += CAST_BLOCK;
- }
+ openssl_evp_set_decrypt_key(ctx, key, EVP_cast5_ecb());
}
const struct nettle_cipher
nettle_openssl_cast128 = {
- "openssl cast128", sizeof(CAST_KEY),
- 8, CAST_KEY_LENGTH,
- openssl_cast128_set_key, openssl_cast128_set_key,
- openssl_cast_encrypt, openssl_cast_decrypt
+ "openssl cast128", sizeof(struct openssl_cipher_ctx),
+ 8, 16,
+ openssl_cast128_set_encrypt_key, openssl_cast128_set_decrypt_key,
+ openssl_evp_encrypt, openssl_evp_decrypt
};
/* Hash functions */
diff --git a/fat-arm.c b/fat-arm.c
index 1156499d..d52b1439 100644
--- a/fat-arm.c
+++ b/fat-arm.c
@@ -29,6 +29,8 @@
not, see http://www.gnu.org/licenses/.
*/
+#define _GNU_SOURCE
+
#if HAVE_CONFIG_H
# include "config.h"
#endif
diff --git a/hkdf.c b/hkdf.c
new file mode 100644
index 00000000..2d7336a5
--- /dev/null
+++ b/hkdf.c
@@ -0,0 +1,84 @@
+/* hkdf.c
+
+ Copyright (C) 2017 Red Hat, Inc.
+
+ Author: Nikos Mavrogiannopoulos
+
+ 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/.
+ */
+
+/* Functions for the HKDF handling.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "hkdf.h"
+
+/* hkdf_extract: Outputs a PRK of digest_size
+ */
+void
+hkdf_extract(void *mac_ctx,
+ nettle_hash_update_func *update,
+ nettle_hash_digest_func *digest,
+ size_t digest_size,
+ size_t secret_size, const uint8_t *secret,
+ uint8_t *dst)
+{
+ update(mac_ctx, secret_size, secret);
+ digest(mac_ctx, digest_size, dst);
+}
+
+/* hkdf_expand: Outputs an arbitrary key of size specified by length
+ */
+void
+hkdf_expand(void *mac_ctx,
+ nettle_hash_update_func *update,
+ nettle_hash_digest_func *digest,
+ size_t digest_size,
+ size_t info_size, const uint8_t *info,
+ size_t length, uint8_t *dst)
+{
+ uint8_t i = 1;
+
+ if (!length)
+ return;
+
+ for (;; dst += digest_size, length -= digest_size, i++)
+ {
+ update(mac_ctx, info_size, info);
+ update(mac_ctx, 1, &i);
+ if (length <= digest_size)
+ break;
+
+ digest(mac_ctx, digest_size, dst);
+ update(mac_ctx, digest_size, dst);
+ }
+
+ digest(mac_ctx, length, dst);
+}
diff --git a/hkdf.h b/hkdf.h
new file mode 100644
index 00000000..43b16ad4
--- /dev/null
+++ b/hkdf.h
@@ -0,0 +1,67 @@
+/* hkdf.h
+
+ TLS PRF code (RFC-5246, RFC-2246).
+
+ Copyright (C) 2017 Red Hat, Inc.
+
+ 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_HKDF_H_INCLUDED
+#define NETTLE_HKDF_H_INCLUDED
+
+#include "nettle-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Namespace mangling */
+#define hkdf_extract nettle_hkdf_extract
+#define hkdf_expand nettle_hkdf_expand
+
+void
+hkdf_extract(void *mac_ctx,
+ nettle_hash_update_func *update,
+ nettle_hash_digest_func *digest,
+ size_t digest_size,
+ size_t secret_size, const uint8_t *secret,
+ uint8_t *dst);
+
+void
+hkdf_expand(void *mac_ctx,
+ nettle_hash_update_func *update,
+ nettle_hash_digest_func *digest,
+ size_t digest_size,
+ size_t info_size, const uint8_t *info,
+ size_t length, uint8_t *dst);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_HKDF_H_INCLUDED */
diff --git a/mini-gmp.c b/mini-gmp.c
index acbe1bec..d4d257c4 100644
--- a/mini-gmp.c
+++ b/mini-gmp.c
@@ -2,7 +2,7 @@
Contributed to the GNU project by Niels Möller
-Copyright 1991-1997, 1999-2014 Free Software Foundation, Inc.
+Copyright 1991-1997, 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -69,8 +69,16 @@ see https://www.gnu.org/licenses/. */
#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b)))
+
+/* Return non-zero if xp,xsize and yp,ysize overlap.
+ If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no
+ overlap. If both these are false, there's an overlap. */
+#define GMP_MPN_OVERLAP_P(xp, xsize, yp, ysize) \
+ ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp))
+
#define gmp_assert_nocarry(x) do { \
- mp_limb_t __cy = x; \
+ mp_limb_t __cy = (x); \
assert (__cy == 0); \
} while (0)
@@ -264,12 +272,12 @@ gmp_default_alloc (size_t size)
static void *
gmp_default_realloc (void *old, size_t old_size, size_t new_size)
{
- mp_ptr p;
+ void * p;
p = realloc (old, new_size);
if (!p)
- gmp_die("gmp_default_realoc: Virtual memory exhausted.");
+ gmp_die("gmp_default_realloc: Virtual memory exhausted.");
return p;
}
@@ -322,14 +330,14 @@ mp_set_memory_functions (void *(*alloc_func) (size_t),
static mp_ptr
gmp_xalloc_limbs (mp_size_t size)
{
- return gmp_xalloc (size * sizeof (mp_limb_t));
+ return (mp_ptr) gmp_xalloc (size * sizeof (mp_limb_t));
}
static mp_ptr
gmp_xrealloc_limbs (mp_ptr old, mp_size_t size)
{
assert (size > 0);
- return (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t));
+ return (mp_ptr) (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t));
}
@@ -346,7 +354,7 @@ mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n)
void
mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n)
{
- while (n-- > 0)
+ while (--n >= 0)
d[n] = s[n];
}
@@ -373,20 +381,22 @@ mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
static mp_size_t
mpn_normalized_size (mp_srcptr xp, mp_size_t n)
{
- for (; n > 0 && xp[n-1] == 0; n--)
- ;
+ while (n > 0 && xp[n-1] == 0)
+ --n;
return n;
}
-#define mpn_zero_p(xp, n) (mpn_normalized_size ((xp), (n)) == 0)
+int
+mpn_zero_p(mp_srcptr rp, mp_size_t n)
+{
+ return mpn_normalized_size (rp, n) == 0;
+}
void
mpn_zero (mp_ptr rp, mp_size_t n)
{
- mp_size_t i;
-
- for (i = 0; i < n; i++)
- rp[i] = 0;
+ while (--n >= 0)
+ rp[n] = 0;
}
mp_limb_t
@@ -452,7 +462,7 @@ mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
{
mp_limb_t a = ap[i];
/* Carry out */
- mp_limb_t cy = a < b;;
+ mp_limb_t cy = a < b;
rp[i] = a - b;
b = cy;
}
@@ -572,23 +582,24 @@ mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
{
assert (un >= vn);
assert (vn >= 1);
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, up, un));
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, vp, vn));
/* We first multiply by the low order limb. This result can be
stored, not added, to rp. We also avoid a loop for zeroing this
way. */
rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
- rp += 1, vp += 1, vn -= 1;
/* Now accumulate the product of up[] and the next higher limb from
vp[]. */
- while (vn >= 1)
+ while (--vn >= 1)
{
+ rp += 1, vp += 1;
rp[un] = mpn_addmul_1 (rp, up, un, vp[0]);
- rp += 1, vp += 1, vn -= 1;
}
- return rp[un - 1];
+ return rp[un];
}
void
@@ -608,7 +619,6 @@ mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
{
mp_limb_t high_limb, low_limb;
unsigned int tnc;
- mp_size_t i;
mp_limb_t retval;
assert (n >= 1);
@@ -623,7 +633,7 @@ mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
retval = low_limb >> tnc;
high_limb = (low_limb << cnt);
- for (i = n; --i != 0;)
+ while (--n != 0)
{
low_limb = *--up;
*--rp = high_limb | (low_limb >> tnc);
@@ -639,7 +649,6 @@ mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
{
mp_limb_t high_limb, low_limb;
unsigned int tnc;
- mp_size_t i;
mp_limb_t retval;
assert (n >= 1);
@@ -651,7 +660,7 @@ mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
retval = (high_limb << tnc);
low_limb = high_limb >> cnt;
- for (i = n; --i != 0;)
+ while (--n != 0)
{
high_limb = *up++;
*rp++ = low_limb | (high_limb << tnc);
@@ -702,24 +711,68 @@ mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit)
i, ptr, i, GMP_LIMB_MAX);
}
+void
+mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (--n >= 0)
+ *rp++ = ~ *up++;
+}
+
+mp_limb_t
+mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (*up == 0)
+ {
+ *rp = 0;
+ if (!--n)
+ return 0;
+ ++up; ++rp;
+ }
+ *rp = - *up;
+ mpn_com (++rp, ++up, --n);
+ return 1;
+}
+
/* MPN division interface. */
+
+/* The 3/2 inverse is defined as
+
+ m = floor( (B^3-1) / (B u1 + u0)) - B
+*/
mp_limb_t
mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
{
- mp_limb_t r, p, m;
- unsigned ul, uh;
- unsigned ql, qh;
+ mp_limb_t r, p, m, ql;
+ unsigned ul, uh, qh;
- /* First, do a 2/1 inverse. */
- /* The inverse m is defined as floor( (B^2 - 1 - u1)/u1 ), so that 0 <
- * B^2 - (B + m) u1 <= u1 */
assert (u1 >= GMP_LIMB_HIGHBIT);
+ /* For notation, let b denote the half-limb base, so that B = b^2.
+ Split u1 = b uh + ul. */
ul = u1 & GMP_LLIMB_MASK;
uh = u1 >> (GMP_LIMB_BITS / 2);
+ /* Approximation of the high half of quotient. Differs from the 2/1
+ inverse of the half limb uh, since we have already subtracted
+ u0. */
qh = ~u1 / uh;
+
+ /* Adjust to get a half-limb 3/2 inverse, i.e., we want
+
+ qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
+ = floor( (b (~u) + b-1) / u),
+
+ and the remainder
+
+ r = b (~u) + b-1 - qh (b uh + ul)
+ = b (~u - qh uh) + b-1 - qh ul
+
+ Subtraction of qh ul may underflow, which implies adjustments.
+ But by normalization, 2 u >= B > qh ul, so we need to adjust by
+ at most 2.
+ */
+
r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
p = (mp_limb_t) qh * ul;
@@ -737,11 +790,19 @@ mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
}
r -= p;
- /* Do a 3/2 division (with half limb size) */
+ /* Low half of the quotient is
+
+ ql = floor ( (b r + b-1) / u1).
+
+ This is a 3/2 division (on half-limbs), for which qh is a
+ suitable inverse. */
+
p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
+ /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
+ work, it is essential that ql is a full mp_limb_t. */
ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
- /* By the 3/2 method, we don't need the high half limb. */
+ /* By the 3/2 trick, we don't need the high half limb. */
r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
if (r >= (p << (GMP_LIMB_BITS / 2)))
@@ -756,6 +817,8 @@ mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
r -= u1;
}
+ /* Now m is the 2/1 invers of u1. If u0 > 0, adjust it to become a
+ 3/2 inverse. */
if (u0 > 0)
{
mp_limb_t th, tl;
@@ -876,7 +939,7 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
d = inv->d1;
di = inv->di;
- while (nn-- > 0)
+ while (--nn >= 0)
{
mp_limb_t q;
@@ -1160,7 +1223,7 @@ mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un)
unsigned char mask;
size_t sn, j;
mp_size_t i;
- int shift;
+ unsigned shift;
sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1])
+ bits - 1) / bits;
@@ -1301,6 +1364,8 @@ mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
return rn;
}
+/* Result is usually normalized, except for all-zero input, in which
+ case a single zero limb is written at *RP, and 1 is returned. */
static mp_size_t
mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn,
mp_limb_t b, const struct mpn_base_info *info)
@@ -1310,16 +1375,18 @@ mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn,
unsigned k;
size_t j;
+ assert (sn > 0);
+
k = 1 + (sn - 1) % info->exp;
j = 0;
w = sp[j++];
- for (; --k > 0; )
+ while (--k != 0)
w = w * b + sp[j++];
rp[0] = w;
- for (rn = (w > 0); j < sn;)
+ for (rn = 1; j < sn;)
{
mp_limb_t cy;
@@ -1362,9 +1429,11 @@ mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base)
void
mpz_init (mpz_t r)
{
- r->_mp_alloc = 1;
+ static const mp_limb_t dummy_limb = 0xc1a0;
+
+ r->_mp_alloc = 0;
r->_mp_size = 0;
- r->_mp_d = gmp_xalloc_limbs (1);
+ r->_mp_d = (mp_ptr) &dummy_limb;
}
/* The utility of this function is a bit limited, since many functions
@@ -1385,15 +1454,19 @@ mpz_init2 (mpz_t r, mp_bitcnt_t bits)
void
mpz_clear (mpz_t r)
{
- gmp_free (r->_mp_d);
+ if (r->_mp_alloc)
+ gmp_free (r->_mp_d);
}
-static void *
+static mp_ptr
mpz_realloc (mpz_t r, mp_size_t size)
{
size = GMP_MAX (size, 1);
- r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size);
+ if (r->_mp_alloc)
+ r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size);
+ else
+ r->_mp_d = gmp_xalloc_limbs (size);
r->_mp_alloc = size;
if (GMP_ABS (r->_mp_size) > size)
@@ -1416,7 +1489,7 @@ mpz_set_si (mpz_t r, signed long int x)
else /* (x < 0) */
{
r->_mp_size = -1;
- r->_mp_d[0] = GMP_NEG_CAST (unsigned long int, x);
+ MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x);
}
}
@@ -1426,7 +1499,7 @@ mpz_set_ui (mpz_t r, unsigned long int x)
if (x > 0)
{
r->_mp_size = 1;
- r->_mp_d[0] = x;
+ MPZ_REALLOC (r, 1)[0] = x;
}
else
r->_mp_size = 0;
@@ -1475,14 +1548,12 @@ mpz_fits_slong_p (const mpz_t u)
{
mp_size_t us = u->_mp_size;
- if (us == 0)
- return 1;
- else if (us == 1)
+ if (us == 1)
return u->_mp_d[0] < GMP_LIMB_HIGHBIT;
else if (us == -1)
return u->_mp_d[0] <= GMP_LIMB_HIGHBIT;
else
- return 0;
+ return (us == 0);
}
int
@@ -1496,14 +1567,11 @@ mpz_fits_ulong_p (const mpz_t u)
long int
mpz_get_si (const mpz_t u)
{
- mp_size_t us = u->_mp_size;
-
- if (us > 0)
- return (long) (u->_mp_d[0] & ~GMP_LIMB_HIGHBIT);
- else if (us < 0)
- return (long) (- u->_mp_d[0] | GMP_LIMB_HIGHBIT);
+ if (u->_mp_size < 0)
+ /* This expression is necessary to properly handle 0x80000000 */
+ return -1 - (long) ((u->_mp_d[0] - 1) & ~GMP_LIMB_HIGHBIT);
else
- return 0;
+ return (long) (mpz_get_ui (u) & ~GMP_LIMB_HIGHBIT);
}
unsigned long int
@@ -1536,7 +1604,7 @@ mpz_realloc2 (mpz_t x, mp_bitcnt_t n)
mp_srcptr
mpz_limbs_read (mpz_srcptr x)
{
- return x->_mp_d;;
+ return x->_mp_d;
}
mp_ptr
@@ -1716,9 +1784,7 @@ mpz_cmp_d (const mpz_t x, double d)
int
mpz_sgn (const mpz_t u)
{
- mp_size_t usize = u->_mp_size;
-
- return (usize > 0) - (usize < 0);
+ return GMP_CMP (u->_mp_size, 0);
}
int
@@ -1733,13 +1799,7 @@ mpz_cmp_si (const mpz_t u, long v)
else if (usize >= 0)
return 1;
else /* usize == -1 */
- {
- mp_limb_t ul = u->_mp_d[0];
- if ((mp_limb_t)GMP_NEG_CAST (unsigned long int, v) < ul)
- return -1;
- else
- return (mp_limb_t)GMP_NEG_CAST (unsigned long int, v) > ul;
- }
+ return GMP_CMP (GMP_NEG_CAST (mp_limb_t, v), u->_mp_d[0]);
}
int
@@ -1752,10 +1812,7 @@ mpz_cmp_ui (const mpz_t u, unsigned long v)
else if (usize < 0)
return -1;
else
- {
- mp_limb_t ul = (usize > 0) ? u->_mp_d[0] : 0;
- return (ul > v) - (ul < v);
- }
+ return GMP_CMP (mpz_get_ui (u), v);
}
int
@@ -1775,15 +1832,10 @@ mpz_cmp (const mpz_t a, const mpz_t b)
int
mpz_cmpabs_ui (const mpz_t u, unsigned long v)
{
- mp_size_t un = GMP_ABS (u->_mp_size);
- mp_limb_t ul;
-
- if (un > 1)
+ if (GMP_ABS (u->_mp_size) > 1)
return 1;
-
- ul = (un == 1) ? u->_mp_d[0] : 0;
-
- return (ul > v) - (ul < v);
+ else
+ return GMP_CMP (mpz_get_ui (u), v);
}
int
@@ -1796,18 +1848,14 @@ mpz_cmpabs (const mpz_t u, const mpz_t v)
void
mpz_abs (mpz_t r, const mpz_t u)
{
- if (r != u)
- mpz_set (r, u);
-
+ mpz_set (r, u);
r->_mp_size = GMP_ABS (r->_mp_size);
}
void
mpz_neg (mpz_t r, const mpz_t u)
{
- if (r != u)
- mpz_set (r, u);
-
+ mpz_set (r, u);
r->_mp_size = -r->_mp_size;
}
@@ -1833,7 +1881,7 @@ mpz_abs_add_ui (mpz_t r, const mpz_t a, unsigned long b)
an = GMP_ABS (a->_mp_size);
if (an == 0)
{
- r->_mp_d[0] = b;
+ MPZ_REALLOC (r, 1)[0] = b;
return b > 0;
}
@@ -1852,14 +1900,15 @@ static mp_size_t
mpz_abs_sub_ui (mpz_t r, const mpz_t a, unsigned long b)
{
mp_size_t an = GMP_ABS (a->_mp_size);
- mp_ptr rp = MPZ_REALLOC (r, an);
+ mp_ptr rp;
if (an == 0)
{
- rp[0] = b;
+ MPZ_REALLOC (r, 1)[0] = b;
return -(b > 0);
}
- else if (an == 1 && a->_mp_d[0] < b)
+ rp = MPZ_REALLOC (r, an);
+ if (an == 1 && a->_mp_d[0] < b)
{
rp[0] = b - a->_mp_d[0];
return -1;
@@ -2077,8 +2126,7 @@ mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits)
else
mpn_copyd (rp + limbs, u->_mp_d, un);
- while (limbs > 0)
- rp[--limbs] = 0;
+ mpn_zero (rp, limbs);
r->_mp_size = (u->_mp_size < 0) ? - rn : rn;
}
@@ -2331,7 +2379,6 @@ mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index,
if (qn <= 0)
qn = 0;
-
else
{
qp = MPZ_REALLOC (q, qn);
@@ -2385,16 +2432,9 @@ mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index,
{
/* Have to negate and sign extend. */
mp_size_t i;
- mp_limb_t cy;
- for (cy = 1, i = 0; i < un; i++)
- {
- mp_limb_t s = ~u->_mp_d[i] + cy;
- cy = s < cy;
- rp[i] = s;
- }
- assert (cy == 0);
- for (; i < rn - 1; i++)
+ gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un));
+ for (i = un; i < rn - 1; i++)
rp[i] = GMP_LIMB_MAX;
rp[rn-1] = mask;
@@ -2419,23 +2459,13 @@ mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index,
if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
{
/* If r != 0, compute 2^{bit_count} - r. */
- mp_size_t i;
+ mpn_neg (rp, rp, rn);
- for (i = 0; i < rn && rp[i] == 0; i++)
- ;
- if (i < rn)
- {
- /* r > 0, need to flip sign. */
- rp[i] = ~rp[i] + 1;
- while (++i < rn)
- rp[i] = ~rp[i];
-
- rp[rn-1] &= mask;
+ rp[rn-1] &= mask;
- /* us is not used for anything else, so we can modify it
- here to indicate flipped sign. */
- us = -us;
- }
+ /* us is not used for anything else, so we can modify it
+ here to indicate flipped sign. */
+ us = -us;
}
}
rn = mpn_normalized_size (rp, rn);
@@ -2550,7 +2580,7 @@ mpz_div_qr_ui (mpz_t q, mpz_t r,
if (r)
{
- r->_mp_d[0] = rl;
+ MPZ_REALLOC (r, 1)[0] = rl;
r->_mp_size = rs;
}
if (q)
@@ -3074,9 +3104,7 @@ void
mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e)
{
mpz_t b;
- mpz_init_set_ui (b, blimb);
- mpz_pow_ui (r, b, e);
- mpz_clear (b);
+ mpz_pow_ui (r, mpz_roinit_n (b, &blimb, 1), e);
}
void
@@ -3148,7 +3176,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
}
mpz_init_set_ui (tr, 1);
- while (en-- > 0)
+ while (--en >= 0)
{
mp_limb_t w = e->_mp_d[en];
mp_limb_t bit;
@@ -3188,9 +3216,7 @@ void
mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m)
{
mpz_t e;
- mpz_init_set_ui (e, elimb);
- mpz_powm (r, b, e, m);
- mpz_clear (e);
+ mpz_powm (r, b, mpz_roinit_n (e, &elimb, 1), m);
}
/* x=trunc(y^(1/z)), r=y-x^z */
@@ -3215,12 +3241,8 @@ mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z)
}
mpz_init (u);
- {
- mp_bitcnt_t tb;
- tb = mpz_sizeinbase (y, 2) / z + 1;
- mpz_init2 (t, tb);
- mpz_setbit (t, tb);
- }
+ mpz_init (t);
+ mpz_setbit (t, mpz_sizeinbase (y, 2) / z + 1);
if (z == 2) /* simplify sqrt loop: z-1 == 1 */
do {
@@ -3333,7 +3355,7 @@ void
mpz_fac_ui (mpz_t x, unsigned long n)
{
mpz_set_ui (x, n + (n == 0));
- for (;n > 2;)
+ while (n > 2)
mpz_mul_ui (x, x, --n);
}
@@ -3504,7 +3526,7 @@ mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index)
must be complemented. */
if (shift > 0 && (w << (GMP_LIMB_BITS - shift)) > 0)
return bit ^ 1;
- while (limb_index-- > 0)
+ while (--limb_index >= 0)
if (d->_mp_d[limb_index] > 0)
return bit ^ 1;
}
@@ -3647,7 +3669,7 @@ mpz_and (mpz_t r, const mpz_t u, const mpz_t v)
/* If the smaller input is positive, higher limbs don't matter. */
rn = vx ? un : vn;
- rp = MPZ_REALLOC (r, rn + rc);
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
up = u->_mp_d;
vp = v->_mp_d;
@@ -3720,7 +3742,7 @@ mpz_ior (mpz_t r, const mpz_t u, const mpz_t v)
don't matter. */
rn = vx ? vn : un;
- rp = MPZ_REALLOC (r, rn + rc);
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
up = u->_mp_d;
vp = v->_mp_d;
@@ -3789,7 +3811,7 @@ mpz_xor (mpz_t r, const mpz_t u, const mpz_t v)
vx = -vc;
rx = -rc;
- rp = MPZ_REALLOC (r, un + rc);
+ rp = MPZ_REALLOC (r, un + (mp_size_t) rc);
up = u->_mp_d;
vp = v->_mp_d;
@@ -3999,7 +4021,7 @@ mpz_sizeinbase (const mpz_t u, int base)
size_t ndigits;
assert (base >= 2);
- assert (base <= 36);
+ assert (base <= 62);
un = GMP_ABS (u->_mp_size);
if (un == 0)
@@ -4049,23 +4071,26 @@ mpz_get_str (char *sp, int base, const mpz_t u)
mp_size_t un;
size_t i, sn;
- if (base >= 0)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ if (base > 1)
{
- digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ if (base <= 36)
+ digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ else if (base > 62)
+ return NULL;
}
+ else if (base >= -1)
+ base = 10;
else
{
base = -base;
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (base > 36)
+ return NULL;
}
- if (base <= 1)
- base = 10;
- if (base > 36)
- return NULL;
sn = 1 + mpz_sizeinbase (u, base);
if (!sp)
- sp = gmp_xalloc (1 + sn);
+ sp = (char *) gmp_xalloc (1 + sn);
un = GMP_ABS (u->_mp_size);
@@ -4109,14 +4134,14 @@ mpz_get_str (char *sp, int base, const mpz_t u)
int
mpz_set_str (mpz_t r, const char *sp, int base)
{
- unsigned bits;
+ unsigned bits, value_of_a;
mp_size_t rn, alloc;
mp_ptr rp;
- size_t sn;
+ size_t dn;
int sign;
unsigned char *dp;
- assert (base == 0 || (base >= 2 && base <= 36));
+ assert (base == 0 || (base >= 2 && base <= 62));
while (isspace( (unsigned char) *sp))
sp++;
@@ -4126,18 +4151,17 @@ mpz_set_str (mpz_t r, const char *sp, int base)
if (base == 0)
{
- if (*sp == '0')
+ if (sp[0] == '0')
{
- sp++;
- if (*sp == 'x' || *sp == 'X')
+ if (sp[1] == 'x' || sp[1] == 'X')
{
base = 16;
- sp++;
+ sp += 2;
}
- else if (*sp == 'b' || *sp == 'B')
+ else if (sp[1] == 'b' || sp[1] == 'B')
{
base = 2;
- sp++;
+ sp += 2;
}
else
base = 8;
@@ -4146,49 +4170,63 @@ mpz_set_str (mpz_t r, const char *sp, int base)
base = 10;
}
- sn = strlen (sp);
- dp = gmp_xalloc (sn + (sn == 0));
+ if (!*sp)
+ {
+ r->_mp_size = 0;
+ return -1;
+ }
+ dp = (unsigned char *) gmp_xalloc (strlen (sp));
- for (sn = 0; *sp; sp++)
+ value_of_a = (base > 36) ? 36 : 10;
+ for (dn = 0; *sp; sp++)
{
unsigned digit;
if (isspace ((unsigned char) *sp))
continue;
- if (*sp >= '0' && *sp <= '9')
+ else if (*sp >= '0' && *sp <= '9')
digit = *sp - '0';
else if (*sp >= 'a' && *sp <= 'z')
- digit = *sp - 'a' + 10;
+ digit = *sp - 'a' + value_of_a;
else if (*sp >= 'A' && *sp <= 'Z')
digit = *sp - 'A' + 10;
else
digit = base; /* fail */
- if (digit >= base)
+ if (digit >= (unsigned) base)
{
gmp_free (dp);
r->_mp_size = 0;
return -1;
}
- dp[sn++] = digit;
+ dp[dn++] = digit;
}
+ if (!dn)
+ {
+ gmp_free (dp);
+ r->_mp_size = 0;
+ return -1;
+ }
bits = mpn_base_power_of_two_p (base);
if (bits > 0)
{
- alloc = (sn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
rp = MPZ_REALLOC (r, alloc);
- rn = mpn_set_str_bits (rp, dp, sn, bits);
+ rn = mpn_set_str_bits (rp, dp, dn, bits);
}
else
{
struct mpn_base_info info;
mpn_get_base_info (&info, base);
- alloc = (sn + info.exp - 1) / info.exp;
+ alloc = (dn + info.exp - 1) / info.exp;
rp = MPZ_REALLOC (r, alloc);
- rn = mpn_set_str_other (rp, dp, sn, base, &info);
+ rn = mpn_set_str_other (rp, dp, dn, base, &info);
+ /* Normalization, needed for all-zero input. */
+ assert (rn > 0);
+ rn -= rp[rn-1] == 0;
}
assert (rn <= alloc);
gmp_free (dp);
diff --git a/mini-gmp.h b/mini-gmp.h
index c043ca7e..bb5c6371 100644
--- a/mini-gmp.h
+++ b/mini-gmp.h
@@ -1,6 +1,6 @@
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
-Copyright 2011-2014 Free Software Foundation, Inc.
+Copyright 2011-2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -82,6 +82,7 @@ void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
void mpn_zero (mp_ptr, mp_size_t);
int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
+int mpn_zero_p (mp_srcptr, mp_size_t);
mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
@@ -107,6 +108,9 @@ mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
+void mpn_com (mp_ptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t);
+
mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
diff --git a/misc/plan.html b/misc/plan.html
index 71ddba3a..99be07d5 100644
--- a/misc/plan.html
+++ b/misc/plan.html
@@ -12,9 +12,9 @@
</head>
<body>
<h1> Nettle release plans </h1>
- <p> This is an attempt at defining a development target for
- Nettle-3.3, inspired by similar pages for recent GMP releases.
- [Last updated 2016-09-19]</p>
+ <p> This is an attempt at defining a development target for the next
+ release of Nettle, inspired by similar pages for recent GMP
+ releases. [Last updated 2017-10-01]</p>
<p class='should'>
This really ought to be done before release
</p>
@@ -28,21 +28,36 @@
Leave for some later release!
</p>
- <h1> Plans for nettle-3.3 </h1>
+ <h1> Plans for nettle-3.4 </h1>
+
+ <h2> Bug fixes </h2>
+ <p class='should'> Fix issues with sizes of objects like the
+ nettle_hashes array and the ecc_curve structs accidentally leaking
+ into the ABI. Fix by another level of indirection, with a function
+ call to return the start address.
+ </p>
<h2> New features </h2>
<p class='postponed'>
Add larger "safe" curves, e.g., M-383, curve41417, curve448 and
- E-521.
+ E-521. (curve448 in progress, on its own branch).
</p>
+
<p class='postponed'>
Add functions for converting ECC points to and from ANSI x9.62.
</p>
- <p class='done'>
- Use side-channel silent mpz_powm_sec for RSA and DSA.
+
+ <p class='postponed'>
+ Support for the Skein hash function.
</p>
- <p class='done'>
- Side-channel silent memeql_sec.
+
+ <p class='postponed'>
+ Support for more GOST standard algorithms.
+ </p>
+
+ <p class='wish'>
+ Support for CFB mode (patch by Dmitry Eremin-Solenikov posted on
+ the list).
</p>
<h2> Optimizations </h2>
@@ -58,42 +73,43 @@
</p>
<h2> Miscellaneous </h2>
- <p class='done'> Use GMP-5 functions unconditionally. </p>
<p class='postponed'>
Use more functions from GMP-6 and later, when available:
mpn_sec_add_1, mpn_sec_tabselect, mpn_sec_invert, mpn_cnd_swap,
...
</p>
- <h2> Documentation </h2>
- <p class='done'>
- Document memeql_sec.
+ <p class='done'> Change base16 and base64 interfaces to use char
+ for encoded data, and fix remaining pointer-signedness warnings.
</p>
+ <h2> Documentation </h2>
+
+
<h2> Build system </h2>
- <p class='postponed'>
- Update AX_CREATE_STDINT_H to the latest version.
+ <p class='should'>
+ Delete AX_CREATE_STDINT_H, use stdint.h unconditionally.
</p>
<h2> Testing </h2>
<p> Since xenofarm isn't up and running, do some manual testing:
</p>
<ul>
- <li class='done'> x86_64-linux-gnu</li>
- <li class='done'> x86-linux-gnu</li>
- <li class='done'> x86_64-freebsd</li>
- <li class='done'> x86-w*ndows (using cross compiler and wine)</li>
- <li class='done'> x86_64-w*ndows (using cross compiler and wine)</li>
+ <li class='should'> x86_64-linux-gnu</li>
+ <li class='should'> x86-linux-gnu</li>
+ <li class='should'> x86_64-freebsd</li>
+ <li class='should'> x86-w*ndows (using cross compiler and wine)</li>
+ <li class='should'> x86_64-w*ndows (using cross compiler and wine)</li>
<li class='should'> x86-darwin (needs help from Nettle users)</li>
<li class='should'> x86_64-darwin (needs help from Nettle users)</li>
<li class='should'> armv5-linux-gnu (qemu)</li>
- <li class='done'> armv7-linux-gnu (qemu)</li>
+ <li class='should'> armv7-linux-gnu (qemu)</li>
<li class='should'> armv8-linux-gnu (qemu)</li>
<li class='should'> ppc64-linux-gnu (qemu)</li>
<li class='should'> ppc32-linux-gnu (qemu)</li>
- <li class='done'> mips64-linux-gnu (qemu)</li>
+ <li class='should'> mips64-linux-gnu (qemu)</li>
<li class='should'> mips32-linux-gnu (qemu)</li>
- <li class='done'> m68k-linux-gnu (aranym)</li>
+ <li class='should'> m68k-linux-gnu (aranym)</li>
<li class='wish'> armv7-android </li>
</ul>
diff --git a/nettle-internal.h b/nettle-internal.h
index 4e3098bb..0b0d25c9 100644
--- a/nettle-internal.h
+++ b/nettle-internal.h
@@ -54,6 +54,7 @@
/* 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
@@ -78,6 +79,7 @@ extern const struct nettle_aead nettle_salsa20r12;
/* Glue to openssl, for comparative benchmarking. Code in
* examples/nettle-openssl.c. */
+extern void nettle_openssl_init(void);
extern const struct nettle_cipher nettle_openssl_aes128;
extern const struct nettle_cipher nettle_openssl_aes192;
extern const struct nettle_cipher nettle_openssl_aes256;
diff --git a/nettle-types.h b/nettle-types.h
index 475937d2..84c375d2 100644
--- a/nettle-types.h
+++ b/nettle-types.h
@@ -89,17 +89,17 @@ typedef size_t nettle_armor_length_func(size_t length);
typedef void nettle_armor_init_func(void *ctx);
typedef size_t nettle_armor_encode_update_func(void *ctx,
- uint8_t *dst,
+ char *dst,
size_t src_length,
const uint8_t *src);
-typedef size_t nettle_armor_encode_final_func(void *ctx, uint8_t *dst);
+typedef size_t nettle_armor_encode_final_func(void *ctx, char *dst);
typedef int nettle_armor_decode_update_func(void *ctx,
size_t *dst_length,
uint8_t *dst,
size_t src_length,
- const uint8_t *src);
+ const char *src);
typedef int nettle_armor_decode_final_func(void *ctx);
diff --git a/nettle.texinfo b/nettle.texinfo
index 9cfaf43a..23eed335 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -93,6 +93,7 @@ Cipher modes
* CBC::
* CTR::
+* CFB::
* GCM::
* CCM::
@@ -1884,21 +1885,23 @@ a message that is larger than the cipher's block size. As explained in
processing them independently with the block cipher (Electronic Code
Book mode, @acronym{ECB}), leaks information.
-Besides @acronym{ECB}, Nettle provides a two other modes of operation:
-Cipher Block Chaining (@acronym{CBC}), Counter mode (@acronym{CTR}), and
-a couple of @acronym{AEAD} modes (@pxref{Authenticated encryption}).
-@acronym{CBC} is widely used, but there are a few subtle issues of
-information leakage, see, e.g.,
+Besides @acronym{ECB}, Nettle provides several other modes of operation:
+Cipher Block Chaining (@acronym{CBC}), Counter mode (@acronym{CTR}), Cipher
+Feedback (@acronym{CFB}) and a couple of @acronym{AEAD} modes
+(@pxref{Authenticated encryption}). @acronym{CBC} is widely used, but
+there are a few subtle issues of information leakage, see, e.g.,
@uref{http://www.kb.cert.org/vuls/id/958563, @acronym{SSH} @acronym{CBC}
vulnerability}. Today, @acronym{CTR} is usually preferred over @acronym{CBC}.
-Modes like @acronym{CBC} and @acronym{CTR} provide @emph{no} message
-authentication, and should always be used together with a @acronym{MAC}
-(@pxref{Keyed hash functions}) or signature to authenticate the message.
+Modes like @acronym{CBC}, @acronym{CTR} and @acronym{CFB} provide @emph{no}
+message authentication, and should always be used together with a
+@acronym{MAC} (@pxref{Keyed hash functions}) or signature to authenticate
+the message.
@menu
* CBC::
* CTR::
+* CFB::
@end menu
@node CBC, CTR, Cipher modes, Cipher modes
@@ -1994,7 +1997,7 @@ These macros use some tricks to make the compiler display a warning if
the types of @var{f} and @var{ctx} don't match, e.g. if you try to use
an @code{struct aes_ctx} context with the @code{des_encrypt} function.
-@node CTR, , CBC, Cipher modes
+@node CTR, CFB, CBC, Cipher modes
@comment node-name, next, previous, up
@subsection Counter mode
@@ -2070,6 +2073,91 @@ last three arguments define the source and destination area for the
operation.
@end deffn
+@node CFB, , CTR, Cipher modes
+@comment node-name, next, previous, up
+@subsection Cipher Feedback mode
+
+@cindex Cipher Feedback Mode
+@cindex CFB Mode
+
+Cipher Feedback mode (@acronym{CFB}) being a close relative to both
+@acronym{CBC} mode and @acronym{CTR} mode borrows some characteristics
+from stream ciphers.
+
+The message is divided into @code{n} blocks @code{M_1},@dots{}
+@code{M_n}, where @code{M_n} is of size @code{m} which may be smaller
+than the block size. Except for the last block, all the message blocks
+must be of size equal to the cipher's block size.
+
+If @code{E_k} is the encryption function of a block cipher, @code{IV} is
+the initialization vector, then the @code{n} plaintext blocks are
+transformed into @code{n} ciphertext blocks @code{C_1},@dots{}
+@code{C_n} as follows:
+
+@example
+C_1 = E_k(IV) XOR M_1
+C_2 = E_k(C_1) XOR M_2
+
+@dots{}
+
+C_(n-1) = E_k(C_(n - 2)) XOR M_(n-1)
+C_n = E_k(C_(n - 1)) [1..m] XOR M_n
+@end example
+
+Nettle's includes two functions for applying a block cipher in Cipher
+Feedback (@acronym{CFB}) mode, one for encryption and one for
+decryption. These functions uses @code{void *} to pass cipher contexts
+around.
+
+@deftypefun {void} cfb_encrypt (const void *@var{ctx}, nettle_cipher_func *@var{f}, size_t @var{block_size}, uint8_t *@var{iv}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx {void} cfb_decrypt (const void *@var{ctx}, nettle_cipher_func *@var{f}, size_t @var{block_size}, uint8_t *@var{iv}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+
+Applies the encryption or decryption function @var{f} in @acronym{CFB}
+mode. The final ciphertext block processed is copied into @var{iv}
+before returning, so that a large message can be processed by a sequence
+of calls to @code{cfb_encrypt}. Note that for @acronym{CFB} mode
+internally uses encryption only function and hence @var{f} should always
+be the encryption function for the underlying block cipher.
+
+When a message is encrypted using a sequence of calls to
+@code{cfb_encrypt}, all but the last call @emph{must} use a length that
+is a multiple of the block size.
+@end deftypefun
+
+Like for @acronym{CBC}, there are also a couple of helper macros.
+
+@deffn Macro CFB_CTX (@var{context_type}, @var{block_size})
+Expands to
+@example
+@{
+ context_type ctx;
+ uint8_t iv[block_size];
+@}
+@end example
+@end deffn
+
+@deffn Macro CFB_SET_IV(@var{ctx}, @var{iv})
+First argument is a pointer to a context struct as defined by
+@code{CFB_CTX}, and the second is a pointer to an initialization vector
+that is copied into that context.
+@end deffn
+
+@deffn Macro CFB_ENCRYPT (@var{ctx}, @var{f}, @var{length}, @var{dst}, @var{src})
+A simpler way to invoke @code{cfb_encrypt}. The first argument is a
+pointer to a context struct as defined by @code{CFB_CTX}, and the second
+argument is an encryption function following Nettle's conventions. The
+last three arguments define the source and destination area for the
+operation.
+@end deffn
+
+@deffn Macro CFB_DECRYPT (@var{ctx}, @var{f}, @var{length}, @var{dst}, @var{src})
+A simpler way to invoke @code{cfb_decrypt}. The first argument is a
+pointer to a context struct as defined by @code{CFB_CTX}, and the second
+argument is an encryption function following Nettle's conventions. The
+last three arguments define the source and destination area for the
+operation.
+@end deffn
+
@node Authenticated encryption, Keyed hash functions, Cipher modes, Reference
@comment node-name, next, previous, up
@@ -3366,12 +3454,7 @@ processing a new message.
@node Key derivation functions, Public-key algorithms, Keyed hash functions, Reference
@comment node-name, next, previous, up
@section Key derivation Functions
-
@cindex Key Derivation Function
-@cindex Password Based Key Derivation Function
-@cindex PKCS #5
-@cindex KDF
-@cindex PBKDF
A @dfn{key derivation function} (@acronym{KDF}) is a function that from
a given symmetric key derives other symmetric keys. A sub-class of KDFs
@@ -3380,7 +3463,51 @@ which take as input a password or passphrase, and its purpose is
typically to strengthen it and protect against certain pre-computation
attacks by using salting and expensive computation.
+@subsection HKDF: HMAC-based Extract-and-Expand
+@cindex HKDF
+
+HKDF is a key derivation function used as a building block of
+higher-level protocols like TLS 1.3. It is a derivation function
+based on HMAC described in @cite{RFC 5869},
+and is split into two logical modules, called 'extract' and 'expand'.
+The extract module takes an initial secret and a random
+salt to "extract" a fixed-length pseudorandom key (PRK). The second stage
+takes as input the previous PRK and some informational data (e.g.,
+text) and expands them into multiple keys.
+
+Nettle's @acronym{HKDF} functions are defined in
+@file{<nettle/hkdf.h>}. There are two abstract functions for the extract
+and expand operations that operate on any HMAC implemented via the @code{nettle_hash_update_func},
+and @code{nettle_hash_digest_func} interfaces.
+
+@deftypefun void hkdf_extract (void *mac_ctx, nettle_hash_update_func *update, nettle_hash_digest_func *digest, size_t digest_size,size_t secret_size, const uint8_t *secret, uint8_t *dst)
+Extract a Pseudorandom Key (PRK) from a secret and a salt according
+to HKDF. The HMAC must have been initialized, with its key being the
+salt for the Extract operation. This function will call the
+@var{update} and @var{digest} functions passing the @var{mac_ctx}
+context parameter as an argument in order to compute digest of size
+@var{digest_size}. Inputs are the secret @var{secret} of length
+@var{secret_length}. The output length is fixed to @var{digest_size} octets,
+thus the output buffer @var{dst} must have room for at least @var{digest_size} octets.
+@end deftypefun
+
+@deftypefun void hkdf_expand (void *mac_ctx, nettle_hash_update_func *update, nettle_hash_digest_func *digest, size_t digest_size, size_t info_size, const uint8_t *info, size_t length, uint8_t *dst)
+Expand a Pseudorandom Key (PRK) to an arbitrary size according to HKDF.
+The HMAC must have been initialized, with its key being the
+PRK from the Extract operation. This function will call the
+@var{update} and @var{digest} functions passing the @var{mac_ctx}
+context parameter as an argument in order to compute digest of size
+@var{digest_size}. Inputs are the info @var{info} of length
+@var{info_length}, and the desired derived output length @var{length}.
+The output buffer is @var{dst} which must have room for at least @var{length} octets.
+@end deftypefun
+
+
@subsection @acronym{PBKDF2}
+@cindex Password Based Key Derivation Function
+@cindex PKCS #5
+@cindex KDF
+@cindex PBKDF
The most well known PBKDF is the @code{PKCS #5 PBKDF2} described in
@cite{RFC 2898} which uses a pseudo-random function such as
@acronym{HMAC-SHA1}.
@@ -3770,6 +3897,43 @@ of the digest together with an object identifier for the used hash
algorithm.
@end deftypefun
+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
+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}
+algorithm, a longer salt value does not always mean a better security
+@uref{http://www.iacr.org/archive/eurocrypt2002/23320268/coron.pdf}.
+The typical choices of the length are between 0 and the digest size of
+the underlying hash function.
+
+Creating an RSA signature with the PSS padding scheme is done with one
+of the following functions:
+
+@deftypefun int rsa_pss_sha256_sign_digest_tr(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{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
+@deftypefunx int rsa_pss_sha384_sign_digest_tr(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{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
+@deftypefunx int rsa_pss_sha512_sign_digest_tr(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{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
+Creates a signature using the PSS padding scheme. @var{salt} should
+point to a salt string of size @var{salt_length}. @var{digest} should
+point to a digest of size @code{SHA256_DIGEST_SIZE},
+@code{SHA384_DIGEST_SIZE}, or @code{SHA512_DIGEST_SIZE}respectively. The
+signature is stored in @var{signature} (which must have been
+@code{mpz_init}:ed earlier).
+Returns one on success, or zero on failure.
+@end deftypefun
+
+Verifying an RSA signature with the PSS padding scheme is done with one
+of the following functions:
+
+@deftypefun int rsa_pss_sha256_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
+@deftypefunx int rsa_pss_sha384_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
+@deftypefunx int rsa_pss_sha512_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
+Returns 1 if the signature is valid, or 0 if it isn't. @var{digest}
+should point to a digest of size @code{SHA256_DIGEST_SIZE},
+@code{SHA384_DIGEST_SIZE}, or @code{SHA512_DIGEST_SIZE} respectively.
+@end deftypefun
+
The following function is used to encrypt a clear text message using RSA.
@deftypefun int rsa_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{length}, const uint8_t *@var{cleartext}, mpz_t @var{ciphertext})
Returns 1 on success, 0 on failure. If the message is too long then this
diff --git a/pgp-encode.c b/pgp-encode.c
index fc78e7f6..c051f9e4 100644
--- a/pgp-encode.c
+++ b/pgp-encode.c
@@ -371,8 +371,8 @@ pgp_armor(struct nettle_buffer *buffer,
length -= BINARY_PER_LINE, data += BINARY_PER_LINE)
{
unsigned done;
- uint8_t *p
- = nettle_buffer_space(buffer, TEXT_PER_LINE);
+ char *p
+ = (char *) nettle_buffer_space(buffer, TEXT_PER_LINE);
if (!p)
return 0;
@@ -393,8 +393,8 @@ pgp_armor(struct nettle_buffer *buffer,
+ BASE64_ENCODE_FINAL_LENGTH;
unsigned done;
- uint8_t *p
- = nettle_buffer_space(buffer, text_size);
+ char *p
+ = (char *) nettle_buffer_space(buffer, text_size);
if (!p)
return 0;
@@ -412,7 +412,7 @@ pgp_armor(struct nettle_buffer *buffer,
return 0;
{
- uint8_t *p = nettle_buffer_space(buffer, 4);
+ char *p = (char *) nettle_buffer_space(buffer, 4);
if (!p)
return 0;
base64_encode_group(p, crc);
diff --git a/pss-mgf1.c b/pss-mgf1.c
new file mode 100644
index 00000000..67df5570
--- /dev/null
+++ b/pss-mgf1.c
@@ -0,0 +1,73 @@
+/* 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 <assert.h>
+#include <string.h>
+
+#include "nettle-internal.h"
+#include "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;;
+ 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/pss-mgf1.h b/pss-mgf1.h
new file mode 100644
index 00000000..4a29c108
--- /dev/null
+++ b/pss-mgf1.h
@@ -0,0 +1,58 @@
+/* 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-meta.h"
+
+#include "sha1.h"
+#include "sha2.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* 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/pss.c b/pss.c
new file mode 100644
index 00000000..88125c06
--- /dev/null
+++ b/pss.c
@@ -0,0 +1,198 @@
+/* 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 "pss-mgf1.h"
+
+#include "bignum.h"
+#include "gmp-glue.h"
+
+#include "memxor.h"
+#include "nettle-internal.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;
+
+ if (mpz_sizeinbase(m, 2) > bits)
+ 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);
+
+ /* The leftmost 8 * emLen - emBits bits of the leftmost octet of EM
+ * must all equal to zero. Always true here, thanks to the above
+ * check on the bit size of m. */
+ assert((*em & ~pss_masks[(8 * key_size - bits)]) == 0);
+
+ /* 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/pss.h b/pss.h
new file mode 100644
index 00000000..7627cfe9
--- /dev/null
+++ b/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-types.h"
+#include "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/rsa-pss-sha256-sign-tr.c b/rsa-pss-sha256-sign-tr.c
new file mode 100644
index 00000000..b17e40ed
--- /dev/null
+++ b/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.h"
+
+#include "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/rsa-pss-sha256-verify.c b/rsa-pss-sha256-verify.c
new file mode 100644
index 00000000..81bc4e68
--- /dev/null
+++ b/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.h"
+
+#include "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/rsa-pss-sha512-sign-tr.c b/rsa-pss-sha512-sign-tr.c
new file mode 100644
index 00000000..59536d6d
--- /dev/null
+++ b/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.h"
+
+#include "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/rsa-pss-sha512-verify.c b/rsa-pss-sha512-verify.c
new file mode 100644
index 00000000..34f8e81d
--- /dev/null
+++ b/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.h"
+
+#include "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/rsa-verify.c b/rsa-verify.c
index 07715e2b..43a55d21 100644
--- a/rsa-verify.c
+++ b/rsa-verify.c
@@ -62,3 +62,17 @@ _rsa_verify(const struct rsa_public_key *key,
return res;
}
+
+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/rsa.h b/rsa.h
index 6d2574bc..2143fcd2 100644
--- a/rsa.h
+++ b/rsa.h
@@ -79,6 +79,12 @@ extern "C" {
#define rsa_sha512_sign_digest nettle_rsa_sha512_sign_digest
#define rsa_sha512_sign_digest_tr nettle_rsa_sha512_sign_digest_tr
#define rsa_sha512_verify_digest nettle_rsa_sha512_verify_digest
+#define rsa_pss_sha256_sign_digest_tr nettle_rsa_pss_sha256_sign_digest_tr
+#define rsa_pss_sha256_verify_digest nettle_rsa_pss_sha256_verify_digest
+#define rsa_pss_sha384_sign_digest_tr nettle_rsa_pss_sha384_sign_digest_tr
+#define rsa_pss_sha384_verify_digest nettle_rsa_pss_sha384_verify_digest
+#define rsa_pss_sha512_sign_digest_tr nettle_rsa_pss_sha512_sign_digest_tr
+#define rsa_pss_sha512_verify_digest nettle_rsa_pss_sha512_verify_digest
#define rsa_encrypt nettle_rsa_encrypt
#define rsa_decrypt nettle_rsa_decrypt
#define rsa_decrypt_tr nettle_rsa_decrypt_tr
@@ -93,6 +99,7 @@ extern "C" {
#define rsa_keypair_from_der nettle_rsa_keypair_from_der
#define rsa_keypair_to_openpgp nettle_rsa_keypair_to_openpgp
#define _rsa_verify _nettle_rsa_verify
+#define _rsa_verify_recover _nettle_rsa_verify_recover
#define _rsa_check_size _nettle_rsa_check_size
#define _rsa_blind _nettle_rsa_blind
#define _rsa_unblind _nettle_rsa_unblind
@@ -341,6 +348,49 @@ rsa_sha512_verify_digest(const struct rsa_public_key *key,
const uint8_t *digest,
const mpz_t signature);
+/* PSS style signatures */
+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);
+
/* RSA encryption, using PKCS#1 */
/* These functions uses the v1.5 padding. What should the v2 (OAEP)
@@ -480,6 +530,11 @@ _rsa_verify(const struct rsa_public_key *key,
const mpz_t m,
const mpz_t s);
+int
+_rsa_verify_recover(const struct rsa_public_key *key,
+ mpz_t m,
+ const mpz_t s);
+
size_t
_rsa_check_size(mpz_t n);
diff --git a/sexp-transport-format.c b/sexp-transport-format.c
index c9946a70..4f83f888 100644
--- a/sexp-transport-format.c
+++ b/sexp-transport-format.c
@@ -40,6 +40,12 @@
#include "base64.h"
#include "buffer.h"
+static inline void
+base64_encode_in_place (size_t length, uint8_t *data)
+{
+ base64_encode_raw ((char *) data, length, data);
+}
+
size_t
sexp_transport_vformat(struct nettle_buffer *buffer,
const char *format, va_list args)
@@ -68,8 +74,7 @@ sexp_transport_vformat(struct nettle_buffer *buffer,
if (!nettle_buffer_space(buffer, base64_length - length))
return 0;
- base64_encode_raw(buffer->contents + start,
- length, buffer->contents + start);
+ base64_encode_in_place(length, buffer->contents + start);
if (!NETTLE_BUFFER_PUTC(buffer, '}'))
return 0;
diff --git a/sexp-transport.c b/sexp-transport.c
index 8736478a..1a34db71 100644
--- a/sexp-transport.c
+++ b/sexp-transport.c
@@ -84,7 +84,7 @@ sexp_transport_iterator_first(struct sexp_iterator *iterator,
base64_decode_init(&ctx);
if (base64_decode_update(&ctx, &coded_length, input + out,
- end - in, input + in)
+ end - in, (const char*) (input + in))
&& base64_decode_final(&ctx))
{
out += coded_length;
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 8e5521b4..5db4e789 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -12,39 +12,61 @@
/cast128-test
/cbc-test
/ccm-test
+/cfb-test
+/chacha-poly1305-test
+/chacha-test
/ctr-test
+/curve25519-dh-test
/cxx-test
/des-compat-test
/des-test
/des3-test
+/dlopen-test
/dsa-keygen-test
/dsa-test
+/eax-test
+/ecc-add-test
+/ecc-dup-test
/ecc-mod-test
/ecc-modinv-test
/ecc-mul-a-test
/ecc-mul-g-test
/ecc-redc-test
+/ecc-sqrt-test
+/ecdh-test
/ecdsa-keygen-test
/ecdsa-sign-test
/ecdsa-verify-test
+/ed25519-test
+/eddsa-compress-test
+/eddsa-sign-test
+/eddsa-verify-test
/gcm-test
/gosthash94-test
+/hkdf-test
/hmac-test
/knuth-lfib-test
/md2-test
/md4-test
/md5-compat-test
/md5-test
+/memeql-test
/memxor-test
+/meta-aead-test
/meta-armor-test
/meta-cipher-test
/meta-hash-test
/pbkdf2-test
/pkcs1-test
+/poly1305-test
+/pss-mgf1-test
+/pss-test
/random-prime-test
/ripemd160-test
/rsa-encrypt-test
/rsa-keygen-test
+/rsa-pss-sign-tr-test
+/rsa-sign-tr-test
/rsa-test
/rsa2sexp-test
/salsa20-test
@@ -62,9 +84,12 @@
/sha3-512-test
/sha3-permute-test
/sha384-test
+/sha512-224-test
+/sha512-256-test
/sha512-test
/twofish-test
/umac-test
+/version-test
/yarrow-test
/test.in
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index b263e1fd..1f780310 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -58,6 +58,9 @@ gosthash94-test$(EXEEXT): gosthash94-test.$(OBJEXT)
ripemd160-test$(EXEEXT): ripemd160-test.$(OBJEXT)
$(LINK) ripemd160-test.$(OBJEXT) $(TEST_OBJS) -o ripemd160-test$(EXEEXT)
+hkdf-test$(EXEEXT): hkdf-test.$(OBJEXT)
+ $(LINK) hkdf-test.$(OBJEXT) $(TEST_OBJS) -o hkdf-test$(EXEEXT)
+
salsa20-test$(EXEEXT): salsa20-test.$(OBJEXT)
$(LINK) salsa20-test.$(OBJEXT) $(TEST_OBJS) -o salsa20-test$(EXEEXT)
@@ -112,6 +115,9 @@ knuth-lfib-test$(EXEEXT): knuth-lfib-test.$(OBJEXT)
cbc-test$(EXEEXT): cbc-test.$(OBJEXT)
$(LINK) cbc-test.$(OBJEXT) $(TEST_OBJS) -o cbc-test$(EXEEXT)
+cfb-test$(EXEEXT): cfb-test.$(OBJEXT)
+ $(LINK) cfb-test.$(OBJEXT) $(TEST_OBJS) -o cfb-test$(EXEEXT)
+
ctr-test$(EXEEXT): ctr-test.$(OBJEXT)
$(LINK) ctr-test.$(OBJEXT) $(TEST_OBJS) -o ctr-test$(EXEEXT)
@@ -157,6 +163,9 @@ yarrow-test$(EXEEXT): yarrow-test.$(OBJEXT)
pbkdf2-test$(EXEEXT): pbkdf2-test.$(OBJEXT)
$(LINK) pbkdf2-test.$(OBJEXT) $(TEST_OBJS) -o pbkdf2-test$(EXEEXT)
+pss-mgf1-test$(EXEEXT): pss-mgf1-test.$(OBJEXT)
+ $(LINK) pss-mgf1-test.$(OBJEXT) $(TEST_OBJS) -o pss-mgf1-test$(EXEEXT)
+
sexp-test$(EXEEXT): sexp-test.$(OBJEXT)
$(LINK) sexp-test.$(OBJEXT) $(TEST_OBJS) -o sexp-test$(EXEEXT)
@@ -178,9 +187,15 @@ 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)
+rsa-pss-sign-tr-test$(EXEEXT): rsa-pss-sign-tr-test.$(OBJEXT)
+ $(LINK) rsa-pss-sign-tr-test.$(OBJEXT) $(TEST_OBJS) -o rsa-pss-sign-tr-test$(EXEEXT)
+
rsa-test$(EXEEXT): rsa-test.$(OBJEXT)
$(LINK) rsa-test.$(OBJEXT) $(TEST_OBJS) -o rsa-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 790b3c78..3117d66d 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -17,7 +17,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
des-test.c des3-test.c des-compat-test.c \
md2-test.c md4-test.c md5-test.c md5-compat-test.c \
memeql-test.c memxor-test.c gosthash94-test.c \
- ripemd160-test.c \
+ ripemd160-test.c hkdf-test.c \
salsa20-test.c \
sha1-test.c sha224-test.c sha256-test.c \
sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \
@@ -25,17 +25,18 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
sha3-384-test.c sha3-512-test.c \
serpent-test.c twofish-test.c version-test.c \
knuth-lfib-test.c \
- cbc-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \
+ cbc-test.c cfb-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \
poly1305-test.c chacha-poly1305-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 pss-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-pss-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 \
@@ -66,6 +67,7 @@ EXTRA_TARGETS = $(EXTRA_SOURCES:.c=$(EXEEXT))
SOURCES = $(TS_SOURCES) $(EXTRA_SOURCES) testutils.c dlopen-test.c
DISTFILES = $(SOURCES) $(CXX_SOURCES) Makefile.in .test-rules.make \
+ test-rules.stamp \
$(TS_SH) setup-env teardown-env \
gold-bug.txt testutils.h sha3.awk
@@ -107,6 +109,14 @@ test-rules:
echo ; \
done) > $(srcdir)/.test-rules.make
+$(srcdir)/.test-rules.make: $(srcdir)/test-rules.stamp
+
+# Updates the stamp file *first*, so that this rule isn't triggered
+# again and again by the recursive $(MAKE).
+$(srcdir)/test-rules.stamp: Makefile.in
+ echo stamp > $(srcdir)/test-rules.stamp
+ $(MAKE) test-rules
+
include $(srcdir)/.test-rules.make
$(TARGETS) $(EXTRA_TARGETS): testutils.$(OBJEXT) ../nettle-internal.$(OBJEXT) \
diff --git a/testsuite/base64-test.c b/testsuite/base64-test.c
index f366a413..cc45c471 100644
--- a/testsuite/base64-test.c
+++ b/testsuite/base64-test.c
@@ -9,7 +9,7 @@ test_fuzz_once(struct base64_encode_ctx *encode,
{
size_t base64_len = BASE64_ENCODE_RAW_LENGTH (size);
size_t out_len;
- uint8_t *base64 = xalloc (base64_len + 2);
+ char *base64 = xalloc (base64_len + 2);
uint8_t *decoded = xalloc (size + 2);
*base64++ = 0x12;
@@ -66,6 +66,20 @@ test_fuzz(void)
}
}
+static inline void
+base64_encode_in_place (size_t length, uint8_t *data)
+{
+ base64_encode_raw ((char *) data, length, data);
+}
+
+static inline int
+base64_decode_in_place (struct base64_decode_ctx *ctx, size_t *dst_length,
+ size_t length, uint8_t *data)
+{
+ return base64_decode_update (ctx, dst_length,
+ data, length, (const char *) data);
+}
+
void
test_main(void)
{
@@ -111,12 +125,12 @@ test_main(void)
size_t dst_length;
ASSERT(BASE64_ENCODE_RAW_LENGTH(5) == 8);
- base64_encode_raw(buffer, 5, buffer);
+ base64_encode_in_place(5, buffer);
ASSERT(MEMEQ(9, buffer, "SGVsbG8=x"));
base64_decode_init(&ctx);
dst_length = 0; /* Output parameter only. */
- ASSERT(base64_decode_update(&ctx, &dst_length, buffer, 8, buffer));
+ ASSERT(base64_decode_in_place(&ctx, &dst_length, 8, buffer));
ASSERT(dst_length == 5);
ASSERT(MEMEQ(9, buffer, "HelloG8=x"));
diff --git a/testsuite/cfb-test.c b/testsuite/cfb-test.c
new file mode 100644
index 00000000..b59bee22
--- /dev/null
+++ b/testsuite/cfb-test.c
@@ -0,0 +1,287 @@
+#include "testutils.h"
+#include "aes.h"
+#include "cfb.h"
+#include "knuth-lfib.h"
+
+/* Test with more data and inplace decryption, to check that the
+ * cfb_decrypt buffering works. */
+#define CFB_BULK_DATA 10000
+
+static void
+test_cfb_bulk(void)
+{
+ struct knuth_lfib_ctx random;
+
+ uint8_t clear[CFB_BULK_DATA];
+
+ uint8_t cipher[CFB_BULK_DATA + 1];
+
+ const uint8_t *key = H("966c7bf00bebe6dc 8abd37912384958a"
+ "743008105a08657d dcaad4128eee38b3");
+
+ const uint8_t *start_iv = H("11adbff119749103 207619cfa0e8d13a");
+ const uint8_t *end_iv = H("1fd0a9189b8480b7 b06a2b36ef5943ba");
+
+ struct CFB_CTX(struct aes_ctx, AES_BLOCK_SIZE) aes;
+
+ knuth_lfib_init(&random, CFB_BULK_DATA);
+ knuth_lfib_random(&random, CFB_BULK_DATA, clear);
+
+ /* Byte that should not be overwritten */
+ cipher[CFB_BULK_DATA] = 17;
+
+ aes_set_encrypt_key(&aes.ctx, 32, key);
+ CFB_SET_IV(&aes, start_iv);
+
+ CFB_ENCRYPT(&aes, aes_encrypt, CFB_BULK_DATA, cipher, clear);
+
+ ASSERT(cipher[CFB_BULK_DATA] == 17);
+
+ if (verbose)
+ {
+ printf("IV after bulk encryption: ");
+ print_hex(AES_BLOCK_SIZE, aes.iv);
+ printf("\n");
+ }
+
+ ASSERT(MEMEQ(AES_BLOCK_SIZE, aes.iv, end_iv));
+
+ /* Decrypt, in place */
+ aes_set_encrypt_key(&aes.ctx, 32, key);
+ CFB_SET_IV(&aes, start_iv);
+ CFB_DECRYPT(&aes, aes_encrypt, CFB_BULK_DATA, cipher, cipher);
+
+ ASSERT(cipher[CFB_BULK_DATA] == 17);
+
+ if (verbose)
+ {
+ printf("IV after bulk decryption: ");
+ print_hex(AES_BLOCK_SIZE, aes.iv);
+ printf("\n");
+ }
+
+ ASSERT (MEMEQ(AES_BLOCK_SIZE, aes.iv, end_iv));
+ ASSERT (MEMEQ(CFB_BULK_DATA, clear, cipher));
+}
+
+void
+test_main(void)
+{
+ /* From NIST spec 800-38a on AES modes.
+ *
+ * F.3 CFB Example Vectors
+ * F.3.13 CFB128-AES128.Encrypt
+ */
+
+ /* Intermediate values, blocks input to AES:
+ *
+ * 000102030405060708090a0b0c0d0e0f
+ * 3b3fd92eb72dad20333449f8e83cfb4a
+ * c8a64537a0b3a93fcde3cdad9f1ce58b
+ * 26751f67a3cbb140b1808cf187a4f4df
+ */
+ test_cipher_cfb(&nettle_aes128,
+ SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+ SHEX("6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ SHEX("3b3fd92eb72dad20333449f8e83cfb4a"
+ "c8a64537a0b3a93fcde3cdad9f1ce58b"
+ "26751f67a3cbb140b1808cf187a4f4df"
+ "c04b05357c5d1c0eeac4c66f9ff7f2e6"),
+ SHEX("000102030405060708090a0b0c0d0e0f"));
+
+ /* F.3.15 CFB128-AES192.Encrypt */
+
+ /* Intermediate values, blocks input to AES:
+ *
+ * 000102030405060708090a0b0c0d0e0f
+ * cdc80d6fddf18cab34c25909c99a4174
+ * 67ce7f7f81173621961a2b70171d3d7a
+ * 2e1e8a1dd59b88b1c8e60fed1efac4c9
+ */
+
+ test_cipher_cfb(&nettle_aes192,
+ SHEX("8e73b0f7da0e6452c810f32b809079e5"
+ "62f8ead2522c6b7b"),
+ SHEX("6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ SHEX("cdc80d6fddf18cab34c25909c99a4174"
+ "67ce7f7f81173621961a2b70171d3d7a"
+ "2e1e8a1dd59b88b1c8e60fed1efac4c9"
+ "c05f9f9ca9834fa042ae8fba584b09ff"),
+ SHEX("000102030405060708090a0b0c0d0e0f"));
+
+ /* F.3.17 CFB128-AES256.Encrypt */
+
+ /* Intermediate values, blcoks input to AES:
+ *
+ * 000102030405060708090a0b0c0d0e0f
+ * dc7e84bfda79164b7ecd8486985d3860
+ * 39ffed143b28b1c832113c6331e5407b
+ * df10132415e54b92a13ed0a8267ae2f9
+ */
+
+ test_cipher_cfb(&nettle_aes256,
+ SHEX("603deb1015ca71be2b73aef0857d7781"
+ "1f352c073b6108d72d9810a30914dff4"),
+ SHEX("6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ SHEX("dc7e84bfda79164b7ecd8486985d3860"
+ "39ffed143b28b1c832113c6331e5407b"
+ "df10132415e54b92a13ed0a8267ae2f9"
+ "75a385741ab9cef82031623d55b1e471"),
+ SHEX("000102030405060708090a0b0c0d0e0f"));
+
+ test_cfb_bulk();
+}
+
+/*
+F.3.13 CFB128-AES128.Encrypt
+Key 2b7e151628aed2a6abf7158809cf4f3c
+IV 000102030405060708090a0b0c0d0e0f
+Segment #1
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block 50fe67cc996d32b6da0937e99bafec60
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Ciphertext 3b3fd92eb72dad20333449f8e83cfb4a
+Segment #2
+Input Block 3b3fd92eb72dad20333449f8e83cfb4a
+Output Block 668bcf60beb005a35354a201dab36bda
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext c8a64537a0b3a93fcde3cdad9f1ce58b
+Segment #3
+Input Block c8a64537a0b3a93fcde3cdad9f1ce58b
+Output Block 16bd032100975551547b4de89daea630
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext 26751f67a3cbb140b1808cf187a4f4df
+Segment #4
+Input Block 26751f67a3cbb140b1808cf187a4f4df
+Output Block 36d42170a312871947ef8714799bc5f6
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+Ciphertext c04b05357c5d1c0eeac4c66f9ff7f2e6
+F.3.14 CFB128-AES128.Decrypt
+Key 2b7e151628aed2a6abf7158809cf4f3c
+IV 000102030405060708090a0b0c0d0e0f
+Segment #1
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block 50fe67cc996d32b6da0937e99bafec60
+Ciphertext 3b3fd92eb72dad20333449f8e83cfb4a
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Segment #2
+Input Block 3b3fd92eb72dad20333449f8e83cfb4a
+Output Block 668bcf60beb005a35354a201dab36bda
+Ciphertext c8a64537a0b3a93fcde3cdad9f1ce58b
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Segment #3
+Input Block c8a64537a0b3a93fcde3cdad9f1ce58b
+Output Block 16bd032100975551547b4de89daea630
+Ciphertext 26751f67a3cbb140b1808cf187a4f4df
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Segment #4
+Input Block 26751f67a3cbb140b1808cf187a4f4df
+Output Block 36d42170a312871947ef8714799bc5f6
+Ciphertext c04b05357c5d1c0eeac4c66f9ff7f2e6
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+F.3.15 CFB128-AES192.Encrypt
+Key 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+000102030405060708090a0b0c0d0e0f
+Segment #1
+50
+IV
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block a609b38df3b1133dddff2718ba09565e
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Ciphertext cdc80d6fddf18cab34c25909c99a4174
+Segment #2
+Input Block cdc80d6fddf18cab34c25909c99a4174
+Output Block c9e3f5289f149abd08ad44dc52b2b32b
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext 67ce7f7f81173621961a2b70171d3d7a
+Segment #3
+Input Block 67ce7f7f81173621961a2b70171d3d7a
+Output Block 1ed6965b76c76ca02d1dcef404f09626
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext 2e1e8a1dd59b88b1c8e60fed1efac4c9
+Segment #4
+Input Block 2e1e8a1dd59b88b1c8e60fed1efac4c9
+Output Block 36c0bbd976ccd4b7ef85cec1be273eef
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+Ciphertext c05f9f9ca9834fa042ae8fba584b09ff
+F.3.16 CFB128-AES192.Decrypt
+Key 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+IV 000102030405060708090a0b0c0d0e0f
+Segment #1
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block a609b38df3b1133dddff2718ba09565e
+Ciphertext cdc80d6fddf18cab34c25909c99a4174
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Segment #2
+Input Block cdc80d6fddf18cab34c25909c99a4174
+Output Block c9e3f5289f149abd08ad44dc52b2b32b
+Ciphertext 67ce7f7f81173621961a2b70171d3d7a
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Segment #3
+Input Block 67ce7f7f81173621961a2b70171d3d7a
+Output Block 1ed6965b76c76ca02d1dcef404f09626
+Ciphertext 2e1e8a1dd59b88b1c8e60fed1efac4c9
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Segment #4
+Input Block 2e1e8a1dd59b88b1c8e60fed1efac4c9
+Output Block 36c0bbd976ccd4b7ef85cec1be273eef
+Ciphertext c05f9f9ca9834fa042ae8fba584b09ff
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+F.3.17 CFB128-AES256.Encrypt
+Key 603deb1015ca71be2b73aef0857d7781
+1f352c073b6108d72d9810a30914dff4
+IV 000102030405060708090a0b0c0d0e0f
+Segment #1
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block b7bf3a5df43989dd97f0fa97ebce2f4a
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Ciphertext dc7e84bfda79164b7ecd8486985d3860
+Segment #2
+Input Block dc7e84bfda79164b7ecd8486985d3860
+Output Block 97d26743252b1d54aca653cf744ace2a
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Ciphertext 39ffed143b28b1c832113c6331e5407b
+Segment #3
+Input Block 39ffed143b28b1c832113c6331e5407b
+Output Block efd80f62b6b9af8344c511b13c70b016
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Ciphertext df10132415e54b92a13ed0a8267ae2f9
+Segment #4
+Input Block df10132415e54b92a13ed0a8267ae2f9
+Output Block 833ca131c5f655ef8d1a2346b3ddd361
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+Ciphertext 75a385741ab9cef82031623d55b1e471
+F.3.18 CFB128-AES256.Decrypt
+Key 603deb1015ca71be2b73aef0857d7781
+1f352c073b6108d72d9810a30914dff4
+IV 000102030405060708090a0b0c0d0e0f
+Segment #1
+Input Block 000102030405060708090a0b0c0d0e0f
+Output Block b7bf3a5df43989dd97f0fa97ebce2f4a
+Ciphertext dc7e84bfda79164b7ecd8486985d3860
+Plaintext 6bc1bee22e409f96e93d7e117393172a
+Segment #2
+Input Block dc7e84bfda79164b7ecd8486985d3860
+Output Block 97d26743252b1d54aca653cf744ace2a
+Ciphertext 39ffed143b28b1c832113c6331e5407b
+Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
+Segment #3
+Input Block 39ffed143b28b1c832113c6331e5407b
+Output Block efd80f62b6b9af8344c511b13c70b016
+Ciphertext df10132415e54b92a13ed0a8267ae2f9
+Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
+Segment #4
+Input Block df10132415e54b92a13ed0a8267ae2f9
+Output Block 833ca131c5f655ef8d1a2346b3ddd361
+Ciphertext 75a385741ab9cef82031623d55b1e471
+Plaintext f69f2445df4f9b17ad2b417be66c3710
+*/
diff --git a/testsuite/dlopen-test.c b/testsuite/dlopen-test.c
index 23ff25ad..99d3535b 100644
--- a/testsuite/dlopen-test.c
+++ b/testsuite/dlopen-test.c
@@ -28,6 +28,7 @@ main (int argc UNUSED, char **argv UNUSED)
fprintf (stderr, "unexpected nettle version\n");
FAIL ();
}
+ dlclose (handle);
return EXIT_SUCCESS;
#else
SKIP();
diff --git a/testsuite/ecc-mul-a-test.c b/testsuite/ecc-mul-a-test.c
index b206b848..245016aa 100644
--- a/testsuite/ecc-mul-a-test.c
+++ b/testsuite/ecc-mul-a-test.c
@@ -26,7 +26,7 @@ test_main (void)
ecc->mul (ecc, p, n, ecc->g, scratch);
ecc->h_to_a (ecc, 0, p, p, scratch);
- if (mpn_cmp (p, ecc->g, 2*size != 0))
+ if (mpn_cmp (p, ecc->g, 2*size) != 0)
die ("curve %d: ecc->mul with n = 1 failed.\n", ecc->p.bit_size);
for (n[0] = 2; n[0] <= 4; n[0]++)
diff --git a/testsuite/ecc-mul-g-test.c b/testsuite/ecc-mul-g-test.c
index 1c4d0c05..27239484 100644
--- a/testsuite/ecc-mul-g-test.c
+++ b/testsuite/ecc-mul-g-test.c
@@ -25,7 +25,7 @@ test_main (void)
ecc->mul_g (ecc, p, n, scratch);
ecc->h_to_a (ecc, 0, p, p, scratch);
- if (mpn_cmp (p, ecc->g, 2*size != 0))
+ if (mpn_cmp (p, ecc->g, 2*size) != 0)
{
fprintf (stderr, "ecc->mul_g with n = 1 failed.\n");
abort ();
diff --git a/testsuite/hkdf-test.c b/testsuite/hkdf-test.c
new file mode 100644
index 00000000..80f4c813
--- /dev/null
+++ b/testsuite/hkdf-test.c
@@ -0,0 +1,143 @@
+#include "testutils.h"
+#include "hkdf.h"
+#include "hmac.h"
+
+static void
+test_hkdf_sha256(const struct tstring *ikm,
+ const struct tstring *salt,
+ const struct tstring *info,
+ const struct tstring *extract_output,
+ const struct tstring *expand_output)
+{
+ struct hmac_sha256_ctx ctx;
+ uint8_t prk[SHA256_DIGEST_SIZE];
+ uint8_t *buffer = xalloc(expand_output->length);
+
+ hmac_sha256_set_key(&ctx, salt->length, salt->data);
+ hkdf_extract(&ctx,
+ (nettle_hash_update_func*) hmac_sha256_update,
+ (nettle_hash_digest_func*) hmac_sha256_digest,
+ SHA256_DIGEST_SIZE,
+ ikm->length, ikm->data, prk);
+
+ if (MEMEQ(SHA256_DIGEST_SIZE, prk, extract_output->data) == 0)
+ {
+ fprintf(stdout, "\nGot:\n");
+ print_hex(SHA256_DIGEST_SIZE, prk);
+ fprintf(stdout, "\nExpected:\n");
+ print_hex(extract_output->length, extract_output->data);
+ abort();
+ }
+
+ hmac_sha256_set_key(&ctx, SHA256_DIGEST_SIZE, prk);
+ hkdf_expand(&ctx,
+ (nettle_hash_update_func*) hmac_sha256_update,
+ (nettle_hash_digest_func*) hmac_sha256_digest,
+ SHA256_DIGEST_SIZE,
+ info->length, info->data,
+ expand_output->length, buffer);
+
+ if (MEMEQ(expand_output->length, expand_output->data, buffer) == 0)
+ {
+ fprintf(stdout, "\nGot:\n");
+ print_hex(expand_output->length, buffer);
+ fprintf(stdout, "\nExpected:\n");
+ print_hex(expand_output->length, expand_output->data);
+ abort();
+ }
+ free(buffer);
+}
+
+static void
+test_hkdf_sha1(const struct tstring *ikm,
+ const struct tstring *salt,
+ const struct tstring *info,
+ const struct tstring *extract_output,
+ const struct tstring *expand_output)
+{
+ struct hmac_sha1_ctx ctx;
+ uint8_t prk[SHA1_DIGEST_SIZE];
+ uint8_t *buffer = xalloc(expand_output->length);
+
+ hmac_sha1_set_key(&ctx, salt->length, salt->data);
+ hkdf_extract(&ctx,
+ (nettle_hash_update_func*) hmac_sha1_update,
+ (nettle_hash_digest_func*) hmac_sha1_digest,
+ SHA1_DIGEST_SIZE,
+ ikm->length, ikm->data,
+ prk);
+
+ if (MEMEQ(SHA1_DIGEST_SIZE, prk, extract_output->data) == 0)
+ {
+ fprintf(stdout, "\nGot:\n");
+ print_hex(SHA1_DIGEST_SIZE, prk);
+ fprintf(stdout, "\nExpected:\n");
+ print_hex(extract_output->length, extract_output->data);
+ abort();
+ }
+
+ hmac_sha1_set_key(&ctx, SHA1_DIGEST_SIZE, prk);
+ hkdf_expand(&ctx,
+ (nettle_hash_update_func*) hmac_sha1_update,
+ (nettle_hash_digest_func*) hmac_sha1_digest,
+ SHA1_DIGEST_SIZE,
+ info->length, info->data,
+ expand_output->length, buffer);
+
+ if (MEMEQ(expand_output->length, expand_output->data, buffer) == 0)
+ {
+ fprintf(stdout, "\nGot:\n");
+ print_hex(expand_output->length, buffer);
+ fprintf(stdout, "\nExpected:\n");
+ print_hex(expand_output->length, expand_output->data);
+ abort();
+ }
+ free(buffer);
+}
+
+void
+test_main(void)
+{
+ /* HKDF test vectors from RFC5869 */
+ test_hkdf_sha256(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ SHEX("000102030405060708090a0b0c"),
+ SHEX("f0f1f2f3f4f5f6f7f8f9"),
+ SHEX("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"),
+ SHEX("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"));
+
+ test_hkdf_sha256(SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"),
+ SHEX("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"),
+ SHEX("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ SHEX("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"),
+ SHEX("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"));
+
+ test_hkdf_sha256(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ SDATA(""),
+ SDATA(""),
+ SHEX("19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"),
+ SHEX("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"));
+
+ test_hkdf_sha1(SHEX("0b0b0b0b0b0b0b0b0b0b0b"),
+ SHEX("000102030405060708090a0b0c"),
+ SHEX("f0f1f2f3f4f5f6f7f8f9"),
+ SHEX("9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"),
+ SHEX("085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"));
+
+ test_hkdf_sha1(SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"),
+ SHEX("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"),
+ SHEX("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ SHEX("8adae09a2a307059478d309b26c4115a224cfaf6"),
+ SHEX("0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"));
+
+ test_hkdf_sha1(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ SDATA(""),
+ SDATA(""),
+ SHEX("da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"),
+ SHEX("0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"));
+
+ test_hkdf_sha1(SHEX("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),
+ SHEX(""),
+ SHEX(""),
+ SHEX("2adccada18779e7c2077ad2eb19d3f3e731385dd"),
+ SHEX("2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"));
+}
diff --git a/testsuite/meta-hash-test.c b/testsuite/meta-hash-test.c
index afc71504..4754f665 100644
--- a/testsuite/meta-hash-test.c
+++ b/testsuite/meta-hash-test.c
@@ -1,6 +1,8 @@
#include "testutils.h"
#include "nettle-internal.h"
#include "nettle-meta.h"
+/* For NETTLE_MAX_HASH_CONTEXT_SIZE */
+#include "sha3.h"
const char* hashes[] = {
"md2",
@@ -28,9 +30,9 @@ test_main(void)
ASSERT(nettle_lookup_hash(hashes[i]) != NULL);
}
- while (NULL != nettle_hashes[i])
- i++;
- ASSERT(i == count); /* we are not missing testing any hashes */
- for (i = 0; NULL != nettle_hashes[i]; i++)
+ for (i = 0; NULL != nettle_hashes[i]; i++) {
ASSERT(nettle_hashes[i]->digest_size <= NETTLE_MAX_HASH_DIGEST_SIZE);
+ ASSERT(nettle_hashes[i]->context_size <= NETTLE_MAX_HASH_CONTEXT_SIZE);
+ }
+ ASSERT(i == count); /* we are not missing testing any hashes */
}
diff --git a/testsuite/pss-mgf1-test.c b/testsuite/pss-mgf1-test.c
new file mode 100644
index 00000000..640500b5
--- /dev/null
+++ b/testsuite/pss-mgf1-test.c
@@ -0,0 +1,36 @@
+#include "testutils.h"
+#include "pss-mgf1.h"
+
+void
+test_main(void)
+{
+ struct sha1_ctx sha1ctx;
+ struct sha256_ctx sha256ctx;
+ const struct tstring *seed, *expected;
+ uint8_t mask[120];
+
+ /* From ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip */
+ seed = SHEX("df1a896f9d8bc816d97cd7a2c43bad54"
+ "6fbe8cfe");
+ expected = SHEX("66e4672e836ad121ba244bed6576b867d9a447c28a6e66a5b87dee"
+ "7fbc7e65af5057f86fae8984d9ba7f969ad6fe02a4d75f7445fefd"
+ "d85b6d3a477c28d24ba1e3756f792dd1dce8ca94440ecb5279ecd3"
+ "183a311fc89739a96643136e8b0f465e87a4535cd4c59b10028d");
+ sha1_init(&sha1ctx);
+ sha1_update(&sha1ctx, seed->length, seed->data);
+ pss_mgf1(&sha1ctx, &nettle_sha1, expected->length, mask);
+ ASSERT(MEMEQ (expected->length, mask, expected->data));
+
+ /* Test with our own data. */
+ seed = SDATA("abc");
+ expected = SHEX("cf2db1ac9867debdf8ce91f99f141e5544bf26ca36b3fd4f8e4035"
+ "eec42cab0d46c386ebccef82ba0bb0b095aaa5548b03cdff695187"
+ "1c6fb505af68af688332f885d324a47d2145a3d8392c37978d7dc9"
+ "84c95728950c4cf3de6becc59e60ea506951bd40e6de3863095064"
+ "3ab2edbb47dc66cb54beb2d1");
+
+ sha256_init(&sha256ctx);
+ sha256_update(&sha256ctx, seed->length, seed->data);
+ pss_mgf1(&sha256ctx, &nettle_sha256, expected->length, mask);
+ ASSERT(MEMEQ (expected->length, mask, expected->data));
+}
diff --git a/testsuite/pss-test.c b/testsuite/pss-test.c
new file mode 100644
index 00000000..f6ba697c
--- /dev/null
+++ b/testsuite/pss-test.c
@@ -0,0 +1,86 @@
+#include "testutils.h"
+
+#include "pss.h"
+
+void
+test_main(void)
+{
+ struct tstring *salt;
+ struct tstring *digest;
+ mpz_t m;
+ mpz_t expected;
+
+ /* From ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip */
+ mpz_init(m);
+ mpz_init(expected);
+
+ salt = SHEX("e3b5d5d002c1bce50c2b65ef88a188d83bce7e61");
+ digest = SHEX("37b66ae0445843353d47ecb0b4fd14c110e62d6a");
+ ASSERT(pss_encode_mgf1(m, 1024, &nettle_sha1,
+ salt->length, salt->data, digest->data));
+
+ mpz_set_str(expected,
+ "66e4672e836ad121ba244bed6576b867d9a447c28a6e66a5b87dee"
+ "7fbc7e65af5057f86fae8984d9ba7f969ad6fe02a4d75f7445fefd"
+ "d85b6d3a477c28d24ba1e3756f792dd1dce8ca94440ecb5279ecd3"
+ "183a311fc896da1cb39311af37ea4a75e24bdbfd5c1da0de7cecdf"
+ "1a896f9d8bc816d97cd7a2c43bad546fbe8cfebc", 16);
+
+ ASSERT(mpz_cmp(m, expected) == 0);
+
+ mpz_add_ui(m, m, 2);
+ ASSERT(!pss_verify_mgf1(m, 1024, &nettle_sha1, salt->length, digest->data));
+
+ mpz_sub_ui(m, m, 2);
+ ASSERT(pss_verify_mgf1(m, 1024, &nettle_sha1, salt->length, digest->data));
+
+ mpz_clear(m);
+ mpz_clear(expected);
+
+ /* Test with our own data. */
+ mpz_init(m);
+ mpz_init(expected);
+
+ salt = SHEX("11223344556677889900");
+ /* From sha256-test.c */
+ digest = SHEX("ba7816bf8f01cfea 414140de5dae2223"
+ "b00361a396177a9c b410ff61f20015ad");
+
+ mpz_set_str(expected,
+ "76b9a52705c8382c5367732f993184eff340b6305c9f73e7e308c8"
+ "004fcc15cbbaab01e976bae4b774628595379a2d448a36b3ea6fa8"
+ "353b97eeea7bdac93b4b7807ac98cd4b3bebfb31f3718e1dd3625f"
+ "227fbb8696606498e7070e21c3cbbd7386ea20eb81ac7927e0c6d1"
+ "d7788826a63af767f301bcc05dd65b00da862cbc", 16);
+
+ /* Try bad salt */
+ salt->data[6] = 0x00;
+ ASSERT(pss_encode_mgf1(m, 1024, &nettle_sha256,
+ salt->length, salt->data, digest->data));
+ ASSERT(mpz_cmp(m, expected) != 0);
+
+ /* Try the good salt */
+ salt->data[6] = 0x77;
+ ASSERT(pss_encode_mgf1(m, 1024, &nettle_sha256,
+ salt->length, salt->data, digest->data));
+ ASSERT(mpz_cmp(m, expected) == 0);
+
+ /* Try bad message */
+ mpz_add_ui(m, m, 2);
+ ASSERT(!pss_verify_mgf1(m, 1024, &nettle_sha256, salt->length, digest->data));
+
+ /* Try the good message */
+ mpz_sub_ui(m, m, 2);
+ ASSERT(pss_verify_mgf1(m, 1024, &nettle_sha256, salt->length, digest->data));
+
+ /* Try bad digest */
+ digest->data[17] = 0x00;
+ ASSERT(!pss_verify_mgf1(m, 1024, &nettle_sha256, salt->length, digest->data));
+
+ /* Try the good digest */
+ digest->data[17] = 0x03;
+ ASSERT(pss_verify_mgf1(m, 1024, &nettle_sha256, salt->length, digest->data));
+
+ mpz_clear(m);
+ mpz_clear(expected);
+}
diff --git a/testsuite/rsa-pss-sign-tr-test.c b/testsuite/rsa-pss-sign-tr-test.c
new file mode 100644
index 00000000..6dfba734
--- /dev/null
+++ b/testsuite/rsa-pss-sign-tr-test.c
@@ -0,0 +1,356 @@
+#include "testutils.h"
+#include "knuth-lfib.h"
+#include "nettle-internal.h"
+
+#define SALT "This is a magic salt"
+#define MSG1 "None so blind as those who will not see"
+#define MSG2 "Fortune knocks once at every man's door"
+
+typedef int (*test_pss_sign_tr_func) (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);
+
+typedef int (*test_pss_verify_func) (const struct rsa_public_key *key,
+ size_t salt_length,
+ const uint8_t *digest,
+ const mpz_t signature);
+
+static void
+test_rsa_pss_sign_tr(struct rsa_public_key *pub,
+ struct rsa_private_key *key,
+ test_pss_sign_tr_func sign_tr_func,
+ test_pss_verify_func verify_func,
+ void *ctx, const struct nettle_hash *hash,
+ size_t salt_length, const uint8_t *salt,
+ size_t length, const uint8_t *message,
+ mpz_t expected)
+{
+ mpz_t signature;
+ struct knuth_lfib_ctx lfib;
+ uint8_t digest[NETTLE_MAX_HASH_DIGEST_SIZE];
+ uint8_t bad_digest[NETTLE_MAX_HASH_DIGEST_SIZE];
+
+ knuth_lfib_init(&lfib, 1111);
+
+ hash->init(ctx);
+ hash->update(ctx, length, message);
+ hash->digest(ctx, hash->digest_size, digest);
+
+ mpz_init(signature);
+
+ mpz_set_ui (signature, 17);
+ /* Try bad private key */
+ mpz_add_ui(key->p, key->p, 2);
+
+ ASSERT(!sign_tr_func(pub, key,
+ &lfib, (nettle_random_func *) knuth_lfib_random,
+ salt_length, salt,
+ digest, signature));
+
+ mpz_sub_ui(key->p, key->p, 2);
+
+ ASSERT(!mpz_cmp_ui(signature, 17));
+
+ /* Try the good private key */
+ ASSERT(sign_tr_func(pub, key,
+ &lfib, (nettle_random_func *) knuth_lfib_random,
+ salt_length, salt,
+ digest, signature));
+
+ if (verbose)
+ {
+ fprintf(stderr, "rsa-pss-tr signature: ");
+ mpz_out_str(stderr, 16, signature);
+ fprintf(stderr, "\nrsa-pss-tr expected: ");
+ mpz_out_str(stderr, 16, expected);
+ fprintf(stderr, "\n");
+ }
+
+ ASSERT (mpz_cmp(signature, expected) == 0);
+
+ /* Try bad digest */
+ memset(bad_digest, 0x17, sizeof(bad_digest));
+ ASSERT (!verify_func(pub, salt_length, bad_digest, signature));
+
+ /* Try the good digest */
+ ASSERT (verify_func(pub, salt_length, digest, signature));
+
+ /* Try bad signature */
+ mpz_combit(signature, 17);
+ ASSERT (!verify_func(pub, salt_length, digest, signature));
+
+ mpz_clear(signature);
+}
+
+
+void
+test_main(void)
+{
+ struct rsa_public_key pub;
+ struct rsa_private_key key;
+ struct sha256_ctx sha256ctx;
+ struct sha384_ctx sha384ctx;
+ struct sha512_ctx sha512ctx;
+ mpz_t p1;
+ mpz_t q1;
+ struct tstring *salt;
+ struct tstring *msg;
+
+ mpz_t expected;
+
+ mpz_init(expected);
+
+ mpz_init(p1);
+ mpz_init(q1);
+
+ rsa_private_key_init(&key);
+ rsa_public_key_init(&pub);
+
+ test_rsa_set_key_1(&pub, &key);
+
+ /* Test signatures */
+ mpz_set_str(expected,
+ "25e6ce0cc00e917e177a09cb4dfd843d104c179b71aded60e68ebc"
+ "ca2cabb1e51502adf28e53fa7ede42619f21a1162755b9658edf88"
+ "a038bb4fea2bb73306fb384d5785c1a8c98a255277c91a4f88ddd3"
+ "52ebdc78f71f7e62b7a870dac4ab25f1004453457e831a1572f7c9"
+ "23fcc48e3b69db582127d14471c7195dce", 16);
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha256_sign_digest_tr,
+ rsa_pss_sha256_verify_digest,
+ &sha256ctx, &nettle_sha256,
+ LDATA(SALT), LDATA(MSG1), expected);
+
+ mpz_set_str(expected,
+ "52f4393ccc92b5672dd3cfd8624765d3a4cdb50c7a92060c33b4663"
+ "fa545b32ce56ec8cd44fe9720df301906ae40921e844b6d80331194"
+ "972f98e309c937c887c53da940778f29d52dd9489e6016a07e9aa16"
+ "b1ea8fefc0860ad69068ad6f94a4b0c8fc8a0797b08c58cf4a8df90"
+ "ee1375feedf7bf73f16ebb2d1cc7e4", 16);
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha256_sign_digest_tr,
+ rsa_pss_sha256_verify_digest,
+ &sha256ctx, &nettle_sha256,
+ LDATA(SALT), LDATA(MSG2), expected);
+
+ /* 777-bit key, generated by
+ *
+ * lsh-keygen -a rsa -l 777 -f advanced-hex
+ *
+ * Interesting because the size of n doesn't equal the sum of the
+ * sizes of p and q.
+ *
+ * (private-key (rsa-pkcs1
+ * (n #013b04440e3eef25 d51c738d508a7fa8 b3445180c342af0f
+ * 4cb5a789047300e2 cfc5c5450974cfc2 448aeaaa7f43c374
+ * c9a3b038b181f2d1 0f1a2327fd2c087b a49bf1086969fd2c
+ * d1df3fd69f81fa4b 162cc8bbb363fc95 b7b24b9c53d0c67e
+ * f52b#)
+ * (e #3f1a012d#)
+ * (d #f9bae89dacca6cca c21e0412b4df8355 6fe7c5322bbae8ad
+ * 3f11494fd12bc076 d4a7da3050fe109d 2074db09cc6a93b4
+ * 745479522558379e a0ddfa74f86c9e9e a22c3b0e93d51447
+ * 0feb38105dd35395 63b91ee32776f40c 67b2a175690f7abb
+ * 25#)
+ * (p #0b73c990eeda0a2a 2c26416052c85560 0c5c0f5ce86a8326
+ * 166acea91786237a 7ff884e66dbfdd3a ab9d9801414c1506
+ * 8b#)
+ * (q #1b81c19a62802a41 9c99283331b0badb 08eb0c25ffce0fbf
+ * 50017850036f32f3 2132a845b91a5236 61f7b451d587383f
+ * e1#)
+ * (a #0a912fc93a6cca6b 3521725a3065b3be 3c9745e29c93303d
+ * 7d29316c6cafa4a2 89945f964fcdea59 1f9d248b0b6734be
+ * c9#)
+ * (b #1658eca933251813 1eb19c77aba13d73 e0b8f4ce986d7615
+ * 764c6b0b03c18146 46b7f332c43e05c5 351e09006979ca5b
+ * 05#)
+ * (c #0114720dace7b27f 2bf2850c1804869f 79a0aad0ec02e6b4
+ * 05e1831619db2f10 bb9b6a8fd5c95df2 eb78f303ea0c0cc8
+ * 06#)))
+ */
+
+ mpz_set_str(pub.n,
+ "013b04440e3eef25" "d51c738d508a7fa8" "b3445180c342af0f"
+ "4cb5a789047300e2" "cfc5c5450974cfc2" "448aeaaa7f43c374"
+ "c9a3b038b181f2d1" "0f1a2327fd2c087b" "a49bf1086969fd2c"
+ "d1df3fd69f81fa4b" "162cc8bbb363fc95" "b7b24b9c53d0c67e"
+ "f52b", 16);
+
+ mpz_set_str(pub.e, "3f1a012d", 16);
+
+ ASSERT (rsa_public_key_prepare(&pub));
+
+ mpz_set_str(key.p,
+ "0b73c990eeda0a2a" "2c26416052c85560" "0c5c0f5ce86a8326"
+ "166acea91786237a" "7ff884e66dbfdd3a" "ab9d9801414c1506"
+ "8b", 16);
+
+ mpz_set_str(key.q,
+ "1b81c19a62802a41" "9c99283331b0badb" "08eb0c25ffce0fbf"
+ "50017850036f32f3" "2132a845b91a5236" "61f7b451d587383f"
+ "e1", 16);
+
+ mpz_set_str(key.a,
+ "0a912fc93a6cca6b" "3521725a3065b3be" "3c9745e29c93303d"
+ "7d29316c6cafa4a2" "89945f964fcdea59" "1f9d248b0b6734be"
+ "c9", 16);
+
+ mpz_set_str(key.b,
+ "1658eca933251813" "1eb19c77aba13d73" "e0b8f4ce986d7615"
+ "764c6b0b03c18146" "46b7f332c43e05c5" "351e09006979ca5b"
+ "05", 16);
+
+ mpz_set_str(key.c,
+ "0114720dace7b27f" "2bf2850c1804869f" "79a0aad0ec02e6b4"
+ "05e1831619db2f10" "bb9b6a8fd5c95df2" "eb78f303ea0c0cc8"
+ "06", 16);
+
+ ASSERT (rsa_private_key_prepare(&key));
+ ASSERT (pub.size == key.size);
+
+ /* Test signatures */
+ mpz_set_str(expected,
+ "1a4d28331341cabf7ac85bc59a58d439b7ec2c607c6a74e35b5909"
+ "1dfa3d9de9fde93e4a431f0f768bec07c39995d253209f86e3dc84"
+ "037ecd5d23d963fab4fa8a001e018d82cb19d743a94ba7dc7a821e"
+ "87b72e67a0fe058f956208f7060dc104", 16);
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha256_sign_digest_tr,
+ rsa_pss_sha256_verify_digest,
+ &sha256ctx, &nettle_sha256,
+ LDATA(SALT), LDATA(MSG1), expected);
+
+ /* From FIPS 186-2 */
+ mpz_set_str(pub.n,
+ "be499b5e7f06c83f" "a0293e31465c8eb6" "b58af920bae52a7b"
+ "5b9bfeb7aa72db12" "64112eb3fd431d31" "a2a7e50941566929"
+ "494a0e891ed56139" "18b4b51b0d1fb977" "83b26acf7d0f384c"
+ "fb35f4d2824f5dd3" "80623a26bf180b63" "961c619dcdb20cae"
+ "406f22f6e276c80a" "37259490cfeb72c1" "a71a84f1846d3308"
+ "77ba3e3101ec9c7b" , 16);
+
+ mpz_set_str(pub.e, "11", 16);
+
+ ASSERT (rsa_public_key_prepare(&pub));
+
+ mpz_set_str(key.p,
+ "e7a80c5d211c06ac" "b900939495f26d36" "5fc2b4825b75e356"
+ "f89003eaa5931e6b" "e5c3f7e6a633ad59" "db6289d06c354c23"
+ "5e739a1e3f3d39fb" "40d1ffb9cb44288f", 16);
+
+ mpz_set_str(key.q,
+ "d248aa248000f720" "258742da67b71194" "0c8f76e1ecd52b67"
+ "a6ffe1e49354d66f" "f84fa601804743f5" "838da2ed4693a5a2"
+ "8658d6528cc1803b" "f6c8dc73c5230b55", 16);
+
+ mpz_set_str(key.d,
+ "0d0f17362bdad181" "db4e1fe03e8de1a3" "208989914e14bf26"
+ "9558826bfa20faf4" "b68dba6bb989a01f" "03a21c44665dc5f6"
+ "48cb5b59b954eb10" "77a80263bd22cdfb" "88d39164b7404f4f"
+ "1106ee01cf60b776" "95748d8fdaf9fd42" "8963fe75144010b1"
+ "934c8e26a8823967" "2cf49b3422a07c4d" "834ba208d570fe40"
+ "8e7095c90547e68d", 16);
+
+ /* a = d % (p-1) */
+ mpz_sub_ui(p1, key.p, 1);
+ mpz_fdiv_r(key.a, key.d, p1);
+ mpz_clear(p1);
+
+ /* b = d % (q-1) */
+ mpz_sub_ui(q1, key.q, 1);
+ mpz_fdiv_r(key.b, key.d, q1);
+ mpz_clear(q1);
+
+ /* c = q^{-1} (mod p) */
+ mpz_invert(key.c, key.q, key.p);
+
+ ASSERT (rsa_private_key_prepare(&key));
+ ASSERT (pub.size == key.size);
+
+ mpz_set_str(expected,
+ "11e169f2fd40b07641b9768a2ab19965fb6c27f10fcf0323fcc6d1"
+ "2eb4f1c06b330ddaa1ea504407afa29de9ebe0374fe9d1e7d0ffbd"
+ "5fc1cf3a3446e4145415d2ab24f789b3464c5c43a256bbc1d692cf"
+ "7f04801dac5bb401a4a03ab7d5728a860c19e1a4dc797ca542c820"
+ "3cec2e601eb0c51f567f2eda022b0b9ebddeeefa", 16);
+
+ salt = SHEX("11223344555432167890");
+ msg = SHEX("c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9"
+ "b02140fe238908e4f6c18f07a89c687c8684669b1f1db2baf9251a"
+ "3c829faccb493084e16ec9e28d58868074a5d6221667dd6e528d16"
+ "fe2c9f3db4cfaf6c4dce8c8439af38ceaaaa9ce2ecae7bc8f4a5a5"
+ "5e3bf96df9cd575c4f9cb327951b8cdfe4087168");
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha256_sign_digest_tr,
+ rsa_pss_sha256_verify_digest,
+ &sha256ctx, &nettle_sha256,
+ salt->length, salt->data, msg->length, msg->data,
+ expected);
+
+ mpz_set_str(expected,
+ "b281ad934b2775c0cba5fb10aa574d2ed85c7f99b942b78e497024"
+ "80069362ed394baded55e56cfcbe7b0b8d2217a05a60e1acd725cb"
+ "09060dfac585bc2132b99b41cdbd530c69d17cdbc84bc6b9830fc7"
+ "dc8e1b2412cfe06dcf8c1a0cc3453f93f25ebf10cb0c90334fac57"
+ "3f449138616e1a194c67f44efac34cc07a526267", 16);
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha384_sign_digest_tr,
+ rsa_pss_sha384_verify_digest,
+ &sha384ctx, &nettle_sha384,
+ salt->length, salt->data, msg->length, msg->data,
+ expected);
+ mpz_set_str(expected,
+ "8ffc38f9b820ef6b080fd2ec7de5626c658d79056f3edf610a295b"
+ "7b0546f73e01ffdf4d0070ebf79c33fd86c2d608be9438b3d420d0"
+ "9535b97cd3d846ecaf8f6551cdf93197e9f8fb048044473ab41a80"
+ "1e9f7fc983c62b324361dade9f71a65952bd35c59faaa4d6ff462f"
+ "68a6c4ec0b428aa47336f2178aeb276136563b7d", 16);
+
+ test_rsa_pss_sign_tr(&pub, &key,
+ rsa_pss_sha512_sign_digest_tr,
+ rsa_pss_sha512_verify_digest,
+ &sha512ctx, &nettle_sha512,
+ salt->length, salt->data, msg->length, msg->data,
+ expected);
+
+ /* The public key n for this test is of size k = 1017 bits, and the
+ pss "em" value is limited to k - 1 = 1016 bits or 127 octets. The
+ alleged signature below results in a 1017 bit number during the
+ signature verification, which is too large, and used to result in
+ an assertion failure when attempting to convert the number to a
+ 127 octet string.
+ */
+ mpz_set_str(pub.n,
+ "1d64559685aad3490e976b48aacf442ecee847268f882341eafe78"
+ "a0ca4ef88f66edbaf55b70e5285cc117aa9ceb322a4227c17e9e89"
+ "27bf38e5672faecf79e2983d92766fbb6624522f072ae0e4e46d37"
+ "052ce1e5745c2dd8fd67de3862e4711161e359b96bda85911ebf4e"
+ "6ce1bea625970269c77004a3cb03f9c382c5f79", 16);
+ mpz_set_str(pub.e, "10001", 16);
+
+ ASSERT (rsa_public_key_prepare(&pub));
+
+ msg = SHEX("7f85e4909ff7bb29536e540a53031ef03ddcb129e553a43273fa1f"
+ "ed28c22a8b57c7bde101ff746f335ba69b29642019");
+ /* Alleged signature, resulting in a too large m. */
+ mpz_set_str(expected,
+ "000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000005ffff05"
+ "000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000", 16);
+
+ ASSERT(!rsa_pss_sha384_verify_digest(&pub, 48, msg->data, expected));
+
+ rsa_private_key_clear(&key);
+ rsa_public_key_clear(&pub);
+ mpz_clear(expected);
+}
diff --git a/testsuite/test-rules.stamp b/testsuite/test-rules.stamp
new file mode 100644
index 00000000..859afb1d
--- /dev/null
+++ b/testsuite/test-rules.stamp
@@ -0,0 +1 @@
+stamp
diff --git a/testsuite/testutils.c b/testsuite/testutils.c
index 6f897617..6ce13c4e 100644
--- a/testsuite/testutils.c
+++ b/testsuite/testutils.c
@@ -4,6 +4,7 @@
#include "base16.h"
#include "cbc.h"
+#include "cfb.h"
#include "ctr.h"
#include "knuth-lfib.h"
#include "macros.h"
@@ -62,7 +63,7 @@ tstring_clear(void)
}
struct tstring *
-tstring_data(size_t length, const char *data)
+tstring_data(size_t length, const uint8_t *data)
{
struct tstring *s = tstring_alloc (length);
memcpy (s->data, data, length);
@@ -245,6 +246,184 @@ test_cipher_cbc(const struct nettle_cipher *cipher,
}
void
+test_cipher_cfb(const struct nettle_cipher *cipher,
+ const struct tstring *key,
+ const struct tstring *cleartext,
+ const struct tstring *ciphertext,
+ const struct tstring *iiv)
+{
+ void *ctx = xalloc(cipher->context_size);
+ uint8_t *data, *data2;
+ uint8_t *iv = xalloc(cipher->block_size);
+ size_t length;
+
+ ASSERT (cleartext->length == ciphertext->length);
+ length = cleartext->length;
+
+ ASSERT (key->length == cipher->key_size);
+ ASSERT (iiv->length == cipher->block_size);
+
+ data = xalloc(length);
+ data2 = xalloc(length);
+
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_encrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, cleartext->data);
+
+ if (!MEMEQ(length, data, ciphertext->data))
+ {
+ fprintf(stderr, "CFB encrypt failed:\nInput:");
+ tstring_print_hex(cleartext);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(ciphertext);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_decrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data2, data);
+
+ if (!MEMEQ(length, data2, cleartext->data))
+ {
+ fprintf(stderr, "CFB decrypt failed:\nInput:");
+ tstring_print_hex(ciphertext);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data2);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(cleartext);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+ memcpy(data, cleartext->data, length);
+
+ cfb_encrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, data);
+
+ if (!MEMEQ(length, data, ciphertext->data))
+ {
+ fprintf(stderr, "CFB inplace encrypt failed:\nInput:");
+ tstring_print_hex(cleartext);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(ciphertext);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_decrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, data);
+
+ if (!MEMEQ(length, data, cleartext->data))
+ {
+ fprintf(stderr, "CFB inplace decrypt failed:\nInput:");
+ tstring_print_hex(ciphertext);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(cleartext);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+
+ /* Repeat all tests with incomplete last block */
+ length -= 1;
+
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_encrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, cleartext->data);
+
+ if (!MEMEQ(length, data, ciphertext->data))
+ {
+ fprintf(stderr, "CFB encrypt failed:\nInput:");
+ print_hex(length, cleartext->data);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ print_hex(length, ciphertext->data);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_decrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data2, data);
+
+ if (!MEMEQ(length, data2, cleartext->data))
+ {
+ fprintf(stderr, "CFB decrypt failed:\nInput:");
+ print_hex(length, ciphertext->data);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data2);
+ fprintf(stderr, "\nExpected:");
+ print_hex(length, cleartext->data);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+ memcpy(data, cleartext->data, length);
+
+ cfb_encrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, data);
+
+ if (!MEMEQ(length, data, ciphertext->data))
+ {
+ fprintf(stderr, "CFB inplace encrypt failed:\nInput:");
+ print_hex(length, cleartext->data);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ print_hex(length, ciphertext->data);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ cipher->set_encrypt_key(ctx, key->data);
+ memcpy(iv, iiv->data, cipher->block_size);
+
+ cfb_decrypt(ctx, cipher->encrypt,
+ cipher->block_size, iv,
+ length, data, data);
+
+ if (!MEMEQ(length, data, cleartext->data))
+ {
+ fprintf(stderr, "CFB inplace decrypt failed:\nInput:");
+ print_hex(length, ciphertext->data);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(length, data);
+ fprintf(stderr, "\nExpected:");
+ print_hex(length, cleartext->data);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+
+ free(ctx);
+ free(data);
+ free(data2);
+ free(iv);
+}
+
+void
test_cipher_ctr(const struct nettle_cipher *cipher,
const struct tstring *key,
const struct tstring *cleartext,
@@ -566,7 +745,7 @@ test_armor(const struct nettle_armor *armor,
const char *ascii)
{
size_t ascii_length = strlen(ascii);
- uint8_t *buffer = xalloc(1 + ascii_length);
+ char *buffer = xalloc(1 + ascii_length);
uint8_t *check = xalloc(1 + armor->decode_length(ascii_length));
void *encode = xalloc(armor->encode_context_size);
void *decode = xalloc(armor->decode_context_size);
diff --git a/testsuite/testutils.h b/testsuite/testutils.h
index 7c44772b..fbbba7b9 100644
--- a/testsuite/testutils.h
+++ b/testsuite/testutils.h
@@ -60,7 +60,7 @@ void
tstring_clear(void);
struct tstring *
-tstring_data(size_t length, const char *data);
+tstring_data(size_t length, const uint8_t *data);
struct tstring *
tstring_hex(const char *hex);
@@ -123,6 +123,13 @@ test_cipher_cbc(const struct nettle_cipher *cipher,
const struct tstring *iv);
void
+test_cipher_cfb(const struct nettle_cipher *cipher,
+ const struct tstring *key,
+ const struct tstring *cleartext,
+ const struct tstring *ciphertext,
+ const struct tstring *iv);
+
+void
test_cipher_ctr(const struct nettle_cipher *cipher,
const struct tstring *key,
const struct tstring *cleartext,
@@ -163,13 +170,6 @@ test_armor(const struct nettle_armor *armor,
const char *ascii);
#if WITH_HOGWEED
-#ifndef mpn_zero_p
-int
-mpn_zero_p (mp_srcptr ap, mp_size_t n);
-#endif
-
-void
-mpn_out_str (FILE *f, int base, const mp_limb_t *xp, mp_size_t xn);
#if NETTLE_USE_MINI_GMP
typedef struct knuth_lfib_ctx gmp_randstate_t[1];
@@ -180,8 +180,20 @@ void mpz_urandomb (mpz_t r, struct knuth_lfib_ctx *ctx, mp_bitcnt_t bits);
/* This is cheating */
#define mpz_rrandomb mpz_urandomb
+/* mini-gmp defines this function (in the GMP library, it was added in
+ gmp in version 6.1.0). */
+#define mpn_zero_p mpn_zero_p
+
#endif /* NETTLE_USE_MINI_GMP */
+#ifndef mpn_zero_p
+int
+mpn_zero_p (mp_srcptr ap, mp_size_t n);
+#endif
+
+void
+mpn_out_str (FILE *f, int base, const mp_limb_t *xp, mp_size_t xn);
+
mp_limb_t *
xalloc_limbs (mp_size_t n);
@@ -281,7 +293,7 @@ test_ecc_mul_h (unsigned curve, unsigned n, const mp_limb_t *p);
#define LDUP(x) strlen(x), strdup(x)
#define SHEX(x) (tstring_hex(x))
-#define SDATA(x) ((const struct tstring *)tstring_data(LLENGTH(x), x))
+#define SDATA(x) ((const struct tstring *)tstring_data(LLENGTH(x), US(x)))
#define H(x) (SHEX(x)->data)
#define MEMEQ(length, a, b) (!memcmp((a), (b), (length)))
diff --git a/tools/input.c b/tools/input.c
index 18a9dff5..90e41a29 100644
--- a/tools/input.c
+++ b/tools/input.c
@@ -90,7 +90,7 @@ sexp_get_char(struct sexp_input *input)
* character at a time. */
if (!input->coding->decode_update(&input->state,
&done, &input->c,
- 1, &input->c))
+ 1, (const char*) &input->c))
die("Invalid coded data.\n");
if (done)
diff --git a/tools/nettle-hash.c b/tools/nettle-hash.c
index d7d4ce2e..24199921 100644
--- a/tools/nettle-hash.c
+++ b/tools/nettle-hash.c
@@ -53,11 +53,11 @@ list_algorithms (void)
{
unsigned i;
const struct nettle_hash *alg;
- printf ("%10s digestsize (internal block size), in units of octets\n", "name");
+ printf ("%10s digestsize (internal block size, context size), in units of octets\n", "name");
for (i = 0; (alg = nettle_hashes[i]); i++)
- printf ("%10s %d (%d)\n",
- alg->name, alg->digest_size, alg->block_size);
+ printf ("%10s %d (%d, %d)\n",
+ alg->name, alg->digest_size, alg->block_size, alg->context_size);
};
/* Also in examples/io.c */
diff --git a/tools/nettle-pbkdf2.c b/tools/nettle-pbkdf2.c
index c9e4d11c..1f0a3015 100644
--- a/tools/nettle-pbkdf2.c
+++ b/tools/nettle-pbkdf2.c
@@ -73,7 +73,7 @@ main (int argc, char **argv)
size_t password_length;
uint8_t *output;
size_t salt_length;
- uint8_t *salt;
+ char *salt;
int raw = 0;
int hex_salt = 0;
int c;
@@ -141,7 +141,7 @@ main (int argc, char **argv)
return EXIT_FAILURE;
}
- salt = (uint8_t *) strdup (argv[0]);
+ salt = strdup (argv[0]);
salt_length = strlen(argv[0]);
if (hex_salt)
@@ -150,7 +150,7 @@ main (int argc, char **argv)
base16_decode_init (&base16);
if (!base16_decode_update (&base16,
- &salt_length, salt,
+ &salt_length, (uint8_t *) salt,
salt_length, salt)
|| !base16_decode_final (&base16))
die ("Invalid salt (expecting hex encoding).\n");
@@ -165,7 +165,7 @@ main (int argc, char **argv)
output = xalloc (output_length);
pbkdf2_hmac_sha256 (password_length, (const uint8_t *) password,
- iterations, salt_length, salt,
+ iterations, salt_length, (const uint8_t*) salt,
output_length, output);
free (salt);
diff --git a/tools/output.c b/tools/output.c
index 02e43d58..80a44a97 100644
--- a/tools/output.c
+++ b/tools/output.c
@@ -114,7 +114,7 @@ sexp_put_char(struct sexp_output *output, uint8_t c)
if (output->coding)
{
/* Two is enough for both base16 and base64. */
- uint8_t encoded[2];
+ char encoded[2];
unsigned done;
unsigned i;
@@ -183,7 +183,7 @@ void
sexp_put_code_end(struct sexp_output *output)
{
/* Enough for both hex and base64 */
- uint8_t encoded[BASE64_ENCODE_FINAL_LENGTH];
+ char encoded[BASE64_ENCODE_FINAL_LENGTH];
unsigned done;
assert(output->coding);
@@ -194,7 +194,7 @@ sexp_put_code_end(struct sexp_output *output)
output->coding = NULL;
- sexp_put_data(output, done, encoded);
+ sexp_put_data(output, done, (const uint8_t*) encoded);
}
void
diff --git a/tools/pkcs1-conv.c b/tools/pkcs1-conv.c
index 9e346858..efd6528a 100644
--- a/tools/pkcs1-conv.c
+++ b/tools/pkcs1-conv.c
@@ -244,6 +244,14 @@ read_pem(struct nettle_buffer *buffer, FILE *f,
}
}
+static inline int
+base64_decode_in_place (struct base64_decode_ctx *ctx, size_t *dst_length,
+ size_t length, uint8_t *data)
+{
+ return base64_decode_update (ctx, dst_length,
+ data, length, (const char *) data);
+}
+
static int
decode_base64(struct nettle_buffer *buffer,
size_t start, size_t *length)
@@ -253,9 +261,8 @@ decode_base64(struct nettle_buffer *buffer,
base64_decode_init(&ctx);
/* Decode in place */
- if (base64_decode_update(&ctx,
- length, buffer->contents + start,
- *length, buffer->contents + start)
+ if (base64_decode_in_place(&ctx, length,
+ *length, buffer->contents + start)
&& base64_decode_final(&ctx))
return 1;