diff --git a/.fmf/version b/.fmf/version deleted file mode 100644 index d00491f..0000000 --- a/.fmf/version +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/.gitignore b/.gitignore index 552f393..65a9913 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1,9 @@ -libgcrypt-1.4.5-hobbled.tar.bz2 -/libgcrypt-1.4.6-hobbled.tar.bz2 -/libgcrypt-1.5.0-hobbled.tar.bz2 -/libgcrypt-1.5.1-hobbled.tar.xz -/libgcrypt-1.5.2-hobbled.tar.xz -/libgcrypt-1.5.3-hobbled.tar.xz -/libgcrypt-1.6.1-hobbled.tar.xz -/libgcrypt-1.6.2-hobbled.tar.xz -/libgcrypt-1.6.3-hobbled.tar.xz -/libgcrypt-1.6.4-hobbled.tar.xz -/libgcrypt-1.6.5-hobbled.tar.xz -/libgcrypt-1.6.6-hobbled.tar.xz -/libgcrypt-1.7.3-hobbled.tar.xz -/libgcrypt-1.7.5-hobbled.tar.xz -/libgcrypt-1.7.6-hobbled.tar.xz -/libgcrypt-1.7.7-hobbled.tar.xz -/libgcrypt-1.7.8-hobbled.tar.xz -/libgcrypt-1.8.0-hobbled.tar.xz -/libgcrypt-1.8.1-hobbled.tar.xz -/libgcrypt-1.8.2-hobbled.tar.xz -/libgcrypt-1.8.3-hobbled.tar.xz -/libgcrypt-1.8.4-hobbled.tar.xz -/libgcrypt-1.8.5-hobbled.tar.xz -/libgcrypt-1.8.6-hobbled.tar.xz -/libgcrypt-1.8.7-hobbled.tar.xz -/libgcrypt-1.9.0-hobbled.tar.xz -/libgcrypt-1.9.1-hobbled.tar.xz -/libgcrypt-1.9.2-hobbled.tar.xz -/libgcrypt-1.9.3-hobbled.tar.xz -/libgcrypt-1.9.4-hobbled.tar.xz -/libgcrypt-1.10.0.tar.bz2 -/libgcrypt-1.10.0.tar.bz2.sig -/libgcrypt-1.10.1.tar.bz2 -/libgcrypt-1.10.1.tar.bz2.sig -/libgcrypt-1.10.2.tar.bz2 -/libgcrypt-1.10.2.tar.bz2.sig -/libgcrypt-1.10.3.tar.bz2 -/libgcrypt-1.10.3.tar.bz2.sig -/libgcrypt-1.11.0.tar.bz2 -/libgcrypt-1.11.0.tar.bz2.sig -/libgcrypt-1.11.1.tar.bz2 -/libgcrypt-1.11.1.tar.bz2.sig -/libgcrypt-1.11.2.tar.bz2 -/libgcrypt-1.11.2.tar.bz2.sig +libgcrypt-1.2.0.tar.gz +libgcrypt-1.2.1.tar.bz2 +libgcrypt-1.2.1.tar.bz2.sig +libgcrypt-1.2.2.tar.bz2 +libgcrypt-1.2.2.tar.bz2.sig +libgcrypt-1.2.3.tar.bz2 +libgcrypt-1.2.3.tar.bz2.sig +libgcrypt-1.2.4.tar.bz2 +libgcrypt-1.2.4.tar.bz2.sig diff --git a/libgcrypt-1.10.1-annobin.patch b/libgcrypt-1.10.1-annobin.patch deleted file mode 100644 index c333c4e..0000000 --- a/libgcrypt-1.10.1-annobin.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -rup libgcrypt.orig/src/Makefile.am libgcrypt-1.8.3/src/Makefile.am ---- libgcrypt.orig/src/Makefile.am 2021-10-18 16:36:20.914025497 +0100 -+++ libgcrypt-1.8.3/src/Makefile.am 2021-10-19 12:23:08.652960618 +0100 -@@ -108,6 +108,7 @@ endif !HAVE_W32_SYSTEM - - - libgcrypt_la_LDFLAGS = $(no_undefined) $(export_symbols) $(extra_ltoptions) \ -+ -Wc,-fplugin=annobin \ - $(libgcrypt_version_script_cmd) -version-info \ - @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@ - libgcrypt_la_DEPENDENCIES = \ -Only in libgcrypt-1.8.3/src: Makefile.am.annobin -diff -rup libgcrypt.orig/src/Makefile.in libgcrypt-1.8.3/src/Makefile.in ---- libgcrypt.orig/src/Makefile.in 2021-10-18 16:36:20.914025497 +0100 -+++ libgcrypt-1.8.3/src/Makefile.in 2021-10-19 12:23:37.791875325 +0100 -@@ -483,6 +483,7 @@ gcrypt_hwf_modules = @GCRYPT_HWF_MODULES - @HAVE_W32_SYSTEM_TRUE@gcrypt_deps = $(gcrypt_res) libgcrypt.def - @HAVE_W32_SYSTEM_FALSE@gcrypt_res_ldflag = - libgcrypt_la_LDFLAGS = $(no_undefined) $(export_symbols) $(extra_ltoptions) \ -+ -Wc,-fplugin=annobin \ - $(libgcrypt_version_script_cmd) -version-info \ - @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@ diff --git a/libgcrypt-1.11.0-marvin.patch b/libgcrypt-1.11.0-marvin.patch deleted file mode 100644 index 78b6809..0000000 --- a/libgcrypt-1.11.0-marvin.patch +++ /dev/null @@ -1,2122 +0,0 @@ -From 984e245fd21ff6e0058403f620f760013a744a3a Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 7 Jun 2024 14:42:33 +0200 -Subject: [PATCH 1/7] rsa: Do not accept invalid PKCS#1.5 padding when - deciphering - -The current code can accept 0-length padding when deciphering -PKCS#1.5 ciphertext. This is against the specification and hopefully -nobody depends on this. - --- -* cipher/rsa-common.c (_gcry_rsa_pkcs1_decode_for_enc): Fail for too - short padding. -* src/const-time.h (ct_lt_s): New. - -Signed-off-by: Jakub Jelen ---- - cipher/rsa-common.c | 2 ++ - src/const-time.h | 6 ++++++ - 2 files changed, 8 insertions(+) - -diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c -index 1920eedd..e45cb30d 100644 ---- a/cipher/rsa-common.c -+++ b/cipher/rsa-common.c -@@ -247,6 +247,8 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - - failed |= not_found; - n0 += ct_is_zero (not_found); /* Skip the zero byte. */ -+ /* the valid padding is at least 8 bytes -- the plaintext needs to start at index 11 or later */ -+ failed |= ct_lt_s (n0, 11); - - /* To avoid an extra allocation we reuse the frame buffer. The only - caller of this function will anyway free the result soon. */ -diff --git a/src/const-time.h b/src/const-time.h -index 46eb187d..245967eb 100644 ---- a/src/const-time.h -+++ b/src/const-time.h -@@ -34,6 +34,12 @@ extern volatile unsigned int _gcry_ct_vone; - #endif - - -+static inline size_t -+ct_lt_s (size_t a, size_t b) -+{ -+ return ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(size_t) * 8 - 1)); -+} -+ - /* - * Return 0 if A is 0 and return 1 otherwise. - */ --- -2.46.0 - - -From aca5bd25e819b2596754fdc6ecb1844462a5b4f0 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 10 Apr 2024 15:18:39 +0200 -Subject: [PATCH 2/7] rsa: Constant time blinding removal - -* cipher/rsa.c (secret_blinded): Use constant time mulm implementation -* configure.ac: New configure option --enable-marvin-workaround -* mpi/Makefile.am: Build constant time multiplication -* mpi/mpi-internal.h: Add constant time function prototypes -* mpi/mpi-mul-cs.c: New file with constant time multiplication and - modulo. -* mpi/mpi-mul.c (_gcry_mpi_mul_sec): New function. - (_gcry_mpi_mod_sec): New function. - (_gcry_mpi_mod_sec): New function. - (_gcry_mpi_reverse_sec): New function. - (_gcry_mpi_mulm_sec): New function. -* src/gcrypt-int.h: Add new functions. - --- - -The current MPI code is not constant time, potentially leaking plaintext -when the attacker can observe enough decipher operations using RSA -PKCS#1.5. This is described as a Marvin Attack: - -https://eprint.iacr.org/2023/1442 - -Note, that this code is tested to be constant time only with the -O3 -optimization level. - -Signed-off-by: Jakub Jelen ---- - cipher/rsa.c | 4 + - configure.ac | 16 +++ - mpi/Makefile.am | 4 + - mpi/mpi-internal.h | 6 ++ - mpi/mpi-mul-cs.c | 263 +++++++++++++++++++++++++++++++++++++++++++++ - mpi/mpi-mul.c | 169 +++++++++++++++++++++++++++++ - src/gcrypt-int.h | 6 ++ - 7 files changed, 468 insertions(+) - create mode 100644 mpi/mpi-mul-cs.c - -diff --git a/cipher/rsa.c b/cipher/rsa.c -index c7a809f4..2f735f9c 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1197,7 +1197,11 @@ secret_blinded (gcry_mpi_t output, gcry_mpi_t input, - /* Undo blinding. Here we calculate: y = (x * r^-1) mod n, where x - * is the blinded decrypted data, ri is the modular multiplicative - * inverse of r and n is the RSA modulus. */ -+#ifdef WITH_MARVIN_WORKAROUND -+ mpi_mulm_sec (output, output, ri, sk->n); -+#else - mpi_mulm (output, output, ri, sk->n); -+#endif /* WITH_MARVIN_WORKAROUND */ - - _gcry_mpi_release (r); - _gcry_mpi_release (ri); -diff --git a/configure.ac b/configure.ac -index 4c45de22..3f63b88e 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -603,6 +603,22 @@ AC_ARG_ENABLE(jent-support, - jentsupport=$enableval,jentsupport=yes) - AC_MSG_RESULT($jentsupport) - -+AC_MSG_CHECKING([whether a Marvin workaround is requested]) -+AC_ARG_ENABLE(marvin-workaround, -+ AS_HELP_STRING([--enable-marvin-workaround], -+ [Enable Marvin workaround for constant time PKCS1.5 depadding]), -+ [with_marvin_workaround="$enableval"], -+ [with_marvin_workaround=no]) -+AC_MSG_RESULT($with_marvin_workaround) -+if test "$with_marvin_workaround" = no ; then -+ WITH_MARVIN_WORKAROUND='' -+else -+ AC_DEFINE(WITH_MARVIN_WORKAROUND,1, -+ [Define to provide constant time PKCS1.5 depadding]) -+fi -+AM_CONDITIONAL(WITH_MARVIN_WORKAROUND, test "x$with_marvin_workaround" != xno) -+AC_SUBST(WITH_MARVIN_WORKAROUND) -+ - # Implementation of the --disable-padlock-support switch. - AC_MSG_CHECKING([whether padlock support is requested]) - AC_ARG_ENABLE(padlock-support, -diff --git a/mpi/Makefile.am b/mpi/Makefile.am -index 6fe63fce..85679e08 100644 ---- a/mpi/Makefile.am -+++ b/mpi/Makefile.am -@@ -181,3 +181,7 @@ EXTRA_libmpi_la_SOURCES = \ - asm-common-aarch64.h \ - asm-common-amd64.h \ - asm-common-i386.h -+ -+if WITH_MARVIN_WORKAROUND -+libmpi_la_SOURCES += mpi-mul-cs.c -+endif -diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h -index 935bf3e1..39de5161 100644 ---- a/mpi/mpi-internal.h -+++ b/mpi/mpi-internal.h -@@ -239,6 +239,12 @@ void _gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, - mpi_ptr_t vp, mpi_size_t vsize, - struct karatsuba_ctx *ctx ); - -+#ifdef WITH_MARVIN_WORKAROUND -+/*-- mpih-mul-cs.c --*/ -+void mul_cs(mpi_limb_t *ret, mpi_limb_t *a, mpi_limb_t *b, size_t n, mpi_limb_t *tmp); -+void mod_cs(mpi_limb_t *ret, mpi_limb_t *a, size_t anum, mpi_limb_t *mod, size_t modnum, mpi_limb_t *tmp); -+size_t mod_limb_numb(size_t anum, size_t modnum); -+#endif /* WITH_MARVIN_WORKAROUND */ - - /*-- mpih-mul_1.c (or xxx/cpu/ *.S) --*/ - mpi_limb_t _gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -diff --git a/mpi/mpi-mul-cs.c b/mpi/mpi-mul-cs.c -new file mode 100644 -index 00000000..3f77ac94 ---- /dev/null -+++ b/mpi/mpi-mul-cs.c -@@ -0,0 +1,263 @@ -+/* Copyright (c) 2024, Hubert Kario, Red Hat -+ * Released under BSD 2-Clause License, see LICENSE for details -+ */ -+#include -+#include -+#include -+#include -+#include -+#include "mpi-internal.h" -+#include "longlong.h" -+ -+/* For multiplication we're using schoolbook multiplication, -+ * so if we have two numbers, each with 6 "digits" (words) -+ * the multiplication is calculated as follows: -+ * A B C D E F -+ * x I J K L M N -+ * -------------- -+ * N*F -+ * N*E -+ * N*D -+ * N*C -+ * N*B -+ * N*A -+ * M*F -+ * M*E -+ * M*D -+ * M*C -+ * M*B -+ * M*A -+ * L*F -+ * L*E -+ * L*D -+ * L*C -+ * L*B -+ * L*A -+ * K*F -+ * K*E -+ * K*D -+ * K*C -+ * K*B -+ * K*A -+ * J*F -+ * J*E -+ * J*D -+ * J*C -+ * J*B -+ * J*A -+ * I*F -+ * I*E -+ * I*D -+ * I*C -+ * I*B -+ * + I*A -+ * ========================== -+ * N*B N*D N*F -+ * + N*A N*C N*E -+ * + M*B M*D M*F -+ * + M*A M*C M*E -+ * + L*B L*D L*F -+ * + L*A L*C L*E -+ * + K*B K*D K*F -+ * + K*A K*C K*E -+ * + J*B J*D J*F -+ * + J*A J*C J*E -+ * + I*B I*D I*F -+ * + I*A I*C I*E -+ * -+ * 1+1 1+3 1+5 -+ * 1+0 1+2 1+4 -+ * 0+1 0+3 0+5 -+ * 0+0 0+2 0+4 -+ * -+ * 0 1 2 3 4 5 6 -+ * which requires n^2 multiplications and 2n full length additions -+ * as we can keep every other result of limb multiplication in two separate -+ * limbs -+ */ -+ -+typedef mpi_limb_t limb_t; -+#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG -+#define LIMB_BIT_SIZE 64 -+#define LIMB_BYTE_SIZE 8 -+#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG -+#define LIMB_BIT_SIZE 32 -+#define LIMB_BYTE_SIZE 4 -+/* if we're on a 32 bit platform */ -+#else -+#define LIMB_BIT_SIZE 16 -+#define LIMB_BYTE_SIZE 2 -+/* -+ * if the compiler doesn't have either a 128bit data type nor a "return -+ * high 64 bits of multiplication" -+ */ -+#endif -+ -+/* add two limbs with carry in, return carry out */ -+static limb_t -+_add_limb (limb_t *ret, limb_t a, limb_t b, limb_t carry) -+{ -+ limb_t carry1, carry2, t; -+ add_ssaaaa (carry1, t, 0, a, 0, carry); -+ add_ssaaaa (carry2, t, 0, b, 0, t); -+ *ret = t; -+ return carry1 + carry2; -+} -+ -+/* add two numbers of the same size, return overflow -+ * -+ * add a to b, place result in ret; all arrays need to be n limbs long -+ * return overflow from addition (0 or 1) -+ */ -+static limb_t -+add (limb_t *ret, limb_t *a, limb_t *b, size_t n) -+{ -+ limb_t c = 0; -+ for (ssize_t i = n - 1; i > -1; i--) -+ { -+ c = _add_limb (&ret[i], a[i], b[i], c); -+ } -+ return c; -+} -+ -+/* multiply two numbers of the same size -+ * -+ * multiply a by b, place result in ret; a and b need to be n limbs long -+ * ret needs to be 2*n limbs long, tmp needs to be 2 * n 2 limbs -+ * long -+ */ -+void -+mul_cs (limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp) -+{ -+ limb_t *r_odd, *r_even; -+ r_odd = tmp; -+ r_even = &tmp[2 * n]; -+ -+ for (size_t i = 0; i < 2 * n; i++) -+ { -+ ret[i] = 0; -+ } -+ -+ for (size_t i=0; i> 1); -+ shift_in = shift_out; -+ } -+} -+ -+/* copy from either a or b to ret based on flag -+ * when flag == 0, then copies from b -+ * when flag == 1, then copies from a -+ */ -+static void -+cselect (limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n) -+{ -+ /* would be more efficient with non volatile mask, but then gcc -+ * generates code with jumps */ -+ limb_t mask1 = ct_limb_gen_mask (flag); -+ limb_t mask2 = ct_limb_gen_inv_mask (flag); -+ for (size_t i = 0; i < n; i++) -+ { -+ ret[i] = (mask1 & a[i]) | (mask2 & b[i]); -+ } -+} -+ -+static limb_t -+_sub_limb (limb_t *ret, limb_t a, limb_t b, limb_t borrow) -+{ -+ limb_t borrow1, borrow2, t; -+ sub_ddmmss (borrow1, t, 0, a, 0, borrow); -+ sub_ddmmss (borrow2, t, 0, t, 0, b); -+ *ret = t; -+ return -(borrow1 + borrow2); -+} -+ -+/* place the result of a - b into ret, return the borrow bit. -+ * All arrays need to be n limbs long -+ */ -+static limb_t -+sub (limb_t *ret, limb_t *a, limb_t *b, size_t n) -+{ -+ limb_t borrow = 0; -+ for (ssize_t i=n-1; i>-1; i--) -+ { -+ borrow = _sub_limb (&ret[i], a[i], b[i], borrow); -+ } -+ return borrow; -+} -+ -+/* return the number of limbs necessary to allocate for the mod() tmp operand */ -+size_t -+mod_limb_numb (size_t anum, size_t modnum) -+{ -+ return (anum + modnum) * 3; -+} -+ -+/* calculate a % mod, place the result in ret -+ * size of a is defined by anum, size of ret and mod is modnum, -+ * size of tmp is returned by mod_limb_numb() -+ */ -+void -+mod_cs (limb_t *ret, limb_t *a, size_t anum, limb_t *mod, size_t modnum, limb_t *tmp) -+{ -+ limb_t *atmp, *modtmp, *rettmp; -+ limb_t res; -+ -+ memset (tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE); -+ -+ atmp = tmp; -+ modtmp = &tmp[anum+modnum]; -+ rettmp = &tmp[(anum+modnum)*2]; -+ -+ for (size_t i=modnum; inlimbs < v->nlimbs) -+ { /* Swap U and V. */ -+ usize = v->nlimbs; -+ usign = v->sign; -+ usecure = mpi_is_secure (v); -+ up = v->d; -+ vsize = u->nlimbs; -+ vsign = u->sign; -+ vsecure = mpi_is_secure (u); -+ vp = u->d; -+ } -+ else -+ { -+ usize = u->nlimbs; -+ usign = u->sign; -+ usecure = mpi_is_secure (u); -+ up = u->d; -+ vsize = v->nlimbs; -+ vsign = v->sign; -+ vsecure = mpi_is_secure (v); -+ vp = v->d; -+ } -+ sign_product = usign ^ vsign; -+ wp = w->d; -+ -+ /* make sure u and v have the same length by extending the limbs to the larger one, now u */ -+ if (usize != vsize) -+ { -+ mpi_limb_t *tmp_vp = mpi_alloc_limb_space (usize, vsecure); -+ clean_vp = 1; -+ MPN_ZERO (tmp_vp, (usize - vsize)); -+ MPN_COPY (tmp_vp + (usize - vsize), vp, vsize); -+ vsize = usize; -+ vp = tmp_vp; -+ } -+ -+ /* w == u */ -+ /* Ensure W has space enough to store the result. */ -+ wsize = usize + vsize; -+ if (!mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v))) -+ { -+ /* w is not allocated in secure space but u or v is. To make sure -+ * that no temporary results are stored in w, we temporary use -+ * a newly allocated limb space for w */ -+ wp = mpi_alloc_limb_space( wsize, 1 ); -+ assign_wp = 2; /* mark it as 2 so that we can later copy it back to -+ * normal memory */ -+ } -+ else if (w->alloced < wsize ) -+ { -+ if (wp == up || wp == vp) -+ { -+ wp = mpi_alloc_limb_space (wsize, mpi_is_secure (w)); -+ assign_wp = 1; -+ } -+ else -+ { -+ mpi_resize(w, wsize ); -+ wp = w->d; -+ } -+ } -+ else -+ { /* Make U and V not overlap with W. */ -+ if (wp == up) -+ { -+ /* W and U are identical. Allocate temporary space for U. */ -+ tmp_limb_nlimbs = usize; -+ up = tmp_limb = mpi_alloc_limb_space (usize, usecure); -+ /* Is V identical too? Keep it identical with U. */ -+ if (wp == vp) -+ vp = up; -+ /* Copy to the temporary space. */ -+ MPN_COPY (up, wp, usize); -+ } -+ else if (wp == vp) -+ { -+ /* W and V are identical. Allocate temporary space for V. */ -+ tmp_limb_nlimbs = vsize; -+ vp = tmp_limb = mpi_alloc_limb_space (vsize, vsecure); -+ /* Copy to the temporary space. */ -+ MPN_COPY (vp, wp, vsize); -+ } -+ } -+ -+ if (!vsize) -+ wsize = 0; -+ else -+ { -+ mpi_limb_t *tmp = mpi_alloc_limb_space (wsize * 2, mpi_is_secure (w)); -+ mul_cs (wp, up, vp, vsize, tmp); -+ _gcry_mpi_free_limb_space (tmp, wsize * 2); -+ } -+ -+ if (clean_vp) -+ { -+ _gcry_mpi_free_limb_space (vp, vsize); -+ } -+ if (assign_wp) -+ { -+ if (assign_wp == 2) -+ { -+ /* copy the temp wp from secure memory back to normal memory */ -+ mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); -+ MPN_COPY (tmp_wp, wp, wsize); -+ _gcry_mpi_free_limb_space (wp, 0); -+ wp = tmp_wp; -+ } -+ _gcry_mpi_assign_limb_space (w, wp, wsize); -+ } -+ w->nlimbs = wsize; -+ w->sign = sign_product; -+ if (tmp_limb) -+ _gcry_mpi_free_limb_space (tmp_limb, tmp_limb_nlimbs); -+} -+#endif /* WITH_MARVIN_WORKAROUND */ - - void - _gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) -@@ -221,3 +348,45 @@ _gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) - if (temp_m) - mpi_free(temp_m); - } -+ -+#ifdef WITH_MARVIN_WORKAROUND -+static void -+_gcry_mpi_mod_sec (gcry_mpi_t ret, gcry_mpi_t a, gcry_mpi_t mod) -+{ -+ size_t asize = a->nlimbs; -+ size_t modsize = mod->nlimbs; -+ size_t tmp_size = mod_limb_numb (asize, modsize); -+ mpi_limb_t *tmp_limb = mpi_alloc_limb_space (tmp_size, mpi_is_secure(a)); -+ mod_cs (ret->d, a->d, asize, mod->d, modsize, tmp_limb); -+ /* cut the length to the mod size */ -+ ret->nlimbs = mod->nlimbs; -+ _gcry_mpi_free_limb_space (tmp_limb, tmp_size); -+} -+ -+/* The constant time code uses different order of the limbs ... */ -+static void -+_gcry_mpi_reverse_sec (gcry_mpi_t w) -+{ -+ for (size_t i = 0; i < w->nlimbs/2; i++) -+ { -+ mpi_limb_t t = w->d[i]; -+ w->d[i] = w->d[w->nlimbs - i - 1]; -+ w->d[w->nlimbs - i - 1] = t; -+ } -+} -+ -+void -+_gcry_mpi_mulm_sec (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) -+{ -+ /* w == u */ -+ _gcry_mpi_reverse_sec (u); -+ _gcry_mpi_reverse_sec (v); -+ _gcry_mpi_reverse_sec (m); -+ _gcry_mpi_mul_sec (w, u, v); -+ _gcry_mpi_mod_sec (w, w, m); -+ -+ /* get them back to the order the rest of the code expects */ -+ _gcry_mpi_reverse_sec (w); /* -- this is the result */ -+ _gcry_mpi_reverse_sec (m); /* -- this might be still used by the calling function */ -+} -+#endif /* WITH_MARVIN_WORKAROUND */ -diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h -index 1b449281..7e9e9894 100644 ---- a/src/gcrypt-int.h -+++ b/src/gcrypt-int.h -@@ -453,6 +453,9 @@ void _gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); - void _gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v); - void _gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v ); - void _gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); -+#ifdef WITH_MARVIN_WORKAROUND -+void _gcry_mpi_mulm_sec (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); -+#endif /* WITH_MARVIN_WORKAROUND */ - void _gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt); - void _gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r, - gcry_mpi_t dividend, gcry_mpi_t divisor, int round); -@@ -548,6 +551,9 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); - #define mpi_mul_2exp(w,u,v) _gcry_mpi_mul_2exp ((w),(u),(v)) - #define mpi_mul(w,u,v) _gcry_mpi_mul ((w),(u),(v)) - #define mpi_mulm(w,u,v,m) _gcry_mpi_mulm ((w),(u),(v),(m)) -+#ifdef WITH_MARVIN_WORKAROUND -+#define mpi_mulm_sec(w,u,v,m) _gcry_mpi_mulm_sec ((w),(u),(v),(m)) -+#endif /* WITH_MARVIN_WORKAROUND */ - #define mpi_powm(w,b,e,m) _gcry_mpi_powm ( (w), (b), (e), (m) ) - #define mpi_tdiv(q,r,a,m) _gcry_mpi_div ( (q), (r), (a), (m), 0) - #define mpi_fdiv(q,r,a,m) _gcry_mpi_div ( (q), (r), (a), (m), -1) --- -2.46.0 - - -From 1b7b995c5f4cd48a3b98915826431efb41a927ce Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 26 Apr 2024 16:39:18 +0200 -Subject: [PATCH 3/7] Constant time conversion of the message to the SEXP - -* cipher/rsa.c (rsa_decrypt): Use constant time conversion to SEXP after - decryption. -* src/const-time.c (_gcry_ct_memcpy): Constant time memcpy. New. -* src/const-time.h (ct_lt): New. - (ct_char_gen{,_inv}_mask): New. -* src/sexp.c (do_vsexp_sscan): Introduce constant time version of %b --- - -The current conversion of the message back to the SEXP buffer leaks the -length of the decrypted message. This introduces a constant-time variant -that should run for the same time for any input length. - -Signed-off-by: Jakub Jelen ---- - cipher/rsa.c | 4 ++++ - src/const-time.c | 28 ++++++++++++++++++++++++++-- - src/const-time.h | 12 ++++++++++++ - src/sexp.c | 39 +++++++++++++++++++++++++++++++++------ - 4 files changed, 75 insertions(+), 8 deletions(-) - -diff --git a/cipher/rsa.c b/cipher/rsa.c -index 2f735f9c..52f2aa89 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1519,7 +1519,11 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); - mpi_free (plain); - plain = NULL; -+#ifdef WITH_MARVIN_WORKAROUND -+ rc_sexp = sexp_build (&result, NULL, "(value %c)", (int)unpadlen, unpad, (nbits + 7) / 8); -+#else - rc_sexp = sexp_build (&result, NULL, "(value %b)", (int)unpadlen, unpad); -+#endif /* WITH_MARVIN_WORKAROUND */ - *r_plain = sexp_null_cond (result, ct_is_not_zero (rc)); - dummy = sexp_null_cond (result, ct_is_zero (rc)); - sexp_release (dummy); -diff --git a/src/const-time.c b/src/const-time.c -index 0fb53a07..cecb1937 100644 ---- a/src/const-time.c -+++ b/src/const-time.c -@@ -77,8 +77,8 @@ _gcry_ct_memmov_cond (void *dst, const void *src, size_t len, - unsigned long op_enable) - { - /* Note: dual mask with AND/OR used for EM leakage mitigation */ -- unsigned char mask1 = ct_ulong_gen_mask(op_enable); -- unsigned char mask2 = ct_ulong_gen_inv_mask(op_enable); -+ volatile unsigned char mask1 = ct_ulong_gen_mask(op_enable); -+ volatile unsigned char mask2 = ct_ulong_gen_inv_mask(op_enable); - unsigned char *b_dst = dst; - const unsigned char *b_src = src; - size_t i; -@@ -86,3 +86,27 @@ _gcry_ct_memmov_cond (void *dst, const void *src, size_t len, - for (i = 0; i < len; i++) - b_dst[i] = (b_dst[i] & mask2) | (b_src[i] & mask1); - } -+ -+/* -+ * Copy LEN bytes from memory area SRC to memory area DST. The -+ * bytes are read up to the BUFFER_LEN size to keep the operation -+ * not dependent on the message length (both SRC and DST buffers -+ * need to have this size!). -+ */ -+void -+_gcry_ct_memcpy (void *dst, const void *src, size_t len, size_t buffer_len) -+{ -+ unsigned char mask_a, mask_b; -+ unsigned char *b_dst = dst; -+ const unsigned char *b_src = src; -+ unsigned int writing; -+ size_t i; -+ -+ for (i = 0; i < buffer_len; i++) -+ { -+ writing = ct_lt (i, len); -+ mask_b = ct_uchar_gen_inv_mask (writing); -+ mask_a = ct_uchar_gen_mask (writing); -+ b_dst[i] = (b_src[i] & mask_a) | (b_dst[i] & mask_b); -+ } -+} -diff --git a/src/const-time.h b/src/const-time.h -index 245967eb..74055a4b 100644 ---- a/src/const-time.h -+++ b/src/const-time.h -@@ -26,6 +26,7 @@ - #define ct_not_memequal _gcry_ct_not_memequal - #define ct_memequal _gcry_ct_memequal - #define ct_memmov_cond _gcry_ct_memmov_cond -+#define ct_memcpy _gcry_ct_memcpy - - - #ifndef HAVE_GCC_ASM_VOLATILE_MEMORY -@@ -33,6 +34,14 @@ extern volatile unsigned int _gcry_ct_vzero; - extern volatile unsigned int _gcry_ct_vone; - #endif - -+/* -+ * Return 1 if A < B and return 0 otherwise. -+ */ -+static inline int -+ct_lt (unsigned int a, unsigned int b) -+{ -+ return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(unsigned int)*8 - 1); -+} - - static inline size_t - ct_lt_s (size_t a, size_t b) -@@ -112,6 +121,7 @@ unsigned int _gcry_ct_memequal (const void *b1, const void *b2, size_t len); - DEFINE_CT_TYPE_GEN_MASK(uintptr, uintptr_t) - DEFINE_CT_TYPE_GEN_MASK(ulong, unsigned long) - DEFINE_CT_TYPE_GEN_MASK(int16, int16_t) -+DEFINE_CT_TYPE_GEN_MASK(uchar, unsigned char) - - /* - * Return all bits set if A is 0 and return 1 otherwise. -@@ -137,6 +147,7 @@ DEFINE_CT_TYPE_GEN_MASK(int16, int16_t) - DEFINE_CT_TYPE_GEN_INV_MASK(uintptr, uintptr_t) - DEFINE_CT_TYPE_GEN_INV_MASK(ulong, unsigned long) - DEFINE_CT_TYPE_GEN_INV_MASK(int16, int16_t) -+DEFINE_CT_TYPE_GEN_INV_MASK(uchar, unsigned char) - - /* - * Return A when OP_ENABLED=1 -@@ -172,5 +183,6 @@ sexp_null_cond (gcry_sexp_t w, unsigned long op_enable) - */ - void _gcry_ct_memmov_cond (void *dst, const void *src, size_t len, - unsigned long op_enable); -+void _gcry_ct_memcpy (void *dst, const void *src, size_t len, size_t buffer_len); - - #endif /*GCRY_CONST_TIME_H*/ -diff --git a/src/sexp.c b/src/sexp.c -index c77d0212..8e6c847f 100644 ---- a/src/sexp.c -+++ b/src/sexp.c -@@ -31,6 +31,7 @@ - - #define GCRYPT_NO_MPI_MACROS 1 - #include "g10lib.h" -+#include "const-time.h" - - - /* Notes on the internal memory layout. -@@ -1079,6 +1080,10 @@ unquote_string (const char *string, size_t length, unsigned char *buf) - * %d - integer stored as string (no autoswitch to secure allocation) - * %b - memory buffer; this takes _two_ arguments: an integer with the - * length of the buffer and a pointer to the buffer. -+ * %c - memory buffer same as %b, but written in constant time; this -+ * takes _three_ arguments: an integer with the length of the buffer, -+ * a pointer to the buffer and the maximum length of the buffer -+ * to avoid potential side channel leaking the buffer length. - * %S - Copy an gcry_sexp_t here. The S-expression needs to be a - * regular one, starting with a parenthesis. - * (no autoswitch to secure allocation) -@@ -1204,7 +1209,7 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, - { - switch (*p) - { -- case 'b': case 't': case 'v': case 'n': case 'f': -+ case 'b': case 'c': case 't': case 'v': case 'n': case 'f': - case 'r': case '"': case '\'': case '\\': - quoted_esc = 0; - break; -@@ -1538,14 +1543,27 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, - memcpy (c.pos, astr, alen); - c.pos += alen; - } -- else if (*p == 'b') -+ else if (*p == 'b' || *p == 'c') - { - /* Insert a memory buffer. */ - const char *astr; -- int alen; -+ int alen, buflen = 0, reallen = 0; - - ARG_NEXT (alen, int); - ARG_NEXT (astr, const char *); -+ if (*p == 'c') -+ { -+ ARG_NEXT (buflen, int); -+ if (buflen < alen) -+ { -+ *erroff = p - buffer; -+ err = GPG_ERR_INV_ARG; -+ goto leave; -+ } -+ /* Do all the calculations with the buflen */ -+ reallen = alen; -+ alen = buflen; -+ } - - if (alen < 0) - { -@@ -1578,9 +1596,18 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, - } - - *c.pos++ = ST_DATA; -- STORE_LEN (c.pos, alen); -- memcpy (c.pos, astr, alen); -- c.pos += alen; -+ if (*p == 'c') -+ { -+ STORE_LEN (c.pos, reallen); -+ ct_memcpy (c.pos, astr, reallen, buflen); -+ c.pos += reallen; -+ } -+ else -+ { -+ STORE_LEN (c.pos, alen); -+ memcpy (c.pos, astr, alen); -+ c.pos += alen; -+ } - } - else if (*p == 'd') - { --- -2.46.0 - - -From 14008d6f9f3985461ea50a6760391086c9bbe72b Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 30 May 2024 17:50:36 +0200 -Subject: [PATCH 5/7] rsa: Implement constant-time conversion of MPI to string - --- -* cipher/rsa-common.c (_gcry_rsa_pkcs1_decode_for_enc): Replace - _gcry_mpi_print() with constant time operation. - -The _gcry_mpi_print() does a lot of housekeeping on the provided MPI -including skipping all the leading zeroes. If the ciphertext decrypted -to many leading zeroes, the output from this function is much shorter -(could be even all zeroes), which would immediately fail. - -This implements the dummy conversion of the MPI with the knowledge that -the encrypted data will always have the fixed length, providing constant -time operation. - -Signed-off-by: Jakub Jelen ---- - cipher/rsa-common.c | 35 ++++++++++++++++++++++++++++++++++- - 1 file changed, 34 insertions(+), 1 deletion(-) - -diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c -index e45cb30d..a61d82e3 100644 ---- a/cipher/rsa-common.c -+++ b/cipher/rsa-common.c -@@ -28,6 +28,7 @@ - #include "cipher.h" - #include "pubkey-internal.h" - #include "const-time.h" -+#include "bufhelp.h" - - - /* Turn VALUE into an octet string and store it in an allocated buffer -@@ -199,7 +200,6 @@ gpg_err_code_t - _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - unsigned int nbits, gcry_mpi_t value) - { -- gcry_error_t err; - unsigned char *frame = NULL; - size_t nframe = (nbits+7) / 8; - size_t n, n0; -@@ -208,6 +208,36 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - - *r_result = NULL; - -+ { -+#ifdef WITH_MARVIN_WORKAROUND -+ /* Allocate more to fit the whole MPI and allow moving it later to the right place */ -+ size_t alloc_len = value->nlimbs * BYTES_PER_MPI_LIMB; -+ if ( !(frame = xtrymalloc_secure (alloc_len))) -+ return gpg_err_code_from_syserror (); -+ -+ /* shovel the MPI content to the buffer as it is */ -+ unsigned char *p = frame; -+ for (int i = value->nlimbs - 1; i >= 0; i--) -+ { -+ mpi_limb_t *alimb = &value->d[i]; -+#if BYTES_PER_MPI_LIMB == 4 -+ buf_put_be32 (p, *alimb); -+ p += 4; -+#elif BYTES_PER_MPI_LIMB == 8 -+ buf_put_be64 (p, *alimb); -+ p += 8; -+#else -+# error please implement for this limb size. -+#endif -+ } -+ /* Remove leading zeroes, but not all! Keep the buffer to the nframe length! -+ * -- valid PKCS#1.5 padding will never have different lengths, than modulus */ -+ memmov_independently (frame, frame + (alloc_len - nframe), nframe, alloc_len); -+ n = 0; -+ failed |= ct_not_equal_byte (frame[n++], 0x00); -+#else -+ gcry_error_t err; -+ - if ( !(frame = xtrymalloc_secure (nframe))) - return gpg_err_code_from_syserror (); - -@@ -235,6 +265,9 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - n = 0; - if (!frame[0]) - n++; -+#endif -+ } -+ - failed |= ct_not_equal_byte (frame[n++], 0x02); - - /* Find the terminating zero byte. */ --- -2.46.0 - - -From 5c0b1707e48d21fa4d860b0bafdeaeb438885707 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 31 May 2024 15:03:29 +0200 -Subject: [PATCH 6/7] cipher: Use the constant time conversion also for OAEP - --- -* cipher/rsa-common.c (mpi_to_string): New function - (_gcry_rsa_pkcs1_decode_for_enc): Use new function for MPI to string - conversion. - (_gcry_rsa_oaep_decode): Use the new function for MPI to string - conversion. -* cipher/rsa.c (rsa_decrypt): Use constant time conversion to S-exp for - OAEP padding. - -Signed-off-by: Jakub Jelen ---- - cipher/rsa-common.c | 75 +++++++++++++++++++++++++++++++-------------- - cipher/rsa.c | 4 +++ - 2 files changed, 56 insertions(+), 23 deletions(-) - -diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c -index a61d82e3..82a9e083 100644 ---- a/cipher/rsa-common.c -+++ b/cipher/rsa-common.c -@@ -192,31 +192,26 @@ memmov_independently (void *dst, const void *src, size_t len, size_t buflen) - } - - --/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. -- NBITS is the size of the secret key. On success the result is -- stored as a newly allocated buffer at R_RESULT and its valid length at -- R_RESULTLEN. On error NULL is stored at R_RESULT. */ --gpg_err_code_t --_gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, -- unsigned int nbits, gcry_mpi_t value) -+static unsigned char * -+mpi_to_string(gcry_mpi_t value, size_t nframe) - { - unsigned char *frame = NULL; -- size_t nframe = (nbits+7) / 8; -- size_t n, n0; -- unsigned int failed = 0; -- unsigned int not_found = 1; -+ unsigned char *p; -+ size_t noff; -+ /* Allocate memory to fit the whole MPI limbs and allow moving it later to the right place */ -+ size_t alloc_len = value->nlimbs * BYTES_PER_MPI_LIMB; - -- *r_result = NULL; -+ /* for too short input, we need to allocate at least modulus length (which might still be valid in case of OAEP) */ -+ noff = (alloc_len < nframe) ? nframe - alloc_len : 0; -+ alloc_len = alloc_len + noff; - -- { --#ifdef WITH_MARVIN_WORKAROUND -- /* Allocate more to fit the whole MPI and allow moving it later to the right place */ -- size_t alloc_len = value->nlimbs * BYTES_PER_MPI_LIMB; - if ( !(frame = xtrymalloc_secure (alloc_len))) -- return gpg_err_code_from_syserror (); -+ return NULL; - -+ if (noff) -+ memset (frame, 0, noff); -+ p = frame + noff; - /* shovel the MPI content to the buffer as it is */ -- unsigned char *p = frame; - for (int i = value->nlimbs - 1; i >= 0; i--) - { - mpi_limb_t *alimb = &value->d[i]; -@@ -230,9 +225,34 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - # error please implement for this limb size. - #endif - } -- /* Remove leading zeroes, but not all! Keep the buffer to the nframe length! -- * -- valid PKCS#1.5 padding will never have different lengths, than modulus */ -+ /* Move the MPI to the right place -- with the least significant bytes aligned to the modulus length -+ * -- this might keep some leading zeroes at the beginning of the buffer, but this might be valid for OAEP */ - memmov_independently (frame, frame + (alloc_len - nframe), nframe, alloc_len); -+ return frame; -+} -+ -+/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. -+ NBITS is the size of the secret key. On success the result is -+ stored as a newly allocated buffer at R_RESULT and its valid length at -+ R_RESULTLEN. On error NULL is stored at R_RESULT. */ -+gpg_err_code_t -+_gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, -+ unsigned int nbits, gcry_mpi_t value) -+{ -+ unsigned char *frame = NULL; -+ size_t nframe = (nbits+7) / 8; -+ size_t n, n0; -+ unsigned int failed = 0; -+ unsigned int not_found = 1; -+ -+ *r_result = NULL; -+ -+ { -+#ifdef WITH_MARVIN_WORKAROUND -+ frame = mpi_to_string(value, nframe); -+ if (frame == NULL) -+ return gpg_err_code_from_syserror (); -+ - n = 0; - failed |= ct_not_equal_byte (frame[n++], 0x00); - #else -@@ -265,7 +285,7 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - n = 0; - if (!frame[0]) - n++; --#endif -+#endif /* WITH_MARVIN_WORKAROUND */ - } - - failed |= ct_not_equal_byte (frame[n++], 0x02); -@@ -709,14 +729,23 @@ _gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen, - happen due to the leading zero in OAEP frames and due to the - following random octets (seed^mask) which may have leading zero - bytes. This all is needed to cope with our leading zeroes -- suppressing MPI implementation. The code implictly implements -+ suppressing MPI implementation. The code implicitly implements - Step 1b (bail out if NFRAME != N). */ -+#ifdef WITH_MARVIN_WORKAROUND -+ frame = mpi_to_string(value, nkey); -+ if (frame == NULL) -+ { -+ xfree (lhash); -+ return gpg_err_code_from_syserror (); -+ } -+#else - rc = octet_string_from_mpi (&frame, NULL, value, nkey); - if (rc) - { - xfree (lhash); - return GPG_ERR_ENCODING_PROBLEM; - } -+#endif /* WITH_MARVIN_WORKAROUND */ - nframe = nkey; - - /* Step 1c: Check that the key is long enough. */ -@@ -731,7 +760,7 @@ _gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen, - gcry_mpi_aprint above. */ - - /* Allocate space for SEED and DB. */ -- seed = xtrymalloc_secure (nframe - 1); -+ seed = xtrymalloc_secure (nframe); - if (!seed) - { - rc = gpg_err_code_from_syserror (); -diff --git a/cipher/rsa.c b/cipher/rsa.c -index 52f2aa89..c196724c 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1537,7 +1537,11 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - plain, ctx.label, ctx.labellen); - mpi_free (plain); - plain = NULL; -+#ifdef WITH_MARVIN_WORKAROUND -+ rc_sexp = sexp_build (&result, NULL, "(value %c)", (int)unpadlen, unpad, (nbits + 7) / 8); -+#else - rc_sexp = sexp_build (&result, NULL, "(value %b)", (int)unpadlen, unpad); -+#endif /* WITH_MARVIN_WORKAROUND */ - *r_plain = sexp_null_cond (result, ct_is_not_zero (rc)); - dummy = sexp_null_cond (result, ct_is_zero (rc)); - sexp_release (dummy); --- -2.46.0 - - -From 4dffeaeadf792931aee61e6f51f59cf911c0c1f5 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 29 Apr 2024 19:06:17 +0200 -Subject: [PATCH 7/7] Implement implicit rejection for PKCS#1.5 decipher - --- -* cipher/pubkey-internal.h - (_gcry_rsa_pkcs1_decode_for_enc_implicit_rejection): New. -* pubkey-util.c (_gcry_pk_util_parse_flaglist): Parse the new flag - no-implicit-rejection. -* cipher/rsa-common.c (rsa_prf): New function. - (_gcry_rsa_pkcs1_decode_for_enc_implicit_rejection): New function. -* cipher/rsa.c (rsa_decrypt): Handle implicit rejection. -* src/cipher.h (pk_encoding): New flag. -* tests/pkcs1v2.c (extract_cmp_data): Allow quiet test. - (check_v15crypt): Add support for implicit rejection. -* tests/pkcs1v2-v15c.h: Add test vectors for implicit rejection. - -Signed-off-by: Jakub Jelen ---- - cipher/pubkey-internal.h | 8 ++ - cipher/pubkey-util.c | 9 ++ - cipher/rsa-common.c | 181 +++++++++++++++++++++++ - cipher/rsa.c | 81 +++++++++++ - src/cipher.h | 37 ++--- - src/const-time.c | 2 +- - src/const-time.h | 3 +- - tests/pkcs1v2-v15c.h | 304 +++++++++++++++++++++++++++++++++++++++ - tests/pkcs1v2.c | 124 +++++++++++----- - 9 files changed, 692 insertions(+), 57 deletions(-) - -diff --git a/cipher/pubkey-internal.h b/cipher/pubkey-internal.h -index acf45105..f66574fa 100644 ---- a/cipher/pubkey-internal.h -+++ b/cipher/pubkey-internal.h -@@ -55,6 +55,14 @@ _gcry_rsa_pkcs1_encode_for_enc (gcry_mpi_t *r_result, unsigned int nbits, - gpg_err_code_t - _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - unsigned int nbits, gcry_mpi_t value); -+#ifdef WITH_MARVIN_WORKAROUND -+gpg_err_code_t -+_gcry_rsa_pkcs1_decode_for_enc_implicit_rejection (unsigned char **r_result, -+ size_t *r_resultlen, -+ unsigned int nbits, -+ gcry_mpi_t value, -+ unsigned char *kdk); -+#endif /* WITH_MARVIN_WORKAROUND */ - gpg_err_code_t - _gcry_rsa_pkcs1_encode_raw_for_sig (gcry_mpi_t *r_result, unsigned int nbits, - const unsigned char *value, size_t valuelen); -diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c -index 68defea6..e760dd4c 100644 ---- a/cipher/pubkey-util.c -+++ b/cipher/pubkey-util.c -@@ -193,6 +193,15 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, - rc = GPG_ERR_INV_FLAG; - break; - -+#ifdef WITH_MARVIN_WORKAROUND -+ case 21: -+ if (!memcmp (s, "no-implicit-rejection", 21)) -+ flags |= PUBKEY_FLAG_NO_IMPLICIT_REJECTION; -+ else if (!igninvflag) -+ rc = GPG_ERR_INV_FLAG; -+ break; -+#endif /* WITH_MARVIN_WORKAROUND */ -+ - default: - if (!igninvflag) - rc = GPG_ERR_INV_FLAG; -diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c -index 82a9e083..e776a309 100644 ---- a/cipher/rsa-common.c -+++ b/cipher/rsa-common.c -@@ -318,6 +318,187 @@ _gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen, - } - - -+#ifdef WITH_MARVIN_WORKAROUND -+#define SHA256_LEN 32 -+static gcry_err_code_t -+rsa_prf(unsigned char *out, size_t out_len, const char *label, size_t label_len, unsigned char *kdk, size_t nbits) -+{ -+ gcry_err_code_t rc = GPG_ERR_NO_ERROR; -+ size_t pos; -+ uint16_t iter = 0; -+ unsigned char be_iter[2]; -+ unsigned char be_bitlen[2]; -+ gcry_md_hd_t hd; -+ gcry_error_t err; -+ -+ be_bitlen[0] = (nbits >> 8) & 0xff; -+ be_bitlen[1] = nbits & 0xff; -+ -+ err = _gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); -+ if (err) -+ { -+ return GPG_ERR_INTERNAL; -+ } -+ err = _gcry_md_setkey (hd, kdk, SHA256_LEN); -+ if (err) -+ { -+ _gcry_md_close (hd); -+ return GPG_ERR_INTERNAL; -+ } -+ for (pos = 0; pos < out_len; pos += SHA256_LEN, iter++) -+ { -+ unsigned char *tmp; -+ -+ _gcry_md_reset(hd); -+ -+ be_iter[0] = (iter >> 8) & 0xff; -+ be_iter[1] = iter & 0xff; -+ _gcry_md_write (hd, be_iter, sizeof (be_iter)); -+ _gcry_md_write (hd, label, label_len); -+ _gcry_md_write (hd, be_bitlen, sizeof (be_bitlen)); -+ -+ tmp = _gcry_md_read(hd, 0); -+ if (pos + SHA256_LEN > out_len) -+ { -+ memcpy(out + pos, tmp, out_len - pos); -+ } -+ else -+ { -+ memcpy(out + pos, tmp, SHA256_LEN); -+ } -+ } -+ _gcry_md_close (hd); -+ return rc; -+} -+ -+ -+/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. -+ NBITS is the size of the secret key. On success the result is -+ stored as a newly allocated buffer at R_RESULT and its valid length at -+ R_RESULTLEN. On error R_RESULT contains bogus value of random length. -+ For more information, see description of Implicit Rejection in Marvin paper -+ https://people.redhat.com/~hkario/marvin/marvin-attack-paper.pdf */ -+#define MAX_LEN_GEN_TRIES 128 -+gpg_err_code_t -+_gcry_rsa_pkcs1_decode_for_enc_implicit_rejection (unsigned char **r_result, -+ size_t *r_resultlen, -+ unsigned int nbits, -+ gcry_mpi_t value, -+ unsigned char *kdk) -+{ -+ unsigned char *frame = NULL; -+ size_t nframe = (nbits+7) / 8; -+ size_t n, n0; -+ unsigned int failed = 0; -+ unsigned int not_found = 1; -+ int i, j; -+ uint16_t len_mask; -+ uint16_t max_sep_offset; -+ unsigned char *synthetic = NULL; -+ unsigned long synthethic_length; -+ uint16_t len_candidate; -+ unsigned char candidate_lengths[MAX_LEN_GEN_TRIES * sizeof(len_candidate)]; -+ int synth_msg_index = 0, msg_index; -+ -+ *r_result = NULL; -+ -+ synthetic = xtrymalloc(nframe); -+ if (synthetic == NULL) -+ { -+ free (synthetic); -+ return gpg_err_code_from_syserror (); -+ } -+ -+ if (rsa_prf(synthetic, nframe, "message", 7, kdk, nframe * 8) < 0) -+ { -+ xfree (synthetic); -+ return GPG_ERR_INTERNAL; -+ } -+ -+ /* decide how long the random message should be */ -+ if (rsa_prf(candidate_lengths, sizeof(candidate_lengths), -+ "length", 6, kdk, MAX_LEN_GEN_TRIES * sizeof(len_candidate) * 8) < 0) -+ { -+ xfree (synthetic); -+ return GPG_ERR_INTERNAL; -+ } -+ -+ len_mask = max_sep_offset = nframe - 2 - 8; -+ len_mask |= len_mask >> 1; -+ len_mask |= len_mask >> 2; -+ len_mask |= len_mask >> 4; -+ len_mask |= len_mask >> 8; -+ -+ synthethic_length = 0; -+ for (i = 0; i < MAX_LEN_GEN_TRIES * (int)sizeof(len_candidate); -+ i += sizeof(len_candidate)) -+ { -+ len_candidate = (candidate_lengths[i] << 8) | candidate_lengths[i + 1]; -+ len_candidate &= len_mask; -+ -+ synthethic_length = ct_ulong_select( -+ len_candidate, synthethic_length, -+ ct_lt(len_candidate, max_sep_offset)); -+ } -+ -+ synth_msg_index = nframe - synthethic_length; -+ -+ /* we have alternative message ready, check the real one */ -+ /* mostly copy from _gcry_rsa_pkcs1_decode_for_enc */ -+ frame = mpi_to_string(value, nframe); -+ if (frame == NULL) -+ { -+ xfree (synthetic); -+ return gpg_err_code_from_syserror (); -+ } -+ -+ /* FRAME = 0x00 || 0x02 || PS || 0x00 || M */ -+ n = 0; -+ failed |= ct_not_equal_byte (frame[n++], 0x00); -+ failed |= ct_not_equal_byte (frame[n++], 0x02); -+ -+ /* Find the terminating zero byte. */ -+ n0 = n; -+ for (; n < nframe; n++) -+ { -+ not_found &= ct_not_equal_byte (frame[n], 0x00); -+ n0 += not_found; -+ } -+ -+ failed |= not_found; -+ n0 += ct_is_zero (not_found); /* Skip the zero byte. */ -+ /* the valid padding is at least 8 bytes -- the plaintext needs to start at index 11 or later */ -+ failed |= ct_lt_s (n0, 11); -+ -+ msg_index = ct_ulong_select (synth_msg_index, n0, failed); -+ -+ /* To avoid the need memmove (O(N*log(N))), we use separate buffer where we move either -+ * of the messages. We can now also use the msg_index safely as its timing is not -+ * possible to distinguish valid and invalid padding */ -+ for (i = msg_index, j = 0; i < nframe && j < nframe; i++, j++) -+ { -+ frame[j] = ct_uchar_select (synthetic[i], frame[i], failed); -+ } -+ -+ *r_resultlen = j; -+ *r_result = frame; -+ -+ if (DBG_CIPHER) -+ { -+ if (!failed) -+ log_printhex ("value extracted from PKCS#1 block type 2 encoded data", -+ frame, nframe - n0); -+ else -+ log_printhex ("Synthetic value from implicit rejection", -+ synthetic, synthethic_length); -+ } -+ -+ xfree (synthetic); -+ return 0; -+} -+#endif /* WITH_MARVIN_WORKAROUND */ -+ -+ - /* Encode {VALUE,VALUELEN} for an NBITS keys and hash algorithm ALGO - using the pkcs#1 block type 1 padding. On success the result is - stored as a new MPI at R_RESULT. On error the value at R_RESULT is -diff --git a/cipher/rsa.c b/cipher/rsa.c -index c196724c..9c1ef1f7 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1436,6 +1436,7 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) - } - - -+#define SHA256_LEN 32 - static gcry_err_code_t - rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - -@@ -1451,6 +1452,9 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - unsigned int nbits = rsa_get_nbits (keyparms); - gcry_sexp_t result = NULL; - gcry_sexp_t dummy = NULL; -+#ifdef WITH_MARVIN_WORKAROUND -+ unsigned char kdk[SHA256_LEN]; -+#endif /* WITH_MARVIN_WORKAROUND */ - - rc = rsa_check_keysize (nbits); - if (rc) -@@ -1498,6 +1502,71 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - mpi_normalize (data); - mpi_fdiv_r (data, data, sk.n); - -+#ifdef WITH_MARVIN_WORKAROUND -+ /* Implicit rejection: Derive KDK */ -+ if (ctx.encoding == PUBKEY_ENC_PKCS1) -+ { -+ unsigned char *buf, *tmp; -+ unsigned int nbytes = (mpi_get_nbits (sk.n)+7)/8; -+ unsigned char key[SHA256_LEN]; -+ gcry_md_hd_t hd; -+ -+ /* (a) Convert `d` to big endian representation, left padded to the length of `n` */ -+ rc = _gcry_mpi_to_octet_string (&buf, NULL, sk.d, nbytes); -+ if (rc) -+ { -+ rc = GPG_ERR_INTERNAL; -+ goto leave; -+ } -+ -+ /* (b) Hash it using SHA-256 */ -+ rc = _gcry_md_open (&hd, GCRY_MD_SHA256, 0); -+ if (rc) -+ { -+ xfree (buf); -+ rc = GPG_ERR_INTERNAL; -+ goto leave; -+ } -+ _gcry_md_write (hd, buf, nbytes); -+ /* keep the buffer around -- it will be needed for the ciphertext */ -+ tmp = _gcry_md_read (hd, GCRY_MD_SHA256); -+ memcpy(key, tmp, SHA256_LEN); -+ _gcry_md_close (hd); -+ -+ /* (c) Use the hash as a SHA-256 HMAC key and ciphertext as a message */ -+ rc = _gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); -+ if (rc) -+ { -+ xfree (buf); -+ rc = GPG_ERR_INTERNAL; -+ goto leave; -+ } -+ rc = _gcry_md_setkey (hd, key, sizeof (key)); -+ if (rc) -+ { -+ xfree (buf); -+ _gcry_md_close (hd); -+ rc = GPG_ERR_INTERNAL; -+ goto leave; -+ } -+ -+ /* We need to convert the ciphertext to string, padded to the length of modulus */ -+ rc = _gcry_mpi_to_octet_string (NULL, buf, data, nbytes); -+ if (rc) -+ { -+ xfree (buf); -+ _gcry_md_close (hd); -+ rc = GPG_ERR_INTERNAL; -+ goto leave; -+ } -+ _gcry_md_write (hd, buf, nbytes); -+ xfree (buf); -+ buf = _gcry_md_read (hd, 0); -+ memcpy(kdk, buf, SHA256_LEN); -+ _gcry_md_close (hd); -+ } -+#endif /* WITH_MARVIN_WORKAROUND */ -+ - /* Allocate MPI for the plaintext. */ - plain = mpi_snew (nbits); - -@@ -1516,6 +1585,18 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - switch (ctx.encoding) - { - case PUBKEY_ENC_PKCS1: -+#ifdef WITH_MARVIN_WORKAROUND -+ if (!(ctx.flags & PUBKEY_FLAG_NO_IMPLICIT_REJECTION)) -+ { -+ rc = _gcry_rsa_pkcs1_decode_for_enc_implicit_rejection (&unpad, &unpadlen, nbits, plain, kdk); -+ mpi_free (plain); -+ plain = NULL; -+ rc_sexp = sexp_build (&result, NULL, "(value %c)", (int)unpadlen, unpad, (nbits + 7) / 8); -+ *r_plain = result; -+ rc = ct_ulong_select (rc_sexp, rc, ct_is_zero (rc) & ct_is_not_zero (rc_sexp)); -+ break; -+ } -+#endif /* WITH_MARVIN_WORKAROUND */ - rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); - mpi_free (plain); - plain = NULL; -diff --git a/src/cipher.h b/src/cipher.h -index 0a2551fe..e522f39b 100644 ---- a/src/cipher.h -+++ b/src/cipher.h -@@ -26,24 +26,25 @@ - - #include "../random/random.h" - --#define PUBKEY_FLAG_NO_BLINDING (1 << 0) --#define PUBKEY_FLAG_RFC6979 (1 << 1) --#define PUBKEY_FLAG_FIXEDLEN (1 << 2) --#define PUBKEY_FLAG_LEGACYRESULT (1 << 3) --#define PUBKEY_FLAG_RAW_FLAG (1 << 4) --#define PUBKEY_FLAG_TRANSIENT_KEY (1 << 5) --#define PUBKEY_FLAG_USE_X931 (1 << 6) --#define PUBKEY_FLAG_USE_FIPS186 (1 << 7) --#define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) --#define PUBKEY_FLAG_PARAM (1 << 9) --#define PUBKEY_FLAG_COMP (1 << 10) --#define PUBKEY_FLAG_NOCOMP (1 << 11) --#define PUBKEY_FLAG_EDDSA (1 << 12) --#define PUBKEY_FLAG_GOST (1 << 13) --#define PUBKEY_FLAG_NO_KEYTEST (1 << 14) --#define PUBKEY_FLAG_DJB_TWEAK (1 << 15) --#define PUBKEY_FLAG_SM2 (1 << 16) --#define PUBKEY_FLAG_PREHASH (1 << 17) -+#define PUBKEY_FLAG_NO_BLINDING (1 << 0) -+#define PUBKEY_FLAG_RFC6979 (1 << 1) -+#define PUBKEY_FLAG_FIXEDLEN (1 << 2) -+#define PUBKEY_FLAG_LEGACYRESULT (1 << 3) -+#define PUBKEY_FLAG_RAW_FLAG (1 << 4) -+#define PUBKEY_FLAG_TRANSIENT_KEY (1 << 5) -+#define PUBKEY_FLAG_USE_X931 (1 << 6) -+#define PUBKEY_FLAG_USE_FIPS186 (1 << 7) -+#define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) -+#define PUBKEY_FLAG_PARAM (1 << 9) -+#define PUBKEY_FLAG_COMP (1 << 10) -+#define PUBKEY_FLAG_NOCOMP (1 << 11) -+#define PUBKEY_FLAG_EDDSA (1 << 12) -+#define PUBKEY_FLAG_GOST (1 << 13) -+#define PUBKEY_FLAG_NO_KEYTEST (1 << 14) -+#define PUBKEY_FLAG_DJB_TWEAK (1 << 15) -+#define PUBKEY_FLAG_SM2 (1 << 16) -+#define PUBKEY_FLAG_PREHASH (1 << 17) -+#define PUBKEY_FLAG_NO_IMPLICIT_REJECTION (1 << 18) - - - enum pk_operation -diff --git a/src/const-time.c b/src/const-time.c -index cecb1937..2b6a4b4e 100644 ---- a/src/const-time.c -+++ b/src/const-time.c -@@ -96,7 +96,7 @@ _gcry_ct_memmov_cond (void *dst, const void *src, size_t len, - void - _gcry_ct_memcpy (void *dst, const void *src, size_t len, size_t buffer_len) - { -- unsigned char mask_a, mask_b; -+ volatile unsigned char mask_a, mask_b; - unsigned char *b_dst = dst; - const unsigned char *b_src = src; - unsigned int writing; -diff --git a/src/const-time.h b/src/const-time.h -index 74055a4b..5e656e15 100644 ---- a/src/const-time.h -+++ b/src/const-time.h -@@ -40,7 +40,7 @@ extern volatile unsigned int _gcry_ct_vone; - static inline int - ct_lt (unsigned int a, unsigned int b) - { -- return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(unsigned int)*8 - 1); -+ return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(unsigned int) * 8 - 1); - } - - static inline size_t -@@ -164,6 +164,7 @@ DEFINE_CT_TYPE_GEN_INV_MASK(uchar, unsigned char) - DEFINE_CT_TYPE_SELECT_FUNC(uintptr, uintptr_t) - DEFINE_CT_TYPE_SELECT_FUNC(ulong, unsigned long) - DEFINE_CT_TYPE_SELECT_FUNC(int16, int16_t) -+DEFINE_CT_TYPE_SELECT_FUNC(uchar, unsigned char) - - /* - * Return NULL when OP_ENABLED=1 -diff --git a/tests/pkcs1v2-v15c.h b/tests/pkcs1v2-v15c.h -index 26c7b238..cb750d4f 100644 ---- a/tests/pkcs1v2-v15c.h -+++ b/tests/pkcs1v2-v15c.h -@@ -21,6 +21,7 @@ - const char *mesg; - const char *seed; - const char *encr; -+ const char *synt; - } m[20]; - } tbl[] = - { -@@ -3915,5 +3916,308 @@ - "25db1dd892b71bb74a5cf68263d8fd58f1a48e6c2fcb8c0b71a251cfc1a20157" - } - } -+ }, -+ { -+ "A 2048-bit RSA Test vectors for the Bleichenbacher workaround", -+ "c8cc839714098da56caa23640f93dc8997c16372968fc1b0c6df5113c1c94e8b21e48ad2297e65419011b4e6d8f5e73b1b78b257400321d1ef6b602d4ec8ce8d141c94905eb4ad306639a49206534b6e7f2607423e97dffd133c88d721399defbc7e96ccdcbd7f3aae1fe892712bfb4929817d511666440a1facb7a208f5ea165910add8a3f2d497202360ccb632024f0d07169c1918f316f794b143aef54ec87522a4c02978f9689980bffbf649c307e81819bff88409638d48bd94be152b59ff649fa0bd629d0ffa1813c3abf4b56bd3c2ea5465dffa14589292a9d8a24ad26be7ee0510741b6382d43c83d5bfa40a46613d062be445517dbcaf0cb4e1a769", -+ "010001", -+ "1455010e0f2d587663a666a6ff1ccdbbf0edd8100646d02a023922908992c4ad39e5565929726ef6508c3a71158ef0b6ff751d39d07580bb2d2f063210442d0603ff50dbbd7b35fe2c9bb19a47a1af85a4c24901e02ca8b58b7919b20edf32aacfbf51adb4bc4b61b9b7e968caa4d570f70ef18d8063228893e47d439efca793259bcf2cd108a3d8688cdf078e7ac799969f2339d2c1f522b969684629a933baaec2681625eab84f4e56f4447e9d88fb9a199cf71023e0e257b14441b33c84d3bc67ca8031d2612618103a7a0a40844262f75d8890cd616e51f9035488fd6e099de8ff6d65a4ff118254807c9f58d2fbba8ba151dc8c68be349c977a204e04c1", -+ { -+ { -+ "1. a random positive test case", -+ NULL, -+ "", -+ "8bfe264e85d3bdeaa6b8851b8e3b956ee3d226fd3f69063a86880173a273d9f283b2eebdd1ed35f7e02d91c571981b6737d5320bd8396b0f3ad5b019daec1b0aab3cbbc026395f4fd14f13673f2dfc81f9b660ec26ac381e6db3299b4e460b43fab9955df2b3cfaa20e900e19c856238fd371899c2bf2ce8c868b76754e5db3b036533fd603746be13c10d4e3e6022ebc905d20c2a7f32b215a4cd53b3f44ca1c327d2c2b651145821c08396c89071f665349c25e44d2733cd9305985ceef6430c3cf57af5fa224089221218fa34737c79c446d28a94c41c96e4e92ac53fbcf384dea8419ea089f8784445a492c812eb0d409467f75afd7d4d1078886205a066", -+ "6c6f72656d20697073756d20646f6c6f722073697420616d6574" -+ },{ -+ "2. a random negative test case decrypting to empty", -+ NULL, -+ "", -+ "20aaa8adbbc593a924ba1c5c7990b5c2242ae4b99d0fe636a19a4cf754edbcee774e472fe028160ed42634f8864900cb514006da642cae6ae8c7d087caebcfa6dad1551301e130344989a1d462d4164505f6393933450c67bc6d39d8f5160907cabc251b737925a1cf21e5c6aa5781b7769f6a2a583d97cce008c0f8b6add5f0b2bd80bee60237aa39bb20719fe75749f4bc4e42466ef5a861ae3a92395c7d858d430bfe38040f445ea93fa2958b503539800ffa5ce5f8cf51fa8171a91f36cb4f4575e8de6b4d3f096ee140b938fd2f50ee13f0d050222e2a72b0a3069ff3a6738e82c87090caa5aed4fcbe882c49646aa250b98f12f83c8d528113614a29e7", -+ "" -+ },{ -+ "3. invalid decrypting to max length message", -+ NULL, -+ "", -+ "48cceab10f39a4db32f60074feea473cbcdb7accf92e150417f76b44756b190e843e79ec12aa85083a21f5437e7bad0a60482e601198f9d86923239c8786ee728285afd0937f7dde12717f28389843d7375912b07b991f4fdb0190fced8ba665314367e8c5f9d2981d0f5128feeb46cb50fc237e64438a86df198dd0209364ae3a842d77532b66b7ef263b83b1541ed671b120dfd660462e2107a4ee7b964e734a7bd68d90dda61770658a3c242948532da32648687e0318286473f675b412d6468f013f14d760a358dfcad3cda2afeec5e268a37d250c37f722f468a70dfd92d7294c3c1ee1e7f8843b7d16f9f37ef35748c3ae93aa155cdcdfeb4e78567303", -+ "22d850137b9eebe092b24f602dc5bb7918c16bd89ddbf20467b119d205f9c2e4bd7d2592cf1e532106e0f33557565923c73a02d4f09c0c22bea89148183e60317f7028b3aa1f261f91c979393101d7e15f4067e63979b32751658ef769610fe97cf9cef3278b3117d384051c3b1d82c251c2305418c8f6840530e631aad63e70e20e025bcd8efb54c92ec6d3b106a2f8e64eeff7d38495b0fc50c97138af4b1c0a67a1c4e27b077b8439332edfa8608dfeae653cd6a628ac550395f7e74390e42c11682234870925eeaa1fa71b76cf1f2ee3bda69f6717033ff8b7c95c9799e7a3bea5e7e4a1c359772fb6b1c6e6c516661dfe30c3" -+ },{ -+ "4. invalid decrypting to message with length specified by second to last value from PRF", -+ NULL, -+ "", -+ "1439e08c3f84c1a7fec74ce07614b20e01f6fa4e8c2a6cffdc3520d8889e5d9a950c6425798f85d4be38d300ea5695f13ecd4cb389d1ff5b82484b494d6280ab7fa78e645933981cb934cce8bfcd114cc0e6811eefa47aae20af638a1cd163d2d3366186d0a07df0c81f6c9f3171cf3561472e98a6006bf75ddb457bed036dcce199369de7d94ef2c68e8467ee0604eea2b3009479162a7891ba5c40cab17f49e1c438cb6eaea4f76ce23cce0e483ff0e96fa790ea15be67671814342d0a23f4a20262b6182e72f3a67cd289711503c85516a9ed225422f98b116f1ab080a80abd6f0216df88d8cfd67c139243be8dd78502a7aaf6bc99d7da71bcdf627e7354", -+ "0f9b" -+ },{ -+ "5. invalid decrypting to message with length specified by third to last value from PRF", -+ NULL, -+ "", -+ "1690ebcceece2ce024f382e467cf8510e74514120937978576caf684d4a02ad569e8d76cbe365a060e00779de2f0865ccf0d923de3b4783a4e2c74f422e2f326086c390b658ba47f31ab013aa80f468c71256e5fa5679b24e83cd82c3d1e05e398208155de2212993cd2b8bab6987cf4cc1293f19909219439d74127545e9ed8a706961b8ee2119f6bfacafbef91b75a789ba65b8b833bc6149cf49b5c4d2c6359f62808659ba6541e1cd24bf7f7410486b5103f6c0ea29334ea6f4975b17387474fe920710ea61568d7b7c0a7916acf21665ad5a31c4eabcde44f8fb6120d8457afa1f3c85d517cda364af620113ae5a3c52a048821731922737307f77a1081", -+ "4f02" -+ },{ -+ "6. positive test with 11 byte long value", -+ NULL, -+ "", -+ "6213634593332c485cef783ea2846e3d6e8b0e005cd8293eaebbaa5079712fd681579bdfbbda138ae4d9d952917a03c92398ec0cb2bb0c6b5a8d55061fed0d0d8d72473563152648cfe640b335dc95331c21cb133a91790fa93ae44497c128708970d2beeb77e8721b061b1c44034143734a77be8220877415a6dba073c3871605380542a9f25252a4babe8331cdd53cf828423f3cc70b560624d0581fb126b2ed4f4ed358f0eb8065cf176399ac1a846a31055f9ae8c9c24a1ba050bc20842125bc1753158f8065f3adb9cc16bfdf83816bdf38b624f12022c5a6fbfe29bc91542be8c0208a770bcd677dc597f5557dc2ce28a11bf3e3857f158717a33f6592", -+ "6c6f72656d20697073756d" -+ },{ -+ "7. positive test with 11 byte long value and zero padded ciphertext", -+ NULL, -+ "", -+ "00a2e8f114ea8d05d12dc843e3cc3b2edc8229ff2a028bda29ba9d55e3cd02911902fef1f42a075bf05e8016e8567213d6f260fa49e360779dd81aeea3e04c2cb567e0d72b98bf754014561b7511e083d20e0bfb9cd23f8a0d3c88900c49d2fcd5843ff0765607b2026f28202a87aa94678aed22a0c20724541394cd8f44e373eba1d2bae98f516c1e2ba3d86852d064f856b1daf24795e767a2b90396e50743e3150664afab131fe40ea405dcf572dd1079af1d3f0392ccadcca0a12740dbb213b925ca2a06b1bc1383e83a658c82ba2e7427342379084d5f66b544579f07664cb26edd4f10fd913fdbc0de05ef887d4d1ec1ac95652397ea7fd4e4759fda8b", -+ "6c6f72656d20697073756d" -+ },{ -+ "8. positive test with 11 byte long value and zero truncated ciphertext", -+ NULL, -+ "", -+ "a2e8f114ea8d05d12dc843e3cc3b2edc8229ff2a028bda29ba9d55e3cd02911902fef1f42a075bf05e8016e8567213d6f260fa49e360779dd81aeea3e04c2cb567e0d72b98bf754014561b7511e083d20e0bfb9cd23f8a0d3c88900c49d2fcd5843ff0765607b2026f28202a87aa94678aed22a0c20724541394cd8f44e373eba1d2bae98f516c1e2ba3d86852d064f856b1daf24795e767a2b90396e50743e3150664afab131fe40ea405dcf572dd1079af1d3f0392ccadcca0a12740dbb213b925ca2a06b1bc1383e83a658c82ba2e7427342379084d5f66b544579f07664cb26edd4f10fd913fdbc0de05ef887d4d1ec1ac95652397ea7fd4e4759fda8b", -+ "6c6f72656d20697073756d" -+ },{ -+ "9. positive test with 11 byte long value and double zero padded ciphertext", -+ NULL, -+ "", -+ "00001f71879b426127f7dead621f7380a7098cf7d22173aa27991b143c46d53383c209bd0c9c00d84078037e715f6b98c65005a77120070522ede51d472c87ef94b94ead4c5428ee108a345561658301911ec5a8f7dd43ed4a3957fd29fb02a3529bf63f8040d3953490939bd8f78b2a3404b6fb5ff70a4bfdaac5c541d6bcce49c9778cc390be24cbef1d1eca7e870457241d3ff72ca44f9f56bdf31a890fa5eb3a9107b603ccc9d06a5dd911a664c82b6abd4fe036f8db8d5a070c2d86386ae18d97adc1847640c211d91ff5c3387574a26f8ef27ca7f48d2dd1f0c7f14b81cc9d33ee6853031d3ecf10a914ffd90947909c8011fd30249219348ebff76bfc", -+ "6c6f72656d20697073756d" -+ },{ -+ "10. a random negative test that generates an 11 byte long message", -+ NULL, -+ "", -+ "5f02f4b1f46935c742ebe62b6f05aa0a3286aab91a49b34780adde6410ab46f7386e05748331864ac98e1da63686e4babe3a19ed40a7f5ceefb89179596aab07ab1015e03b8f825084dab028b6731288f2e511a4b314b6ea3997d2e8fe2825cef8897cbbdfb6c939d441d6e04948414bb69e682927ef8576c9a7090d4aad0e74c520d6d5ce63a154720f00b76de8cc550b1aa14f016d63a7b6d6eaa1f7dbe9e50200d3159b3d099c900116bf4eba3b94204f18b1317b07529751abf64a26b0a0bf1c8ce757333b3d673211b67cc0653f2fe2620d57c8b6ee574a0323a167eab1106d9bc7fd90d415be5f1e9891a0e6c709f4fc0404e8226f8477b4e939b36eb2", -+ "af9ac70191c92413cb9f2d" -+ },{ -+ "11. an otherwise correct plaintext, but with wrong first byte (0x01 instead of 0x00), generates a random 11 byte long plaintext", -+ NULL, -+ "", -+ "9b2ec9c0c917c98f1ad3d0119aec6be51ae3106e9af1914d48600ab6a2c0c0c8ae02a2dc3039906ff3aac904af32ec798fd65f3ad1afa2e69400e7c1de81f5728f3b3291f38263bc7a90a0563e43ce7a0d4ee9c0d8a716621ca5d3d081188769ce1b131af7d35b13dea99153579c86db31fe07d5a2c14d621b77854e48a8df41b5798563af489a291e417b6a334c63222627376118c02c53b6e86310f728734ffc86ef9d7c8bf56c0c841b24b82b59f51aee4526ba1c4268506d301e4ebc498c6aebb6fd5258c876bf900bac8ca4d309dd522f6a6343599a8bc3760f422c10c72d0ad527ce4af1874124ace3d99bb74db8d69d2528db22c3a37644640f95c05f", -+ "a1f8c9255c35cfba403ccc" -+ },{ -+ "12. an otherwise correct plaintext, but with wrong second byte (0x01 instead of 0x02), generates a random 11 byte long plaintext", -+ NULL, -+ "", -+ "782c2b59a21a511243820acedd567c136f6d3090c115232a82a5efb0b178285f55b5ec2d2bac96bf00d6592ea7cdc3341610c8fb07e527e5e2d20cfaf2c7f23e375431f45e998929a02f25fd95354c33838090bca838502259e92d86d568bc2cdb132fab2a399593ca60a015dc2bb1afcd64fef8a3834e17e5358d822980dc446e845b3ab4702b1ee41fe5db716d92348d5091c15d35a110555a35deb4650a5a1d2c98025d42d4544f8b32aa6a5e02dc02deaed9a7313b73b49b0d4772a3768b0ea0db5846ace6569cae677bf67fb0acf3c255dc01ec8400c963b6e49b1067728b4e563d7e1e1515664347b92ee64db7efb5452357a02fff7fcb7437abc2e579", -+ "e6d700309ca0ed62452254" -+ },{ -+ "13. an invalid ciphertext, with a zero byte in first byte of ciphertext, decrypts to a random 11 byte long synthethic plaintext", -+ NULL, -+ "", -+ "0096136621faf36d5290b16bd26295de27f895d1faa51c800dafce73d001d60796cd4e2ac3fa2162131d859cd9da5a0c8a42281d9a63e5f353971b72e36b5722e4ac444d77f892a5443deb3dca49fa732fe855727196e23c26eeac55eeced8267a209ebc0f92f4656d64a6c13f7f7ce544ebeb0f668fe3a6c0f189e4bcd5ea12b73cf63e0c8350ee130dd62f01e5c97a1e13f52fde96a9a1bc9936ce734fdd61f27b18216f1d6de87f49cf4f2ea821fb8efd1f92cdad529baf7e31aff9bff4074f2cad2b4243dd15a711adcf7de900851fbd6bcb53dac399d7c880531d06f25f7002e1aaf1722765865d2c2b902c7736acd27bc6cbd3e38b560e2eecf7d4b576", -+ "ba27b1842e7c21c0e7ef6a" -+ },{ -+ "14. an invalid ciphertext, with a zero byte removed from first byte of ciphertext, decrypts to a random 11 byte long synthethic plaintext", -+ NULL, -+ "", -+ "96136621faf36d5290b16bd26295de27f895d1faa51c800dafce73d001d60796cd4e2ac3fa2162131d859cd9da5a0c8a42281d9a63e5f353971b72e36b5722e4ac444d77f892a5443deb3dca49fa732fe855727196e23c26eeac55eeced8267a209ebc0f92f4656d64a6c13f7f7ce544ebeb0f668fe3a6c0f189e4bcd5ea12b73cf63e0c8350ee130dd62f01e5c97a1e13f52fde96a9a1bc9936ce734fdd61f27b18216f1d6de87f49cf4f2ea821fb8efd1f92cdad529baf7e31aff9bff4074f2cad2b4243dd15a711adcf7de900851fbd6bcb53dac399d7c880531d06f25f7002e1aaf1722765865d2c2b902c7736acd27bc6cbd3e38b560e2eecf7d4b576", -+ "ba27b1842e7c21c0e7ef6a" -+ },{ -+ "15. an invalid ciphertext, with two zero bytes in first bytes of ciphertext, decrypts to a random 11 byte long synthethic plaintext", -+ NULL, -+ "", -+ "0000587cccc6b264bdfe0dc2149a988047fa921801f3502ea64624c510c6033d2f427e3f136c26e88ea9f6519e86a542cec96aad1e5e9013c3cc203b6de15a69183050813af5c9ad79703136d4b92f50ce171eefc6aa7988ecf02f319ffc5eafd6ee7a137f8fce64b255bb1b8dd19cfe767d64fdb468b9b2e9e7a0c24dae03239c8c714d3f40b7ee9c4e59ac15b17e4d328f1100756bce17133e8e7493b54e5006c3cbcdacd134130c5132a1edebdbd01a0c41452d16ed7a0788003c34730d0808e7e14c797a21f2b45a8aa1644357fd5e988f99b017d9df37563a354c788dc0e2f9466045622fa3f3e17db63414d27761f57392623a2bef6467501c63e8d645", -+ "d5cf555b1d6151029a429a" -+ },{ -+ "16. an invalid ciphertext, with two zero bytes removed from first bytes of ciphertext, decrypts to a random 11 byte long synthethic plaintext", -+ NULL, -+ "", -+ "587cccc6b264bdfe0dc2149a988047fa921801f3502ea64624c510c6033d2f427e3f136c26e88ea9f6519e86a542cec96aad1e5e9013c3cc203b6de15a69183050813af5c9ad79703136d4b92f50ce171eefc6aa7988ecf02f319ffc5eafd6ee7a137f8fce64b255bb1b8dd19cfe767d64fdb468b9b2e9e7a0c24dae03239c8c714d3f40b7ee9c4e59ac15b17e4d328f1100756bce17133e8e7493b54e5006c3cbcdacd134130c5132a1edebdbd01a0c41452d16ed7a0788003c34730d0808e7e14c797a21f2b45a8aa1644357fd5e988f99b017d9df37563a354c788dc0e2f9466045622fa3f3e17db63414d27761f57392623a2bef6467501c63e8d645", -+ "d5cf555b1d6151029a429a" -+ },{ -+ "17. and invalid ciphertext, otherwise valid but starting with 000002, decrypts to random 11 byte long synthethic plaintext", -+ NULL, -+ "", -+ "1786550ce8d8433052e01ecba8b76d3019f1355b212ac9d0f5191b023325a7e7714b7802f8e9a17c4cb3cd3a84041891471b10ca1fcfb5d041d34c82e6d0011cf4dc76b90e9c2e0743590579d55bcd7857057152c4a8040361343d1d22ba677d62b011407c652e234b1d663af25e2386251d7409190f19fc8ec3f9374fdf1254633874ce2ec2bff40ad0cb473f9761ec7b68da45a4bd5e33f5d7dac9b9a20821df9406b653f78a95a6c0ea0a4d57f867e4db22c17bf9a12c150f809a7b72b6db86c22a8732241ebf3c6a4f2cf82671d917aba8bc61052b40ccddd743a94ea9b538175106201971cca9d136d25081739aaf6cd18b2aecf9ad320ea3f89502f955", -+ "3d4a054d9358209e9cbbb9" -+ },{ -+ "18. negative test with otherwise valid padding but a zero byte in first byte of padding", -+ NULL, -+ "", -+ "179598823812d2c58a7eb50521150a48bcca8b4eb53414018b6bca19f4801456c5e36a940037ac516b0d6412ba44ec6b4f268a55ef1c5ffbf18a2f4e3522bb7b6ed89774b79bffa22f7d3102165565642de0d43a955e96a1f2e80e5430671d7266eb4f905dc8ff5e106dc5588e5b0289e49a4913940e392a97062616d2bda38155471b7d360cfb94681c702f60ed2d4de614ea72bf1c53160e63179f6c5b897b59492bee219108309f0b7b8cb2b136c346a5e98b8b4b8415fb1d713bae067911e3057f1c335b4b7e39101eafd5d28f0189037e4334f4fdb9038427b1d119a6702aa8233319cc97d496cc289ae8c956ddc84042659a2d43d6aa22f12b81ab884e", -+ "1f037dd717b07d3e7f7359" -+ },{ -+ "19. negative test with otherwise valid padding but a zero byte at the eigth byte of padding", -+ NULL, -+ "", -+ "a7a340675a82c30e22219a55bc07cdf36d47d01834c1834f917f18b517419ce9de2a96460e745024436470ed85e94297b283537d52189c406a3f533cb405cc6a9dba46b482ce98b6e3dd52d8fce2237425617e38c11fbc46b61897ef200d01e4f25f5f6c4c5b38cd0de38ba11908b86595a8036a08a42a3d05b79600a97ac18ba368a08d6cf6ccb624f6e8002afc75599fba4de3d4f3ba7d208391ebe8d21f8282b18e2c10869eb2702e68f9176b42b0ddc9d763f0c86ba0ff92c957aaeab76d9ab8da52ea297ec11d92d770146faa1b300e0f91ef969b53e7d2907ffc984e9a9c9d11fb7d6cba91972059b46506b035efec6575c46d7114a6b935864858445f", -+ "63cb0bf65fc8255dd29e17" -+ },{ -+ "20. negative test with an otherwise valid plaintext but with missing separator byte", -+ NULL, -+ "", -+ "3d1b97e7aa34eaf1f4fc171ceb11dcfffd9a46a5b6961205b10b302818c1fcc9f4ec78bf18ea0cee7e9fa5b16fb4c611463b368b3312ac11cf9c06b7cf72b54e284848a508d3f02328c62c2999d0fb60929f81783c7a256891bc2ff4d91df2af96a24fc5701a1823af939ce6dbdc510608e3d41eec172ad2d51b9fc61b4217c923cadcf5bac321355ef8be5e5f090cdc2bd0c697d9058247db3ad613fdce87d2955a6d1c948a5160f93da21f731d74137f5d1f53a1923adb513d2e6e1589d44cc079f4c6ddd471d38ac82d20d8b1d21f8d65f3b6907086809f4123e08d86fb38729585de026a485d8f0e703fd4772f6668febf67df947b82195fa3867e3a3065", -+ "6f09a0b62699337c497b0b" -+ } -+ } -+ }, -+ { -+ "A 2049-bit RSA Test vectors for the Bleichenbacher workaround", -+ "0155f889556a1775f1c7a7786a50b18bc28c9e986ede5667cab39b84124e90eba75c1db083ac3e443bba94dc23560f75e3a81693a2a43bdc7426d8c4eafe68c85de0fe757f6e49bb9ed447e602430800dbb04ceb22e7fa57a18d338fb66026cdb467e70cc040e7d367ef403c7bf1e3df624650094631f21eafd2fb5bc915ff04379acd1112f732c0b46607c178d38a20f52eda509f2f9c0405d51069e80ccf941554d0470467505c3cf541ea0897dfc9f400cecb298ffc753372d9f6933af174cc40ed96d467031733b97f8cddd3f92bc3a03ea8576c417f24007b5e4f7501105b544de9fadcdffadf98dfb4bb05b8199f3f85acfd91f7a9a094b9a383f5049097", -+ "010001", -+ "0119c2b3f50a7ad6152679d7ff510958ac2d8ca6f0028592f332d55a16736178a8e67f17e705ce300e3e87547251006013f974d0a3db49ef344ca5a26a34c0450704d0e422e0ce23a69425c15fefb6f26e106eeff64cc8b9d7442e4da4e8c85008eaeb365859a2294fa3937bc26be56332e7d81e2c160ef635cc528aa7be55e633a723dbc1e16ba29e52b29aef2f9e5654fdc0666bb0fc254acbe80e63874f0f5f020782e3c9dcfc2520d0c9c4a7b634e4503fbb493e1aafeeb3f88bd7a13398725dae6fe399e775cd5d4cf09fc838347c4c98dab1a4883cce620513615afaa10a63368e6d7b79df4166ab162739ef515a4402ee1e0601c5a55bc71df0e30edf81", -+ { -+ { -+ "1. malformed that generates length specified by 3rd last value from PRF", -+ NULL, -+ "", -+ "00b26f6404b82649629f2704494282443776929122e279a9cf30b0c6fe8122a0a9042870d97cc8ef65490fe58f031eb2442352191f5fbc311026b5147d32df914599f38b825ebb824af0d63f2d541a245c5775d1c4b78630e4996cc5fe413d38455a776cf4edcc0aa7fccb31c584d60502ed2b77398f536e137ff7ba6430e9258e21c2db5b82f5380f566876110ac4c759178900fbad7ab70ea07b1daf7a1639cbb4196543a6cbe8271f35dddb8120304f6eef83059e1c5c5678710f904a6d760c4d1d8ad076be17904b9e69910040b47914a0176fb7eea0c06444a6c4b86d674d19a556a1de5490373cb01ce31bbd15a5633362d3d2cd7d4af1b4c5121288b894", -+ "42" -+ },{ -+ "2. simple positive test case", -+ NULL, -+ "", -+ "013300edbf0bb3571e59889f7ed76970bf6d57e1c89bbb6d1c3991d9df8e65ed54b556d928da7d768facb395bbcc81e9f8573b45cf8195dbd85d83a59281cddf4163aec11b53b4140053e3bd109f787a7c3cec31d535af1f50e0598d85d96d91ea01913d07097d25af99c67464ebf2bb396fb28a9233e56f31f7e105d71a23e9ef3b736d1e80e713d1691713df97334779552fc94b40dd733c7251bc522b673d3ec9354af3dd4ad44fa71c0662213a57ada1d75149697d0eb55c053aaed5ffd0b815832f454179519d3736fb4faf808416071db0d0f801aca8548311ee708c131f4be658b15f6b54256872c2903ac708bd43b017b073b5707bc84c2cd9da70e967", -+ "6c6f72656d20697073756d" -+ },{ -+ "3. positive test case with null padded ciphertext", -+ NULL, -+ "", -+ "0002aadf846a329fadc6760980303dbd87bfadfa78c2015ce4d6c5782fd9d3f1078bd3c0a2c5bfbdd1c024552e5054d98b5bcdc94e476dd280e64d650089326542ce7c61d4f1ab40004c2e6a88a883613568556a10f3f9edeab67ae8dddc1e6b0831c2793d2715de943f7ce34c5c05d1b09f14431fde566d17e76c9feee90d86a2c158616ec81dda0c642f58c0ba8fa4495843124a7235d46fb4069715a51bf710fd024259131ba94da73597ace494856c94e7a3ec261545793b0990279b15fa91c7fd13dbfb1df2f221dab9fa9f7c1d21e48aa49f6aaecbabf5ee76dc6c2af2317ffb4e303115386a97f8729afc3d0c89419669235f1a3a69570e0836c79fc162", -+ "6c6f72656d20697073756d" -+ },{ -+ "4. positive test case with null truncated ciphertext", -+ NULL, -+ "", -+ "02aadf846a329fadc6760980303dbd87bfadfa78c2015ce4d6c5782fd9d3f1078bd3c0a2c5bfbdd1c024552e5054d98b5bcdc94e476dd280e64d650089326542ce7c61d4f1ab40004c2e6a88a883613568556a10f3f9edeab67ae8dddc1e6b0831c2793d2715de943f7ce34c5c05d1b09f14431fde566d17e76c9feee90d86a2c158616ec81dda0c642f58c0ba8fa4495843124a7235d46fb4069715a51bf710fd024259131ba94da73597ace494856c94e7a3ec261545793b0990279b15fa91c7fd13dbfb1df2f221dab9fa9f7c1d21e48aa49f6aaecbabf5ee76dc6c2af2317ffb4e303115386a97f8729afc3d0c89419669235f1a3a69570e0836c79fc162", -+ "6c6f72656d20697073756d" -+ },{ -+ "5. positive test case with double null padded ciphertext", -+ NULL, -+ "", -+ "0000f36da3b72d8ff6ded74e7efd08c01908f3f5f0de7b55eab92b5f875190809c39d4162e1e6649618f854fd84aeab03970d16bb814e999852c06de38d82b95c0f32e2a7b5714021fe303389be9c0eac24c90a6b7210f929d390fabf903d44e04110bb7a7fd6c383c275804721efa6d7c93aa64c0bb2b18d97c5220a846c66a4895ae52adddbe2a9996825e013585adcec4b32ba61d782737bd343e5fabd68e8a95b8b1340318559860792dd70dffbe05a1052b54cbfb48cfa7bb3c19cea52076bddac5c25ee276f153a610f6d06ed696d192d8ae4507ffae4e5bdda10a625d6b67f32f7cffcd48dee2431fe66f6105f9d17e611cdcc674868e81692a360f4052", -+ "6c6f72656d20697073756d" -+ },{ -+ "6. positive test case with double null truncated ciphertext", -+ NULL, -+ "", -+ "f36da3b72d8ff6ded74e7efd08c01908f3f5f0de7b55eab92b5f875190809c39d4162e1e6649618f854fd84aeab03970d16bb814e999852c06de38d82b95c0f32e2a7b5714021fe303389be9c0eac24c90a6b7210f929d390fabf903d44e04110bb7a7fd6c383c275804721efa6d7c93aa64c0bb2b18d97c5220a846c66a4895ae52adddbe2a9996825e013585adcec4b32ba61d782737bd343e5fabd68e8a95b8b1340318559860792dd70dffbe05a1052b54cbfb48cfa7bb3c19cea52076bddac5c25ee276f153a610f6d06ed696d192d8ae4507ffae4e5bdda10a625d6b67f32f7cffcd48dee2431fe66f6105f9d17e611cdcc674868e81692a360f4052", -+ "6c6f72656d20697073756d" -+ },{ -+ "7. a random negative test case that generates an 11 byte long message", -+ NULL, -+ "", -+ "00f910200830fc8fff478e99e145f1474b312e2512d0f90b8cef77f8001d09861688c156d1cbaf8a8957f7ebf35f724466952d0524cad48aad4fba1e45ce8ea27e8f3ba44131b7831b62d60c0762661f4c1d1a88cd06263a259abf1ba9e6b0b172069afb86a7e88387726f8ab3adb30bfd6b3f6be6d85d5dfd044e7ef052395474a9cbb1c3667a92780b43a22693015af6c513041bdaf87d43b24ddd244e791eeaea1066e1f4917117b3a468e22e0f7358852bb981248de4d720add2d15dccba6280355935b67c96f9dcb6c419cc38ab9f6fba2d649ef2066e0c34c9f788ae49babd9025fa85b21113e56ce4f43aa134c512b030dd7ac7ce82e76f0be9ce09ebca", -+ "1189b6f5498fd6df532b00" -+ },{ -+ "8. otherwise correct plaintext, but with wrong first byte (0x01 instead of 0x00)", -+ NULL, -+ "", -+ "002c9ddc36ba4cf0038692b2d3a1c61a4bb3786a97ce2e46a3ba74d03158aeef456ce0f4db04dda3fe062268a1711250a18c69778a6280d88e133a16254e1f0e30ce8dac9b57d2e39a2f7d7be3ee4e08aec2fdbe8dadad7fdbf442a29a8fb40857407bf6be35596b8eefb5c2b3f58b894452c2dc54a6123a1a38d642e23751746597e08d71ac92704adc17803b19e131b4d1927881f43b0200e6f95658f559f912c889b4cd51862784364896cd6e8618f485a992f82997ad6a0917e32ae5872eaf850092b2d6c782ad35f487b79682333c1750c685d7d32ab3e1538f31dcaa5e7d5d2825875242c83947308dcf63ba4bfff20334c9c140c837dbdbae7a8dee72ff", -+ "f6d0f5b78082fe61c04674" -+ },{ -+ "9. otherwise correct plaintext, but with wrong second byte (0x01 instead of 0x02)", -+ NULL, -+ "", -+ "00c5d77826c1ab7a34d6390f9d342d5dbe848942e2618287952ba0350d7de6726112e9cebc391a0fae1839e2bf168229e3e0d71d4161801509f1f28f6e1487ca52df05c466b6b0a6fbbe57a3268a970610ec0beac39ec0fa67babce1ef2a86bf77466dc127d7d0d2962c20e66593126f276863cd38dc6351428f884c1384f67cad0a0ffdbc2af16711fb68dc559b96b37b4f04cd133ffc7d79c43c42ca4948fa895b9daeb853150c8a5169849b730cc77d68b0217d6c0e3dbf38d751a1998186633418367e7576530566c23d6d4e0da9b038d0bb5169ce40133ea076472d055001f0135645940fd08ea44269af2604c8b1ba225053d6db9ab43577689401bdc0f3", -+ "1ab287fcef3ff17067914d" -+ },{ -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ } -+ } -+ }, -+ { -+ "RSA decrypt with 3072 bit keys", -+ "afd71caad5e9f5b8c6c367070a47f19d7e66aede18a5b2741fb3c4d33434560692a2d909ef6888ec602ff6b93af258ee74303c301afcd4edbec43311ddc8ddbf00ddbbe386d33b8d0e22b1b44936dc489871b85237b34ce747ad8fdb0c4e4d1daa7aadf07385c5c8732ccb7d5a49e2e50c883c7d7ac10ed6a74d9ac90df9129905a17d4a087210fc78b6d04b1eb969482c11a6eeb79c50e5b16f3f254f7571528b2f1716ab816d6eca0727bdea98059329730eb8c33ce71d61dd4ac393b6256e07ac1d124f0200d1c3e05a4c1bc7f1ed2fc83e57199cfe5908b10087e27fbd97d2c24214619c7147c8fbefca39bc256762a6823531f7e234d68eae7a0d9faf10dd15e9523780c7d5ae58094ad525a9063b4c33f95e1006da2eb12d3743689495c1f2023e407353c5eb3e4ca1c48cff81a10900d14820eb801af4f1a596c4b9ce9a531fcf8a54d9ffd724258b6eec20108df6fdfd76d4ae03ba7ea598dcb0e4a280849587286f4d7f256ce85e5eb5679b1dacc1f9095649b72e5fa072aeb00379", -+ "010001", -+ "2517eacb3afef4bffae60398df9957a5d2a154a83368d8e15842b2f59ee09f79197bd2ef1e9addaf8786f6b4127447405e3042b21f2f50b7aa73771680c3bbcb6c225a5d5ff6b56c471c1882a0a33b0af165a3ed6c249dc7783e6bc758ac37e6572d33fe325078ed952650f2eb9604902ef99a511a1119d13c4fc9a43a175dcdfbfb1a1400fe17093b69cd3cdb895f65432ea2195f90511c7336b58a685dacff2daf4c5e92e565b1665ae60e512baa9965b808d5ff119ceb7cd692cbf920067afacd809f66be706da26810ac790db156c948e6fe581bc9849157f4da493f3a64b0c6e119e031b107f8436ce29160b458b8f9f1095fdeb19263384ff5387557bc4f10b4034de841703bad2c1e769c23853eb630a36d1061dd46e2a6bbaf743a97f0b32c36f50c1a3722def3a394d91c2e078bf09d795ecde5e56b8202f974026f75fc56e9a0dd6a88f2e7cb78ef1298cc6c65207ca45bd37188807b4fcdb1e60dd8e5b85648fb7efa8b6fdd448f39741a8d9809fe163af3de45bac24a5a841c81", -+ { -+ { -+ "1. a random invalid ciphertext that generates an empty synthethic one", -+ NULL, -+ "", -+ "5e956cd9652f4a2ece902931013e09662b6a9257ad1e987fb75f73a0606df2a4b04789770820c2e02322c4e826f767bd895734a01e20609c3be4517a7a2a589ea1cdc137beb73eb38dac781b52e863de9620f79f9b90fd5b953651fcbfef4a9f1cc07421d511a87dd6942caab6a5a0f4df473e62defb529a7de1509ab99c596e1dff1320402298d8be73a896cc86c38ae3f2f576e9ea70cc28ad575cb0f854f0be43186baa9c18e29c47c6ca77135db79c811231b7c1730955887d321fdc06568382b86643cf089b10e35ab23e827d2e5aa7b4e99ff2e914f302351819eb4d1693243b35f8bf1d42d08f8ec4acafa35f747a4a975a28643ec630d8e4fa5be59d81995660a14bb64c1fea5146d6b11f92da6a3956dd5cb5e0d747cf2ea23f81617769185336263d46ef4c144b754de62a6337342d6c85a95f19f015724546ee3fc4823eca603dbc1dc01c2d5ed50bd72d8e96df2dc048edde0081284068283fc5e73a6139851abf2f29977d0b3d160c883a42a37efba1be05c1a0b1741d7ddf59", -+ "" -+ },{ -+ "2. a random invalid that has PRF output with a length one byte too long", -+ NULL, -+ "", -+ "7db0390d75fcf9d4c59cf27b264190d856da9abd11e92334d0e5f71005cfed865a711dfa28b791188374b61916dbc11339bf14b06f5f3f68c206c5607380e13da3129bfb744157e1527dd6fdf6651248b028a496ae1b97702d44706043cdaa7a59c0f41367303f21f268968bf3bd2904db3ae5239b55f8b438d93d7db9d1666c071c0857e2ec37757463769c54e51f052b2a71b04c2869e9e7049a1037b8429206c99726f07289bac18363e7eb2a5b417f47c37a55090cda676517b3549c873f2fe95da9681752ec9864b069089a2ed2f340c8b04ee00079055a817a3355b46ac7dc00d17f4504ccfbcfcadb0c04cb6b22069e179385ae1eafabad5521bac2b8a8ee1dfff59a22eb3fdacfc87175d10d7894cfd869d056057dd9944b869c1784fcc27f731bc46171d39570fbffbadf082d33f6352ecf44aca8d9478e53f5a5b7c852b401e8f5f74da49da91e65bdc97765a9523b7a0885a6f8afe5759d58009fbfa837472a968e6ae92026a5e0202a395483095302d6c3985b5f5831c521a271", -+ "56a3bea054e01338be9b7d7957539c" -+ },{ -+ "3. a random invalid that generates a synthethic of maximum size", -+ NULL, -+ "", -+ "1715065322522dff85049800f6a29ab5f98c465020467414b2a44127fe9446da47fa18047900f99afe67c2df6f50160bb8e90bff296610fde632b3859d4d0d2e644f23835028c46cca01b84b88231d7e03154edec6627bcba23de76740d839851fa12d74c8f92e540c73fe837b91b7d699b311997d5f0f7864c486d499c3a79c111faaacbe4799597a25066c6200215c3d158f3817c1aa57f18bdaad0be1658da9da93f5cc6c3c4dd72788af57adbb6a0c26f42d32d95b8a4f95e8c6feb2f8a5d53b19a50a0b7cbc25e055ad03e5ace8f3f7db13e57759f67b65d143f08cca15992c6b2aae643390483de111c2988d4e76b42596266005103c8de6044fb7398eb3c28a864fa672de5fd8774510ff45e05969a11a4c7d3f343e331190d2dcf24fb9154ba904dc94af98afc5774a9617d0418fe6d13f8245c7d7626c176138dd698a23547c25f27c2b98ea4d8a45c7842b81888e4cc14e5b72e9cf91f56956c93dbf2e5f44a8282a7813157fc481ff1371a0f66b31797e81ebdb09a673d4db96d6", -+ "7b036fcd6243900e4236c894e2462c17738acc87e01a76f4d95cb9a328d9acde81650283b8e8f60a217e3bdee835c7b222ad4c85d0acdb9a309bd2a754609a65dec50f3aa04c6d5891034566b9563d42668ede1f8992b17753a2132e28970584e255efc8b45a41c5dbd7567f014acec5fe6fdb6d484790360a913ebb9defcd74ff377f2a8ba46d2ed85f733c9a3da08eb57ecedfafda806778f03c66b2c5d2874cec1c291b2d49eb194c7b5d0dd2908ae90f4843268a2c45563092ade08acb6ab481a08176102fc803fbb2f8ad11b0e1531bd37df543498daf180b12017f4d4d426ca29b4161075534bfb914968088a9d13785d0adc0e2580d3548494b2a9e91605f2b27e6cc701c796f0de7c6f471f6ab6cb9272a1ed637ca32a60d117505d82af3c1336104afb537d01a8f70b510e1eebf4869cb976c419473795a66c7f5e6e20a8094b1bb603a74330c537c5c0698c31538bd2e138c1275a1bdf24c5fa8ab3b7b526324e7918a382d1363b3d463764222150e04" -+ },{ -+ "4. a positive test case that decrypts to 9 byte long value", -+ NULL, -+ "", -+ "6c60845a854b4571f678941ae35a2ac03f67c21e21146f9db1f2306be9f136453b86ad55647d4f7b5c9e62197aaff0c0e40a3b54c4cde14e774b1c5959b6c2a2302896ffae1f73b00b862a20ff4304fe06cea7ff30ecb3773ca9af27a0b54547350d7c07dfb0a39629c7e71e83fc5af9b2adbaf898e037f1de696a3f328cf45af7ec9aff7173854087fb8fbf34be981efbd8493f9438d1b2ba2a86af082662aa46ae9adfbec51e5f3d9550a4dd1dcb7c8969c9587a6edc82a8cabbc785c40d9fbd12064559fb769450ac3e47e87bc046148130d7eaa843e4b3ccef3675d0630500803cb7ffee3882378c1a404e850c3e20707bb745e42b13c18786c4976076ed9fa8fd0ff15e571bef02cbbe2f90c908ac3734a433b73e778d4d17fcc28f49185ebc6e8536a06d293202d94496453bfdf1c2c7833a3f99fa38ca8a81f42eaa529d603b890308a319c0ab63a35ff8ebac965f6278f5a7e5d622be5d5fe55f0ca3ec993d55430d2bf59c5d3e860e90c16d91a04596f6fdf60d89ed95d88c036dde", -+ "666f7274792074776f" -+ },{ -+ "5. a positive test case with null padded ciphertext", -+ NULL, -+ "", -+ "00f4d565a3286784dbb85327db8807ae557ead229f92aba945cecda5225f606a7d6130edeeb6f26724d1eff1110f9eb18dc3248140ee3837e6688391e78796c526791384f045e21b6b853fb6342a11f309eb77962f37ce23925af600847fbd30e6e07e57de50b606e6b7f288cc777c1a6834f27e6edace508452128916eef7788c8bb227e3548c6a761cc4e9dd1a3584176dc053ba3500adb1d5e1611291654f12dfc5722832f635db3002d73f9defc310ace62c63868d341619c7ee15b20243b3371e05078e11219770c701d9f341af35df1bc729de294825ff2e416aa11526612852777eb131f9c45151eb144980d70608d2fc4043477368369aa0fe487a48bd57e66b00c3c58f941549f5ec050fca64449debe7a0c4ac51e55cb71620a70312aa4bd85fac1410c9c7f9d6ec610b7d11bf8faeffa20255d1a1bead9297d0aa8765cd2805847d639bc439f4a6c896e2008f746f9590ff4596de5ddde000ed666c452c978043ff4298461eb5a26d5e63d821438627f91201924bf7f2aeee1727", -+ "666f7274792074776f" -+ },{ -+ "6. a positive test case with double null padded ciphertext", -+ NULL, -+ "", -+ "00001ec97ac981dfd9dcc7a7389fdfa9d361141dac80c23a060410d472c16094e6cdffc0c3684d84aa402d7051dfccb2f6da33f66985d2a259f5b7fbf39ac537e95c5b7050eb18844a0513abef812cc8e74a3c5240009e6e805dcadf532bc1a2702d5acc9e585fad5b89d461fcc1397351cdce35171523758b171dc041f412e42966de7f94856477356d06f2a6b40e3ff0547562a4d91bbf1338e9e049facbee8b20171164505468cd308997447d3dc4b0acb49e7d368fedd8c734251f30a83491d2506f3f87318cc118823244a393dc7c5c739a2733d93e1b13db6840a9429947357f47b23fbe39b7d2d61e5ee26f9946c4632f6c4699e452f412a26641d4751135400713cd56ec66f0370423d55d2af70f5e7ad0adea8e4a0d904a01e4ac272eba4af1a029dd53eb71f115bf31f7a6c8b19a6523adeecc0d4c3c107575e38572a8f8474ccad163e46e2e8b08111132aa97a16fb588c9b7e37b3b3d7490381f3c55d1a9869a0fd42cd86fed59ecec78cb6b2dfd06a497f5afe3419691314ba0", -+ "666f7274792074776f" -+ },{ -+ "7. a positive test case with double null truncated ciphertext", -+ NULL, -+ "", -+ "1ec97ac981dfd9dcc7a7389fdfa9d361141dac80c23a060410d472c16094e6cdffc0c3684d84aa402d7051dfccb2f6da33f66985d2a259f5b7fbf39ac537e95c5b7050eb18844a0513abef812cc8e74a3c5240009e6e805dcadf532bc1a2702d5acc9e585fad5b89d461fcc1397351cdce35171523758b171dc041f412e42966de7f94856477356d06f2a6b40e3ff0547562a4d91bbf1338e9e049facbee8b20171164505468cd308997447d3dc4b0acb49e7d368fedd8c734251f30a83491d2506f3f87318cc118823244a393dc7c5c739a2733d93e1b13db6840a9429947357f47b23fbe39b7d2d61e5ee26f9946c4632f6c4699e452f412a26641d4751135400713cd56ec66f0370423d55d2af70f5e7ad0adea8e4a0d904a01e4ac272eba4af1a029dd53eb71f115bf31f7a6c8b19a6523adeecc0d4c3c107575e38572a8f8474ccad163e46e2e8b08111132aa97a16fb588c9b7e37b3b3d7490381f3c55d1a9869a0fd42cd86fed59ecec78cb6b2dfd06a497f5afe3419691314ba0", -+ "666f7274792074776f" -+ },{ -+ "8. a random negative test case that generates a 9 byte long message", -+ NULL, -+ "", -+ "5c8555f5cef627c15d37f85c7f5fd6e499264ea4b8e3f9112023aeb722eb38d8eac2be3751fd5a3785ab7f2d59fa3728e5be8c3de78a67464e30b21ee23b5484bb3cd06d0e1c6ad25649c8518165653eb80488bfb491b20c04897a6772f69292222fc5ef50b5cf9efc6d60426a449b6c489569d48c83488df629d695653d409ce49a795447fcec2c58a1a672e4a391401d428baaf781516e11e323d302fcf20f6eab2b2dbe53a48c987e407c4d7e1cb41131329138313d330204173a4f3ff06c6fadf970f0ed1005d0b27e35c3d11693e0429e272d583e57b2c58d24315c397856b34485dcb077665592b747f889d34febf2be8fce66c265fd9fc3575a6286a5ce88b4b413a08efc57a07a8f57a999605a837b0542695c0d189e678b53662ecf7c3d37d9dbeea585eebfaf79141118e06762c2381fe27ca6288edddc19fd67cd64f16b46e06d8a59ac530f22cd83cc0bc4e37feb52015cbb2283043ccf5e78a4eb7146827d7a466b66c8a4a4826c1bad68123a7f2d00fc1736525ff90c058f56", -+ "257906ca6de8307728" -+ },{ -+ "9. a random negative test case that generates a 9 byte long message based on second to last value from PRF", -+ NULL, -+ "", -+ "758c215aa6acd61248062b88284bf43c13cb3b3d02410be4238607442f1c0216706e21a03a2c10eb624a63322d854da195c017b76fea83e274fa371834dcd2f3b7accf433fc212ad76c0bac366e1ed32e25b279f94129be7c64d6e162adc08ccebc0cfe8e926f01c33ab9c065f0e0ac83ae5137a4cb66702615ad68a35707d8676d2740d7c1a954680c83980e19778ed11eed3a7c2dbdfc461a9bbef671c1bc00c882d361d29d5f80c42bdf5efec886c34138f83369c6933b2ac4e93e764265351b4a0083f040e14f511f09b22f96566138864e4e6ff24da4810095da98e0585410951538ced2f757a277ff8e17172f06572c9024eeae503f176fd46eb6c5cd9ba07af11cde31dccac12eb3a4249a7bfd3b19797ad1656984bfcbf6f74e8f99d8f1ac420811f3d166d87f935ef15ae858cf9e72c8e2b547bf16c3fb09a8c9bf88fd2e5d38bf24ed610896131a84df76b9f920fe76d71fff938e9199f3b8cd0c11fd0201f9139d7673a871a9e7d4adc3bbe360c8813617cd60a90128fbe34c9d5", -+ "043383c929060374ed" -+ },{ -+ "10. a random negative test that generates message based on 3rd last value from PRF", -+ NULL, -+ "", -+ "7b22d5e62d287968c6622171a1f75db4b0fd15cdf3134a1895d235d56f8d8fe619f2bf4868174a91d7601a82975d2255190d28b869141d7c395f0b8c4e2be2b2c1b4ffc12ce749a6f6803d4cfe7fba0a8d6949c04151f981c0d84592aa2ff25d1bd3ce5d10cb03daca6b496c6ad40d30bfa8acdfd02cdb9326c4bdd93b949c9dc46caa8f0e5f429785bce64136a429a3695ee674b647452bea1b0c6de9c5f1e8760d5ef6d5a9cfff40457b023d3c233c1dcb323e7808103e73963b2eafc928c9eeb0ee3294955415c1ddd9a1bb7e138fecd79a3cb89c57bd2305524624814aaf0fd1acbf379f7f5b39421f12f115ba488d380586095bb53f174fae424fa4c8e3b299709cd344b9f949b1ab57f1c645d7ed3c8f81d5594197355029fee8960970ff59710dc0e5eb50ea6f4c3938e3f89ed7933023a2c2ddffaba07be147f686828bd7d520f300507ed6e71bdaee05570b27bc92741108ac2eb433f028e138dd6d63067bc206ea2d826a7f41c0d613daed020f0f30f4e272e9618e0a8c39018a83", -+ "70263fa6050534b9e0" -+ },{ -+ "11. an otherwise valid plaintext, but with wrong first byte (0x01 instead of 0x00)", -+ NULL, -+ "", -+ "6db80adb5ff0a768caf1378ecc382a694e7d1bde2eff4ba12c48aaf794ded7a994a5b2b57acec20dbec4ae385c9dd531945c0f197a5496908725fc99d88601a17d3bb0b2d38d2c1c3100f39955a4cb3dbed5a38bf900f23d91e173640e4ec655c84fdfe71fcdb12a386108fcf718c9b7af37d39703e882436224c877a2235e8344fba6c951eb7e2a4d1d1de81fb463ac1b880f6cc0e59ade05c8ce35179ecd09546731fc07b141d3d6b342a97ae747e61a9130f72d37ac5a2c30215b6cbd66c7db893810df58b4c457b4b54f34428247d584e0fa71062446210db08254fb9ead1ba1a393c724bd291f0cf1a7143f32df849051dc896d7d176fef3b57ab6dffd626d0c3044e9edb2e3d012ace202d2581df01bec7e9aa0727a6650dd373d374f0bc0f4a611f8139dfe97d63e70c6188f4df5b672e47c51d8aa567097293fbff127c75ec690b43407578b73c85451710a0cece58fd497d7f7bd36a8a92783ef7dc6265dff52aac8b70340b996508d39217f2783ce6fc91a1cc94bb2ac487b84f62", -+ "6d8d3a094ff3afff4c" -+ },{ -+ "12. an otherwise valid plaintext, but with wrong second byte (0x01 instead of 0x02)", -+ NULL, -+ "", -+ "417328c034458563079a4024817d0150340c34e25ae16dcad690623f702e5c748a6ebb3419ff48f486f83ba9df35c05efbd7f40613f0fc996c53706c30df6bba6dcd4a40825f96133f3c21638a342bd4663dffbd0073980dac47f8c1dd8e97ce1412e4f91f2a8adb1ac2b1071066efe8d718bbb88ca4a59bd61500e826f2365255a409bece0f972df97c3a55e09289ef5fa815a2353ef393fd1aecfc888d611c16aec532e5148be15ef1bf2834b8f75bb26db08b66d2baad6464f8439d1986b533813321dbb180080910f233bcc4dd784fb21871aef41be08b7bfad4ecc3b68f228cb5317ac6ec1227bc7d0e452037ba918ee1da9fdb8393ae93b1e937a8d4691a17871d5092d2384b6190a53df888f65b951b05ed4ad57fe4b0c6a47b5b22f32a7f23c1a234c9feb5d8713d949686760680da4db454f4acad972470033472b9864d63e8d23eefc87ebcf464ecf33f67fbcdd48eab38c5292586b36aef5981ed2fa07b2f9e23fc57d9eb71bfff4111c857e9fff23ceb31e72592e70c874b4936", -+ "c6ae80ffa80bc184b0" -+ },{ -+ "13. an otherwise valid plaintext, but with zero byte in first byte of padding", -+ NULL, -+ "", -+ "8542c626fe533467acffcd4e617692244c9b5a3bf0a215c5d64891ced4bf4f9591b4b2aedff9843057986d81631b0acb3704ec2180e5696e8bd15b217a0ec36d2061b0e2182faa3d1c59bd3f9086a10077a3337a3f5da503ec3753535ffd25b837a12f2541afefd0cffb0224b8f874e4bed13949e105c075ed44e287c5ae03b155e06b90ed247d2c07f1ef3323e3508cce4e4074606c54172ad74d12f8c3a47f654ad671104bf7681e5b061862747d9afd37e07d8e0e2291e01f14a95a1bb4cbb47c304ef067595a3947ee2d722067e38a0f046f43ec29cac6a8801c6e3e9a2331b1d45a7aa2c6af3205be382dd026e389614ee095665a611ab2e8dced2ee1c9d08ac9de11aef5b3803fc9a9ce8231ec87b5fed386fb92ee3db995a89307bcba844bd0a691c29ae51216e949dfc813133cb06a07265fd807bcb3377f6adb0a481d9b7f442003115895939773e6b95371c4febef29edae946fa245e7c50729e2e558cfaad773d1fd5f67b457a6d9d17a847c6fcbdb103a86f35f228cefc06cea0", -+ "a8a9301daa01bb25c7" -+ },{ -+ "14. an otherwise valid plaintext, but with zero byte in eight byte of padding", -+ NULL, -+ "", -+ "449dfa237a70a99cb0351793ec8677882021c2aa743580bf6a0ea672055cffe8303ac42855b1d1f3373aae6af09cb9074180fc963e9d1478a4f98b3b4861d3e7f0aa8560cf603711f139db77667ca14ba3a1acdedfca9ef4603d6d7eb0645bfc805304f9ad9d77d34762ce5cd84bd3ec9d35c30e3be72a1e8d355d5674a141b5530659ad64ebb6082e6f73a80832ab6388912538914654d34602f4b3b1c78589b4a5d964b2efcca1dc7004c41f6cafcb5a7159a7fc7c0398604d0edbd4c8f4f04067da6a153a05e7cbeea13b5ee412400ef7d4f3106f4798da707ec37a11286df2b7a204856d5ff773613fd1e453a7114b78e347d3e8078e1cb3276b3562486ba630bf719697e0073a123c3e60ebb5c7a1ccff4279faffa2402bc1109f8d559d6766e73591943dfcf25ba10c3762f02af85187799b8b4b135c3990793a6fd32642f1557405ba55cc7cf7336a0e967073c5fa50743f9cc5e3017c172d9898d2af83345e71b3e0c22ab791eacb6484a32ec60ebc226ec9deaee91b1a0560c2b571", -+ "6c716fe01d44398018" -+ },{ -+ "15. an otherwise valid plaintext, but with null separator missing", -+ NULL, -+ "", -+ "a7a5c99e50da48769ecb779d9abe86ef9ec8c38c6f43f17c7f2d7af608a4a1bd6cf695b47e97c191c61fb5a27318d02f495a176b9fae5a55b5d3fabd1d8aae4957e3879cb0c60f037724e11be5f30f08fc51c033731f14b44b414d11278cd3dba7e1c8bfe208d2b2bb7ec36366dacb6c88b24cd79ab394adf19dbbc21dfa5788bacbadc6a62f79cf54fd8cf585c615b5c0eb94c35aa9de25321c8ffefb8916bbaa2697cb2dd82ee98939df9b6704cee77793edd2b4947d82e00e5749664970736c59a84197bd72b5c71e36aae29cd39af6ac73a368edbc1ca792e1309f442aafcd77c992c88f8e4863149f221695cb7b0236e75b2339a02c4ea114854372c306b9412d8eedb600a31532002f2cea07b4df963a093185e4607732e46d753b540974fb5a5c3f9432df22e85bb17611370966c5522fd23f2ad3484341ba7fd8885fc8e6d379a611d13a2aca784fba2073208faad2137bf1979a0fa146c1880d4337db3274269493bab44a1bcd0681f7227ffdf589c2e925ed9d36302509d1109ba4", -+ "aa2de6cde4e2442884" -+ },{ -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ } -+ } - } - }; -diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c -index ab070a94..a2153728 100644 ---- a/tests/pkcs1v2.c -+++ b/tests/pkcs1v2.c -@@ -82,7 +82,7 @@ data_from_hex (const char *string, size_t *r_length) - - static int - extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected, -- const char *description) -+ const char *description, int quiet) - { - gcry_sexp_t l1; - const void *a; -@@ -96,13 +96,15 @@ extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected, - b = data_from_hex (expected, &blen); - if (!a) - { -- info ("%s: parameter \"%s\" missing in key\n", description, name); -+ if (!quiet) -+ info ("%s: parameter \"%s\" missing in key\n", description, name); - rc = 1; - } - else if ( alen != blen || memcmp (a, b, alen) ) - { -- info ("%s: parameter \"%s\" does not match expected value\n", -- description, name); -+ if (!quiet) -+ info ("%s: parameter \"%s\" does not match expected value\n", -+ description, name); - rc = 1; - } - gcry_free (b); -@@ -192,7 +194,7 @@ check_oaep (void) - else - { - if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, -- tbl[tno].m[mno].desc)) -+ tbl[tno].m[mno].desc, 0)) - { - show_sexp ("encrypt result:\n", ciph); - fail ("mismatch in gcry_pk_encrypt\n"); -@@ -223,7 +225,7 @@ check_oaep (void) - else - { - if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg, -- tbl[tno].m[mno].desc)) -+ tbl[tno].m[mno].desc, 0)) - { - show_sexp ("decrypt result:\n", plain); - fail ("mismatch in gcry_pk_decrypt\n"); -@@ -326,7 +328,7 @@ check_pss (void) - else - { - if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign, -- tbl[tno].m[mno].desc)) -+ tbl[tno].m[mno].desc, 0)) - { - show_sexp ("sign result:\n", sig); - fail ("mismatch in gcry_pk_sign\n"); -@@ -429,44 +431,89 @@ check_v15crypt (void) - size_t mesg_len, seed_len, encr_len; - gcry_sexp_t plain, ciph; - -+ if (tbl[tno].m[mno].desc == NULL) -+ break; -+ - if (verbose) - info ("running test: %s\n", tbl[tno].m[mno].desc); - -- mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len); -- seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); -+ if (tbl[tno].m[mno].mesg) -+ { -+ mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len); -+ seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); -+ -+ err = gcry_sexp_build (&plain, NULL, -+ "(data (flags pkcs1)" -+ "(value %b)(random-override %b))", -+ (int)mesg_len, mesg, -+ (int)seed_len, seed); -+ if (err) -+ die ("constructing plain data failed: %s\n", gpg_strerror (err)); -+ gcry_free (mesg); -+ gcry_free (seed); -+ -+ err = gcry_pk_encrypt (&ciph, plain, pub_key); -+ if (err) -+ { -+ show_sexp ("plain:\n", ciph); -+ fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); -+ } -+ else -+ { -+ if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, -+ tbl[tno].m[mno].desc, 0)) -+ { -+ show_sexp ("encrypt result:\n", ciph); -+ fail ("mismatch in gcry_pk_encrypt\n"); -+ } -+ gcry_sexp_release (ciph); -+ ciph = NULL; -+ } -+ gcry_sexp_release (plain); -+ plain = NULL; -+ } - -- err = gcry_sexp_build (&plain, NULL, -- "(data (flags pkcs1)" -- "(value %b)(random-override %b))", -- (int)mesg_len, mesg, -- (int)seed_len, seed); -+ /* Now test the decryption. */ -+ encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len); -+ seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); -+ -+#ifdef WITH_MARVIN_WORKAROUND -+ /* First try without implicit rejection -- this should fail for invalid inputs */ -+ err = gcry_sexp_build (&ciph, NULL, -+ "(enc-val (flags pkcs1 no-implicit-rejection)" -+ "(rsa (a %b)))", -+ (int)encr_len, encr); - if (err) -- die ("constructing plain data failed: %s\n", gpg_strerror (err)); -- gcry_free (mesg); -- gcry_free (seed); -+ die ("constructing cipher data failed: %s\n", gpg_strerror (err)); - -- err = gcry_pk_encrypt (&ciph, plain, pub_key); -+ err = gcry_pk_decrypt (&plain, ciph, sec_key); - if (err) - { -- show_sexp ("plain:\n", ciph); -- fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); -+ /* If the message is not set, the padding is invalid and failure is expected */ -+ if (tbl[tno].m[mno].mesg != NULL) -+ { -+ show_sexp ("ciph:\n", ciph); -+ fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err)); -+ } - } - else - { -- if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, -- tbl[tno].m[mno].desc)) -+ /* If the message is not set, it is in the synthetic field */ -+ const char *msg = tbl[tno].m[mno].mesg; -+ if (msg == NULL) -+ msg = tbl[tno].m[mno].synt; -+ if (extract_cmp_data (plain, "value", msg, -+ tbl[tno].m[mno].desc, 0)) - { -- show_sexp ("encrypt result:\n", ciph); -- fail ("mismatch in gcry_pk_encrypt\n"); -+ show_sexp ("decrypt result:\n", plain); -+ fail ("mismatch in gcry_pk_decrypt.\n"); - } -- gcry_sexp_release (ciph); -- ciph = NULL; -+ gcry_sexp_release (plain); -+ plain = NULL; - } -- gcry_sexp_release (plain); -- plain = NULL; -- -- /* Now test the decryption. */ -- encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len); -+ gcry_sexp_release (ciph); -+ ciph = NULL; -+#endif /* WITH_MARVIN_WORKAROUND */ - - err = gcry_sexp_build (&ciph, NULL, - "(enc-val (flags pkcs1)" -@@ -484,15 +530,19 @@ check_v15crypt (void) - } - else - { -- if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg, -- tbl[tno].m[mno].desc)) -+ /* If the message is not set, expect the synthetic message here */ -+ const char *msg = tbl[tno].m[mno].mesg; -+ if (msg == NULL) -+ msg = tbl[tno].m[mno].synt; -+ if (extract_cmp_data (plain, "value", msg, -+ tbl[tno].m[mno].desc, 0)) - { - show_sexp ("decrypt result:\n", plain); -- fail ("mismatch in gcry_pk_decrypt\n"); -+ fail ("mismatch in gcry_pk_decrypt. Expected %s\n", msg); - } -- gcry_sexp_release (plain); -- plain = NULL; - } -+ gcry_sexp_release (plain); -+ plain = NULL; - gcry_sexp_release (ciph); - ciph = NULL; - } -@@ -584,7 +634,7 @@ check_v15sign (void) - else - { - if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign, -- tbl[tno].m[mno].desc)) -+ tbl[tno].m[mno].desc, 0)) - { - show_sexp ("sign result:\n", sig); - fail ("mismatch in gcry_pk_sign\n"); --- -2.46.0 - diff --git a/libgcrypt-1.2.2-lib64.patch b/libgcrypt-1.2.2-lib64.patch new file mode 100644 index 0000000..4f68d7b --- /dev/null +++ b/libgcrypt-1.2.2-lib64.patch @@ -0,0 +1,14 @@ +We should suppress an explicit -L on 64-bit arches, too. + +--- libgcrypt-1.2.2/src/libgcrypt-config.in 2006-05-16 18:50:43.000000000 -0400 ++++ libgcrypt-1.2.2/src/libgcrypt-config.in 2006-05-16 18:50:50.000000000 -0400 +@@ -138,7 +138,8 @@ + libs_final="$libs" + + # Set up `libdirs'. +- if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/lib"; then ++ if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/lib" -a \ ++ "x$libdir" != "x/usr/lib64" -a "x$libdir" != "x/lib64"; then + libdirs="-L$libdir" + fi + diff --git a/libgcrypt.spec b/libgcrypt.spec index 23ec779..ddba6d3 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -1,50 +1,22 @@ -# This is taken from gnutls.spec -%define srpmhash() %{lua: -local files = rpm.expand("%_specdir/libgcrypt.spec") -for i, p in ipairs(patches) do - files = files.." "..p -end -for i, p in ipairs(sources) do - files = files.." "..p -end -local sha256sum = assert(io.popen("cat "..files.."| sha256sum")) -local hash = sha256sum:read("*a") -sha256sum:close() -print(string.sub(hash, 0, 16)) -} - Name: libgcrypt -Version: 1.11.2 -Release: 1%{?dist} -URL: https://www.gnupg.org/ -Source0: https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2 -Source1: https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2.sig -Source2: https://gnupg.org/signature_key.asc -# Pass the annobin flags to the libgcrypt.so (#2016349) -Patch1: libgcrypt-1.10.1-annobin.patch -# https://gitlab.com/redhat-crypto/libgcrypt/libgcrypt-mirror/-/merge_requests/19/ -Patch5: libgcrypt-1.11.0-marvin.patch - -%global gcrylibdir %{_libdir} -%global gcrysoname libgcrypt.so.20 -%global hmackey orboDeJITITejsirpADONivirpUkvarP - -License: BSD-3-Clause AND (BSD-3-Clause OR GPL-2.0-only) AND GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later AND MIT-Modern-Variant -Summary: A general-purpose cryptography library -BuildRequires: gcc -BuildRequires: gawk, libgpg-error-devel >= 1.11, pkgconfig -# This is needed only when patching the .texi doc. -BuildRequires: texinfo -BuildRequires: autoconf, automake, libtool -BuildRequires: make -BuildRequires: gnupg2 -BuildRequires: annobin-annocheck binutils +Version: 1.2.4 +Release: 1 +Source0: ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2 +Source1: ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2.sig +Source2: wk@g10code.com +Patch0: libgcrypt-1.2.2-lib64.patch +License: LGPL +Summary: A general-purpose cryptography library. +BuildRoot: %{_tmppath}/%{name}-%{version}-root +BuildRequires: libgpg-error-devel pkgconfig +Group: System Environment/Libraries %package devel -Summary: Development files for the %{name} package +Summary: Development files for the %{name} package. +Group: Development/Libraries +PreReq: /sbin/install-info Requires: libgpg-error-devel -Requires: %{name}%{?_isa} = %{version}-%{release} -Requires: pkgconfig +Requires: %{name} = %{version}-%{release} %description Libgcrypt is a general purpose crypto library based on the code used @@ -56,573 +28,60 @@ in GNU Privacy Guard. This package contains files needed to develop applications using libgcrypt. %prep -%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' %setup -q -%patch 1 -p1 -%patch 5 -p1 +#%patch0 -p1 -b .lib64 %build -# should be all algorithms except SM3 and SM4, aria -export DIGESTS='crc gostr3411-94 md4 md5 rmd160 sha1 sha256 sha512 sha3 tiger whirlpool stribog blake2' -export CIPHERS='arcfour blowfish cast5 des aes twofish serpent rfc2268 seed camellia idea salsa20 gost28147 chacha20' - -eval $(sed -n 's/^\(\(NAME\|VERSION_ID\)=.*\)/OS_\1/p' /etc/os-release) -export FIPS_MODULE_NAME="$OS_NAME ${OS_VERSION_ID%%.*} %name" - -autoreconf -f -%configure --disable-static \ -%ifarch sparc64 - --disable-asm \ -%endif - --enable-noexecstack \ - --enable-hmac-binary-check=%{hmackey} \ - --disable-jent-support \ - --disable-O-flag-munging \ - --enable-digests="$DIGESTS" \ - --enable-ciphers="$CIPHERS" \ - --enable-marvin-workaround \ - --with-fips-module-version="$FIPS_MODULE_NAME %{version}-%{srpmhash}" -sed -i -e '/^sys_lib_dlsearch_path_spec/s,/lib /usr/lib,/usr/lib /lib64 /usr/lib64 /lib,g' libtool -%make_build - -%check +%configure --disable-asm +make make check -# try in faked FIPS mode too -LIBGCRYPT_FORCE_FIPS_MODE=1 make check - -%define libpath $RPM_BUILD_ROOT%{gcrylibdir}/%{gcrysoname}.?.? - -PROFILE=%{?dist} annocheck --ignore-unknown --verbose --profile=${PROFILE:1} %{libpath} - -# Add generation of HMAC checksums of the final stripped binaries -%define __spec_install_post \ - %{?__debug_package:%{__debug_install_post}} \ - %{__arch_install_post} \ - %{__os_install_post} \ - cd src \ - sed -i -e 's|FILE=.*|FILE=\\\$1|' gen-note-integrity.sh \ - READELF=readelf AWK=awk ECHO_N="-n" bash gen-note-integrity.sh %{libpath} > %{libpath}.hmac \ - objcopy --update-section .note.fdo.integrity=%{libpath}.hmac %{libpath} %{libpath}.new \ - mv -f %{libpath}.new %{libpath} \ - rm -f %{libpath}.hmac -%{nil} %install -%make_install +rm -fr $RPM_BUILD_ROOT +%makeinstall # Change /usr/lib64 back to /usr/lib. This saves us from having to patch the # script to "know" that -L/usr/lib64 should be suppressed, and also removes # a file conflict between 32- and 64-bit versions of this package. -# Also replace my_host with none. sed -i -e 's,^libdir="/usr/lib.*"$,libdir="/usr/lib",g' $RPM_BUILD_ROOT/%{_bindir}/libgcrypt-config -sed -i -e 's,^my_host=".*"$,my_host="none",g' $RPM_BUILD_ROOT/%{_bindir}/libgcrypt-config rm -f ${RPM_BUILD_ROOT}/%{_infodir}/dir ${RPM_BUILD_ROOT}/%{_libdir}/*.la /sbin/ldconfig -n $RPM_BUILD_ROOT/%{_libdir} -%if "%{gcrylibdir}" != "%{_libdir}" -# Relocate the shared libraries to %{gcrylibdir}. -mkdir -p $RPM_BUILD_ROOT%{gcrylibdir} -for shlib in $RPM_BUILD_ROOT%{_libdir}/*.so* ; do - if test -L "$shlib" ; then - rm "$shlib" - else - mv "$shlib" $RPM_BUILD_ROOT%{gcrylibdir}/ - fi -done +%clean +rm -fr $RPM_BUILD_ROOT -# Add soname symlink. -/sbin/ldconfig -n $RPM_BUILD_ROOT/%{_lib}/ -%endif +%post -p /sbin/ldconfig -# Overwrite development symlinks. -pushd $RPM_BUILD_ROOT/%{gcrylibdir} -for shlib in lib*.so.?? ; do - target=$RPM_BUILD_ROOT/%{_libdir}/`echo "$shlib" | sed -e 's,\.so.*,,g'`.so -%if "%{gcrylibdir}" != "%{_libdir}" - shlib=%{gcrylibdir}/$shlib -%endif - ln -sf $shlib $target -done -popd +%postun -p /sbin/ldconfig -# Create /etc/gcrypt (hardwired, not dependent on the configure invocation) so -# that _someone_ owns it. -mkdir -p -m 755 $RPM_BUILD_ROOT/etc/gcrypt +%post devel +/sbin/install-info %{_infodir}/gcrypt.info.gz %{_infodir}/dir +exit 0 -%ldconfig_scriptlets +%preun devel +if [ $1 = 0 ]; then + /sbin/install-info --delete %{_infodir}/gcrypt.info.gz %{_infodir}/dir +fi +exit 0 %files -%dir /etc/gcrypt -%{gcrylibdir}/libgcrypt.so.*.* -%{gcrylibdir}/%{gcrysoname} -%license COPYING.LIB -%doc AUTHORS NEWS THANKS +%defattr(-,root,root) +%{_libdir}/*.so.* +#%{_libdir}/%{name} %files devel +%defattr(-,root,root) %{_bindir}/%{name}-config -%{_bindir}/dumpsexp -%{_bindir}/hmac256 -%{_bindir}/mpicalc %{_includedir}/* +%{_libdir}/*.a %{_libdir}/*.so -%{_libdir}/pkgconfig/libgcrypt.pc %{_datadir}/aclocal/* -%{_mandir}/man1/* +#%{_datadir}/%{name} %{_infodir}/gcrypt.info* -%license COPYING %changelog -* Mon Nov 03 2025 Jakub Jelen - 1.11.2-1 -- New upstream release (#2406804) - -* Thu Jul 24 2025 Fedora Release Engineering - 1.11.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Tue May 13 2025 Jakub Jelen - 1.11.1-1 -- New upstream release (#2364878) - -* Fri Jan 17 2025 Fedora Release Engineering - 1.11.0-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Tue Oct 29 2024 Jakub Jelen - 1.11.0-4 -- Run annocheck as part of the build -- Use upstream CF protection patches -- Fix PAC/BTI protection for Aarch64 -- Fix CVE-2024-2236 (#2274128) - -* Thu Jul 25 2024 Jakub Jelen - 1.11.0-3 -- Disable -O flag munging and remove needles modification of LTO flags. - -* Thu Jul 18 2024 Fedora Release Engineering - 1.11.0-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Wed Jun 19 2024 Jakub Jelen - 1.11.0-1 -- New upstream release (#2293064) - -* Tue Mar 26 2024 Jakub Jelen - 1.10.3-4 -- Replace deprecated fgrep (#2271503) - -* Thu Jan 25 2024 Fedora Release Engineering - 1.10.3-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sun Jan 21 2024 Fedora Release Engineering - 1.10.3-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Tue Nov 14 2023 Jakub Jelen - 1.10.3-1 -- New upstream release (#2249639) - -* Thu Jul 20 2023 Fedora Release Engineering - 1.10.2-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Tue Apr 11 2023 Jakub Jelen - 1.10.2-1 -- New upstream release (#2185084) - -* Thu Jan 19 2023 Fedora Release Engineering - 1.10.1-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Sat Dec 3 2022 Florian Weimer - 1.10.1-6 -- Port configure script to C99 - -* Tue Nov 08 2022 Todd Zullinger - 1.10.1-5 -- enable brainpool by default (#1413618) -- fix sporadic failures generating RSA keys in FIPS mode - -* Thu Jul 21 2022 Fedora Release Engineering - 1.10.1-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Sun May 29 2022 Todd Zullinger - 1.10.1-3 -- improve --disable-brainpool configure output -- use %%bcond_with to disable brainpool curves - -* Fri Apr 08 2022 Jakub Jelen - 1.10.1-2 -- Adjust integrity check creation to match upstream (#2073018) - -* Tue Mar 29 2022 Jakub Jelen - 1.10.1-1 -- Final release (#2069263) - -* Wed Feb 02 2022 Jakub Jelen - 1.10.0-1 -- New upstream release (#2049322) - -* Thu Jan 20 2022 Fedora Release Engineering - 1.9.4-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Mon Aug 23 2021 Jakub Jelen - 1.9.4-1 -- New upstream release (#1996467) - -* Thu Jul 22 2021 Fedora Release Engineering - 1.9.3-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Jun 15 2021 Jakub Jelen - 1.9.3-3 -- Fix for CVE-2021-33560 (#1970098) - -* Wed Apr 28 2021 Jakub Jelen - 1.9.3-2 -- Restore the CET protection (#1954049) - -* Tue Apr 20 2021 Jakub Jelen - 1.9.3-1 -- New upstream release (#1951325) - -* Thu Apr 15 2021 Jakub Jelen - 1.9.2-3 -- Fix issues reported by coverity - -* Mon Mar 29 2021 Jakub Jelen - 1.9.2-2 -- Fix OCB tag creation on s390x (failing gnupg2 tests) - -* Wed Feb 17 2021 Jakub Jelen - 1.9.2-1 -- New upstream release (#1929630) - -* Fri Jan 29 2021 Jakub Jelen - 1.9.1-1 -- New upstream release (#1922156, #1922097) - -* Wed Jan 20 2021 Jakub Jelen - 1.9.0-1 -- New upstream release (#1917878) - -* Tue Nov 24 2020 Jakub Jelen - 1.8.7-1 -- new upstream release (#1891123) - -* Fri Aug 21 2020 Jeff Law - 1.8.6-4 -- Re-enable LTO - -* Tue Jul 28 2020 Fedora Release Engineering - 1.8.6-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Tue Jul 21 2020 Tom Stellard - 1.8.6-2 -- Use make macros -- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro - -* Mon Jul 20 2020 Tomáš Mráz 1.8.6-1 -- new upstream version 1.8.6 - -* Wed Jul 1 2020 Tomáš Mráz 1.8.5-7 -- use the hmac256 tool to calculate the library hmac - -* Tue Jun 30 2020 Jeff Law -- Disable LTO - -* Thu Apr 23 2020 Tomáš Mráz 1.8.5-6 -- Fix regression - missing -ldl linkage - -* Wed Apr 22 2020 Tomáš Mráz 1.8.5-5 -- AES performance improvements backported from master branch - -* Mon Apr 20 2020 Tomáš Mráz 1.8.5-4 -- FIPS selftest is run directly from the constructor -- FIPS module is implicit with kernel FIPS flag - -* Thu Jan 30 2020 Tomáš Mráz 1.8.5-3 -- fix the build on ARMv7 - -* Thu Jan 23 2020 Tomáš Mráz 1.8.5-2 -- Intel CET support by H. J. Lu - -* Tue Sep 3 2019 Tomáš Mráz 1.8.5-1 -- new upstream version 1.8.5 -- add CMAC selftest for FIPS POST -- add continuous FIPS entropy test -- disable non-approved FIPS hashes in the enforced FIPS mode - -* Thu Jul 25 2019 Fedora Release Engineering - 1.8.4-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Tue Feb 12 2019 Tomáš Mráz 1.8.4-3 -- fix the build tests to pass in the FIPS mode - -* Fri Feb 01 2019 Fedora Release Engineering - 1.8.4-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Tue Nov 20 2018 Tomáš Mráz 1.8.4-1 -- new upstream version 1.8.4 - -* Fri Jul 13 2018 Fedora Release Engineering - 1.8.3-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Thu Jul 12 2018 Tomáš Mráz 1.8.3-2 -- make only_urandom a default in non-presence of configuration file -- run the full FIPS selftests only when the library is called from - application - -* Thu Jun 14 2018 Tomáš Mráz 1.8.3-1 -- new upstream version 1.8.3 - -* Tue Feb 6 2018 Tomáš Mráz 1.8.2-2 -- fix behavior when getrandom syscall is not present (#1542453) - -* Thu Dec 21 2017 Tomáš Mráz 1.8.2-1 -- new upstream version 1.8.2 - -* Tue Dec 5 2017 Tomáš Mráz 1.8.1-3 -- do not try to access() /dev/urandom either if getrandom() works - -* Mon Dec 4 2017 Tomáš Mráz 1.8.1-2 -- do not try to open /dev/urandom if getrandom() works (#1380866) - -* Tue Sep 5 2017 Tomáš Mráz 1.8.1-1 -- new upstream version 1.8.1 - -* Wed Aug 16 2017 Tomáš Mráz 1.8.0-1 -- new upstream version 1.8.0 - -* Thu Aug 03 2017 Fedora Release Engineering - 1.7.8-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Wed Jul 26 2017 Fedora Release Engineering - 1.7.8-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Thu Jun 29 2017 Tomáš Mráz 1.7.8-1 -- new upstream version 1.7.8 - -* Fri Jun 2 2017 Tomáš Mráz 1.7.7-1 -- new upstream version 1.7.7 -- GOST is now enabled - -* Fri Feb 10 2017 Fedora Release Engineering - 1.7.6-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Mon Jan 30 2017 Tomáš Mráz 1.7.6-1 -- new upstream version 1.7.6 - -* Fri Dec 16 2016 Tomáš Mráz 1.7.5-1 -- new upstream version 1.7.5 - -* Wed Nov 23 2016 Tomáš Mráz 1.7.3-1 -- new upstream version 1.7.3 - -* Wed Aug 17 2016 Tomáš Mráz 1.6.6-1 -- new upstream version with important security fix (CVE-2016-6316) - -* Thu Jul 21 2016 Tomáš Mráz 1.6.5-1 -- new upstream version fixing low impact issue CVE-2015-7511 - -* Thu Feb 04 2016 Fedora Release Engineering - 1.6.4-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Wed Sep 9 2015 Tomáš Mráz 1.6.4-1 -- new upstream version - -* Wed Jun 17 2015 Fedora Release Engineering - 1.6.3-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Fri Apr 3 2015 Tomáš Mráz 1.6.3-4 -- deinitialize the RNG after the selftest is run - -* Tue Mar 24 2015 Tomáš Mráz 1.6.3-3 -- touch only urandom in the selftest and when /dev/random is - unavailable for example by SELinux confinement -- fix the RSA selftest key (p q swap) (#1204517) - -* Fri Mar 13 2015 Tomáš Mráz 1.6.3-2 -- do not use strict aliasing for bufhelp functions (#1201219) - -* Fri Mar 6 2015 Tomáš Mráz 1.6.3-1 -- new upstream version - -* Wed Feb 25 2015 Tomáš Mráz 1.6.2-4 -- do not initialize secure memory during the selftest (#1195850) - -* Sat Feb 21 2015 Till Maas - 1.6.2-3 -- Rebuilt for Fedora 23 Change - https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code - -* Wed Jan 14 2015 Tomáš Mráz 1.6.2-2 -- fix buildability of programs using gcrypt.h with -ansi (#1182200) - -* Mon Dec 8 2014 Tomáš Mráz 1.6.2-1 -- new upstream version - -* Sun Aug 17 2014 Fedora Release Engineering - 1.6.1-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild - -* Thu Jul 17 2014 Tom Callaway - 1.6.1-6 -- fix license handling - -* Sat Jun 07 2014 Fedora Release Engineering - 1.6.1-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Tue May 20 2014 Kyle McMartin 1.6.1-4 -- Re-enable below algos, apply patch from upstream list to make - that code -fPIC friendly. (rhbz#1069792) - -* Mon May 19 2014 Kyle McMartin 1.6.1-3 -- Disable rijndael, cast5, camellia ARM assembly, as it's non-PIC as - presently written, which results in .text relocations in the shared - library. (rhbz#1069792) - -* Thu Apr 24 2014 Tomáš Mráz 1.6.1-2 -- drop the temporary compat shared library version -- fix the soname version in -use-fipscheck.patch - -* Fri Feb 28 2014 Tomáš Mráz 1.6.1-1 -- new upstream version breaking ABI compatibility -- this release temporarily includes old compatibility .so - -* Tue Jan 21 2014 Tomáš Mráz 1.5.3-3 -- add back the nistp521r1 EC curve -- fix a bug in the Whirlpool hash implementation -- speed up the PBKDF2 computation - -* Sun Oct 20 2013 Tom Callaway - 1.5.3-2 -- add cleared ECC support - -* Fri Jul 26 2013 Tomáš Mráz 1.5.3-1 -- new upstream version fixing cache side-channel attack on RSA private keys - -* Thu Jun 20 2013 Tomáš Mráz 1.5.2-3 -- silence false error detected by valgrind (#968288) - -* Thu Apr 25 2013 Tomáš Mráz 1.5.2-2 -- silence strict aliasing warning in Rijndael -- apply UsrMove -- spec file cleanups - -* Fri Apr 19 2013 Tomáš Mráz 1.5.2-1 -- new upstream version - -* Wed Mar 20 2013 Tomas Mraz 1.5.1-1 -- new upstream version - -* Tue Mar 5 2013 Tomas Mraz 1.5.0-11 -- use poll() instead of select() when gathering randomness (#913773) - -* Thu Feb 14 2013 Fedora Release Engineering - 1.5.0-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild - -* Thu Jan 3 2013 Tomas Mraz 1.5.0-9 -- allow empty passphrase in PBKDF2 needed for cryptsetup (=891266) - -* Mon Dec 3 2012 Tomas Mraz 1.5.0-8 -- fix multilib conflict in libgcrypt-config -- fix minor memory leaks and other bugs found by Coverity scan - -* Thu Jul 19 2012 Fedora Release Engineering - 1.5.0-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild - -* Thu Apr 5 2012 Tomas Mraz 1.5.0-5 -- Correctly rebuild the info documentation - -* Wed Apr 4 2012 Tomas Mraz 1.5.0-4 -- Add GCRYCTL_SET_ENFORCED_FIPS_FLAG command - -* Fri Jan 13 2012 Fedora Release Engineering - 1.5.0-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild - -* Mon Aug 15 2011 Kalev Lember 1.5.0-2 -- Rebuilt for rpm bug #728707 - -* Thu Jul 21 2011 Tomas Mraz 1.5.0-1 -- new upstream version - -* Mon Jun 20 2011 Tomas Mraz 1.4.6-4 -- Always xor seed from /dev/urandom over /etc/gcrypt/rngseed - -* Mon May 30 2011 Tomas Mraz 1.4.6-3 -- Make the FIPS-186-3 DSA implementation CAVS testable -- add configurable source of RNG seed /etc/gcrypt/rngseed - in the FIPS mode (#700388) - -* Fri Feb 11 2011 Tomas Mraz 1.4.6-1 -- new upstream version with minor changes - -* Mon Feb 07 2011 Fedora Release Engineering - 1.4.5-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild - -* Fri Feb 4 2011 Tomas Mraz 1.4.5-6 -- fix a bug in the fips-186-3 dsa parameter generation code - -* Tue Feb 1 2011 Tomas Mraz 1.4.5-5 -- use /dev/urandom for seeding in the FIPS mode -- make the tests to pass in the FIPS mode also fixing - the FIPS-186-3 DSA keygen - -* Sun Feb 14 2010 Rex Dieter 1.4.5-4 -- FTBFS libgcrypt-1.4.5-3.fc13: ImplicitDSOLinking (#564973) - -* Wed Feb 3 2010 Tomas Mraz 1.4.5-3 -- drop the S390 build workaround as it is no longer needed -- additional spec file cleanups for merge review (#226008) - -* Mon Dec 21 2009 Tomas Mraz 1.4.5-1 -- workaround for build on S390 (#548825) -- spec file cleanups -- upgrade to new minor upstream release - -* Tue Aug 11 2009 Tomas Mraz 1.4.4-8 -- fix warning when installed with --excludedocs (#515961) - -* Fri Jul 24 2009 Fedora Release Engineering - 1.4.4-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild - -* Thu Jun 18 2009 Tomas Mraz 1.4.4-6 -- and now really apply the padlock patch - -* Wed Jun 17 2009 Tomas Mraz 1.4.4-5 -- fix VIA padlock RNG inline assembly call (#505724) - -* Thu Mar 5 2009 Tomas Mraz 1.4.4-4 -- with the integrity verification check the library needs to link to libdl - (#488702) - -* Tue Mar 3 2009 Tomas Mraz 1.4.4-3 -- add hmac FIPS integrity verification check - -* Wed Feb 25 2009 Fedora Release Engineering - 1.4.4-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild - -* Fri Jan 30 2009 Tomas Mraz 1.4.4-1 -- update to 1.4.4 -- do not abort when the fips mode kernel flag is inaccessible - due to permissions (#470219) -- hobble the library to drop the ECC support - -* Mon Oct 20 2008 Dennis Gilmore 1.4.3-2 -- disable asm on sparc64 - -* Thu Sep 18 2008 Nalin Dahyabhai 1.4.3-1 -- update to 1.4.3 -- own /etc/gcrypt - -* Mon Sep 15 2008 Nalin Dahyabhai -- invoke make with %%{?_smp_mflags} to build faster on multi-processor - systems (Steve Grubb) - -* Mon Sep 8 2008 Nalin Dahyabhai 1.4.2-1 -- update to 1.4.2 - -* Tue Apr 29 2008 Nalin Dahyabhai 1.4.1-1 -- update to 1.4.1 -- bump libgpgerror-devel requirement to 1.4, matching the requirement enforced - by the configure script - -* Thu Apr 3 2008 Joe Orton 1.4.0-3 -- add patch from upstream to fix severe performance regression - in entropy gathering - -* Tue Feb 19 2008 Fedora Release Engineering - 1.4.0-2 -- Autorebuild for GCC 4.3 - -* Mon Dec 10 2007 Nalin Dahyabhai - 1.4.0-1 -- update to 1.4.0 - -* Tue Oct 16 2007 Nalin Dahyabhai - 1.2.4-6 -- use ldconfig to build the soname symlink for packaging along with the - shared library (#334731) - -* Wed Aug 22 2007 Nalin Dahyabhai - 1.2.4-5 -- add missing gawk buildrequirement -- switch from explicitly specifying the /dev/random RNG to just verifying - that the non-LGPL ones were disabled by the configure script - -* Thu Aug 16 2007 Nalin Dahyabhai - 1.2.4-4 -- clarify license -- force use of the linux /dev/random RNG, to avoid accidentally falling back - to others which would affect the license of the resulting library - -* Mon Jul 30 2007 Nalin Dahyabhai - 1.2.4-3 -- disable static libraries (part of #249815) - -* Fri Jul 27 2007 Nalin Dahyabhai - 1.2.4-2 -- move libgcrypt shared library to /%%{_lib} (#249815) - * Tue Feb 6 2007 Nalin Dahyabhai - 1.2.4-1 - update to 1.2.4 @@ -703,5 +162,5 @@ mkdir -p -m 755 $RPM_BUILD_ROOT/etc/gcrypt * Thu Jan 10 2002 Nalin Dahyabhai 1.1.5-1 - fix the Source tag so that it's a real URL -* Thu Dec 20 2001 Nalin Dahyabhai +* Wed Dec 20 2001 Nalin Dahyabhai - initial package diff --git a/signature_key.asc b/signature_key.asc deleted file mode 100644 index 151e8fa..0000000 --- a/signature_key.asc +++ /dev/null @@ -1,86 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -eiInsGZ/+h5XYrpXTgA= -=4+Sn ------END PGP PUBLIC KEY BLOCK----- diff --git a/sources b/sources index 90c992c..ba81f61 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (libgcrypt-1.11.2.tar.bz2) = b706cea602cc8f0896e57ce979643bf78974b05faec27c1b053b773c57d8b04250e30e95a4ef5899e1df981d01d8d08f0a36e10b5820a5ec4183e74c02e5f1f0 -SHA512 (libgcrypt-1.11.2.tar.bz2.sig) = e63d240a9b97aa218c98c5baa72a30321ae85412d4a8748e36578bd9498fe8c8ee2ba84835d1783cdfc1e5dfb66b0a89409d6263e9c06f4cd11e919d4bce0cd2 +3675d3e74c3a44aed629d9b12a30bb51 libgcrypt-1.2.4.tar.bz2 +b6323d3acf8c08ad849e8090fb8986b9 libgcrypt-1.2.4.tar.bz2.sig diff --git a/tests/smoke-test/Makefile b/tests/smoke-test/Makefile deleted file mode 100644 index 0682152..0000000 --- a/tests/smoke-test/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Makefile of /CoreOS/libgcrypt/smoke-test -# Description: Test calls upstream test suite. -# Author: Ondrej Moris -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Copyright (c) 2010 Red Hat, Inc. All rights reserved. -# -# This copyrighted material is made available to anyone wishing -# to use, modify, copy, or redistribute it subject to the terms -# and conditions of the GNU General Public License version 2. -# -# This program 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 a copy of the GNU General Public -# License along with this program; if not, write to the Free -# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -export TEST=/CoreOS/libgcrypt/smoke-test -export TESTVERSION=1.0 - -BUILT_FILES= - -FILES=$(METADATA) runtest.sh Makefile PURPOSE - -.PHONY: all install download clean - -run: $(FILES) build - ./runtest.sh - -build: $(BUILT_FILES) - chmod a+x runtest.sh - -clean: - rm -f *~ $(BUILT_FILES) - - -include /usr/share/rhts/lib/rhts-make.include - -$(METADATA): Makefile - @echo "Owner: Ondrej Moris " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "Description: Test calls upstream test suite." >> $(METADATA) - @echo "Type: Sanity" >> $(METADATA) - @echo "TestTime: 15m" >> $(METADATA) - @echo "RunFor: libgcrypt" >> $(METADATA) - @echo "Requires: libgcrypt" >> $(METADATA) - @echo "Requires: nfs-utils" >> $(METADATA) - @echo "Requires: rpm-build" >> $(METADATA) - @echo "Requires: autoconf automake libtool" >> $(METADATA) - @echo "Requires: gawk" >> $(METADATA) - @echo "Requires: gcc-c++" >> $(METADATA) - @echo "Requires: libgpg-error-devel" >> $(METADATA) - @echo "Requires: pkgconfig texinfo fipscheck libkcapi-fipscheck" >> $(METADATA) - @echo "Requires: crypto-policies-scripts" >> $(METADATA) - @echo "Requires: bc" >> $(METADATA) - @echo "RhtsRequires: library(distribution/fips)" >> $(METADATA) - @echo "Releases: -RHEL3 -RHEL4" >> $(METADATA) - @echo "Priority: Normal" >> $(METADATA) - @echo "Architectures: i386 x86_64 s390x ia64" >> $(METADATA) - @echo "License: GPLv2" >> $(METADATA) - @echo "Confidential: no" >> $(METADATA) - @echo "Destructive: no" >> $(METADATA) - - rhts-lint $(METADATA) diff --git a/tests/smoke-test/PURPOSE b/tests/smoke-test/PURPOSE deleted file mode 100644 index 5df6ca9..0000000 --- a/tests/smoke-test/PURPOSE +++ /dev/null @@ -1,3 +0,0 @@ -PURPOSE of /CoreOS/libgcrypt/Sanity/smoke-test -Description: Test calls upstream test suite. -Author: Ondrej Moris diff --git a/tests/smoke-test/main.fmf b/tests/smoke-test/main.fmf deleted file mode 100644 index 70bd1ba..0000000 --- a/tests/smoke-test/main.fmf +++ /dev/null @@ -1,25 +0,0 @@ -summary: Test calls upstream test suite. -test: ./runtest.sh -enabled: true -framework: beakerlib -require: - - library(distribution/fips) -recommend: - - libgcrypt - - nfs-utils - - rpm-build - - autoconf - - automake - - libtool - - gawk - - gcc-c++ - - libgpg-error-devel - - pkgconfig - - texinfo - - fipscheck - - libkcapi-fipscheck - - crypto-policies-scripts - - bc - - annobin-annocheck - - gnupg2 -duration: 45m diff --git a/tests/smoke-test/runtest.sh b/tests/smoke-test/runtest.sh deleted file mode 100755 index 0f5bc82..0000000 --- a/tests/smoke-test/runtest.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash -# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# runtest.sh of /CoreOS/libgcrypt/smoke-test -# Description: Test calls upstream test suite. -# Author: Ondrej Moris -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Copyright (c) 2010 Red Hat, Inc. All rights reserved. -# -# This copyrighted material is made available to anyone wishing -# to use, modify, copy, or redistribute it subject to the terms -# and conditions of the GNU General Public License version 2. -# -# This program 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 a copy of the GNU General Public -# License along with this program; if not, write to the Free -# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -. /usr/share/beakerlib/beakerlib.sh - -PACKAGE="libgcrypt" - -rlJournalStart - - rlPhaseStartSetup - rlImport distribution/fips || rlFail "FIPS library needed for some phases" - TmpDir=`mktemp -d` - rlAssertRpm $PACKAGE - rlRun "rlFileBackup --clean /etc/gcrypt/fips_enabled" - if [[ -r /etc/gcrypt/hwf.deny ]]; then - rlRun "rlFileBackup /etc/gcrypt/hwf.deny" - rlRun "rm -f /etc/gcrypt/hwf.deny" - fi - rlRun "pushd $TmpDir" 0 - rlRun "rlFetchSrcForInstalled $PACKAGE" - rlRun "rpm -ihv `ls *.rpm`" 0 - if grep '1' /proc/sys/crypto/fips_enabled; then - rlRun "echo '1' > /etc/gcrypt/fips_enabled" 0 - fi - rlPhaseEnd - - rlPhaseStartTest "Package build" - TOPDIR=`rpm --eval %_topdir` - rlRun "pushd $TOPDIR" 0 - rlRun "rm -rf BUILD/libgcrypt-*" 0-255 - rlRun "rpmbuild -vv -bc SPECS/libgcrypt.spec" 0 - libgcrypt_dir="libgcrypt-`rpm -q --qf "%{VERSION}\n" libgcrypt | head -1`" - if [ -d "BUILD/$libgcrypt_dir-build" ]; then - BUILDDIR="BUILD/$libgcrypt_dir-build/$libgcrypt_dir" - else - BUILDDIR="BUILD/$libgcrypt_dir" - fi - rlRun "pushd $BUILDDIR" 0 - rlRun "fipshmac src/.libs/libgcrypt.so.??" 0 - rlRun "popd" - rlRun "popd" - rlPhaseEnd - - rlPhaseStartTest "Upstream testsuite" - rlRun "pushd $TOPDIR/$BUILDDIR" 0 - exp_fails=() - - rlRun "echo 'Expecting ${#exp_fails[@]} fails'" - exp_exitcode=0 - if [[ ${#exp_fails[@]} -gt 0 ]]; then exp_exitcode=2; fi - rlRun "make check &> $TmpDir/make_check.out" $exp_exitcode - rlRun "grep ^FAIL: $TmpDir/make_check.out" 0,1 "Print fails" - if [[ ${#exp_fails[@]} -gt 0 ]]; then - for f in $(grep '^FAIL:' $TmpDir/make_check.out | awk -F ': ' '{print $2}'); do - if [[ "${exp_fails[@]}" =~ "$f" ]]; then - rlLog "$f failure is expected" - else - rlFail "$f failure is not expected" - fi - done - else - rlRun "grep \"All [0-9]\+ tests passed\" $TmpDir/make_check.out" 0 \ - "All tests passed" - fi - rlRun "cat $TmpDir/make_check.out" - rlRun "popd" - rlPhaseEnd - - if ! (rlIsRHEL '<=8.4' || ([[ $fipsMode = "enabled" ]] && rlIsFedora '<37')); then - # (we are ~expecting to fix HW optimization problem around Fedora-37) - rlPhaseStartTest "Performance with HW optimizations disabled - bz1990059" - # we are gathering more samples, so that this test is robust in shared environments - N_SAMPLES=5 - N_MEDIAN=$(echo "$N_SAMPLES/2+1" |bc) - HWF_DENY_FILE="/etc/gcrypt/hwf.deny" - # Disabling via cmdline arguments would need either handpicking - # all the algorithms (variant with ":"), or making "all" work. - # "--disable-hwf all" does not work: https://dev.gnupg.org/T5636 - #dis_arg="--disable-hwf all" - dis_arg="" - - for x in "cipher:aes256:CBC enc" "hash:sha256:SHA256" "mac:hmac_sha256:HMAC_SHA256"; do - alg_type=$(echo $x |cut -d: -f1) - algorithm=$(echo $x |cut -d: -f2) - alg_line=$(echo $x |cut -d: -f3) - rlRun "rm -f $algorithm.ena $algorithm.dis" - rlLogInfo "Performance measurements started ..." - for i in `seq 1 $N_SAMPLES`; do - # run with HW optimizations ENAbled - rm -f $HWF_DENY_FILE - $TOPDIR/$BUILDDIR/tests/bench-slope $alg_type $algorithm |grep "$alg_line" >>$algorithm.ena - - # run with HW optimizations DISabled - # this looks idiotic, but I wasn't able to make --disable-hwf work - echo "all" >$HWF_DENY_FILE - $TOPDIR/$BUILDDIR/tests/bench-slope $dis_arg $alg_type $algorithm |grep "$alg_line" >>$algorithm.dis - done - rlLogInfo "Performance measurements finished" - rlRun "cat $algorithm.ena" - rlRun "cat $algorithm.dis" - dis=$(cat $algorithm.dis |cut -d'|' -f2 |awk '{ print $1 }' |sort -n |sed -n "$N_MEDIAN p") - ena=$(cat $algorithm.ena |cut -d'|' -f2 |awk '{ print $1 }' |sort -n |sed -n "$N_MEDIAN p") - rlRun "echo '$algorithm Time: disabled $dis enabled $ena'" - if (( $(echo "$dis > $ena" |bc -l) )); then - rlPass "HW optimizations work for $algorithm" - else - rlFail "HW optimizations DO NOT work for $algorithm" - fi - done - rlPhaseEnd - fi - - rlPhaseStartCleanup - rlRun "popd" - rlRun "rm -r $TmpDir" 0 - rlRun "rlFileRestore" - rlPhaseEnd - -rlJournalPrintText -rlJournalEnd diff --git a/wk@g10code.com b/wk@g10code.com new file mode 100644 index 0000000..3482c48 --- /dev/null +++ b/wk@g10code.com @@ -0,0 +1,624 @@ +Login: wk Name: Werner Koch +No project. +No plan. +Public key: +pub 1024D/621CC013 1998-07-07 Werner Koch +uid Werner Koch +uid Werner Koch + +pub 1024D/5B0358A2 1999-03-15 Werner Koch +uid Werner Koch + +pub 768R/0C9857A5 1995-09-30 Werner Koch (mein alter key) +uid Werner Koch + +pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) + + +621CC013 is my every days working key - use this one! +5B0358A2 is my certification key. +0C9857A5 is my old PGP 2 key - don't use it. +57548DCD is used to sign GNU crypto software. + +I use a separate certification key (5B0358A2) to sign my other keys. +This key is stored at a more or less secure place and only used on a +spare laptop which is not connected to any network. If you find a key +certified by this one, you can be sure that I personally met this +person and checked the name part of the user ID against an official +looking passport or another suitable photo id. My signature does not +say anything about the email address (I merely check that the address +looks plausible). + +The working key (621cc013) has several subkeys; an OpenPGP +implementation should automagically select the most recent one for +encryption. Note, that the certification and the GNU signature key +can't be used for encryption becuase they are sign-only keys. + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.1 (GNU/Linux) + +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 +=01kM +-----END PGP PUBLIC KEY BLOCK-----