From hanno at hboeck.de Wed Apr 2 10:41:05 2014 From: hanno at hboeck.de (Hanno =?UTF-8?B?QsO2Y2s=?=) Date: Wed, 2 Apr 2014 10:41:05 +0200 Subject: Key import segfault in libgcrypt Message-ID: <20140402104105.634e2d26@hboeck.de> Hello, On my system if I try to import this key http://pgp.mit.edu/pks/lookup?op=get&search=0x98EEB6F7D87171CF with gnupg it segfaults. Backtrace (see below) indicates that the crash happens somewhere in libgcrypt, so I'm posting it here. My libgcrypt version is 1.6.1, gnupg is 2.0.22. I can reproduce it on another system with libgcrypt 1.5.3. Both are Gentoo. Can anyone else reproduce? Any more info needed? cu, Hanno B?ck Backtrace: 0x00007ffff731c130 in _gcry_mpi_get_flag () from /usr/lib64/libgcrypt.so.20 (gdb) bt #0 0x00007ffff731c130 in _gcry_mpi_get_flag () from /usr/lib64/libgcrypt.so.20 #1 0x00007ffff7286509 in do_vsexp_sscan () from /usr/lib64/libgcrypt.so.20 #2 0x00007ffff7287aac in _gcry_sexp_vbuild () from /usr/lib64/libgcrypt.so.20 #3 0x00007ffff7281382 in gcry_sexp_build () from /usr/lib64/libgcrypt.so.20 #4 0x0000000000432fba in pk_verify () #5 0x000000000042e1d8 in do_check () #6 0x000000000042efc2 in check_key_signature2 () #7 0x000000000042f1bb in check_key_signature () #8 0x000000000044b526 in import_one.isra () #9 0x000000000044d22d in import () #10 0x000000000044dd15 in import_keys_internal () #11 0x000000000044de7c in import_keys () #12 0x000000000040b77c in main () -- Hanno B?ck http://hboeck.de/ mail/jabber: hanno at hboeck.de GPG: BBB51E42 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: not available URL: From kristian.fiskerstrand at sumptuouscapital.com Thu Apr 3 17:52:43 2014 From: kristian.fiskerstrand at sumptuouscapital.com (Kristian Fiskerstrand) Date: Thu, 03 Apr 2014 17:52:43 +0200 Subject: Key import segfault in libgcrypt In-Reply-To: <20140402104105.634e2d26@hboeck.de> References: <20140402104105.634e2d26@hboeck.de> Message-ID: <533D83CB.4010808@sumptuouscapital.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 On 04/02/2014 10:41 AM, Hanno B?ck wrote: > Hello, > > On my system if I try to import this key > http://pgp.mit.edu/pks/lookup?op=get&search=0x98EEB6F7D87171CF > with gnupg it segfaults. > > Backtrace (see below) indicates that the crash happens somewhere in > libgcrypt, so I'm posting it here. > > My libgcrypt version is 1.6.1, gnupg is 2.0.22. > > I can reproduce it on another system with libgcrypt 1.5.3. Both are > Gentoo. > > Can anyone else reproduce? Any more info needed? I can reproduce this using $ gpg2 --version gpg (GnuPG) 2.0.22 libgcrypt 1.7.0-beta60 $ gpg2 --import segfault-key.asc gpg: signal Segmentation fault caught ... exiting Segmentation fault The error does not present in kristianf at kflaptop ~/Tmp $ gpg2.1 --version gpg (GnuPG) 2.1.0-beta308 libgcrypt 1.7.0-beta60 $ gpg2.1 --import segfault-key.asc gpg: key 0x98EEB6F7D87171CF: public key "<>" imported this is running a gentoo system on amd64 > > cu, Hanno B?ck > > Backtrace: 0x00007ffff731c130 in _gcry_mpi_get_flag () from > /usr/lib64/libgcrypt.so.20 (gdb) bt #0 0x00007ffff731c130 in > _gcry_mpi_get_flag () from /usr/lib64/libgcrypt.so.20 #1 > 0x00007ffff7286509 in do_vsexp_sscan () from > /usr/lib64/libgcrypt.so.20 #2 0x00007ffff7287aac in > _gcry_sexp_vbuild () from /usr/lib64/libgcrypt.so.20 #3 > 0x00007ffff7281382 in gcry_sexp_build () from > /usr/lib64/libgcrypt.so.20 #4 0x0000000000432fba in pk_verify () > #5 0x000000000042e1d8 in do_check () #6 0x000000000042efc2 in > check_key_signature2 () #7 0x000000000042f1bb in > check_key_signature () #8 0x000000000044b526 in import_one.isra > () #9 0x000000000044d22d in import () #10 0x000000000044dd15 in > import_keys_internal () #11 0x000000000044de7c in import_keys () > #12 0x000000000040b77c in main () > > > > > > _______________________________________________ Gcrypt-devel > mailing list Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > - -- - ---------------------------- Kristian Fiskerstrand Blog: http://blog.sumptuouscapital.com Twitter: @krifisk - ---------------------------- Public PGP key 0xE3EDFAE3 at hkp://pool.sks-keyservers.net fpr:94CB AFDD 3034 5109 5618 35AA 0B7F 8B60 E3ED FAE3 - ---------------------------- "There is no urge so great as for one man to edit another man's work." (Mark Twain) -----BEGIN PGP SIGNATURE----- iQIcBAEBCgAGBQJTPYPHAAoJEPw7F94F4TagMbcP/iFidE1jlgFRRflqVUn34oP4 ZlQJ2TaUiEF44CvxAMTn0OEmHy0OfHhTKpR9OiEbCJXh9qOQAyiMy96m6DmXoVba Y9o4iT3Tbh/toXpXQFTjPtAQMu3GX+6yRM1fjHcU5FzOMMba4CqSinXEidKXSrcn 6TyKq0xTHufChKHsuor9CchItntlCk+w2HhcUHP6Shwirulr1aFBjJYwCQS4obn9 V0lw0au4h6MgEWxSBXvZks4fMwFuSDTbFvfrr0iv0HPEcMpnk7yzmNLYPUmM7TKD nLHVEhEqaqrB75avD6UZOcF8c5DWDmr0IWGyDwhYGNOxMM5eMhjV4DdT3a+3G2/8 FYKWhEeimI8DlQPyV9zrf2Dvosdj6k4qHmMk8xIiKUhFJSIGr9zsA2gJ8QivFOg4 YD1yXKnSfX3b/e5DLoQR7qwaP2XH+7puJH5BNx1q0HYZ8TBbwUdyHmdAvlkeqCRw 6YxXs7w3sXeR+za4sYgMHPfahR8K4y9kwKBSalPr1O69PYEKOU7h/FWBSD2Ojw6n +bpOyGRVizhgYichejdAig9A2VmryPnUIGG+84nVk9y6VeBDPl9qpCglHLsPQudE EJd7dwDmtnnwwgPMmne0GTgvhztKnGbVNZ32svy4C/ilO6TbftSWxb8qBLFwyVkL FptD/GlLxdg2FWot6C8O =BPtn -----END PGP SIGNATURE----- From cvs at cvs.gnupg.org Fri Apr 4 17:07:19 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Fri, 04 Apr 2014 17:07:19 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-61-gb76b632 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via b76b632a453b8d100d024e2439b4358454dc286e (commit) from 50aeee51a0b1a09dd9fff2bb71749a816fe7a791 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b76b632a453b8d100d024e2439b4358454dc286e Author: Jussi Kivilinna Date: Sun Mar 30 18:11:09 2014 +0300 3des: add amd64 assembly implementation for 3DES * cipher/Makefile.am: Add 'des-amd64.S'. * cipher/cipher-selftests.c (_gcry_selftest_helper_cbc) (_gcry_selftest_helper_cfb, _gcry_selftest_helper_ctr): Handle failures from 'setkey' function. * cipher/cipher.c (_gcry_cipher_open_internal) [USE_DES]: Setup bulk functions for 3DES. * cipher/des-amd64.S: New file. * cipher/des.c (USE_AMD64_ASM, ATTR_ALIGNED_16): New macros. [USE_AMD64_ASM] (_gcry_3des_amd64_crypt_block) (_gcry_3des_amd64_ctr_enc), _gcry_3des_amd64_cbc_dec) (_gcry_3des_amd64_cfb_dec): New prototypes. [USE_AMD64_ASM] (tripledes_ecb_crypt): New function. (TRIPLEDES_ECB_BURN_STACK): New macro. (_gcry_3des_ctr_enc, _gcry_3des_cbc_dec, _gcry_3des_cfb_dec) (bulk_selftest_setkey, selftest_ctr, selftest_cbc, selftest_cfb): New functions. (selftest): Add call to CTR, CBC and CFB selftest functions. (do_tripledes_encrypt, do_tripledes_decrypt): Use TRIPLEDES_ECB_BURN_STACK. * configure.ac [host=x86-64]: Add 'des-amd64.lo'. * src/cipher.h (_gcry_3des_ctr_enc, _gcry_3des_cbc_dec) (_gcry_3des_cfb_dec): New prototypes. -- Add non-parallel functions for small speed-up and 3-way parallel functions for modes of operation that support parallel processing. Old vs new (Intel Core i5-4570): ================================ enc dec ECB 1.17x 1.17x CBC 1.17x 2.51x CFB 1.16x 2.49x OFB 1.17x 1.17x CTR 2.56x 2.56x Old vs new (Intel Core i5-2450M): ================================= enc dec ECB 1.28x 1.28x CBC 1.27x 2.33x CFB 1.27x 2.34x OFB 1.27x 1.27x CTR 2.36x 2.35x New (Intel Core i5-4570): ========================= 3DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 28.39 ns/B 33.60 MiB/s 90.84 c/B ECB dec | 28.27 ns/B 33.74 MiB/s 90.45 c/B CBC enc | 29.50 ns/B 32.33 MiB/s 94.40 c/B CBC dec | 13.35 ns/B 71.45 MiB/s 42.71 c/B CFB enc | 29.59 ns/B 32.23 MiB/s 94.68 c/B CFB dec | 13.41 ns/B 71.12 MiB/s 42.91 c/B OFB enc | 28.90 ns/B 33.00 MiB/s 92.47 c/B OFB dec | 28.90 ns/B 33.00 MiB/s 92.48 c/B CTR enc | 13.39 ns/B 71.20 MiB/s 42.86 c/B CTR dec | 13.39 ns/B 71.21 MiB/s 42.86 c/B Old (Intel Core i5-4570): ========================= 3DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 33.24 ns/B 28.69 MiB/s 106.4 c/B ECB dec | 33.26 ns/B 28.67 MiB/s 106.4 c/B CBC enc | 34.45 ns/B 27.69 MiB/s 110.2 c/B CBC dec | 33.45 ns/B 28.51 MiB/s 107.1 c/B CFB enc | 34.43 ns/B 27.70 MiB/s 110.2 c/B CFB dec | 33.41 ns/B 28.55 MiB/s 106.9 c/B OFB enc | 33.79 ns/B 28.22 MiB/s 108.1 c/B OFB dec | 33.79 ns/B 28.22 MiB/s 108.1 c/B CTR enc | 34.27 ns/B 27.83 MiB/s 109.7 c/B CTR dec | 34.27 ns/B 27.83 MiB/s 109.7 c/B New (Intel Core i5-2450M): ========================== 3DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 42.21 ns/B 22.59 MiB/s 105.5 c/B ECB dec | 42.23 ns/B 22.58 MiB/s 105.6 c/B CBC enc | 43.70 ns/B 21.82 MiB/s 109.2 c/B CBC dec | 23.25 ns/B 41.02 MiB/s 58.12 c/B CFB enc | 43.71 ns/B 21.82 MiB/s 109.3 c/B CFB dec | 23.23 ns/B 41.05 MiB/s 58.08 c/B OFB enc | 42.73 ns/B 22.32 MiB/s 106.8 c/B OFB dec | 42.73 ns/B 22.32 MiB/s 106.8 c/B CTR enc | 23.31 ns/B 40.92 MiB/s 58.27 c/B CTR dec | 23.35 ns/B 40.84 MiB/s 58.38 c/B Old (Intel Core i5-2450M): ========================== 3DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 53.98 ns/B 17.67 MiB/s 134.9 c/B ECB dec | 54.00 ns/B 17.66 MiB/s 135.0 c/B CBC enc | 55.43 ns/B 17.20 MiB/s 138.6 c/B CBC dec | 54.27 ns/B 17.57 MiB/s 135.7 c/B CFB enc | 55.42 ns/B 17.21 MiB/s 138.6 c/B CFB dec | 54.35 ns/B 17.55 MiB/s 135.9 c/B OFB enc | 54.49 ns/B 17.50 MiB/s 136.2 c/B OFB dec | 54.49 ns/B 17.50 MiB/s 136.2 c/B CTR enc | 55.02 ns/B 17.33 MiB/s 137.5 c/B CTR dec | 55.01 ns/B 17.34 MiB/s 137.5 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 462e6db..3c20d3c 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -60,7 +60,7 @@ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ crc.c \ -des.c \ +des.c des-amd64.S \ dsa.c \ elgamal.c \ ecc.c ecc-curves.c ecc-misc.c ecc-common.h \ diff --git a/cipher/cipher-selftest.c b/cipher/cipher-selftest.c index 5e95814..852368a 100644 --- a/cipher/cipher-selftest.c +++ b/cipher/cipher-selftest.c @@ -82,7 +82,11 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func, ciphertext = plaintext2 + nblocks * blocksize; /* Initialize ctx */ - setkey_func (ctx, key, sizeof(key)); + if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR) + { + xfree(mem); + return "setkey failed"; + } /* Test single block code path */ memset (iv, 0x4e, blocksize); @@ -199,7 +203,11 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func, ciphertext = plaintext2 + nblocks * blocksize; /* Initialize ctx */ - setkey_func (ctx, key, sizeof(key)); + if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR) + { + xfree(mem); + return "setkey failed"; + } /* Test single block code path */ memset(iv, 0xd3, blocksize); @@ -316,7 +324,11 @@ _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func, ciphertext2 = ciphertext + nblocks * blocksize; /* Initialize ctx */ - setkey_func (ctx, key, sizeof(key)); + if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR) + { + xfree(mem); + return "setkey failed"; + } /* Test single block code path */ memset (iv, 0xff, blocksize); diff --git a/cipher/cipher.c b/cipher/cipher.c index baa4720..6552ed3 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -513,6 +513,13 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, h->bulk.ctr_enc = _gcry_camellia_ctr_enc; break; #endif /*USE_CAMELLIA*/ +#ifdef USE_DES + case GCRY_CIPHER_3DES: + h->bulk.cbc_dec = _gcry_3des_cbc_dec; + h->bulk.cfb_dec = _gcry_3des_cfb_dec; + h->bulk.ctr_enc = _gcry_3des_ctr_enc; + break; +#endif /*USE_DES*/ #ifdef USE_SERPENT case GCRY_CIPHER_SERPENT128: case GCRY_CIPHER_SERPENT192: diff --git a/cipher/des-amd64.S b/cipher/des-amd64.S new file mode 100644 index 0000000..e8b2c56 --- /dev/null +++ b/cipher/des-amd64.S @@ -0,0 +1,1030 @@ +/* des-amd64.S - AMD64 assembly implementation of 3DES cipher + * + * Copyright (C) 2014 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef __x86_64 +#include +#if defined(USE_DES) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) + +#ifdef __PIC__ +# define RIP (%rip) +#else +# define RIP +#endif + +.text + +#define s1 0 +#define s2 ((s1) + (64*8)) +#define s3 ((s2) + (64*8)) +#define s4 ((s3) + (64*8)) +#define s5 ((s4) + (64*8)) +#define s6 ((s5) + (64*8)) +#define s7 ((s6) + (64*8)) +#define s8 ((s7) + (64*8)) + +/* register macros */ +#define CTX %rdi +#define SBOXES %rbp + +#define RL0 %r8 +#define RL1 %r9 +#define RL2 %r10 + +#define RL0d %r8d +#define RL1d %r9d +#define RL2d %r10d + +#define RR0 %r11 +#define RR1 %r12 +#define RR2 %r13 + +#define RR0d %r11d +#define RR1d %r12d +#define RR2d %r13d + +#define RW0 %rax +#define RW1 %rbx +#define RW2 %rcx + +#define RW0d %eax +#define RW1d %ebx +#define RW2d %ecx + +#define RW0bl %al +#define RW1bl %bl +#define RW2bl %cl + +#define RW0bh %ah +#define RW1bh %bh +#define RW2bh %ch + +#define RT0 %r15 +#define RT1 %rsi +#define RT2 %r14 +#define RT3 %rdx + +#define RT0d %r15d +#define RT1d %esi +#define RT2d %r14d +#define RT3d %edx + +/*********************************************************************** + * 1-way 3DES + ***********************************************************************/ +#define do_permutation(a, b, offset, mask) \ + movl a, RT0d; \ + shrl $(offset), RT0d; \ + xorl b, RT0d; \ + andl $(mask), RT0d; \ + xorl RT0d, b; \ + shll $(offset), RT0d; \ + xorl RT0d, a; + +#define expand_to_64bits(val, mask) \ + movl val##d, RT0d; \ + rorl $4, RT0d; \ + shlq $32, RT0; \ + orq RT0, val; \ + andq mask, val; + +#define compress_to_64bits(val) \ + movq val, RT0; \ + shrq $32, RT0; \ + roll $4, RT0d; \ + orl RT0d, val##d; + +#define initial_permutation(left, right) \ + do_permutation(left##d, right##d, 4, 0x0f0f0f0f); \ + do_permutation(left##d, right##d, 16, 0x0000ffff); \ + do_permutation(right##d, left##d, 2, 0x33333333); \ + do_permutation(right##d, left##d, 8, 0x00ff00ff); \ + movabs $0x3f3f3f3f3f3f3f3f, RT3; \ + movl left##d, RW0d; \ + roll $1, right##d; \ + xorl right##d, RW0d; \ + andl $0xaaaaaaaa, RW0d; \ + xorl RW0d, left##d; \ + xorl RW0d, right##d; \ + roll $1, left##d; \ + expand_to_64bits(right, RT3); \ + expand_to_64bits(left, RT3); + +#define final_permutation(left, right) \ + compress_to_64bits(right); \ + compress_to_64bits(left); \ + movl right##d, RW0d; \ + rorl $1, left##d; \ + xorl left##d, RW0d; \ + andl $0xaaaaaaaa, RW0d; \ + xorl RW0d, right##d; \ + xorl RW0d, left##d; \ + rorl $1, right##d; \ + do_permutation(right##d, left##d, 8, 0x00ff00ff); \ + do_permutation(right##d, left##d, 2, 0x33333333); \ + do_permutation(left##d, right##d, 16, 0x0000ffff); \ + do_permutation(left##d, right##d, 4, 0x0f0f0f0f); + +#define round1(n, from, to, load_next_key) \ + xorq from, RW0; \ + \ + movzbl RW0bl, RT0d; \ + movzbl RW0bh, RT1d; \ + shrq $16, RW0; \ + movzbl RW0bl, RT2d; \ + movzbl RW0bh, RT3d; \ + shrq $16, RW0; \ + movq s8(SBOXES, RT0, 8), RT0; \ + xorq s6(SBOXES, RT1, 8), to; \ + movzbl RW0bl, RL1d; \ + movzbl RW0bh, RT1d; \ + shrl $16, RW0d; \ + xorq s4(SBOXES, RT2, 8), RT0; \ + xorq s2(SBOXES, RT3, 8), to; \ + movzbl RW0bl, RT2d; \ + movzbl RW0bh, RT3d; \ + xorq s7(SBOXES, RL1, 8), RT0; \ + xorq s5(SBOXES, RT1, 8), to; \ + xorq s3(SBOXES, RT2, 8), RT0; \ + load_next_key(n, RW0); \ + xorq RT0, to; \ + xorq s1(SBOXES, RT3, 8), to; \ + +#define load_next_key(n, RWx) \ + movq (((n) + 1) * 8)(CTX), RWx; + +#define dummy2(a, b) /*_*/ + +#define read_block(io, left, right) \ + movl (io), left##d; \ + movl 4(io), right##d; \ + bswapl left##d; \ + bswapl right##d; + +#define write_block(io, left, right) \ + bswapl left##d; \ + bswapl right##d; \ + movl left##d, (io); \ + movl right##d, 4(io); + +.align 8 +.globl _gcry_3des_amd64_crypt_block +.type _gcry_3des_amd64_crypt_block, at function; + +_gcry_3des_amd64_crypt_block: + /* input: + * %rdi: round keys, CTX + * %rsi: dst + * %rdx: src + */ + pushq %rbp; + pushq %rbx; + pushq %r12; + pushq %r13; + pushq %r14; + pushq %r15; + pushq %rsi; /*dst*/ + + leaq .L_s1 RIP, SBOXES; + + read_block(%rdx, RL0, RR0); + initial_permutation(RL0, RR0); + + movq (CTX), RW0; + + round1(0, RR0, RL0, load_next_key); + round1(1, RL0, RR0, load_next_key); + round1(2, RR0, RL0, load_next_key); + round1(3, RL0, RR0, load_next_key); + round1(4, RR0, RL0, load_next_key); + round1(5, RL0, RR0, load_next_key); + round1(6, RR0, RL0, load_next_key); + round1(7, RL0, RR0, load_next_key); + round1(8, RR0, RL0, load_next_key); + round1(9, RL0, RR0, load_next_key); + round1(10, RR0, RL0, load_next_key); + round1(11, RL0, RR0, load_next_key); + round1(12, RR0, RL0, load_next_key); + round1(13, RL0, RR0, load_next_key); + round1(14, RR0, RL0, load_next_key); + round1(15, RL0, RR0, load_next_key); + + round1(16+0, RL0, RR0, load_next_key); + round1(16+1, RR0, RL0, load_next_key); + round1(16+2, RL0, RR0, load_next_key); + round1(16+3, RR0, RL0, load_next_key); + round1(16+4, RL0, RR0, load_next_key); + round1(16+5, RR0, RL0, load_next_key); + round1(16+6, RL0, RR0, load_next_key); + round1(16+7, RR0, RL0, load_next_key); + round1(16+8, RL0, RR0, load_next_key); + round1(16+9, RR0, RL0, load_next_key); + round1(16+10, RL0, RR0, load_next_key); + round1(16+11, RR0, RL0, load_next_key); + round1(16+12, RL0, RR0, load_next_key); + round1(16+13, RR0, RL0, load_next_key); + round1(16+14, RL0, RR0, load_next_key); + round1(16+15, RR0, RL0, load_next_key); + + round1(32+0, RR0, RL0, load_next_key); + round1(32+1, RL0, RR0, load_next_key); + round1(32+2, RR0, RL0, load_next_key); + round1(32+3, RL0, RR0, load_next_key); + round1(32+4, RR0, RL0, load_next_key); + round1(32+5, RL0, RR0, load_next_key); + round1(32+6, RR0, RL0, load_next_key); + round1(32+7, RL0, RR0, load_next_key); + round1(32+8, RR0, RL0, load_next_key); + round1(32+9, RL0, RR0, load_next_key); + round1(32+10, RR0, RL0, load_next_key); + round1(32+11, RL0, RR0, load_next_key); + round1(32+12, RR0, RL0, load_next_key); + round1(32+13, RL0, RR0, load_next_key); + round1(32+14, RR0, RL0, load_next_key); + round1(32+15, RL0, RR0, dummy2); + + popq RW2; /*dst*/ + final_permutation(RR0, RL0); + write_block(RW2, RR0, RL0); + + popq %r15; + popq %r14; + popq %r13; + popq %r12; + popq %rbx; + popq %rbp; + + ret; +.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block; + +/*********************************************************************** + * 3-way 3DES + ***********************************************************************/ +#define expand_to_64bits(val, mask) \ + movl val##d, RT0d; \ + rorl $4, RT0d; \ + shlq $32, RT0; \ + orq RT0, val; \ + andq mask, val; + +#define compress_to_64bits(val) \ + movq val, RT0; \ + shrq $32, RT0; \ + roll $4, RT0d; \ + orl RT0d, val##d; + +#define initial_permutation3(left, right) \ + do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \ + do_permutation(left##0d, right##0d, 16, 0x0000ffff); \ + do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \ + do_permutation(left##1d, right##1d, 16, 0x0000ffff); \ + do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f); \ + do_permutation(left##2d, right##2d, 16, 0x0000ffff); \ + \ + do_permutation(right##0d, left##0d, 2, 0x33333333); \ + do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \ + do_permutation(right##1d, left##1d, 2, 0x33333333); \ + do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \ + do_permutation(right##2d, left##2d, 2, 0x33333333); \ + do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \ + \ + movabs $0x3f3f3f3f3f3f3f3f, RT3; \ + \ + movl left##0d, RW0d; \ + roll $1, right##0d; \ + xorl right##0d, RW0d; \ + andl $0xaaaaaaaa, RW0d; \ + xorl RW0d, left##0d; \ + xorl RW0d, right##0d; \ + roll $1, left##0d; \ + expand_to_64bits(right##0, RT3); \ + expand_to_64bits(left##0, RT3); \ + movl left##1d, RW1d; \ + roll $1, right##1d; \ + xorl right##1d, RW1d; \ + andl $0xaaaaaaaa, RW1d; \ + xorl RW1d, left##1d; \ + xorl RW1d, right##1d; \ + roll $1, left##1d; \ + expand_to_64bits(right##1, RT3); \ + expand_to_64bits(left##1, RT3); \ + movl left##2d, RW2d; \ + roll $1, right##2d; \ + xorl right##2d, RW2d; \ + andl $0xaaaaaaaa, RW2d; \ + xorl RW2d, left##2d; \ + xorl RW2d, right##2d; \ + roll $1, left##2d; \ + expand_to_64bits(right##2, RT3); \ + expand_to_64bits(left##2, RT3); + +#define final_permutation3(left, right) \ + compress_to_64bits(right##0); \ + compress_to_64bits(left##0); \ + movl right##0d, RW0d; \ + rorl $1, left##0d; \ + xorl left##0d, RW0d; \ + andl $0xaaaaaaaa, RW0d; \ + xorl RW0d, right##0d; \ + xorl RW0d, left##0d; \ + rorl $1, right##0d; \ + compress_to_64bits(right##1); \ + compress_to_64bits(left##1); \ + movl right##1d, RW1d; \ + rorl $1, left##1d; \ + xorl left##1d, RW1d; \ + andl $0xaaaaaaaa, RW1d; \ + xorl RW1d, right##1d; \ + xorl RW1d, left##1d; \ + rorl $1, right##1d; \ + compress_to_64bits(right##2); \ + compress_to_64bits(left##2); \ + movl right##2d, RW2d; \ + rorl $1, left##2d; \ + xorl left##2d, RW2d; \ + andl $0xaaaaaaaa, RW2d; \ + xorl RW2d, right##2d; \ + xorl RW2d, left##2d; \ + rorl $1, right##2d; \ + \ + do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \ + do_permutation(right##0d, left##0d, 2, 0x33333333); \ + do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \ + do_permutation(right##1d, left##1d, 2, 0x33333333); \ + do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \ + do_permutation(right##2d, left##2d, 2, 0x33333333); \ + \ + do_permutation(left##0d, right##0d, 16, 0x0000ffff); \ + do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \ + do_permutation(left##1d, right##1d, 16, 0x0000ffff); \ + do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \ + do_permutation(left##2d, right##2d, 16, 0x0000ffff); \ + do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f); + +#define round3(n, from, to, load_next_key, do_movq) \ + xorq from##0, RW0; \ + movzbl RW0bl, RT3d; \ + movzbl RW0bh, RT1d; \ + shrq $16, RW0; \ + xorq s8(SBOXES, RT3, 8), to##0; \ + xorq s6(SBOXES, RT1, 8), to##0; \ + movzbl RW0bl, RT3d; \ + movzbl RW0bh, RT1d; \ + shrq $16, RW0; \ + xorq s4(SBOXES, RT3, 8), to##0; \ + xorq s2(SBOXES, RT1, 8), to##0; \ + movzbl RW0bl, RT3d; \ + movzbl RW0bh, RT1d; \ + shrl $16, RW0d; \ + xorq s7(SBOXES, RT3, 8), to##0; \ + xorq s5(SBOXES, RT1, 8), to##0; \ + movzbl RW0bl, RT3d; \ + movzbl RW0bh, RT1d; \ + load_next_key(n, RW0); \ + xorq s3(SBOXES, RT3, 8), to##0; \ + xorq s1(SBOXES, RT1, 8), to##0; \ + xorq from##1, RW1; \ + movzbl RW1bl, RT3d; \ + movzbl RW1bh, RT1d; \ + shrq $16, RW1; \ + xorq s8(SBOXES, RT3, 8), to##1; \ + xorq s6(SBOXES, RT1, 8), to##1; \ + movzbl RW1bl, RT3d; \ + movzbl RW1bh, RT1d; \ + shrq $16, RW1; \ + xorq s4(SBOXES, RT3, 8), to##1; \ + xorq s2(SBOXES, RT1, 8), to##1; \ + movzbl RW1bl, RT3d; \ + movzbl RW1bh, RT1d; \ + shrl $16, RW1d; \ + xorq s7(SBOXES, RT3, 8), to##1; \ + xorq s5(SBOXES, RT1, 8), to##1; \ + movzbl RW1bl, RT3d; \ + movzbl RW1bh, RT1d; \ + do_movq(RW0, RW1); \ + xorq s3(SBOXES, RT3, 8), to##1; \ + xorq s1(SBOXES, RT1, 8), to##1; \ + xorq from##2, RW2; \ + movzbl RW2bl, RT3d; \ + movzbl RW2bh, RT1d; \ + shrq $16, RW2; \ + xorq s8(SBOXES, RT3, 8), to##2; \ + xorq s6(SBOXES, RT1, 8), to##2; \ + movzbl RW2bl, RT3d; \ + movzbl RW2bh, RT1d; \ + shrq $16, RW2; \ + xorq s4(SBOXES, RT3, 8), to##2; \ + xorq s2(SBOXES, RT1, 8), to##2; \ + movzbl RW2bl, RT3d; \ + movzbl RW2bh, RT1d; \ + shrl $16, RW2d; \ + xorq s7(SBOXES, RT3, 8), to##2; \ + xorq s5(SBOXES, RT1, 8), to##2; \ + movzbl RW2bl, RT3d; \ + movzbl RW2bh, RT1d; \ + do_movq(RW0, RW2); \ + xorq s3(SBOXES, RT3, 8), to##2; \ + xorq s1(SBOXES, RT1, 8), to##2; + +#define __movq(src, dst) \ + movq src, dst; + +#define read_block(io, left, right) \ + movl (io), left##d; \ + movl 4(io), right##d; \ + bswapl left##d; \ + bswapl right##d; + +#define write_block(io, left, right) \ + bswapl left##d; \ + bswapl right##d; \ + movl left##d, (io); \ + movl right##d, 4(io); + +.align 8 +.type _gcry_3des_amd64_crypt_blk3, at function; +_gcry_3des_amd64_crypt_blk3: + /* input: + * %rdi: round keys, CTX + * RL0d, RR0d, RL1d, RR1d, RL2d, RR2d: 3 input blocks + * RR0d, RL0d, RR1d, RL1d, RR2d, RL2d: 3 output blocks + */ + + leaq .L_s1 RIP, SBOXES; + + initial_permutation3(RL, RR); + + movq 0(CTX), RW0; + movq RW0, RW1; + movq RW0, RW2; + + round3(0, RR, RL, load_next_key, __movq); + round3(1, RL, RR, load_next_key, __movq); + round3(2, RR, RL, load_next_key, __movq); + round3(3, RL, RR, load_next_key, __movq); + round3(4, RR, RL, load_next_key, __movq); + round3(5, RL, RR, load_next_key, __movq); + round3(6, RR, RL, load_next_key, __movq); + round3(7, RL, RR, load_next_key, __movq); + round3(8, RR, RL, load_next_key, __movq); + round3(9, RL, RR, load_next_key, __movq); + round3(10, RR, RL, load_next_key, __movq); + round3(11, RL, RR, load_next_key, __movq); + round3(12, RR, RL, load_next_key, __movq); + round3(13, RL, RR, load_next_key, __movq); + round3(14, RR, RL, load_next_key, __movq); + round3(15, RL, RR, load_next_key, __movq); + + round3(16+0, RL, RR, load_next_key, __movq); + round3(16+1, RR, RL, load_next_key, __movq); + round3(16+2, RL, RR, load_next_key, __movq); + round3(16+3, RR, RL, load_next_key, __movq); + round3(16+4, RL, RR, load_next_key, __movq); + round3(16+5, RR, RL, load_next_key, __movq); + round3(16+6, RL, RR, load_next_key, __movq); + round3(16+7, RR, RL, load_next_key, __movq); + round3(16+8, RL, RR, load_next_key, __movq); + round3(16+9, RR, RL, load_next_key, __movq); + round3(16+10, RL, RR, load_next_key, __movq); + round3(16+11, RR, RL, load_next_key, __movq); + round3(16+12, RL, RR, load_next_key, __movq); + round3(16+13, RR, RL, load_next_key, __movq); + round3(16+14, RL, RR, load_next_key, __movq); + round3(16+15, RR, RL, load_next_key, __movq); + + round3(32+0, RR, RL, load_next_key, __movq); + round3(32+1, RL, RR, load_next_key, __movq); + round3(32+2, RR, RL, load_next_key, __movq); + round3(32+3, RL, RR, load_next_key, __movq); + round3(32+4, RR, RL, load_next_key, __movq); + round3(32+5, RL, RR, load_next_key, __movq); + round3(32+6, RR, RL, load_next_key, __movq); + round3(32+7, RL, RR, load_next_key, __movq); + round3(32+8, RR, RL, load_next_key, __movq); + round3(32+9, RL, RR, load_next_key, __movq); + round3(32+10, RR, RL, load_next_key, __movq); + round3(32+11, RL, RR, load_next_key, __movq); + round3(32+12, RR, RL, load_next_key, __movq); + round3(32+13, RL, RR, load_next_key, __movq); + round3(32+14, RR, RL, load_next_key, __movq); + round3(32+15, RL, RR, dummy2, dummy2); + + final_permutation3(RR, RL); + + ret; +.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3; + +.align 8 +.globl _gcry_3des_amd64_cbc_dec +.type _gcry_3des_amd64_cbc_dec, at function; +_gcry_3des_amd64_cbc_dec: + /* input: + * %rdi: ctx, CTX + * %rsi: dst (3 blocks) + * %rdx: src (3 blocks) + * %rcx: iv (64bit) + */ + + pushq %rbp; + pushq %rbx; + pushq %r12; + pushq %r13; + pushq %r14; + pushq %r15; + + pushq %rsi; /*dst*/ + pushq %rdx; /*src*/ + pushq %rcx; /*iv*/ + + /* load input */ + movl 0 * 4(%rdx), RL0d; + movl 1 * 4(%rdx), RR0d; + movl 2 * 4(%rdx), RL1d; + movl 3 * 4(%rdx), RR1d; + movl 4 * 4(%rdx), RL2d; + movl 5 * 4(%rdx), RR2d; + + bswapl RL0d; + bswapl RR0d; + bswapl RL1d; + bswapl RR1d; + bswapl RL2d; + bswapl RR2d; + + call _gcry_3des_amd64_crypt_blk3; + + popq %rcx; /*iv*/ + popq %rdx; /*src*/ + popq %rsi; /*dst*/ + + bswapl RR0d; + bswapl RL0d; + bswapl RR1d; + bswapl RL1d; + bswapl RR2d; + bswapl RL2d; + + movq 2 * 8(%rdx), RT0; + xorl 0 * 4(%rcx), RR0d; + xorl 1 * 4(%rcx), RL0d; + xorl 0 * 4(%rdx), RR1d; + xorl 1 * 4(%rdx), RL1d; + xorl 2 * 4(%rdx), RR2d; + xorl 3 * 4(%rdx), RL2d; + movq RT0, (%rcx); /* store new IV */ + + movl RR0d, 0 * 4(%rsi); + movl RL0d, 1 * 4(%rsi); + movl RR1d, 2 * 4(%rsi); + movl RL1d, 3 * 4(%rsi); + movl RR2d, 4 * 4(%rsi); + movl RL2d, 5 * 4(%rsi); + + popq %r15; + popq %r14; + popq %r13; + popq %r12; + popq %rbx; + popq %rbp; + + ret; +.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec; + +.align 8 +.globl _gcry_3des_amd64_ctr_enc +.type _gcry_3des_amd64_ctr_enc, at function; +_gcry_3des_amd64_ctr_enc: + /* input: + * %rdi: ctx, CTX + * %rsi: dst (3 blocks) + * %rdx: src (3 blocks) + * %rcx: iv (64bit) + */ + + pushq %rbp; + pushq %rbx; + pushq %r12; + pushq %r13; + pushq %r14; + pushq %r15; + + pushq %rsi; /*dst*/ + pushq %rdx; /*src*/ + movq %rcx, RW2; + + /* load IV and byteswap */ + movq (RW2), RT0; + bswapq RT0; + movq RT0, RR0; + + /* construct IVs */ + leaq 1(RT0), RR1; + leaq 2(RT0), RR2; + leaq 3(RT0), RT0; + movq RR0, RL0; + movq RR1, RL1; + movq RR2, RL2; + bswapq RT0; + shrq $32, RL0; + shrq $32, RL1; + shrq $32, RL2; + + /* store new IV */ + movq RT0, (RW2); + + call _gcry_3des_amd64_crypt_blk3; + + popq %rdx; /*src*/ + popq %rsi; /*dst*/ + + bswapl RR0d; + bswapl RL0d; + bswapl RR1d; + bswapl RL1d; + bswapl RR2d; + bswapl RL2d; + + xorl 0 * 4(%rdx), RR0d; + xorl 1 * 4(%rdx), RL0d; + xorl 2 * 4(%rdx), RR1d; + xorl 3 * 4(%rdx), RL1d; + xorl 4 * 4(%rdx), RR2d; + xorl 5 * 4(%rdx), RL2d; + + movl RR0d, 0 * 4(%rsi); + movl RL0d, 1 * 4(%rsi); + movl RR1d, 2 * 4(%rsi); + movl RL1d, 3 * 4(%rsi); + movl RR2d, 4 * 4(%rsi); + movl RL2d, 5 * 4(%rsi); + + popq %r15; + popq %r14; + popq %r13; + popq %r12; + popq %rbx; + popq %rbp; + + ret; +.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec; + +.align 8 +.globl _gcry_3des_amd64_cfb_dec +.type _gcry_3des_amd64_cfb_dec, at function; +_gcry_3des_amd64_cfb_dec: + /* input: + * %rdi: ctx, CTX + * %rsi: dst (3 blocks) + * %rdx: src (3 blocks) + * %rcx: iv (64bit) + */ + pushq %rbp; + pushq %rbx; + pushq %r12; + pushq %r13; + pushq %r14; + pushq %r15; + + pushq %rsi; /*dst*/ + pushq %rdx; /*src*/ + movq %rcx, RW2; + + /* Load input */ + movl 0 * 4(RW2), RL0d; + movl 1 * 4(RW2), RR0d; + movl 0 * 4(%rdx), RL1d; + movl 1 * 4(%rdx), RR1d; + movl 2 * 4(%rdx), RL2d; + movl 3 * 4(%rdx), RR2d; + + bswapl RL0d; + bswapl RR0d; + bswapl RL1d; + bswapl RR1d; + bswapl RL2d; + bswapl RR2d; + + /* Update IV */ + movq 4 * 4(%rdx), RW0; + movq RW0, (RW2); + + call _gcry_3des_amd64_crypt_blk3; + + popq %rdx; /*src*/ + popq %rsi; /*dst*/ + + bswapl RR0d; + bswapl RL0d; + bswapl RR1d; + bswapl RL1d; + bswapl RR2d; + bswapl RL2d; + + xorl 0 * 4(%rdx), RR0d; + xorl 1 * 4(%rdx), RL0d; + xorl 2 * 4(%rdx), RR1d; + xorl 3 * 4(%rdx), RL1d; + xorl 4 * 4(%rdx), RR2d; + xorl 5 * 4(%rdx), RL2d; + + movl RR0d, 0 * 4(%rsi); + movl RL0d, 1 * 4(%rsi); + movl RR1d, 2 * 4(%rsi); + movl RL1d, 3 * 4(%rsi); + movl RR2d, 4 * 4(%rsi); + movl RL2d, 5 * 4(%rsi); + + popq %r15; + popq %r14; + popq %r13; + popq %r12; + popq %rbx; + popq %rbp; + ret; +.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec; + +.data +.align 16 +.L_s1: + .quad 0x0010100001010400, 0x0000000000000000 + .quad 0x0000100000010000, 0x0010100001010404 + .quad 0x0010100001010004, 0x0000100000010404 + .quad 0x0000000000000004, 0x0000100000010000 + .quad 0x0000000000000400, 0x0010100001010400 + .quad 0x0010100001010404, 0x0000000000000400 + .quad 0x0010000001000404, 0x0010100001010004 + .quad 0x0010000001000000, 0x0000000000000004 + .quad 0x0000000000000404, 0x0010000001000400 + .quad 0x0010000001000400, 0x0000100000010400 + .quad 0x0000100000010400, 0x0010100001010000 + .quad 0x0010100001010000, 0x0010000001000404 + .quad 0x0000100000010004, 0x0010000001000004 + .quad 0x0010000001000004, 0x0000100000010004 + .quad 0x0000000000000000, 0x0000000000000404 + .quad 0x0000100000010404, 0x0010000001000000 + .quad 0x0000100000010000, 0x0010100001010404 + .quad 0x0000000000000004, 0x0010100001010000 + .quad 0x0010100001010400, 0x0010000001000000 + .quad 0x0010000001000000, 0x0000000000000400 + .quad 0x0010100001010004, 0x0000100000010000 + .quad 0x0000100000010400, 0x0010000001000004 + .quad 0x0000000000000400, 0x0000000000000004 + .quad 0x0010000001000404, 0x0000100000010404 + .quad 0x0010100001010404, 0x0000100000010004 + .quad 0x0010100001010000, 0x0010000001000404 + .quad 0x0010000001000004, 0x0000000000000404 + .quad 0x0000100000010404, 0x0010100001010400 + .quad 0x0000000000000404, 0x0010000001000400 + .quad 0x0010000001000400, 0x0000000000000000 + .quad 0x0000100000010004, 0x0000100000010400 + .quad 0x0000000000000000, 0x0010100001010004 +.L_s2: + .quad 0x0801080200100020, 0x0800080000000000 + .quad 0x0000080000000000, 0x0001080200100020 + .quad 0x0001000000100000, 0x0000000200000020 + .quad 0x0801000200100020, 0x0800080200000020 + .quad 0x0800000200000020, 0x0801080200100020 + .quad 0x0801080000100000, 0x0800000000000000 + .quad 0x0800080000000000, 0x0001000000100000 + .quad 0x0000000200000020, 0x0801000200100020 + .quad 0x0001080000100000, 0x0001000200100020 + .quad 0x0800080200000020, 0x0000000000000000 + .quad 0x0800000000000000, 0x0000080000000000 + .quad 0x0001080200100020, 0x0801000000100000 + .quad 0x0001000200100020, 0x0800000200000020 + .quad 0x0000000000000000, 0x0001080000100000 + .quad 0x0000080200000020, 0x0801080000100000 + .quad 0x0801000000100000, 0x0000080200000020 + .quad 0x0000000000000000, 0x0001080200100020 + .quad 0x0801000200100020, 0x0001000000100000 + .quad 0x0800080200000020, 0x0801000000100000 + .quad 0x0801080000100000, 0x0000080000000000 + .quad 0x0801000000100000, 0x0800080000000000 + .quad 0x0000000200000020, 0x0801080200100020 + .quad 0x0001080200100020, 0x0000000200000020 + .quad 0x0000080000000000, 0x0800000000000000 + .quad 0x0000080200000020, 0x0801080000100000 + .quad 0x0001000000100000, 0x0800000200000020 + .quad 0x0001000200100020, 0x0800080200000020 + .quad 0x0800000200000020, 0x0001000200100020 + .quad 0x0001080000100000, 0x0000000000000000 + .quad 0x0800080000000000, 0x0000080200000020 + .quad 0x0800000000000000, 0x0801000200100020 + .quad 0x0801080200100020, 0x0001080000100000 +.L_s3: + .quad 0x0000002000000208, 0x0000202008020200 + .quad 0x0000000000000000, 0x0000200008020008 + .quad 0x0000002008000200, 0x0000000000000000 + .quad 0x0000202000020208, 0x0000002008000200 + .quad 0x0000200000020008, 0x0000000008000008 + .quad 0x0000000008000008, 0x0000200000020000 + .quad 0x0000202008020208, 0x0000200000020008 + .quad 0x0000200008020000, 0x0000002000000208 + .quad 0x0000000008000000, 0x0000000000000008 + .quad 0x0000202008020200, 0x0000002000000200 + .quad 0x0000202000020200, 0x0000200008020000 + .quad 0x0000200008020008, 0x0000202000020208 + .quad 0x0000002008000208, 0x0000202000020200 + .quad 0x0000200000020000, 0x0000002008000208 + .quad 0x0000000000000008, 0x0000202008020208 + .quad 0x0000002000000200, 0x0000000008000000 + .quad 0x0000202008020200, 0x0000000008000000 + .quad 0x0000200000020008, 0x0000002000000208 + .quad 0x0000200000020000, 0x0000202008020200 + .quad 0x0000002008000200, 0x0000000000000000 + .quad 0x0000002000000200, 0x0000200000020008 + .quad 0x0000202008020208, 0x0000002008000200 + .quad 0x0000000008000008, 0x0000002000000200 + .quad 0x0000000000000000, 0x0000200008020008 + .quad 0x0000002008000208, 0x0000200000020000 + .quad 0x0000000008000000, 0x0000202008020208 + .quad 0x0000000000000008, 0x0000202000020208 + .quad 0x0000202000020200, 0x0000000008000008 + .quad 0x0000200008020000, 0x0000002008000208 + .quad 0x0000002000000208, 0x0000200008020000 + .quad 0x0000202000020208, 0x0000000000000008 + .quad 0x0000200008020008, 0x0000202000020200 +.L_s4: + .quad 0x1008020000002001, 0x1000020800002001 + .quad 0x1000020800002001, 0x0000000800000000 + .quad 0x0008020800002000, 0x1008000800000001 + .quad 0x1008000000000001, 0x1000020000002001 + .quad 0x0000000000000000, 0x0008020000002000 + .quad 0x0008020000002000, 0x1008020800002001 + .quad 0x1000000800000001, 0x0000000000000000 + .quad 0x0008000800000000, 0x1008000000000001 + .quad 0x1000000000000001, 0x0000020000002000 + .quad 0x0008000000000000, 0x1008020000002001 + .quad 0x0000000800000000, 0x0008000000000000 + .quad 0x1000020000002001, 0x0000020800002000 + .quad 0x1008000800000001, 0x1000000000000001 + .quad 0x0000020800002000, 0x0008000800000000 + .quad 0x0000020000002000, 0x0008020800002000 + .quad 0x1008020800002001, 0x1000000800000001 + .quad 0x0008000800000000, 0x1008000000000001 + .quad 0x0008020000002000, 0x1008020800002001 + .quad 0x1000000800000001, 0x0000000000000000 + .quad 0x0000000000000000, 0x0008020000002000 + .quad 0x0000020800002000, 0x0008000800000000 + .quad 0x1008000800000001, 0x1000000000000001 + .quad 0x1008020000002001, 0x1000020800002001 + .quad 0x1000020800002001, 0x0000000800000000 + .quad 0x1008020800002001, 0x1000000800000001 + .quad 0x1000000000000001, 0x0000020000002000 + .quad 0x1008000000000001, 0x1000020000002001 + .quad 0x0008020800002000, 0x1008000800000001 + .quad 0x1000020000002001, 0x0000020800002000 + .quad 0x0008000000000000, 0x1008020000002001 + .quad 0x0000000800000000, 0x0008000000000000 + .quad 0x0000020000002000, 0x0008020800002000 +.L_s5: + .quad 0x0000001000000100, 0x0020001002080100 + .quad 0x0020000002080000, 0x0420001002000100 + .quad 0x0000000000080000, 0x0000001000000100 + .quad 0x0400000000000000, 0x0020000002080000 + .quad 0x0400001000080100, 0x0000000000080000 + .quad 0x0020001002000100, 0x0400001000080100 + .quad 0x0420001002000100, 0x0420000002080000 + .quad 0x0000001000080100, 0x0400000000000000 + .quad 0x0020000002000000, 0x0400000000080000 + .quad 0x0400000000080000, 0x0000000000000000 + .quad 0x0400001000000100, 0x0420001002080100 + .quad 0x0420001002080100, 0x0020001002000100 + .quad 0x0420000002080000, 0x0400001000000100 + .quad 0x0000000000000000, 0x0420000002000000 + .quad 0x0020001002080100, 0x0020000002000000 + .quad 0x0420000002000000, 0x0000001000080100 + .quad 0x0000000000080000, 0x0420001002000100 + .quad 0x0000001000000100, 0x0020000002000000 + .quad 0x0400000000000000, 0x0020000002080000 + .quad 0x0420001002000100, 0x0400001000080100 + .quad 0x0020001002000100, 0x0400000000000000 + .quad 0x0420000002080000, 0x0020001002080100 + .quad 0x0400001000080100, 0x0000001000000100 + .quad 0x0020000002000000, 0x0420000002080000 + .quad 0x0420001002080100, 0x0000001000080100 + .quad 0x0420000002000000, 0x0420001002080100 + .quad 0x0020000002080000, 0x0000000000000000 + .quad 0x0400000000080000, 0x0420000002000000 + .quad 0x0000001000080100, 0x0020001002000100 + .quad 0x0400001000000100, 0x0000000000080000 + .quad 0x0000000000000000, 0x0400000000080000 + .quad 0x0020001002080100, 0x0400001000000100 +.L_s6: + .quad 0x0200000120000010, 0x0204000020000000 + .quad 0x0000040000000000, 0x0204040120000010 + .quad 0x0204000020000000, 0x0000000100000010 + .quad 0x0204040120000010, 0x0004000000000000 + .quad 0x0200040020000000, 0x0004040100000010 + .quad 0x0004000000000000, 0x0200000120000010 + .quad 0x0004000100000010, 0x0200040020000000 + .quad 0x0200000020000000, 0x0000040100000010 + .quad 0x0000000000000000, 0x0004000100000010 + .quad 0x0200040120000010, 0x0000040000000000 + .quad 0x0004040000000000, 0x0200040120000010 + .quad 0x0000000100000010, 0x0204000120000010 + .quad 0x0204000120000010, 0x0000000000000000 + .quad 0x0004040100000010, 0x0204040020000000 + .quad 0x0000040100000010, 0x0004040000000000 + .quad 0x0204040020000000, 0x0200000020000000 + .quad 0x0200040020000000, 0x0000000100000010 + .quad 0x0204000120000010, 0x0004040000000000 + .quad 0x0204040120000010, 0x0004000000000000 + .quad 0x0000040100000010, 0x0200000120000010 + .quad 0x0004000000000000, 0x0200040020000000 + .quad 0x0200000020000000, 0x0000040100000010 + .quad 0x0200000120000010, 0x0204040120000010 + .quad 0x0004040000000000, 0x0204000020000000 + .quad 0x0004040100000010, 0x0204040020000000 + .quad 0x0000000000000000, 0x0204000120000010 + .quad 0x0000000100000010, 0x0000040000000000 + .quad 0x0204000020000000, 0x0004040100000010 + .quad 0x0000040000000000, 0x0004000100000010 + .quad 0x0200040120000010, 0x0000000000000000 + .quad 0x0204040020000000, 0x0200000020000000 + .quad 0x0004000100000010, 0x0200040120000010 +.L_s7: + .quad 0x0002000000200000, 0x2002000004200002 + .quad 0x2000000004000802, 0x0000000000000000 + .quad 0x0000000000000800, 0x2000000004000802 + .quad 0x2002000000200802, 0x0002000004200800 + .quad 0x2002000004200802, 0x0002000000200000 + .quad 0x0000000000000000, 0x2000000004000002 + .quad 0x2000000000000002, 0x0000000004000000 + .quad 0x2002000004200002, 0x2000000000000802 + .quad 0x0000000004000800, 0x2002000000200802 + .quad 0x2002000000200002, 0x0000000004000800 + .quad 0x2000000004000002, 0x0002000004200000 + .quad 0x0002000004200800, 0x2002000000200002 + .quad 0x0002000004200000, 0x0000000000000800 + .quad 0x2000000000000802, 0x2002000004200802 + .quad 0x0002000000200800, 0x2000000000000002 + .quad 0x0000000004000000, 0x0002000000200800 + .quad 0x0000000004000000, 0x0002000000200800 + .quad 0x0002000000200000, 0x2000000004000802 + .quad 0x2000000004000802, 0x2002000004200002 + .quad 0x2002000004200002, 0x2000000000000002 + .quad 0x2002000000200002, 0x0000000004000000 + .quad 0x0000000004000800, 0x0002000000200000 + .quad 0x0002000004200800, 0x2000000000000802 + .quad 0x2002000000200802, 0x0002000004200800 + .quad 0x2000000000000802, 0x2000000004000002 + .quad 0x2002000004200802, 0x0002000004200000 + .quad 0x0002000000200800, 0x0000000000000000 + .quad 0x2000000000000002, 0x2002000004200802 + .quad 0x0000000000000000, 0x2002000000200802 + .quad 0x0002000004200000, 0x0000000000000800 + .quad 0x2000000004000002, 0x0000000004000800 + .quad 0x0000000000000800, 0x2002000000200002 +.L_s8: + .quad 0x0100010410001000, 0x0000010000001000 + .quad 0x0000000000040000, 0x0100010410041000 + .quad 0x0100000010000000, 0x0100010410001000 + .quad 0x0000000400000000, 0x0100000010000000 + .quad 0x0000000400040000, 0x0100000010040000 + .quad 0x0100010410041000, 0x0000010000041000 + .quad 0x0100010010041000, 0x0000010400041000 + .quad 0x0000010000001000, 0x0000000400000000 + .quad 0x0100000010040000, 0x0100000410000000 + .quad 0x0100010010001000, 0x0000010400001000 + .quad 0x0000010000041000, 0x0000000400040000 + .quad 0x0100000410040000, 0x0100010010041000 + .quad 0x0000010400001000, 0x0000000000000000 + .quad 0x0000000000000000, 0x0100000410040000 + .quad 0x0100000410000000, 0x0100010010001000 + .quad 0x0000010400041000, 0x0000000000040000 + .quad 0x0000010400041000, 0x0000000000040000 + .quad 0x0100010010041000, 0x0000010000001000 + .quad 0x0000000400000000, 0x0100000410040000 + .quad 0x0000010000001000, 0x0000010400041000 + .quad 0x0100010010001000, 0x0000000400000000 + .quad 0x0100000410000000, 0x0100000010040000 + .quad 0x0100000410040000, 0x0100000010000000 + .quad 0x0000000000040000, 0x0100010410001000 + .quad 0x0000000000000000, 0x0100010410041000 + .quad 0x0000000400040000, 0x0100000410000000 + .quad 0x0100000010040000, 0x0100010010001000 + .quad 0x0100010410001000, 0x0000000000000000 + .quad 0x0100010410041000, 0x0000010000041000 + .quad 0x0000010000041000, 0x0000010400001000 + .quad 0x0000010400001000, 0x0000000400040000 + .quad 0x0100000010000000, 0x0100010010041000 + +#endif +#endif diff --git a/cipher/des.c b/cipher/des.c index 6611fd3..bc2a474 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -119,9 +119,27 @@ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-selftest.h" + + +#define DES_BLOCKSIZE 8 + + +/* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ +#undef USE_AMD64_ASM +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) +# define USE_AMD64_ASM 1 +#endif + +/* Helper macro to force alignment to 16 bytes. */ +#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED +# define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) +#else +# define ATTR_ALIGNED_16 +#endif #if defined(__GNUC__) && defined(__GNU_LIBRARY__) -#define working_memcmp memcmp +# define working_memcmp memcmp #else /* * According to the SunOS man page, memcmp returns indeterminate sign @@ -171,6 +189,12 @@ static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int); static int is_weak_key ( const byte *key ); static const char *selftest (void); +static unsigned int do_tripledes_encrypt(void *context, byte *outbuf, + const byte *inbuf ); +static unsigned int do_tripledes_decrypt(void *context, byte *outbuf, + const byte *inbuf ); +static gcry_err_code_t do_tripledes_setkey(void *context, const byte *key, + unsigned keylen); static int initialized; @@ -727,6 +751,46 @@ tripledes_set3keys (struct _tripledes_ctx *ctx, +#ifdef USE_AMD64_ASM + +/* Assembly implementation of triple-DES. */ +extern void _gcry_3des_amd64_crypt_block(const void *keys, byte *out, + const byte *in); + +/* These assembly implementations process three blocks in parallel. */ +extern void _gcry_3des_amd64_ctr_enc(const void *keys, byte *out, + const byte *in, byte *ctr); + +extern void _gcry_3des_amd64_cbc_dec(const void *keys, byte *out, + const byte *in, byte *iv); + +extern void _gcry_3des_amd64_cfb_dec(const void *keys, byte *out, + const byte *in, byte *iv); + +#define TRIPLEDES_ECB_BURN_STACK (8 * sizeof(void *)) + +/* + * Electronic Codebook Mode Triple-DES encryption/decryption of data + * according to 'mode'. Sometimes this mode is named 'EDE' mode + * (Encryption-Decryption-Encryption). + */ +static inline int +tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, + byte * to, int mode) +{ + u32 *keys; + + keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; + + _gcry_3des_amd64_crypt_block(keys, to, from); + + return 0; +} + +#else /*USE_AMD64_ASM*/ + +#define TRIPLEDES_ECB_BURN_STACK 32 + /* * Electronic Codebook Mode Triple-DES encryption/decryption of data * according to 'mode'. Sometimes this mode is named 'EDE' mode @@ -777,8 +841,158 @@ tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, return 0; } +#endif /*!USE_AMD64_ASM*/ + + + +/* Bulk encryption of complete blocks in CTR mode. This function is only + intended for the bulk encryption feature of cipher.c. CTR is expected to be + of size DES_BLOCKSIZE. */ +void +_gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, + const void *inbuf_arg, size_t nblocks) +{ + struct _tripledes_ctx *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char tmpbuf[DES_BLOCKSIZE]; + int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; + int i; + +#ifdef USE_AMD64_ASM + { + int asm_burn_depth = 9 * sizeof(void *); + + if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) + burn_stack_depth = asm_burn_depth; + + /* Process data in 3 block chunks. */ + while (nblocks >= 3) + { + _gcry_3des_amd64_ctr_enc(ctx->encrypt_subkeys, outbuf, inbuf, ctr); + + nblocks -= 3; + outbuf += 3 * DES_BLOCKSIZE; + inbuf += 3 * DES_BLOCKSIZE; + } + + /* Use generic code to handle smaller chunks... */ + } +#endif + + for ( ;nblocks; nblocks-- ) + { + /* Encrypt the counter. */ + tripledes_ecb_encrypt (ctx, ctr, tmpbuf); + /* XOR the input with the encrypted counter and store in output. */ + buf_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); + outbuf += DES_BLOCKSIZE; + inbuf += DES_BLOCKSIZE; + /* Increment the counter. */ + for (i = DES_BLOCKSIZE; i > 0; i--) + { + ctr[i-1]++; + if (ctr[i-1]) + break; + } + } + + wipememory(tmpbuf, sizeof(tmpbuf)); + _gcry_burn_stack(burn_stack_depth); +} + + +/* Bulk decryption of complete blocks in CBC mode. This function is only + intended for the bulk encryption feature of cipher.c. */ +void +_gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, + const void *inbuf_arg, size_t nblocks) +{ + struct _tripledes_ctx *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char savebuf[DES_BLOCKSIZE]; + int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; + +#ifdef USE_AMD64_ASM + { + int asm_burn_depth = 10 * sizeof(void *); + + if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) + burn_stack_depth = asm_burn_depth; + + /* Process data in 3 block chunks. */ + while (nblocks >= 3) + { + _gcry_3des_amd64_cbc_dec(ctx->decrypt_subkeys, outbuf, inbuf, iv); + + nblocks -= 3; + outbuf += 3 * DES_BLOCKSIZE; + inbuf += 3 * DES_BLOCKSIZE; + } + + /* Use generic code to handle smaller chunks... */ + } +#endif + + for ( ;nblocks; nblocks-- ) + { + /* INBUF is needed later and it may be identical to OUTBUF, so store + the intermediate result to SAVEBUF. */ + tripledes_ecb_decrypt (ctx, inbuf, savebuf); + + buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); + inbuf += DES_BLOCKSIZE; + outbuf += DES_BLOCKSIZE; + } + + wipememory(savebuf, sizeof(savebuf)); + _gcry_burn_stack(burn_stack_depth); +} + + +/* Bulk decryption of complete blocks in CFB mode. This function is only + intended for the bulk encryption feature of cipher.c. */ +void +_gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, + const void *inbuf_arg, size_t nblocks) +{ + struct _tripledes_ctx *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; + +#ifdef USE_AMD64_ASM + { + int asm_burn_depth = 9 * sizeof(void *); + + if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) + burn_stack_depth = asm_burn_depth; + /* Process data in 3 block chunks. */ + while (nblocks >= 3) + { + _gcry_3des_amd64_cfb_dec(ctx->encrypt_subkeys, outbuf, inbuf, iv); + nblocks -= 3; + outbuf += 3 * DES_BLOCKSIZE; + inbuf += 3 * DES_BLOCKSIZE; + } + + /* Use generic code to handle smaller chunks... */ + } +#endif + + for ( ;nblocks; nblocks-- ) + { + tripledes_ecb_encrypt (ctx, iv, iv); + buf_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); + outbuf += DES_BLOCKSIZE; + inbuf += DES_BLOCKSIZE; + } + + _gcry_burn_stack(burn_stack_depth); +} /* @@ -815,6 +1029,67 @@ is_weak_key ( const byte *key ) } +/* Alternative setkey for selftests; need larger key than default. */ +static gcry_err_code_t +bulk_selftest_setkey (void *context, const byte *__key, unsigned __keylen) +{ + static const unsigned char key[24] ATTR_ALIGNED_16 = { + 0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, + 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22, + 0x18,0x2A,0x39,0x47,0x5E,0x6F,0x75,0x82 + }; + + (void)__key; + (void)__keylen; + + return do_tripledes_setkey(context, key, sizeof(key)); +} + + +/* Run the self-tests for DES-CTR, tests IV increment of bulk CTR + encryption. Returns NULL on success. */ +static const char * +selftest_ctr (void) +{ + const int nblocks = 3+1; + const int blocksize = DES_BLOCKSIZE; + const int context_size = sizeof(struct _tripledes_ctx); + + return _gcry_selftest_helper_ctr("3DES", &bulk_selftest_setkey, + &do_tripledes_encrypt, &_gcry_3des_ctr_enc, nblocks, blocksize, + context_size); +} + + +/* Run the self-tests for DES-CBC, tests bulk CBC decryption. + Returns NULL on success. */ +static const char * +selftest_cbc (void) +{ + const int nblocks = 3+2; + const int blocksize = DES_BLOCKSIZE; + const int context_size = sizeof(struct _tripledes_ctx); + + return _gcry_selftest_helper_cbc("3DES", &bulk_selftest_setkey, + &do_tripledes_encrypt, &_gcry_3des_cbc_dec, nblocks, blocksize, + context_size); +} + + +/* Run the self-tests for DES-CFB, tests bulk CBC decryption. + Returns NULL on success. */ +static const char * +selftest_cfb (void) +{ + const int nblocks = 3+2; + const int blocksize = DES_BLOCKSIZE; + const int context_size = sizeof(struct _tripledes_ctx); + + return _gcry_selftest_helper_cfb("3DES", &bulk_selftest_setkey, + &do_tripledes_encrypt, &_gcry_3des_cfb_dec, nblocks, blocksize, + context_size); +} + /* * Performs a selftest of this DES/Triple-DES implementation. @@ -824,6 +1099,8 @@ is_weak_key ( const byte *key ) static const char * selftest (void) { + const char *r; + /* * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation * need this. @@ -1003,6 +1280,15 @@ selftest (void) return "DES weak key detection failed"; } + if ( (r = selftest_cbc ()) ) + return r; + + if ( (r = selftest_cfb ()) ) + return r; + + if ( (r = selftest_ctr ()) ) + return r; + return 0; } @@ -1060,7 +1346,7 @@ do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); - return /*burn_stack*/ (32); + return /*burn_stack*/ TRIPLEDES_ECB_BURN_STACK; } static unsigned int @@ -1068,7 +1354,7 @@ do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); - return /*burn_stack*/ (32); + return /*burn_stack*/ TRIPLEDES_ECB_BURN_STACK; } static gcry_err_code_t diff --git a/configure.ac b/configure.ac index a0f75a5..79f79ef 100644 --- a/configure.ac +++ b/configure.ac @@ -1671,6 +1671,13 @@ LIST_MEMBER(des, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS des.lo" AC_DEFINE(USE_DES, 1, [Defined if this module should be included]) + + case "${host}" in + x86_64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS des-amd64.lo" + ;; + esac fi LIST_MEMBER(aes, $enabled_ciphers) diff --git a/src/cipher.h b/src/cipher.h index cd981b3..5d1b5f6 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -173,6 +173,19 @@ void _gcry_camellia_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); +/*-- des.c --*/ +void _gcry_3des_ctr_enc (void *context, unsigned char *ctr, + void *outbuf_arg, const void *inbuf_arg, + size_t nblocks); + +void _gcry_3des_cbc_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + size_t nblocks); + +void _gcry_3des_cfb_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + size_t nblocks); + /*-- serpent.c --*/ void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 2 +- cipher/cipher-selftest.c | 18 +- cipher/cipher.c | 7 + cipher/des-amd64.S | 1030 ++++++++++++++++++++++++++++++++++++++++++++++ cipher/des.c | 292 ++++++++++++- configure.ac | 7 + src/cipher.h | 13 + 7 files changed, 1362 insertions(+), 7 deletions(-) create mode 100644 cipher/des-amd64.S hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From dkg at fifthhorseman.net Mon Apr 7 06:26:49 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 07 Apr 2014 00:26:49 -0400 Subject: Key import segfault in libgcrypt In-Reply-To: <20140402104105.634e2d26@hboeck.de> References: <20140402104105.634e2d26@hboeck.de> Message-ID: <53422909.7020701@fifthhorseman.net> On 04/02/2014 04:41 AM, Hanno B?ck wrote: > On my system if I try to import this key > http://pgp.mit.edu/pks/lookup?op=get&search=0x98EEB6F7D87171CF > with gnupg it segfaults. > > Backtrace (see below) indicates that the crash happens somewhere in > libgcrypt, so I'm posting it here. > > My libgcrypt version is 1.6.1, gnupg is 2.0.22. I can reproduce with packages from debian, gnupg2 v2.0.22-3 and libgcrypt11 v1.5.3. backtrace: Program received signal SIGSEGV, Segmentation fault. _gcry_mpi_get_flag (a=a at entry=0x0, flag=flag at entry=GCRYMPI_FLAG_OPAQUE) at mpiutil.c:455 455 mpiutil.c: No such file or directory. (gdb) bt #0 _gcry_mpi_get_flag (a=a at entry=0x0, flag=flag at entry=GCRYMPI_FLAG_OPAQUE) at mpiutil.c:455 #1 0x00007ffff72e1448 in vsexp_sscan (retsexp=retsexp at entry=0x7fffffffddb8, erroff=0x7fffffffdbd0, erroff at entry=0x0, buffer=buffer at entry=0x5555555e602a "(public-key(rsa(n%m)(e%m)))", length=, argflag=argflag at entry=1, arg_list=arg_list at entry=0x0, arg_ptr=arg_ptr at entry=0x7fffffffdcb8) at sexp.c:1273 #2 0x00007ffff72e289c in _gcry_sexp_vbuild (retsexp=0x7fffffffddb8, erroff=0x0, format=0x5555555e602a "(public-key(rsa(n%m)(e%m)))", arg_ptr=arg_ptr at entry=0x7fffffffdcb8) at sexp.c:1620 #3 0x00007ffff72dd212 in gcry_sexp_build (retsexp=, erroff=, format=) at visibility.c:115 #4 0x000055555558f0bf in ?? () --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From gniibe at fsij.org Wed Apr 9 08:54:42 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 09 Apr 2014 15:54:42 +0900 Subject: Key import segfault in libgcrypt In-Reply-To: <53422909.7020701@fifthhorseman.net> References: <20140402104105.634e2d26@hboeck.de> <53422909.7020701@fifthhorseman.net> Message-ID: <1397026482.1551.4.camel@cfw2.gniibe.org> On 2014-04-07 at 00:26 -0400, Daniel Kahn Gillmor wrote: > On 04/02/2014 04:41 AM, Hanno B?ck wrote: > > > On my system if I try to import this key > > http://pgp.mit.edu/pks/lookup?op=get&search=0x98EEB6F7D87171CF > > with gnupg it segfaults. > > > > Backtrace (see below) indicates that the crash happens somewhere in > > libgcrypt, so I'm posting it here. > > > > My libgcrypt version is 1.6.1, gnupg is 2.0.22. > > I can reproduce with packages from debian, gnupg2 v2.0.22-3 and > libgcrypt11 v1.5.3. I think that the problem is the algorithm ID 3. pgpdump says: Old: Public Key Packet(tag 6)(269 bytes) Ver 4 - new Public key creation time - Tue Jan 7 18:10:15 JST 2014 Pub alg - RSA Sign-Only(pub 3) ^^^^^^^^^^^^^^^^^^^^ I don't know where to be fixed, GnuPG or libgcrypt. If it's GnuPG, it's something like: diff --git a/g10/misc.c b/g10/misc.c index 9b7c8ab..975ff4e 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1359,6 +1359,8 @@ pubkey_get_npkey( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_RSA_E || algo == PUBKEY_ALGO_RSA_S) + algo = PUBKEY_ALGO_RSA; if (gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo), GCRYCTL_GET_ALGO_NPKEY, NULL, &n)) n = 0; @@ -1379,6 +1381,8 @@ pubkey_get_nskey( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_RSA_E || algo == PUBKEY_ALGO_RSA_S) + algo = PUBKEY_ALGO_RSA; if (gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo), GCRYCTL_GET_ALGO_NSKEY, NULL, &n )) n = 0; @@ -1399,6 +1403,8 @@ pubkey_get_nsig( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_RSA_E || algo == PUBKEY_ALGO_RSA_S) + algo = PUBKEY_ALGO_RSA; if (gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo), GCRYCTL_GET_ALGO_NSIGN, NULL, &n)) n = 0; -- From cvs at cvs.gnupg.org Tue Apr 15 22:21:01 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 15 Apr 2014 22:21:01 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-62-gae1fbce Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via ae1fbce6dacf14747af0126e640bd4e54cb8c680 (commit) from b76b632a453b8d100d024e2439b4358454dc286e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ae1fbce6dacf14747af0126e640bd4e54cb8c680 Author: Werner Koch Date: Tue Apr 15 16:40:48 2014 +0200 cipher: Fix possible NULL dereference. * cipher/md.c (_gcry_md_selftest): Check for spec being NULL. -- Also removed left-over code in unused file cipher/test-getrusage.c. Found by Hans-Christoph Steiner with cppcheck. diff --git a/cipher/md.c b/cipher/md.c index 461ad64..5ab89cb 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1250,7 +1250,8 @@ _gcry_md_selftest (int algo, int extended, selftest_report_func_t report) ec = spec->selftest (algo, extended, report); else { - ec = spec->selftest? GPG_ERR_DIGEST_ALGO : GPG_ERR_NOT_IMPLEMENTED; + ec = (spec && spec->selftest) ? GPG_ERR_DIGEST_ALGO + /* */ : GPG_ERR_NOT_IMPLEMENTED; if (report) report ("digest", algo, "module", (spec && !spec->flags.disabled)? diff --git a/cipher/test-getrusage.c b/cipher/test-getrusage.c index 6fc8372..7f586dd 100644 --- a/cipher/test-getrusage.c +++ b/cipher/test-getrusage.c @@ -45,10 +45,6 @@ main (int argc, char **argv) printf ("ru_nvcsw = %ld\n", buf.ru_nvcsw ); printf ("ru_nivcsw = %ld\n", buf.ru_nivcsw ); - fprintf (stderr, "ru_utime ru_stime ru_minflt ru_nccsw ru_nivcsw\n"); - fprintf (stderr, "%ld.%06ld %ld.%06ld %5ld %5ld %5ld\n"); - - return 0; } ----------------------------------------------------------------------- Summary of changes: cipher/md.c | 3 ++- cipher/test-getrusage.c | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From gniibe at fsij.org Wed Apr 16 06:22:39 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 16 Apr 2014 13:22:39 +0900 Subject: 25519 is 255-bit? Message-ID: <1397622159.28835.1.camel@cfw2.gniibe.org> I don't know if we should "fix" this or not, but I think that it's 255-bit. GnuPG uses this information when it tries to send private key to smartcard. In development version of Gnuk, the key attribute says it's 255-bit. And I encounter the mismatch. Here is a patch to show the issue. It is no problem for me to modify Gnuk side. diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 0f622f7..13e043e 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -118,7 +118,7 @@ static const ecc_domain_parms_t domain_parms[] = { { /* (-x^2 + y^2 = 1 + dx^2y^2) */ - "Ed25519", 256, 0, + "Ed25519", 255, 0, MPI_EC_EDWARDS, ECC_DIALECT_ED25519, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", "-0x01", -- From wk at gnupg.org Wed Apr 16 14:16:49 2014 From: wk at gnupg.org (Werner Koch) Date: Wed, 16 Apr 2014 14:16:49 +0200 Subject: 25519 is 255-bit? In-Reply-To: <1397622159.28835.1.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Wed, 16 Apr 2014 13:22:39 +0900") References: <1397622159.28835.1.camel@cfw2.gniibe.org> Message-ID: <87fvld1nbi.fsf@vigenere.g10code.de> On Wed, 16 Apr 2014 06:22, gniibe at fsij.org said: > I don't know if we should "fix" this or not, but I think that > it's 255-bit. There was some problem with using 255 bit. I can't remember right not. Possible in an application using Libgcrypt. Thus I rounded it up to 256 bit. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Wed Apr 16 15:03:50 2014 From: wk at gnupg.org (Werner Koch) Date: Wed, 16 Apr 2014 15:03:50 +0200 Subject: Key import segfault in libgcrypt In-Reply-To: <1397026482.1551.4.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Wed, 09 Apr 2014 15:54:42 +0900") References: <20140402104105.634e2d26@hboeck.de> <53422909.7020701@fifthhorseman.net> <1397026482.1551.4.camel@cfw2.gniibe.org> Message-ID: <877g6p1l55.fsf@vigenere.g10code.de> On Wed, 9 Apr 2014 08:54, gniibe at fsij.org said: > I don't know where to be fixed, GnuPG or libgcrypt. If it's GnuPG, > it's something like: Actually at both places. Fixing GnuPG is suffcient but it is better to also map the deprecated RSA_E and RSA_S to RSA in Libgcrypt. I just did that for master and will check the other branches soon. > + else if (algo == PUBKEY_ALGO_RSA_E || algo == PUBKEY_ALGO_RSA_S) > + algo = PUBKEY_ALGO_RSA; > if (gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo), With the excaption of an extra blanl line we had the same idea. I also patched pubkey_nbits. Patch posted to gnupg-devel. master is not affected. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Wed Apr 16 15:03:32 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 16 Apr 2014 15:03:32 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-63-g773e236 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 773e23698218755e9172d2507031a8263c47cc0b (commit) from ae1fbce6dacf14747af0126e640bd4e54cb8c680 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 773e23698218755e9172d2507031a8263c47cc0b Author: Werner Koch Date: Tue Apr 15 16:40:48 2014 +0200 pubkey: Re-map all depreccated RSA algo numbers. * cipher/pubkey.c (map_algo): Mape RSA_E and RSA_S. diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 9aeaced..e3842c0 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -57,18 +57,16 @@ map_algo (int algo) { switch (algo) { - case GCRY_PK_ECDSA: - case GCRY_PK_ECDH: - return GCRY_PK_ECC; - case GCRY_PK_ELG_E: - return GCRY_PK_ELG; - default: - return algo; + case GCRY_PK_RSA_E: return GCRY_PK_RSA; + case GCRY_PK_RSA_S: return GCRY_PK_RSA; + case GCRY_PK_ELG_E: return GCRY_PK_ELG; + case GCRY_PK_ECDSA: return GCRY_PK_ECC; + case GCRY_PK_ECDH: return GCRY_PK_ECC; + default: return algo; } } - /* Return the spec structure for the public key algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_pk_spec_t * ----------------------------------------------------------------------- Summary of changes: cipher/pubkey.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From dkg at fifthhorseman.net Wed Apr 16 16:30:44 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Wed, 16 Apr 2014 10:30:44 -0400 Subject: 25519 is 255-bit? In-Reply-To: <87fvld1nbi.fsf@vigenere.g10code.de> References: <1397622159.28835.1.camel@cfw2.gniibe.org> <87fvld1nbi.fsf@vigenere.g10code.de> Message-ID: <534E9414.3050901@fifthhorseman.net> On 04/16/2014 08:16 AM, Werner Koch wrote: > On Wed, 16 Apr 2014 06:22, gniibe at fsij.org said: >> I don't know if we should "fix" this or not, but I think that >> it's 255-bit. > > There was some problem with using 255 bit. I can't remember right not. > Possible in an application using Libgcrypt. Thus I rounded it up to 256 > bit. rounding up seems like a risky business if this information is ever used as a security estimation. I understand that it's not a large difference, but it seems like the bug ought to be fixed in the application using libgcrypt (presumably it needs to do the byte-wise rounding up itself for buffer allocation or something) rather than having libgcrypt report incorrect information. --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From cvs at cvs.gnupg.org Tue Apr 22 10:34:32 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 22 Apr 2014 10:34:32 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-64-ga79c4ad Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via a79c4ad7c56ee4410f17beb73eeb58b0dd36bfc6 (commit) from 773e23698218755e9172d2507031a8263c47cc0b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a79c4ad7c56ee4410f17beb73eeb58b0dd36bfc6 Author: Werner Koch Date: Tue Apr 15 16:40:48 2014 +0200 random: Small patch for consistency and really burn the stack. * random/rndlinux.c (_gcry_rndlinux_gather_random): s/int/size_t/. (_gcry_rndlinux_gather_random): Replace memset by wipememory. -- size_t was suggested by Marcus Meissner . While looking at the code I identified the useless (i.e. likely optimized away) memset. diff --git a/random/rndlinux.c b/random/rndlinux.c index 89ac203..9eeec57 100644 --- a/random/rndlinux.c +++ b/random/rndlinux.c @@ -226,21 +226,23 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, do { - int nbytes = length < sizeof(buffer)? length : sizeof(buffer); - n = read(fd, buffer, nbytes ); - if( n >= 0 && n > nbytes ) + size_t nbytes; + + nbytes = length < sizeof(buffer)? length : sizeof(buffer); + n = read (fd, buffer, nbytes); + if (n >= 0 && n > nbytes) { log_error("bogus read from random device (n=%d)\n", n ); n = nbytes; } } - while( n == -1 && errno == EINTR ); - if ( n == -1 ) + while (n == -1 && errno == EINTR); + if (n == -1) log_fatal("read error on random device: %s\n", strerror(errno)); - (*add)( buffer, n, origin ); + (*add)(buffer, n, origin); length -= n; } - memset(buffer, 0, sizeof(buffer) ); + wipememory (buffer, sizeof buffer); if (any_need_entropy) _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want); ----------------------------------------------------------------------- Summary of changes: random/rndlinux.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From gniibe at fsij.org Wed Apr 23 13:06:13 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 23 Apr 2014 20:06:13 +0900 Subject: [PATCH] Curve25519 support Message-ID: <1398251173.2587.3.camel@cfw2.gniibe.org> Hello, Here is a patch to support Curve25519. It's not mature, to be revised, but it works for me with GnuPG (with patch). I'm posting this now, to share what's going on my side. In this code, we don't put any information in Y (it's 0), and it is assumed that only X coordinate will be used by ECDH. TODO: It breaks "make check". It fails now. We need to consider number of bits in Elliptic curve domain parameter. We have the field, but it's not precise, and it's a kind of UI. We need precise number of bits so that we can use the information for key generation. We need to consider to have cofactor field in Elliptic curve domain parameter. We need to consider about cofactor and key handling. We need to consider ephemeral key generation in libgcrypt (currently, GnuPG does its own ephemeral key generation). We need to introduce selective copy routine to avoid branches based on scalar (which is secret) in _gcry_mpi_ec_add_points. We need to implement Jivsov's compact representation. We need to implement _gcry_mpi_ec_curve_point for Montgomery curve. Also, dup_point_montgomery and add_points_montgomery. diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 0f622f7..e7dbc17 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -40,7 +40,7 @@ static const struct const char *other; /* Other name. */ } curve_aliases[] = { - /*{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },*/ + { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" }, { "Ed25519", "1.3.6.1.4.1.11591.15.1" }, { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ @@ -127,6 +127,17 @@ static const ecc_domain_parms_t domain_parms[] = "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A", "0x6666666666666666666666666666666666666666666666666666666666666658" }, + { + /* (y^2 = x^3 + 486662*x^2 + x) */ + "Curve25519", 256, 0, + MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD, + "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", + "0x01DB41", /* (A-2)/4 */ + "0x01", + "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9" + }, #if 0 /* No real specs yet found. */ { /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */ @@ -507,9 +518,8 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, { case MPI_EC_WEIERSTRASS: case MPI_EC_EDWARDS: - break; case MPI_EC_MONTGOMERY: - return GPG_ERR_NOT_SUPPORTED; + break; default: return GPG_ERR_BUG; } diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 3f284fe..595aa0c 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -202,8 +202,13 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) } if (*buf != 4) { + /* x-coordinate only */ + mpi_set (result->x, value); + mpi_clear (result->y); + mpi_set_ui (result->z, 1); + xfree (buf_memory); - return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ + return 0; } if ( ((n-1)%2) ) { diff --git a/cipher/ecc.c b/cipher/ecc.c index e0be2d4..679aa39 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -117,7 +117,25 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, point_init (&Q); /* Generate a secret. */ - if (ctx->dialect == ECC_DIALECT_ED25519) + /* + * FIXME. It should be something like this: + * + * When the co-factor of the curve is not 1, we guarantee that + * scalar value k is multiple of its co-factor to avoid sub-group + * attack. Also, we make sure that the most significant bit of k + * is 1. + * + * It works for now as we only have two curves which have co-factor!=1; + * Ed25519 and Curve25519. + * Note that we need some a way to get number of bits of the curve to + * set MSB of k. Currently, E.nbits is not precise for this purpuse. + * We also need a way to get co-factor of a curve. + * + * Currently, we distinguish the two curves by ECC_DIALECT_ED25519 + * and MPI_EC_MONTGOMERY, which works, but is not that correct. + */ + if (ctx->dialect == ECC_DIALECT_ED25519 + || E->model == MPI_EC_MONTGOMERY) { char *rndbuf; @@ -156,7 +174,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, * possibilities without any loss of security. Note that we don't * do that for Ed25519 so that we do not violate the special * construction of the secret key. */ - if (E->dialect == ECC_DIALECT_ED25519) + if (E->dialect == ECC_DIALECT_ED25519 || E->model == MPI_EC_MONTGOMERY) point_set (&sk->Q, &Q); else { @@ -227,12 +245,8 @@ static void test_keys (ECC_secret_key *sk, unsigned int nbits) { ECC_public_key pk; - gcry_mpi_t test = mpi_new (nbits); + gcry_mpi_t test; mpi_point_struct R_; - gcry_mpi_t c = mpi_new (nbits); - gcry_mpi_t out = mpi_new (nbits); - gcry_mpi_t r = mpi_new (nbits); - gcry_mpi_t s = mpi_new (nbits); if (DBG_CIPHER) log_debug ("Testing key.\n"); @@ -243,27 +257,84 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) point_init (&pk.Q); point_set (&pk.Q, &sk->Q); - _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); + if (sk->E.model == MPI_EC_MONTGOMERY) + /* It's ECDH only. */ + /* FIXME: see the FIXME comment of nist_generate_key. + * Here, we generate ephemeral key, same handling is needed for secret. + */ + { + char *rndbuf; + gcry_mpi_t x0, x1; + mpi_ec_t ec; + + test = mpi_new (256); + rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM); + rndbuf[0] &= 0x7f; /* Clear bit 255. */ + rndbuf[0] |= 0x40; /* Set bit 254. */ + rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */ + _gcry_mpi_set_buffer (test, rndbuf, 32, 0); + xfree (rndbuf); + + ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0, + pk.E.p, pk.E.a, pk.E.b); + x0 = mpi_new (0); + x1 = mpi_new (0); - if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) ) - log_fatal ("ECDSA operation: sign failed\n"); + /* R_ = kQ <=> R_ = kdG */ + _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec); + if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec)) + log_fatal ("ecdh: Failed to get affine coordinates for kQ\n"); - if (_gcry_ecc_ecdsa_verify (test, &pk, r, s)) - { - log_fatal ("ECDSA operation: sign, verify failed\n"); + /* R_ = kG */ + _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec); + /* R_ = dkG */ + _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec); + + if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec)) + log_fatal ("ecdh: Failed to get affine coordinates for dkG\n"); + + if (mpi_cmp (x0, x1)) + { + log_printmpi ("x0 ", x0); + log_printmpi ("x1 ", x1); + log_fatal ("ECDH test failed.\n"); + } + + mpi_free (x0); + mpi_free (x1); + _gcry_mpi_ec_free (ec); } + else + { + gcry_mpi_t c = mpi_new (nbits); + gcry_mpi_t out = mpi_new (nbits); + gcry_mpi_t r = mpi_new (nbits); + gcry_mpi_t s = mpi_new (nbits); - if (DBG_CIPHER) - log_debug ("ECDSA operation: sign, verify ok.\n"); + test = mpi_new (nbits); + _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); + + if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) ) + log_fatal ("ECDSA operation: sign failed\n"); + + if (_gcry_ecc_ecdsa_verify (test, &pk, r, s)) + { + log_fatal ("ECDSA operation: sign, verify failed\n"); + } + + if (DBG_CIPHER) + log_debug ("ECDSA operation: sign, verify ok.\n"); + + mpi_free (s); + mpi_free (r); + mpi_free (out); + mpi_free (c); + } point_free (&pk.Q); _gcry_ecc_curve_free (&pk.E); point_free (&R_); - mpi_free (s); - mpi_free (r); - mpi_free (out); - mpi_free (c); mpi_free (test); } diff --git a/mpi/ec.c b/mpi/ec.c index 4f35de0..4fd9e53 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -600,10 +600,13 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point, case MPI_EC_MONTGOMERY: { - log_fatal ("%s: %s not yet supported\n", - "_gcry_mpi_ec_get_affine", "Montgomery"); + if (x) + mpi_set (x, point->x); + + if (y) + mpi_set (y, point->y); } - return -1; + return 0; case MPI_EC_EDWARDS: { @@ -1073,6 +1076,35 @@ add_points_edwards (mpi_point_t result, } +/* PRD = 2 * P1. + SUM = P1 + P2. + P1 - P2 = DIF */ +static void +dup_and_add_montgomery (mpi_point_t prd, mpi_point_t sum, + mpi_point_t p1, mpi_point_t p2, gcry_mpi_t dif_x, + mpi_ec_t ctx) +{ + ec_addm (sum->x, p2->x, p2->z, ctx); + ec_subm (p2->z, p2->x, p2->z, ctx); + ec_addm (prd->x, p1->x, p1->z, ctx); + ec_subm (p1->z, p1->x, p1->z, ctx); + ec_mulm (p2->x, p1->z, sum->x, ctx); + ec_mulm (p2->z, prd->x, p2->z, ctx); + ec_pow2 (p1->x, prd->x, ctx); + ec_pow2 (p1->z, p1->z, ctx); + ec_addm (sum->x, p2->x, p2->z, ctx); + ec_subm (p2->z, p2->x, p2->z, ctx); + ec_mulm (prd->x, p1->x, p1->z, ctx); + ec_subm (p1->z, p1->x, p1->z, ctx); + ec_pow2 (sum->x, sum->x, ctx); + ec_pow2 (sum->z, p2->z, ctx); + ec_mulm (prd->z, p1->z, ctx->a, ctx); /* ctx->a: (A-2)/4 */ + ec_mulm (sum->z, sum->z, dif_x, ctx); + ec_addm (prd->z, p1->x, prd->z, ctx); + ec_mulm (prd->z, prd->z, p1->z, ctx); +} + + /* RESULT = P1 + P2 */ void _gcry_mpi_ec_add_points (mpi_point_t result, @@ -1144,6 +1176,86 @@ _gcry_mpi_ec_mul_point (mpi_point_t result, } return; } + else if (ctx->model == MPI_EC_MONTGOMERY) + { + unsigned int nbits; + int j; + mpi_point_struct p1_, p2_; + + nbits = mpi_get_nbits (scalar); + point_init (&p1); + point_init (&p2); + point_init (&p1_); + point_init (&p2_); + mpi_set_ui (p1.x, 1); + mpi_free (p2.x); + p2.x = mpi_copy (point->x); + mpi_set_ui (p2.z, 1); + + for (j=nbits-1; j >= 0; j--) + { + mpi_point_t q1, q2; + mpi_point_t sum_n, prd_n; + + if (mpi_test_bit (scalar, j)) + { + q1 = &p2; + q2 = &p1; + sum_n = &p1_; + prd_n = &p2_; + } + else + { + q1 = &p1; + q2 = &p2; + sum_n = &p2_; + prd_n = &p1_; + } + dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx); + + if (--j < 0) + break; + + if (mpi_test_bit (scalar, j)) + { + q1 = &p2_; + q2 = &p1_; + sum_n = &p1; + prd_n = &p2; + } + else + { + q1 = &p1_; + q2 = &p2_; + sum_n = &p2; + prd_n = &p1; + } + + dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx); + } + + z1 = mpi_new (0); + mpi_clear (result->y); + mpi_set_ui (result->z, 1); + if ((nbits & 1)) + { + ec_invm (z1, p1_.z, ctx); + ec_mulm (result->x, p1_.x, z1, ctx); + mpi_clear (result->y); + } + else + { + ec_invm (z1, p1.z, ctx); + ec_mulm (result->x, p1.x, z1, ctx); + } + + mpi_free (z1); + point_free (&p1); + point_free (&p2); + point_free (&p1_); + point_free (&p2_); + return; + } x1 = mpi_alloc_like (ctx->p); y1 = mpi_alloc_like (ctx->p); diff --git a/tests/curves.c b/tests/curves.c index 0581452..977001e 100644 --- a/tests/curves.c +++ b/tests/curves.c @@ -29,7 +29,7 @@ #include "../src/gcrypt-int.h" /* Number of curves defined in ../cipger/ecc.c */ -#define N_CURVES 21 +#define N_CURVES 22 /* A real world sample public key. */ static char const sample_key_1[] = diff --git a/tests/keygen.c b/tests/keygen.c index 4aff9c9..c53246c 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -365,7 +365,7 @@ static void check_ecc_keys (void) { const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256", - "Ed25519", NULL }; + "Ed25519", "Curve25519", NULL }; int testno; gcry_sexp_t keyparm, key; int rc; -- From doug at douglasheld.net Wed Apr 23 23:09:03 2014 From: doug at douglasheld.net (Douglas Held) Date: Wed, 23 Apr 2014 22:09:03 +0100 Subject: libgcrypt compile error on OS X: mpih-mul1-asm.S:43:9: error: invalid alignment value Message-ID: Hello all, I had trouble building 1.6.1 on OS X. So I tried building 1.6.0 and I get the same error. I am happy to make an OS X 10.9 server available if a developer would like to take a look. $ make /Applications/Xcode.app/Contents/Developer/usr/bin/make all-recursive Making all in compat make[2]: Nothing to be done for `all'. Making all in mpi /bin/sh ../libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src -g -O2 -MT mpih-mul1-asm.lo -MD -MP -MF .deps/mpih-mul1-asm.Tpo -c -o mpih-mul1-asm.lo mpih-mul1-asm.S libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src -g -O2 -MT mpih-mul1-asm.lo -MD -MP -MF .deps/mpih-mul1-asm.Tpo -c mpih-mul1-asm.S -fno-common -DPIC -o .libs/mpih-mul1-asm.o mpih-mul1-asm.S:43:9: error: invalid alignment value .align 1<<(5) ^ make[2]: *** [mpih-mul1-asm.lo] Error 1 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2 $ uname -a Darwin dougair 13.1.0 Darwin Kernel Version 13.1.0: Wed Apr 2 23:52:02 PDT 2014; root:xnu-2422.92.1~2/RELEASE_X86_64 x86_64 $ make --version GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This program built for i386-apple-darwin11.3.0 $ -- Douglas Held doug at douglasheld.net +447775733093 -------------- next part -------------- An HTML attachment was scrubbed... URL: From gniibe at fsij.org Thu Apr 24 08:04:01 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 24 Apr 2014 15:04:01 +0900 Subject: libgcrypt compile error on OS X: mpih-mul1-asm.S:43:9: error: invalid alignment value In-Reply-To: References: Message-ID: <1398319441.4289.2.camel@cfw2.gniibe.org> Hello, On 2014-04-23 at 22:09 +0100, Douglas Held wrote: > mpih-mul1-asm.S:43:9: error: invalid alignment value > .align 1<<(5) > ^ [...] > $ uname -a > Darwin dougair 13.1.0 Darwin Kernel Version 13.1.0: Wed Apr 2 > 23:52:02 PDT 2014; root:xnu-2422.92.1~2/RELEASE_X86_64 x86_64 Although I don't have any experience, I think that some patch like following is needed. Please try and let me know if it works. diff --git a/mpi/config.links b/mpi/config.links index 0217d35..4f35ea2 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -127,6 +127,12 @@ case "${host}" in path="i586 i386" mpi_cpu_arch="x86" ;; + x86_64-apple-darwin*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="amd64" + mpi_cpu_arch="x86" + ;; x86_64-*-*) echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h -- From gniibe at fsij.org Fri Apr 25 02:39:20 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 25 Apr 2014 09:39:20 +0900 Subject: [PATCH] ECC sign & verify Message-ID: <1398386360.1511.3.camel@cfw2.gniibe.org> Hello, I'm currently testing GnuPG development version with ECC. When I tested existing ecc.test of GnuPG (with secret key import), I found this problem. While decryption works, signing doesn't. In the test, ecc_sign is called with no curve name but explicit curve parameters, and fails as (ctx.flags & PUBKEY_FLAG_PARAM) == 0. In ecc_sign, it tries to extract paramerters from KEYPARMS, only when (ctx.flags & PUBKEY_FLAG_PARAM) is on. However, there is it makes no sense to check ctx.flags here, since it is not dependent on the key (but data to be signed). On the other hand, ecc_decrypt_raw, it tries to extract paramerters from KEYPARMS, and then tries curve name (with no checking of (ctx.flags & PUBKEY_FLAG_PARAM)). If it's really needed, we could add something like: l1 = sexp_find_token (keyparms, "flags", 0); if (l1) { rc = _gcry_pk_util_parse_flaglist (l1, &ctx.flags, NULL); sexp_release (l1); l1 = NULL; if (rc) goto leave; } But, I think that "(flags param)" only makes sense for key generation. Here's a patch to show the problem. It works for me. diff --git a/cipher/ecc.c b/cipher/ecc.c index 6a60785..f7a16ec 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -810,13 +810,9 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) /* * Extract the key. */ - if ((ctx.flags & PUBKEY_FLAG_PARAM)) - rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", - &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, - &mpi_q, &sk.d, NULL); - else - rc = sexp_extract_param (keyparms, NULL, "/q?+d", - &mpi_q, &sk.d, NULL); + rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", + &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, + &mpi_q, &sk.d, NULL); if (rc) goto leave; if (mpi_g) -- From gniibe at fsij.org Fri Apr 25 04:37:22 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 25 Apr 2014 11:37:22 +0900 Subject: [PATCH] ECC: (flags param) is only for key generation In-Reply-To: <1398386360.1511.3.camel@cfw2.gniibe.org> References: <1398386360.1511.3.camel@cfw2.gniibe.org> Message-ID: <1398393442.1511.7.camel@cfw2.gniibe.org> On 2014-04-25 at 09:39 +0900, NIIBE Yutaka wrote: > But, I think that "(flags param)" only makes sense for key generation. This is revised patch, full version. diff --git a/cipher/ecc.c b/cipher/ecc.c index 6a60785..c73d9aa 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -577,15 +577,9 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) goto leave; } - if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA)) - { - rc = sexp_build - (&curve_flags, NULL, - ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))? - "(flags param eddsa)" : - ((flags & PUBKEY_FLAG_PARAM))? - "(flags param)" : - "(flags eddsa)"); + if ((flags & PUBKEY_FLAG_EDDSA)) + { + rc = sexp_build (&curve_flags, NULL, "(flags eddsa)"); if (rc) goto leave; } @@ -673,13 +667,9 @@ ecc_check_secret_key (gcry_sexp_t keyparms) } /* Extract the parameters. */ - if ((flags & PUBKEY_FLAG_PARAM)) - rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", - &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, - &mpi_q, &sk.d, NULL); - else - rc = sexp_extract_param (keyparms, NULL, "/q?+d", - &mpi_q, &sk.d, NULL); + rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", + &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, + &mpi_q, &sk.d, NULL); if (rc) goto leave; @@ -810,13 +800,9 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) /* * Extract the key. */ - if ((ctx.flags & PUBKEY_FLAG_PARAM)) - rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", - &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, - &mpi_q, &sk.d, NULL); - else - rc = sexp_extract_param (keyparms, NULL, "/q?+d", - &mpi_q, &sk.d, NULL); + rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", + &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, + &mpi_q, &sk.d, NULL); if (rc) goto leave; if (mpi_g) @@ -974,13 +960,9 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) /* * Extract the key. */ - if ((ctx.flags & PUBKEY_FLAG_PARAM)) - rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q", - &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, - &mpi_q, NULL); - else - rc = sexp_extract_param (s_keyparms, NULL, "/q", - &mpi_q, NULL); + rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q", + &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, + &mpi_q, NULL); if (rc) goto leave; if (mpi_g) @@ -1550,28 +1532,16 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms) } /* Extract the parameters. */ - if ((flags & PUBKEY_FLAG_PARAM)) - { - if ((flags & PUBKEY_FLAG_EDDSA)) - rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?/q", - &values[0], &values[1], &values[2], - &values[3], &values[4], &values[5], - NULL); - else - rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?q", - &values[0], &values[1], &values[2], - &values[3], &values[4], &values[5], - NULL); - } + if ((flags & PUBKEY_FLAG_EDDSA)) + rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?/q", + &values[0], &values[1], &values[2], + &values[3], &values[4], &values[5], + NULL); else - { - if ((flags & PUBKEY_FLAG_EDDSA)) - rc = sexp_extract_param (keyparms, NULL, "/q", - &values[5], NULL); - else - rc = sexp_extract_param (keyparms, NULL, "q", - &values[5], NULL); - } + rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?q", + &values[0], &values[1], &values[2], + &values[3], &values[4], &values[5], + NULL); if (rc) goto leave; -- From smueller at chronox.de Sat Apr 26 22:16:43 2014 From: smueller at chronox.de (Stephan Mueller) Date: Sat, 26 Apr 2014 22:16:43 +0200 Subject: [PATCH v5 1/7] SP800-90A Deterministic Random Bit Generator In-Reply-To: <1441801.LxIjhxD44Y@myon.chronox.de> References: <1573675.V5Uuq2JQxy@myon.chronox.de> <2263776.uX4ZkX09LR@myon.chronox.de> <1441801.LxIjhxD44Y@myon.chronox.de> Message-ID: <36817128.1Nd8mvqQGL@myon.chronox.de> Changes v5: * add const to all possible variables as suggested by Joe Perches * change name of cores[] to drbg_cores[] as suggested by Joe Perches * return code of generate function now returns error status Signed-off-by: Stephan Mueller -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-SP800-90A-Deterministic-Random-Bit-Generator.patch.bz2 Type: application/x-bzip Size: 16119 bytes Desc: not available URL: From gniibe at fsij.org Wed Apr 30 07:21:24 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 30 Apr 2014 14:21:24 +0900 Subject: (flags eddsa) and (flags gost) Message-ID: <1398835284.22783.6.camel@cfw2.gniibe.org> Hello, Currently, we use (flags eddsa) or (flags gost) with (data ...) to be signed or to be encrypted/decrypted. However, I think that it is the curve parameter. I mean, for a particular curve, if it's for EdDSA, data always needs to have (flags eddsa). Are there any use cases, where a curve not intended to EdDSA will be used with (data (flags eddsa)...)? It seems for me that (flags gost) is same. If this is true, should we get such a flag from curve, instead of from data? -- From dbaryshkov at gmail.com Wed Apr 30 08:08:04 2014 From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov) Date: Wed, 30 Apr 2014 10:08:04 +0400 Subject: (flags eddsa) and (flags gost) In-Reply-To: <1398835284.22783.6.camel@cfw2.gniibe.org> References: <1398835284.22783.6.camel@cfw2.gniibe.org> Message-ID: Hello, On Wed, Apr 30, 2014 at 9:21 AM, NIIBE Yutaka wrote: > Currently, we use (flags eddsa) or (flags gost) with (data ...) to be > signed or to be encrypted/decrypted. > > However, I think that it is the curve parameter. I mean, for a > particular curve, if it's for EdDSA, data always needs to have (flags > eddsa). Regarding (flags gost). GOST R 34.10-2001/-2012 use Weierstrassian curves. Nothing stops us from calculating ECDSA on GOST curves or GOST signatures e.g. on NIST curves. Thus (and because of eddsa flag) using (flags gost) with (data ...) seemed logical. However if (flags eddsa) is moved to the curve specification, I see no problem with moving (flags gost) to the curve to unify the design. -- With best wishes Dmitry From wk at gnupg.org Wed Apr 30 09:02:47 2014 From: wk at gnupg.org (Werner Koch) Date: Wed, 30 Apr 2014 09:02:47 +0200 Subject: (flags eddsa) and (flags gost) In-Reply-To: <1398835284.22783.6.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Wed, 30 Apr 2014 14:21:24 +0900") References: <1398835284.22783.6.camel@cfw2.gniibe.org> Message-ID: <87siovguzs.fsf@vigenere.g10code.de> On Wed, 30 Apr 2014 07:21, gniibe at fsij.org said: > If this is true, should we get such a flag from curve, instead of from > data? If the flag is missing, it would be okay to get it from the curve (i.e. using the default). If the flag is given a consistency check would be useful. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Wed Apr 30 09:33:22 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 30 Apr 2014 16:33:22 +0900 Subject: (flags eddsa) and (flags gost) In-Reply-To: <87siovguzs.fsf@vigenere.g10code.de> References: <1398835284.22783.6.camel@cfw2.gniibe.org> <87siovguzs.fsf@vigenere.g10code.de> Message-ID: <1398843202.26670.0.camel@cfw2.gniibe.org> Hello, On 2014-04-30 at 10:08 +0400, Dmitry Eremin-Solenikov wrote: > Regarding (flags gost). GOST R 34.10-2001/-2012 use Weierstrassian > curves. Nothing stops us from calculating ECDSA on GOST curves > or GOST signatures e.g. on NIST curves. Thus (and because of eddsa > flag) using (flags gost) with (data ...) seemed logical. Thank you for the clarification. I understand this case. I didn't consider this is the case. On 2014-04-30 at 09:02 +0200, Werner Koch wrote: > If the flag is missing, it would be okay to get it from the curve > (i.e. using the default). If the flag is given a consistency check > would be useful. I see. That's reasonable. When I'll find adding the feature to get it from curve is useful, I'll propose it. For now, I remember that it is data where we specify the flags. --