From jussi.kivilinna at iki.fi Mon Aug 1 16:25:34 2022 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 1 Aug 2022 17:25:34 +0300 Subject: [PATCH] sm4: add ARMv8 CE accelerated implementation for XTS mode In-Reply-To: <20220728082655.47697-1-tianjia.zhang@linux.alibaba.com> References: <20220728082655.47697-1-tianjia.zhang@linux.alibaba.com> Message-ID: <88833b2a-cdc8-8e81-75f7-de8a05a3b279@iki.fi> Hello, Patch applied to master, thanks. -Jussi On 28.7.2022 11.26, Tianjia Zhang via Gcrypt-devel wrote: > * cipher/sm4-armv8-aarch64-ce.S (_gcry_sm4_armv8_ce_xts_crypt): New. > * cipher/sm4.c (_gcry_sm4_armv8_ce_xts_crypt): New. > (_gcry_sm4_xts_crypt) [USE_ARM_CE]: Add ARMv8 CE implementation for XTS. > -- > > Benchmark on T-Head Yitian-710 2.75 GHz: > > Before: > SM4 | nanosecs/byte mebibytes/sec cycles/byte auto Mhz > XTS enc | 0.373 ns/B 2560 MiB/s 1.02 c/B 2749 > XTS dec | 0.372 ns/B 2562 MiB/s 1.02 c/B 2750 > > After (1.18x faster): > SM4 | nanosecs/byte mebibytes/sec cycles/byte auto Mhz > XTS enc | 0.314 ns/B 3038 MiB/s 0.863 c/B 2749 > XTS dec | 0.314 ns/B 3037 MiB/s 0.863 c/B 2749 > > Signed-off-by: Tianjia Zhang > --- > cipher/sm4-armv8-aarch64-ce.S | 151 ++++++++++++++++++++++++++++++++++ > cipher/sm4.c | 18 +++- > 2 files changed, 168 insertions(+), 1 deletion(-) > > diff --git a/cipher/sm4-armv8-aarch64-ce.S b/cipher/sm4-armv8-aarch64-ce.S > index 5fb55947edc1..1a4ff736ad27 100644 > --- a/cipher/sm4-armv8-aarch64-ce.S > +++ b/cipher/sm4-armv8-aarch64-ce.S > @@ -62,6 +62,7 @@ > #define RTMP3 v19 > > #define RIV v20 > +#define RMASK v21 > > /* Helper macros. */ > > @@ -69,6 +70,20 @@ > ld1 {v24.16b-v27.16b}, [ptr], #64; \ > ld1 {v28.16b-v31.16b}, [ptr]; > > +#define SM4_CRYPT_BLK(b0) \ > + rev32 b0.16b, b0.16b; \ > + sm4e(b0, v24); \ > + sm4e(b0, v25); \ > + sm4e(b0, v26); \ > + sm4e(b0, v27); \ > + sm4e(b0, v28); \ > + sm4e(b0, v29); \ > + sm4e(b0, v30); \ > + sm4e(b0, v31); \ > + rev64 b0.4s, b0.4s; \ > + ext b0.16b, b0.16b, b0.16b, #8; \ > + rev32 b0.16b, b0.16b; > + > #define crypt_blk4(b0, b1, b2, b3) \ > rev32 b0.16b, b0.16b; \ > rev32 b1.16b, b1.16b; \ > @@ -577,4 +592,140 @@ _gcry_sm4_armv8_ce_ctr_enc: > CFI_ENDPROC(); > ELF(.size _gcry_sm4_armv8_ce_ctr_enc,.-_gcry_sm4_armv8_ce_ctr_enc;) > > +.align 3 > +.global _gcry_sm4_armv8_ce_xts_crypt > +ELF(.type _gcry_sm4_armv8_ce_xts_crypt,%function;) > +_gcry_sm4_armv8_ce_xts_crypt: > + /* input: > + * x0: round key array, CTX > + * x1: dst > + * x2: src > + * x3: tweak (big endian, 128 bit) > + * x4: nblocks > + */ > + CFI_STARTPROC() > + VPUSH_ABI > + > + load_rkey(x0) > + > + mov x7, #0x87 > + mov x8, #0x1 > + mov RMASK.d[0], x7 > + mov RMASK.d[1], x8 > + > + ld1 {RIV.16b}, [x3] > + mov v8.16b, RIV.16b > + ext RIV.16b, RIV.16b, RIV.16b, #8 > + > +.Lxts_loop_blk: > + sub x4, x4, #8 > + tbnz x4, #63, .Lxts_tail8 > + > +#define tweak_next(vt, vin, RTMP) \ > + sshr RTMP.2d, RIV.2d, #63; \ > + add vt.2d, vin.2d, vin.2d; \ > + and RTMP.16b, RTMP.16b, RMASK.16b; \ > + add RIV.2d, RIV.2d, RIV.2d; \ > + eor vt.16b, vt.16b, RTMP.16b; > + > + tweak_next( v9, v8, RTMP0) > + tweak_next(v10, v9, RTMP1) > + tweak_next(v11, v10, RTMP2) > + tweak_next(v12, v11, RTMP3) > + tweak_next(v13, v12, RTMP0) > + tweak_next(v14, v13, RTMP1) > + tweak_next(v15, v14, RTMP2) > + > + ld1 {v0.16b-v3.16b}, [x2], #64 > + eor v0.16b, v0.16b, v8.16b > + eor v1.16b, v1.16b, v9.16b > + eor v2.16b, v2.16b, v10.16b > + eor v3.16b, v3.16b, v11.16b > + ld1 {v4.16b-v7.16b}, [x2], #64 > + eor v4.16b, v4.16b, v12.16b > + eor v5.16b, v5.16b, v13.16b > + eor v6.16b, v6.16b, v14.16b > + eor v7.16b, v7.16b, v15.16b > + > + crypt_blk8(v0, v1, v2, v3, v4, v5, v6, v7) > + > + eor v0.16b, v0.16b, v8.16b > + eor v1.16b, v1.16b, v9.16b > + eor v2.16b, v2.16b, v10.16b > + eor v3.16b, v3.16b, v11.16b > + st1 {v0.16b-v3.16b}, [x1], #64 > + eor v4.16b, v4.16b, v12.16b > + eor v5.16b, v5.16b, v13.16b > + eor v6.16b, v6.16b, v14.16b > + eor v7.16b, v7.16b, v15.16b > + st1 {v4.16b-v7.16b}, [x1], #64 > + > + tweak_next(v8, v15, RTMP3) > + > + cbz x4, .Lxts_end > + b .Lxts_loop_blk > + > +.Lxts_tail8: > + add x4, x4, #8 > + cmp x4, #4 > + blt .Lxts_tail4 > + > + sub x4, x4, #4 > + > + tweak_next( v9, v8, RTMP0) > + tweak_next(v10, v9, RTMP1) > + tweak_next(v11, v10, RTMP2) > + > + ld1 {v0.16b-v3.16b}, [x2], #64 > + eor v0.16b, v0.16b, v8.16b > + eor v1.16b, v1.16b, v9.16b > + eor v2.16b, v2.16b, v10.16b > + eor v3.16b, v3.16b, v11.16b > + > + crypt_blk4(v0, v1, v2, v3); > + > + eor v0.16b, v0.16b, v8.16b > + eor v1.16b, v1.16b, v9.16b > + eor v2.16b, v2.16b, v10.16b > + eor v3.16b, v3.16b, v11.16b > + st1 {v0.16b-v3.16b}, [x1], #64 > + > + tweak_next(v8, v11, RTMP3) > + > + cbz x4, .Lxts_end > + > +.Lxts_tail4: > + sub x4, x4, #1 > + > + ld1 {v0.16b}, [x2], #16 > + eor v0.16b, v0.16b, v8.16b > + > + SM4_CRYPT_BLK(v0) > + > + eor v0.16b, v0.16b, v8.16b > + st1 {v0.16b}, [x1], #16 > + > + tweak_next(v8, v8, RTMP0) > + > + cbnz x4, .Lxts_tail4 > + > +.Lxts_end: > + /* store new tweak */ > + st1 {v8.16b}, [x3] > + > + CLEAR_REG(v8) > + CLEAR_REG(v9) > + CLEAR_REG(v10) > + CLEAR_REG(v11) > + CLEAR_REG(v12) > + CLEAR_REG(v13) > + CLEAR_REG(v14) > + CLEAR_REG(v15) > + CLEAR_REG(RIV) > + > + VPOP_ABI > + ret_spec_stop > + CFI_ENDPROC() > +ELF(.size _gcry_sm4_armv8_ce_xts_crypt,.-_gcry_sm4_armv8_ce_xts_crypt;) > + > #endif > diff --git a/cipher/sm4.c b/cipher/sm4.c > index b5d4691ddbcb..4cac3b6c64b0 100644 > --- a/cipher/sm4.c > +++ b/cipher/sm4.c > @@ -1,6 +1,6 @@ > /* sm4.c - SM4 Cipher Algorithm > * Copyright (C) 2020 Alibaba Group. > - * Copyright (C) 2020 Tianjia Zhang > + * Copyright (C) 2020-2022 Tianjia Zhang > * Copyright (C) 2020-2022 Jussi Kivilinna > * > * This file is part of Libgcrypt. > @@ -539,6 +539,11 @@ extern void _gcry_sm4_armv8_ce_cfb_dec(const u32 *rk_enc, byte *out, > byte *iv, > size_t nblocks); > > +extern void _gcry_sm4_armv8_ce_xts_crypt(const u32 *rk, byte *out, > + const byte *in, > + byte *tweak, > + size_t nblocks); > + > extern void _gcry_sm4_armv8_ce_crypt_blk1_8(const u32 *rk, byte *out, > const byte *in, > size_t num_blocks); > @@ -1510,6 +1515,17 @@ _gcry_sm4_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, > const unsigned char *inbuf = inbuf_arg; > int burn_stack_depth = 0; > > +#ifdef USE_ARM_CE > + if (ctx->use_arm_ce) > + { > + /* Process all blocks at a time. */ > + _gcry_sm4_armv8_ce_xts_crypt(encrypt ? ctx->rkey_enc : ctx->rkey_dec, > + outbuf, inbuf, tweak, nblocks); > + > + nblocks = 0; > + } > +#endif > + > /* Process remaining blocks. */ > if (nblocks) > { From cllang at redhat.com Tue Aug 2 13:26:37 2022 From: cllang at redhat.com (Clemens Lang) Date: Tue, 2 Aug 2022 13:26:37 +0200 Subject: [PATCH] tests/basic: Add ifdefs for SM4 and CAMELLIA tests Message-ID: <20220802112637.18868-1-cllang@redhat.com> * tests/basic.c (check_gcm_siv_cipher): Do not run test vectors that are known to fail when compiled without support for SM4 or CAMELLIA. -- Fixes test execution when configured --enable-ciphers excluding sm4 or camellia. Signed-off-by: Clemens Lang --- tests/basic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/basic.c b/tests/basic.c index 0d03636b..26980e15 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -6160,6 +6160,7 @@ check_gcm_siv_cipher (void) "\xee\x12\x55\x82\x25\x25\x30\xb9\xa6\xf8\x3c\x81\x36\xcd\xef", "\xce\xc3\x13\x6c\x40\x2a\xcc\x51\xa1\xce\xb3\xed\xe8\xa6\x5b\x04", }, +#if USE_SM4 { GCRY_CIPHER_SM4, FLAG_NOFIPS, "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" @@ -6298,6 +6299,8 @@ check_gcm_siv_cipher (void) "\x64\x15\x17\x55\x60\x71\xb4\xaf\xcd\xc8\x90\x25\xc8\xc8\x62", "\xe2\x32\xda\x3a\x5a\x0e\x45\x1b\x8e\xf8\xbb\xe6\x60\x71\x81\xeb", }, +#endif /* USE_SM4 */ +#if USE_CAMELLIA { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" @@ -6564,6 +6567,7 @@ check_gcm_siv_cipher (void) "\xfb\x92\x1d\xd1\x31\x8d\x9d\xa1\xc3\x46\x69\xfa\x71\x2c\x42", "\xc6\x54\xf9\xf0\x22\x2c\xc3\xee\xdd\x13\x02\xb8\xe7\x5a\x2e\x7e" } +#endif /* USE_CAMELLIA */ }; gcry_cipher_hd_t hde, hdd; unsigned char out[MAX_DATA_LEN * 2]; -- 2.37.1 From jussi.kivilinna at iki.fi Tue Aug 2 18:05:12 2022 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 2 Aug 2022 19:05:12 +0300 Subject: [PATCH] tests/basic: Add ifdefs for SM4 and CAMELLIA tests In-Reply-To: <20220802112637.18868-1-cllang@redhat.com> References: <20220802112637.18868-1-cllang@redhat.com> Message-ID: <1812555c-903c-68f6-1163-a4a9d133aa7f@iki.fi> Hello, Patch applied to master, thanks. -Jussi On 2.8.2022 14.26, Clemens Lang via Gcrypt-devel wrote: > * tests/basic.c (check_gcm_siv_cipher): Do not run test vectors that > are known to fail when compiled without support for SM4 or CAMELLIA. > > -- > > Fixes test execution when configured --enable-ciphers excluding sm4 or > camellia. > > Signed-off-by: Clemens Lang > --- > tests/basic.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/tests/basic.c b/tests/basic.c > index 0d03636b..26980e15 100644 > --- a/tests/basic.c > +++ b/tests/basic.c > @@ -6160,6 +6160,7 @@ check_gcm_siv_cipher (void) > "\xee\x12\x55\x82\x25\x25\x30\xb9\xa6\xf8\x3c\x81\x36\xcd\xef", > "\xce\xc3\x13\x6c\x40\x2a\xcc\x51\xa1\xce\xb3\xed\xe8\xa6\x5b\x04", > }, > +#if USE_SM4 > { > GCRY_CIPHER_SM4, FLAG_NOFIPS, > "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" > @@ -6298,6 +6299,8 @@ check_gcm_siv_cipher (void) > "\x64\x15\x17\x55\x60\x71\xb4\xaf\xcd\xc8\x90\x25\xc8\xc8\x62", > "\xe2\x32\xda\x3a\x5a\x0e\x45\x1b\x8e\xf8\xbb\xe6\x60\x71\x81\xeb", > }, > +#endif /* USE_SM4 */ > +#if USE_CAMELLIA > { > GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, > "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" > @@ -6564,6 +6567,7 @@ check_gcm_siv_cipher (void) > "\xfb\x92\x1d\xd1\x31\x8d\x9d\xa1\xc3\x46\x69\xfa\x71\x2c\x42", > "\xc6\x54\xf9\xf0\x22\x2c\xc3\xee\xdd\x13\x02\xb8\xe7\x5a\x2e\x7e" > } > +#endif /* USE_CAMELLIA */ > }; > gcry_cipher_hd_t hde, hdd; > unsigned char out[MAX_DATA_LEN * 2]; From gmazyland at gmail.com Thu Aug 11 21:54:26 2022 From: gmazyland at gmail.com (Milan Broz) Date: Thu, 11 Aug 2022 21:54:26 +0200 Subject: [PATCH] kdf: Allow empty password for Argon2 Message-ID: <20220811195426.525805-1-gmazyland@gmail.com> * cipher/kdf.c (_gcry_kdf_open) allow empty password for Argon2. -- This patch fixes libcryptsetup requirement to support empty passwords for PBKDF (and passes Argon2 test vectors there now). Signed-off-by: Milan Broz --- cipher/kdf.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cipher/kdf.c b/cipher/kdf.c index d371bdd7..3e51e115 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -402,10 +402,13 @@ argon2_fill_first_blocks (argon2_ctx_t a) iov[iov_count].len = 4 * 7; iov[iov_count].off = 0; iov_count++; - iov[iov_count].data = (void *)a->password; - iov[iov_count].len = a->passwordlen; - iov[iov_count].off = 0; - iov_count++; + if (a->passwordlen) + { + iov[iov_count].data = (void *)a->password; + iov[iov_count].len = a->passwordlen; + iov[iov_count].off = 0; + iov_count++; + } buf_put_le32 (buf[7], a->saltlen); iov[iov_count].data = buf[7]; @@ -1861,7 +1864,7 @@ _gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo, switch (algo) { case GCRY_KDF_ARGON2: - if (!inputlen || !saltlen) + if (!saltlen) ec = GPG_ERR_INV_VALUE; else ec = argon2_open (hd, subalgo, param, paramlen, -- 2.36.1 From jussi.kivilinna at iki.fi Thu Aug 18 07:21:46 2022 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 18 Aug 2022 08:21:46 +0300 Subject: [PATCH] kdf: Allow empty password for Argon2 In-Reply-To: <20220811195426.525805-1-gmazyland@gmail.com> References: <20220811195426.525805-1-gmazyland@gmail.com> Message-ID: <88c65e46-d9e9-6cf2-34cb-44dc5a0a0d1f@iki.fi> Hello, On 11.8.2022 22.54, Milan Broz via Gcrypt-devel wrote: > * cipher/kdf.c (_gcry_kdf_open) allow empty password for Argon2. > -- > > This patch fixes libcryptsetup requirement to support empty > passwords for PBKDF (and passes Argon2 test vectors there now). Patch looks good to me. It would be nice if patch would also add same empty password test vector to gcrypt's "tests/t-kdf.c". -Jussi > > Signed-off-by: Milan Broz > --- > cipher/kdf.c | 13 ++++++++----- > 1 file changed, 8 insertions(+), 5 deletions(-) > > diff --git a/cipher/kdf.c b/cipher/kdf.c > index d371bdd7..3e51e115 100644 > --- a/cipher/kdf.c > +++ b/cipher/kdf.c > @@ -402,10 +402,13 @@ argon2_fill_first_blocks (argon2_ctx_t a) > iov[iov_count].len = 4 * 7; > iov[iov_count].off = 0; > iov_count++; > - iov[iov_count].data = (void *)a->password; > - iov[iov_count].len = a->passwordlen; > - iov[iov_count].off = 0; > - iov_count++; > + if (a->passwordlen) > + { > + iov[iov_count].data = (void *)a->password; > + iov[iov_count].len = a->passwordlen; > + iov[iov_count].off = 0; > + iov_count++; > + } > > buf_put_le32 (buf[7], a->saltlen); > iov[iov_count].data = buf[7]; > @@ -1861,7 +1864,7 @@ _gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo, > switch (algo) > { > case GCRY_KDF_ARGON2: > - if (!inputlen || !saltlen) > + if (!saltlen) > ec = GPG_ERR_INV_VALUE; > else > ec = argon2_open (hd, subalgo, param, paramlen, From gmazyland at gmail.com Thu Aug 18 16:18:41 2022 From: gmazyland at gmail.com (Milan Broz) Date: Thu, 18 Aug 2022 16:18:41 +0200 Subject: [PATCH 1/2] kdf: Restructure KDF test vectors In-Reply-To: <88c65e46-d9e9-6cf2-34cb-44dc5a0a0d1f@iki.fi> References: <88c65e46-d9e9-6cf2-34cb-44dc5a0a0d1f@iki.fi> Message-ID: <20220818141842.636445-1-gmazyland@gmail.com> * cipher/kdf.c Restructure KDF test vectors to allow easy addition new vectors. Also remove some ugly C code like goto again. -- Signed-off-by: Milan Broz --- tests/t-kdf.c | 766 +++++++++++++++++++++++--------------------------- 1 file changed, 351 insertions(+), 415 deletions(-) diff --git a/tests/t-kdf.c b/tests/t-kdf.c index d9d57778..17402762 100644 --- a/tests/t-kdf.c +++ b/tests/t-kdf.c @@ -1341,10 +1341,10 @@ static gcry_error_t my_kdf_derive (int parallel, int algo, int subalgo, const unsigned long *params, unsigned int paramslen, - const unsigned char *pass, size_t passlen, - const unsigned char *salt, size_t saltlen, - const unsigned char *key, size_t keylen, - const unsigned char *ad, size_t adlen, + const char *pass, size_t passlen, + const char *salt, size_t saltlen, + const char *key, size_t keylen, + const char *ad, size_t adlen, size_t outlen, unsigned char *out) { gcry_error_t err; @@ -1405,98 +1405,127 @@ my_kdf_derive (int parallel, return err; } - static void check_argon2 (void) { gcry_error_t err; - const unsigned long param[4] = { 32, 3, 32, 4 }; - const unsigned char pass[32] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }; - const unsigned char salt[16] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + static struct { + int subalgo; + unsigned long param[4]; + size_t passlen; + const char *pass; + size_t saltlen; + const char *salt; + size_t keylen; + const char *key; + size_t adlen; + const char *ad; + size_t dklen; + const char *dk; + } tv[] = { + { + GCRY_KDF_ARGON2D, + { 32, 3, 32, 4 }, + 32, + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", + 16, + "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02", + 8, + "\x03\x03\x03\x03\x03\x03\x03\x03", + 12, + "\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04", + 32, + "\x51\x2b\x39\x1b\x6f\x11\x62\x97\x53\x71\xd3\x09\x19\x73\x42\x94" + "\xf8\x68\xe3\xbe\x39\x84\xf3\xc1\xa1\x3a\x4d\xb9\xfa\xbe\x4a\xcb" + }, + { + GCRY_KDF_ARGON2I, + { 32, 3, 32, 4 }, + 32, + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", + 16, + "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02", + 8, + "\x03\x03\x03\x03\x03\x03\x03\x03", + 12, + "\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04", + 32, + "\xc8\x14\xd9\xd1\xdc\x7f\x37\xaa\x13\xf0\xd7\x7f\x24\x94\xbd\xa1" + "\xc8\xde\x6b\x01\x6d\xd3\x88\xd2\x99\x52\xa4\xc4\x67\x2b\x6c\xe8" + }, + { + GCRY_KDF_ARGON2ID, + { 32, 3, 32, 4 }, + 32, + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", + 16, + "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02", + 8, + "\x03\x03\x03\x03\x03\x03\x03\x03", + 12, + "\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04", + 32, + "\x0d\x64\x0d\xf5\x8d\x78\x76\x6c\x08\xc0\x37\xa3\x4a\x8b\x53\xc9" + "\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e\xb5\x25\x20\xe9\x6b\x01\xe6\x59" + }, }; - const unsigned char key[8] = { 3, 3, 3, 3, 3, 3, 3, 3 }; - const unsigned char ad[12] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; unsigned char out[32]; - unsigned char expected[3][32] = { - { /* GCRY_KDF_ARGON2D */ - 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, - 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, - 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, - 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb - }, - { /* GCRY_KDF_ARGON2I */ - 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa, - 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1, - 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2, - 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8 - }, - { /* GCRY_KDF_ARGON2ID */ - 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c, - 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9, - 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e, - 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59 - } - }; int i; - int subalgo = GCRY_KDF_ARGON2D; - int count = 0; - - again: + int count; - if (verbose) - fprintf (stderr, "checking ARGON2 test vector %d\n", count); - - err = my_kdf_derive (0, - GCRY_KDF_ARGON2, subalgo, param, 4, - pass, 32, salt, 16, key, 8, ad, 12, - 32, out); - if (err) - fail ("argon2 test %d failed: %s\n", count*2+0, gpg_strerror (err)); - else if (memcmp (out, expected[count], 32)) - { - fail ("argon2 test %d failed: mismatch\n", count*2+0); - fputs ("got:", stderr); - for (i=0; i < 32; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); - } + for (count = 0; count < DIM(tv); count++) + { + if (verbose) + fprintf (stderr, "checking ARGON2 test vector %d\n", count); + + err = my_kdf_derive (0, GCRY_KDF_ARGON2, + tv[count].subalgo, tv[count].param, 4, + tv[count].pass, tv[count].passlen, + tv[count].salt, tv[count].saltlen, + tv[count].key, tv[count].keylen, + tv[count].ad, tv[count].adlen, + tv[count].dklen, out); + if (err) + fail ("argon2 test %d failed: %s\n", count*2+0, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("argon2 test %d failed: mismatch\n", count*2+0); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } #ifdef HAVE_PTHREAD - err = my_kdf_derive (1, - GCRY_KDF_ARGON2, subalgo, param, 4, - pass, 32, salt, 16, key, 8, ad, 12, - 32, out); - if (err) - fail ("argon2 test %d failed: %s\n", count*2+1, gpg_strerror (err)); - else if (memcmp (out, expected[count], 32)) - { - fail ("argon2 test %d failed: mismatch\n", count*2+1); - fputs ("got:", stderr); - for (i=0; i < 32; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); - } + err = my_kdf_derive (1, GCRY_KDF_ARGON2, + tv[count].subalgo, tv[count].param, 4, + tv[count].pass, tv[count].passlen, + tv[count].salt, tv[count].saltlen, + tv[count].key, tv[count].keylen, + tv[count].ad, tv[count].adlen, + tv[count].dklen, out); + if (err) + fail ("argon2 test %d failed: %s\n", count*2+1, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("argon2 test %d failed: mismatch\n", count*2+1); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } #endif - - /* Next algo */ - if (subalgo == GCRY_KDF_ARGON2D) - subalgo = GCRY_KDF_ARGON2I; - else if (subalgo == GCRY_KDF_ARGON2I) - subalgo = GCRY_KDF_ARGON2ID; - - count++; - if (count < 3) - goto again; + } } static void check_balloon (void) { + gcry_error_t err; /* Two test vectors generated by the research prototype implementation. $ balloon abcdefghijklmno t_cost = 1 @@ -1519,91 +1548,84 @@ check_balloon (void) $8Yor74EqTwBrrdaeYeSVx0VXVAgDrsILAnJWdVUy93s= $FaNb9ofeWEggzhW9BUSODgZH5/awzNz5Adoub48+BgQ= */ - gcry_error_t err; - const unsigned long param[2][4] = { - { 1024, 1, 1 }, - { 4096, 12, 4 } - }; - const unsigned char *pass[2] = { - (const unsigned char *)"abcdefghijklmno", - (const unsigned char *)"Long_sentence_used_as_passphrase" - }; - const unsigned char salt[2][32] = { - { - 0x15, 0x1c, 0xea, 0x3a, 0x22, 0x2e, 0x3e, 0xfb, - 0xa8, 0xcb, 0x9e, 0x6f, 0x19, 0xf2, 0xb3, 0xca, - 0xc7, 0xbe, 0xd9, 0xfd, 0xbc, 0x17, 0xb9, 0xbd, - 0x88, 0x51, 0xc2, 0x72, 0xd9, 0xc4, 0x07, 0x08 - }, - { - 0xf1, 0x8a, 0x2b, 0xef, 0x81, 0x2a, 0x4f, 0x00, - 0x6b, 0xad, 0xd6, 0x9e, 0x61, 0xe4, 0x95, 0xc7, - 0x45, 0x57, 0x54, 0x08, 0x03, 0xae, 0xc2, 0x0b, - 0x02, 0x72, 0x56, 0x75, 0x55, 0x32, 0xf7, 0x7b - } - }; - const unsigned char expected[2][32] = { + static struct { + int subalgo; + unsigned long param[3]; + size_t passlen; + const char *pass; + size_t saltlen; + const char *salt; + size_t dklen; + const char *dk; + } tv[] = { { - 0x37, 0x13, 0x86, 0x34, 0xfc, 0x93, 0x3d, 0x9c, - 0xca, 0x88, 0x98, 0xe0, 0x8f, 0xb1, 0xfa, 0xa4, - 0x90, 0xcb, 0x22, 0x04, 0x74, 0xe4, 0x72, 0x3b, - 0x55, 0xac, 0x49, 0xa7, 0x11, 0x1a, 0xa3, 0x94 + GCRY_MD_SHA256, + { 1024, 1, 1 }, + 15, + "abcdefghijklmno", + 32, + "\x15\x1c\xea\x3a\x22\x2e\x3e\xfb\xa8\xcb\x9e\x6f\x19\xf2\xb3\xca" + "\xc7\xbe\xd9\xfd\xbc\x17\xb9\xbd\x88\x51\xc2\x72\xd9\xc4\x07\x08", + 32, + "\x37\x13\x86\x34\xfc\x93\x3d\x9c\xca\x88\x98\xe0\x8f\xb1\xfa\xa4" + "\x90\xcb\x22\x04\x74\xe4\x72\x3b\x55\xac\x49\xa7\x11\x1a\xa3\x94" }, { - 0x15, 0xa3, 0x5b, 0xf6, 0x87, 0xde, 0x58, 0x48, - 0x20, 0xce, 0x15, 0xbd, 0x05, 0x44, 0x8e, 0x0e, - 0x06, 0x47, 0xe7, 0xf6, 0xb0, 0xcc, 0xdc, 0xf9, - 0x01, 0xda, 0x2e, 0x6f, 0x8f, 0x3e, 0x06, 0x04 + GCRY_MD_SHA256, + { 4096, 12, 4 }, + 32, + "Long_sentence_used_as_passphrase", + 32, + "\xf1\x8a\x2b\xef\x81\x2a\x4f\x00\x6b\xad\xd6\x9e\x61\xe4\x95\xc7" + "\x45\x57\x54\x08\x03\xae\xc2\x0b\x02\x72\x56\x75\x55\x32\xf7\x7b", + 32, + "\x15\xa3\x5b\xf6\x87\xde\x58\x48\x20\xce\x15\xbd\x05\x44\x8e\x0e" + "\x06\x47\xe7\xf6\xb0\xcc\xdc\xf9\x01\xda\x2e\x6f\x8f\x3e\x06\x04" } }; unsigned char out[32]; int i; - int subalgo = GCRY_MD_SHA256; - int count = 0; - - again: + int count; - if (verbose) - fprintf (stderr, "checking Balloon test vector %d\n", count); + for (count = 0; count < DIM(tv); count++) + { + if (verbose) + fprintf (stderr, "checking Balloon test vector %d\n", count); - err = my_kdf_derive (0, - GCRY_KDF_BALLOON, subalgo, param[count], 3, - pass[count], strlen ((char *)pass[count]), - salt[count], 32, NULL, 0, NULL, 0, - 32, out); - if (err) - fail ("balloon test %d failed: %s\n", count*2+0, gpg_strerror (err)); - else if (memcmp (out, expected[count], 32)) - { - fail ("balloon test %d failed: mismatch\n", count*2+0); - fputs ("got:", stderr); - for (i=0; i < 32; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); - } + err = my_kdf_derive (0, GCRY_KDF_BALLOON, + tv[count].subalgo, tv[count].param, 3, + tv[count].pass, tv[count].passlen, + tv[count].salt, tv[count].saltlen, + NULL, 0, NULL, 0, tv[count].dklen, out); + if (err) + fail ("balloon test %d failed: %s\n", count*2+0, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("balloon test %d failed: mismatch\n", count*2+0); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } #ifdef HAVE_PTHREAD - err = my_kdf_derive (1, - GCRY_KDF_BALLOON, subalgo, param[count], 3, - pass[count], strlen ((char *)pass[count]), - salt[count], 32, NULL, 0, NULL, 0, - 32, out); - if (err) - fail ("balloon test %d failed: %s\n", count*2+1, gpg_strerror (err)); - else if (memcmp (out, expected[count], 32)) - { - fail ("balloon test %d failed: mismatch\n", count*2+1); - fputs ("got:", stderr); - for (i=0; i < 32; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); - } + err = my_kdf_derive (1, GCRY_KDF_BALLOON, + tv[count].subalgo, tv[count].param, 3, + tv[count].pass, tv[count].passlen, + tv[count].salt, tv[count].saltlen, + NULL, 0, NULL, 0, tv[count].dklen, out); + if (err) + fail ("balloon test %d failed: %s\n", count*2+1, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("balloon test %d failed: mismatch\n", count*2+1); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } #endif - - /* Next test vector */ - count++; - if (count < 2) - goto again; + } } @@ -1611,128 +1633,103 @@ static void check_onestep_kdf (void) { gcry_error_t err; - const unsigned long param[4] = { 38, 68, 44, 56 }; - unsigned char out[68]; - const unsigned char input[4][16] = { - { - 0x3f, 0x89, 0x2b, 0xd8, 0xb8, 0x4d, 0xae, 0x64, - 0xa7, 0x82, 0xa3, 0x5f, 0x6e, 0xaa, 0x8f, 0x00 - }, - { - 0xe6, 0x5b, 0x19, 0x05, 0x87, 0x8b, 0x95, 0xf6, - 0x8b, 0x55, 0x35, 0xbd, 0x3b, 0x2b, 0x10, 0x13 - }, - { - 0x02, 0xb4, 0x0d, 0x33, 0xe3, 0xf6, 0x85, 0xae, - 0xae, 0x67, 0x7a, 0xc3, 0x44, 0xee, 0xaf, 0x77 - }, - { - 0x8e, 0x5c, 0xd5, 0xf6, 0xae, 0x55, 0x8f, 0xfa, - 0x04, 0xcd, 0xa2, 0xfa, 0xd9, 0x4d, 0xd6, 0x16 - } - }; - const unsigned char other[4][12] = { - { - 0xec, 0x3f, 0x1c, 0xd8, 0x73, 0xd2, 0x88, 0x58, - 0xa5, 0x8c, 0xc3, 0x9e - }, + static struct { + int algo; + int subalgo; + unsigned long param[1]; + size_t inputlen; + const char *input; + size_t otherlen; + const char *other; + size_t keylen; + const char *key; + size_t dklen; + const char *dk; + } tv[] = { { - 0x83, 0x02, 0x21, 0xb1, 0x73, 0x0d, 0x91, 0x76, - 0xf8, 0x07, 0xd4, 0x07 + GCRY_KDF_ONESTEP_KDF, GCRY_MD_SHA256, + { 38 }, + 16, + "\x3f\x89\x2b\xd8\xb8\x4d\xae\x64\xa7\x82\xa3\x5f\x6e\xaa\x8f\x00", + 12, + "\xec\x3f\x1c\xd8\x73\xd2\x88\x58\xa5\x8c\xc3\x9e", + 0, NULL, + 38, + "\xa7\xc0\x66\x52\x98\x25\x25\x31\xe0\xdb\x37\x73\x7a\x37\x46\x51" + "\xb3\x68\x27\x5f\x20\x48\x28\x4d\x16\xa1\x66\xc6\xd8\xa9\x0a\x91" + "\xa4\x91\xc1\x6f\x49\x64" + }, + { + GCRY_KDF_ONESTEP_KDF, GCRY_MD_SHA512, + { 68 }, + 16, + "\xe6\x5b\x19\x05\x87\x8b\x95\xf6\x8b\x55\x35\xbd\x3b\x2b\x10\x13", + 12, + "\x83\x02\x21\xb1\x73\x0d\x91\x76\xf8\x07\xd4\x07", + 0, NULL, + 68, + "\xb8\xc4\x4b\xdf\x0b\x85\xa6\x4b\x6a\x51\xc1\x2a\x06\x71\x0e\x37" + "\x3d\x82\x9b\xb1\xfd\xa5\xb4\xe1\xa2\x07\x95\xc6\x19\x95\x94\xf6" + "\xfa\x65\x19\x8a\x72\x12\x57\xf7\xd5\x8c\xb2\xf6\xf6\xdb\x9b\xb5" + "\x69\x9f\x73\x86\x30\x45\x90\x90\x54\xb2\x38\x9e\x06\xec\x00\xfe" + "\x31\x8c\xab\xd9" + }, + { + GCRY_KDF_ONESTEP_KDF_MAC, GCRY_MAC_HMAC_SHA256, + { 44 }, + 16, + "\x02\xb4\x0d\x33\xe3\xf6\x85\xae\xae\x67\x7a\xc3\x44\xee\xaf\x77", + 12, + "\xc6\x7c\x38\x95\x80\x12\x8f\x18\xf6\xcf\x85\x92", + 16, + "\x0a\xd5\x2c\x93\x57\xc8\x5e\x47\x81\x29\x6a\x36\xca\x72\x03\x9c", + 44, + "\xbe\x32\xe7\xd3\x06\xd8\x91\x02\x8b\xe0\x88\xf2\x13\xf9\xf9\x47" + "\xc5\x04\x20\xd9\xb5\xa1\x2c\xa6\x98\x18\xdd\x99\x95\xde\xdd\x8e" + "\x61\x37\xc7\x10\x4d\x67\xf2\xca\x90\x91\x5d\xda" }, { - 0xc6, 0x7c, 0x38, 0x95, 0x80, 0x12, 0x8f, 0x18, - 0xf6, 0xcf, 0x85, 0x92 + GCRY_KDF_ONESTEP_KDF_MAC, GCRY_MAC_HMAC_SHA512, + { 56 }, + 16, + "\x8e\x5c\xd5\xf6\xae\x55\x8f\xfa\x04\xcd\xa2\xfa\xd9\x4d\xd6\x16", + 12, + "\x4a\x43\x30\x18\xe5\x1c\x09\xbb\xd6\x13\x26\xbb", + 16, + "\x6e\xd9\x3b\x6f\xe5\xb3\x50\x2b\xb4\x2b\x4c\x0f\xcb\x13\x36\x62", + 56, + "\x29\x5d\xfb\xeb\x54\xec\x0f\xe2\x4e\xce\x32\xf5\xb8\x7c\x85\x3e" + "\x69\x9a\x62\xe3\x9d\x9c\x9e\xe6\xee\x78\xf8\xb9\xa0\xee\x50\xa3" + "\x6a\x82\xe6\x06\x2c\x95\xed\x53\xbc\x36\x67\x00\xe2\xd0\xe0\x93" + "\xbf\x75\x2e\xea\x42\x99\x47\x2e" }, - { - 0x4a, 0x43, 0x30, 0x18, 0xe5, 0x1c, 0x09, 0xbb, - 0xd6, 0x13, 0x26, 0xbb - } - }; - const unsigned char key0[16] = { - 0x0a, 0xd5, 0x2c, 0x93, 0x57, 0xc8, 0x5e, 0x47, - 0x81, 0x29, 0x6a, 0x36, 0xca, 0x72, 0x03, 0x9c - }; - const unsigned char key1[16] = { - 0x6e, 0xd9, 0x3b, 0x6f, 0xe5, 0xb3, 0x50, 0x2b, - 0xb4, 0x2b, 0x4c, 0x0f, 0xcb, 0x13, 0x36, 0x62 - }; - const unsigned char *key[4] = { - NULL, NULL, key0, key1 - }; - const unsigned char expected[4][68] = { - { - 0xa7, 0xc0, 0x66, 0x52, 0x98, 0x25, 0x25, 0x31, - 0xe0, 0xdb, 0x37, 0x73, 0x7a, 0x37, 0x46, 0x51, - 0xb3, 0x68, 0x27, 0x5f, 0x20, 0x48, 0x28, 0x4d, - 0x16, 0xa1, 0x66, 0xc6, 0xd8, 0xa9, 0x0a, 0x91, - 0xa4, 0x91, 0xc1, 0x6f, 0x49, 0x64 - }, - { - 0xb8, 0xc4, 0x4b, 0xdf, 0x0b, 0x85, 0xa6, 0x4b, - 0x6a, 0x51, 0xc1, 0x2a, 0x06, 0x71, 0x0e, 0x37, - 0x3d, 0x82, 0x9b, 0xb1, 0xfd, 0xa5, 0xb4, 0xe1, - 0xa2, 0x07, 0x95, 0xc6, 0x19, 0x95, 0x94, 0xf6, - 0xfa, 0x65, 0x19, 0x8a, 0x72, 0x12, 0x57, 0xf7, - 0xd5, 0x8c, 0xb2, 0xf6, 0xf6, 0xdb, 0x9b, 0xb5, - 0x69, 0x9f, 0x73, 0x86, 0x30, 0x45, 0x90, 0x90, - 0x54, 0xb2, 0x38, 0x9e, 0x06, 0xec, 0x00, 0xfe, - 0x31, 0x8c, 0xab, 0xd9 - }, - { - 0xbe, 0x32, 0xe7, 0xd3, 0x06, 0xd8, 0x91, 0x02, - 0x8b, 0xe0, 0x88, 0xf2, 0x13, 0xf9, 0xf9, 0x47, - 0xc5, 0x04, 0x20, 0xd9, 0xb5, 0xa1, 0x2c, 0xa6, - 0x98, 0x18, 0xdd, 0x99, 0x95, 0xde, 0xdd, 0x8e, - 0x61, 0x37, 0xc7, 0x10, 0x4d, 0x67, 0xf2, 0xca, - 0x90, 0x91, 0x5d, 0xda - }, - { - 0x29, 0x5d, 0xfb, 0xeb, 0x54, 0xec, 0x0f, 0xe2, - 0x4e, 0xce, 0x32, 0xf5, 0xb8, 0x7c, 0x85, 0x3e, - 0x69, 0x9a, 0x62, 0xe3, 0x9d, 0x9c, 0x9e, 0xe6, - 0xee, 0x78, 0xf8, 0xb9, 0xa0, 0xee, 0x50, 0xa3, - 0x6a, 0x82, 0xe6, 0x06, 0x2c, 0x95, 0xed, 0x53, - 0xbc, 0x36, 0x67, 0x00, 0xe2, 0xd0, 0xe0, 0x93, - 0xbf, 0x75, 0x2e, 0xea, 0x42, 0x99, 0x47, 0x2e - } }; + unsigned char out[68]; int i; - int algo[4] = { - GCRY_MD_SHA256, GCRY_MD_SHA512, - GCRY_MAC_HMAC_SHA256, GCRY_MAC_HMAC_SHA512, - }; - int count = 0; - - again: + int count; - if (verbose) - fprintf (stderr, "checking OneStepKDF test vector %d\n", count); - - err = my_kdf_derive (0, - count < 2 ? GCRY_KDF_ONESTEP_KDF - : GCRY_KDF_ONESTEP_KDF_MAC, - algo[count], ¶m[count], 1, - input[count], 16, NULL, 0, - key[count], - key[count] == NULL? 0 : 16, - other[count], 12, - param[count], out); - if (err) - fail ("OneStepKDF test %d failed: %s\n", count, gpg_strerror (err)); - else if (memcmp (out, expected[count], param[count])) - { - fail ("OneStepKDF test %d failed: mismatch\n", count); - fputs ("got:", stderr); - for (i=0; i < param[count]; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); + for (count = 0; count < DIM(tv); count++) + { + if (verbose) + fprintf (stderr, "checking OneStepKDF test vector %d\n", count); + + err = my_kdf_derive (0, tv[count].algo, tv[count].subalgo, + tv[count].param, 1, + tv[count].input, tv[count].inputlen, NULL, 0, + tv[count].key, tv[count].keylen, + tv[count].other, tv[count].otherlen, + tv[count].dklen, out); + if (err) + fail ("OneStepKDF test %d failed: %s\n", count, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("OneStepKDF test %d failed: mismatch\n", count); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } } - - /* Next test vector */ - count++; - if (count < 4) - goto again; } @@ -1740,159 +1737,98 @@ static void check_hkdf (void) { gcry_error_t err; - unsigned long param[1]; - unsigned char out[82]; - const unsigned char input0[] = { - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b - }; - const unsigned char input1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f - }; - const unsigned char salt0[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c - }; - const unsigned char salt1[] = { - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf - }; - const unsigned char info0[] = { - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9 - }; - const unsigned char info1[] = { - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff - }; - const unsigned char expected0[] = { - 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, - 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, - 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, - 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, - 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, - 0x58, 0x65 - }; - const unsigned char expected1[] = { - 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, - 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, - 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, - 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, - 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, - 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, - 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, - 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, - 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, - 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, - 0x1d, 0x87 - }; - const unsigned char expected2[] = { - 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, - 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, - 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, - 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, - 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, - 0x96, 0xc8 + static struct { + unsigned long param[1]; + size_t inputlen; + const char *input; + size_t saltlen; + const char *salt; + size_t infolen; + const char *info; + size_t dklen; + const char *dk; + } tv[] = { + { + { 42 }, + 22, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b", + 13, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", + 10, + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", + 42, + "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36\x2f\x2a" + "\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56\xec\xc4\xc5\xbf" + "\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65" + }, + { + { 82 }, + 80, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", + 80, + "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + 80, + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + 82, + "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a\x49\x34" + "\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c\x19\xaf\xa9\x7c" + "\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb\x41\xc6\x5e\x59\x0e\x09" + "\xda\x32\x75\x60\x0c\x2f\x09\xb8\x36\x77\x93\xa9\xac\xa3\xdb\x71" + "\xcc\x30\xc5\x81\x79\xec\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f" + "\x1d\x87" + }, + { + { 42 }, + 22, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b", + 0, NULL, + 0, NULL, + 42, + "\x8d\xa4\xe7\x75\xa5\x63\xc1\x8f\x71\x5f\x80\x2a\x06\x3c\x5a\x31" + "\xb8\xa1\x1f\x5c\x5e\xe1\x87\x9e\xc3\x45\x4e\x5f\x3c\x73\x8d\x2d" + "\x9d\x20\x13\x95\xfa\xa4\xb6\x1a\x96\xc8" + }, }; - + unsigned char out[82]; int i; - int count = 0; - const unsigned char *input; - const unsigned char *salt; - const unsigned char *info; - const unsigned char *expected; - size_t inputlen; - size_t saltlen; - size_t infolen; - size_t expectedlen; - - again: - - if (verbose) - fprintf (stderr, "checking HKDF test vector %d\n", count); - - switch (count) - { - case 0: - input = input0; - inputlen = sizeof (input0); - salt = salt0; - saltlen = sizeof (salt0); - info = info0; - infolen = sizeof (info0); - expected = expected0; - expectedlen = sizeof (expected0); - break; - case 1: - input = input1; - inputlen = sizeof (input1); - salt = salt1; - saltlen = sizeof (salt1); - info = info1; - infolen = sizeof (info1); - expected = expected1; - expectedlen = sizeof (expected1); - break; - case 2: - input = input0; - inputlen = sizeof (input0); - salt = NULL; - saltlen = 0; - info = NULL; - infolen = 0; - expected = expected2; - expectedlen = sizeof (expected2); - break; - } + int count; - param[0] = expectedlen; - err = my_kdf_derive (0, GCRY_KDF_HKDF, GCRY_MAC_HMAC_SHA256, - param, 1, - input, inputlen, NULL, 0, - salt, saltlen, - info, infolen, - expectedlen, out); - if (err) - fail ("HKDF test %d failed: %s\n", count, gpg_strerror (err)); - else if (memcmp (out, expected, expectedlen)) - { - fail ("HKDF test %d failed: mismatch\n", count); - fputs ("got:", stderr); - for (i=0; i < expectedlen; i++) - fprintf (stderr, " %02x", out[i]); - putc ('\n', stderr); + for (count = 0; count < DIM(tv); count++) + { + if (verbose) + fprintf (stderr, "checking HKDF test vector %d\n", count); + + err = my_kdf_derive (0, GCRY_KDF_HKDF, GCRY_MAC_HMAC_SHA256, + tv[count].param, 1, + tv[count].input, tv[count].inputlen, NULL, 0, + tv[count].salt, tv[count].saltlen, + tv[count].info, tv[count].infolen, + tv[count].dklen, out); + if (err) + fail ("HKDF test %d failed: %s\n", count, gpg_strerror (err)); + else if (memcmp (out, tv[count].dk, tv[count].dklen)) + { + fail ("HKDF test %d failed: mismatch\n", count); + fputs ("got:", stderr); + for (i=0; i < tv[count].dklen; i++) + fprintf (stderr, " %02x", out[i]); + putc ('\n', stderr); + } } - - /* Next test vector */ - count++; - if (count < 3) - goto again; } static void -- 2.37.2 From gmazyland at gmail.com Thu Aug 18 16:18:42 2022 From: gmazyland at gmail.com (Milan Broz) Date: Thu, 18 Aug 2022 16:18:42 +0200 Subject: [PATCH 2/2] kdf: Allow empty password for Argon2 In-Reply-To: <20220818141842.636445-1-gmazyland@gmail.com> References: <88c65e46-d9e9-6cf2-34cb-44dc5a0a0d1f@iki.fi> <20220818141842.636445-1-gmazyland@gmail.com> Message-ID: <20220818141842.636445-2-gmazyland@gmail.com> * cipher/kdf.c (_gcry_kdf_open) allow empty password for Argon2. -- This patch fixes libcryptsetup requirement to support empty passwords for PBKDF (and passes Argon2 test vectors there now). Signed-off-by: Milan Broz --- cipher/kdf.c | 13 ++++++++----- tests/t-kdf.c | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/cipher/kdf.c b/cipher/kdf.c index d371bdd7..3e51e115 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -402,10 +402,13 @@ argon2_fill_first_blocks (argon2_ctx_t a) iov[iov_count].len = 4 * 7; iov[iov_count].off = 0; iov_count++; - iov[iov_count].data = (void *)a->password; - iov[iov_count].len = a->passwordlen; - iov[iov_count].off = 0; - iov_count++; + if (a->passwordlen) + { + iov[iov_count].data = (void *)a->password; + iov[iov_count].len = a->passwordlen; + iov[iov_count].off = 0; + iov_count++; + } buf_put_le32 (buf[7], a->saltlen); iov[iov_count].data = buf[7]; @@ -1861,7 +1864,7 @@ _gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo, switch (algo) { case GCRY_KDF_ARGON2: - if (!inputlen || !saltlen) + if (!saltlen) ec = GPG_ERR_INV_VALUE; else ec = argon2_open (hd, subalgo, param, paramlen, diff --git a/tests/t-kdf.c b/tests/t-kdf.c index 17402762..c0192d7b 100644 --- a/tests/t-kdf.c +++ b/tests/t-kdf.c @@ -1471,6 +1471,32 @@ check_argon2 (void) "\x0d\x64\x0d\xf5\x8d\x78\x76\x6c\x08\xc0\x37\xa3\x4a\x8b\x53\xc9" "\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e\xb5\x25\x20\xe9\x6b\x01\xe6\x59" }, + { + /* empty password */ + GCRY_KDF_ARGON2I, + { 32, 3, 128, 1 }, + 0, NULL, + 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + 0, NULL, + 0, NULL, + 32, + "\xbb\x1f\xf2\xb9\x9f\xd4\x4a\xd9\xdf\x7f\xb9\x54\x55\x9e\xb8\xeb" + "\xb5\x9d\xab\xce\x2e\x62\x9f\x9b\x89\x09\xfe\xde\x57\xcc\x63\x86" + }, + { + /* empty password */ + GCRY_KDF_ARGON2ID, + { 32, 3, 128, 1 }, + 0, NULL, + 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + 0, NULL, + 0, NULL, + 32, + "\x09\x2f\x38\x35\xac\xb2\x43\x92\x93\xeb\xcd\xe8\x04\x16\x6a\x31" + "\xce\x14\xd4\x55\xdb\xd8\xf7\xe6\xb4\xf5\x9d\x64\x8e\xd0\x3a\xdb" + }, }; unsigned char out[32]; int i; -- 2.37.2 From jussi.kivilinna at iki.fi Thu Aug 25 18:41:24 2022 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 25 Aug 2022 19:41:24 +0300 Subject: [PATCH] cipher: length checks for geniv Message-ID: <20220825164124.910169-1-jussi.kivilinna@iki.fi> * cipher/cipher.c (_gcry_cipher_setup_geniv, _gcry_cipher_geniv): Check input lengths for valid range; Avoid calling memcpy with zero length. -- Patch adds few length checks for setup_geniv and makes sure that memcpy is not called with zero length. Signed-off-by: Jussi Kivilinna --- cipher/cipher.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cipher/cipher.c b/cipher/cipher.c index e8743496..91379d13 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1271,12 +1271,22 @@ _gcry_cipher_setup_geniv (gcry_cipher_hd_t hd, int method, if (method != GCRY_CIPHER_GENIV_METHOD_CONCAT) return GPG_ERR_INV_ARG; + if (fixed_iv_len > sizeof(hd->aead.fixed)) + return GPG_ERR_INV_LENGTH; + + if (dyn_iv_len > sizeof(hd->aead.dynamic)) + return GPG_ERR_INV_LENGTH; + + if (dyn_iv_len == 0) /* Zero-length dynamic would mean fixed IV only. */ + return GPG_ERR_INV_LENGTH; + hd->aead.geniv_method = GCRY_CIPHER_GENIV_METHOD_CONCAT; hd->aead.fixed_iv_len = fixed_iv_len; hd->aead.dynamic_iv_len = dyn_iv_len; memset (hd->aead.fixed, 0, MAX_BLOCKSIZE); memset (hd->aead.dynamic, 0, MAX_BLOCKSIZE); - memcpy (hd->aead.fixed, fixed_iv, fixed_iv_len); + if (fixed_iv_len > 0) + memcpy (hd->aead.fixed, fixed_iv, fixed_iv_len); memcpy (hd->aead.dynamic, dyn_iv, dyn_iv_len); return rc; @@ -1295,7 +1305,11 @@ _gcry_cipher_geniv (gcry_cipher_hd_t hd, void *iv, size_t iv_len) if (iv_len != hd->aead.fixed_iv_len + hd->aead.dynamic_iv_len) return GPG_ERR_INV_ARG; - memcpy (iv, hd->aead.fixed, hd->aead.fixed_iv_len); + if (hd->aead.dynamic_iv_len == 0) + return GPG_ERR_INV_STATE; /* Dynamic not set through setup_geniv. */ + + if (hd->aead.fixed_iv_len > 0) + memcpy (iv, hd->aead.fixed, hd->aead.fixed_iv_len); memcpy ((byte *)iv+hd->aead.fixed_iv_len, hd->aead.dynamic, hd->aead.dynamic_iv_len); rc = hd->mode_ops.setiv (hd, iv, iv_len); -- 2.34.1