From cvs at cvs.gnupg.org Sun Sep 1 16:14:40 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 01 Sep 2013 16:14:40 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-202-g99d1554 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 99d15543b8d94a8f1ef66c6ccb862b0ce82c514d (commit) via 03da7f8ba3ec24d4639a2bcebbc0d9d831734c08 (commit) via 9c95be105f518d18407115c2c06893857c24b116 (commit) via 7b0ebe69fe35f2ee13e1e1beb2766a1eaadb7f0c (commit) from e9b711e6ddb480a71d2996465074e436c752c005 (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 99d15543b8d94a8f1ef66c6ccb862b0ce82c514d Author: Jussi Kivilinna Date: Sat Aug 31 12:48:31 2013 +0300 sha512: add ARM/NEON assembly version of transform function * cipher/Makefile.am: Add 'sha512-armv7-neon.S'. * cipher/sha512-armv7-neon.S: New file. * cipher/sha512.c (USE_ARM_NEON_ASM): New macro. (SHA512_CONTEXT)?[USE_ARM_NEON_ASM]: Add 'use_neon'. (sha512_init, sha384_init) [USE_ARM_NEON_ASM]: Enable 'use_neon' if CPU support NEON instructions. (k): Round constant array moved outside of 'transform' function. (__transform): Renamed from 'tranform' function. [USE_ARM_NEON_ASM] (_gcry_sha512_transform_armv7_neon): New prototype. (transform): New wrapper function for different transform versions. (sha512_write, sha512_final): Burn stack by the amount returned by transform function. * configure.ac (sha512) [neonsupport]: Add 'sha512-armv7-neon.lo'. -- Add NEON assembly for transform function for faster SHA512 on ARM. Major speed up thanks to 64-bit integer registers and large register file that can hold full input buffer. Benchmark results on Cortex-A8, 1Ghz: Old: $ tests/benchmark --hash-repetitions 100 md sha512 sha384 SHA512 17050ms 18780ms 29120ms 18040ms 17190ms SHA384 17130ms 18720ms 29160ms 18090ms 17280ms New: $ tests/benchmark --hash-repetitions 100 md sha512 sha384 SHA512 3600ms 5070ms 15330ms 4510ms 3480ms SHA384 3590ms 5060ms 15350ms 4510ms 3520ms New vs old: SHA512 4.74x 3.70x 1.90x 4.00x 4.94x SHA384 4.77x 3.70x 1.90x 4.01x 4.91x Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index e233e79..3dd6f88 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -73,7 +73,7 @@ seed.c \ serpent.c serpent-sse2-amd64.S serpent-avx2-amd64.S \ sha1.c \ sha256.c \ -sha512.c \ +sha512.c sha512-armv7-neon.S \ tiger.c \ whirlpool.c \ twofish.c twofish-amd64.S \ diff --git a/cipher/sha512-armv7-neon.S b/cipher/sha512-armv7-neon.S new file mode 100644 index 0000000..042b15a --- /dev/null +++ b/cipher/sha512-armv7-neon.S @@ -0,0 +1,316 @@ +/* sha512-armv7-neon.S - ARM/NEON assembly implementation of SHA-512 transform + * + * Copyright ? 2013 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 . + */ + +#include + +#if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \ + defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_NEON) + +.text + +.syntax unified +.fpu neon +.arm + +/* structure of SHA512_CONTEXT */ +#define hd_a 0 +#define hd_b ((hd_a) + 8) +#define hd_c ((hd_b) + 8) +#define hd_d ((hd_c) + 8) +#define hd_e ((hd_d) + 8) +#define hd_f ((hd_e) + 8) +#define hd_g ((hd_f) + 8) + +/* register macros */ +#define RK %r2 + +#define RA d0 +#define RB d1 +#define RC d2 +#define RD d3 +#define RE d4 +#define RF d5 +#define RG d6 +#define RH d7 + +#define RT0 d8 +#define RT1 d9 +#define RT2 d10 +#define RT3 d11 +#define RT4 d12 +#define RT5 d13 +#define RT6 d14 +#define RT7 d15 + +#define RW0 d16 +#define RW1 d17 +#define RW2 d18 +#define RW3 d19 +#define RW4 d20 +#define RW5 d21 +#define RW6 d22 +#define RW7 d23 +#define RW8 d24 +#define RW9 d25 +#define RW10 d26 +#define RW11 d27 +#define RW12 d28 +#define RW13 d29 +#define RW14 d30 +#define RW15 d31 + +#define RW01q q8 +#define RW23q q9 +#define RW45q q10 +#define RW67q q11 +#define RW89q q12 +#define RW1011q q13 +#define RW1213q q14 +#define RW1415q q15 + +/*********************************************************************** + * ARM assembly implementation of sha512 transform + ***********************************************************************/ +#define round_0_63(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw14, rw9, rw1) \ + /* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \ + vshr.u64 RT1, re, #14; \ + vshl.u64 RT3, re, #64 - 14; \ + vshr.u64 RT4, re, #18; \ + vshl.u64 RT5, re, #64 - 18; \ + veor.64 RT1, RT1, RT3; \ + vld1.64 {RT0}, [RK]!; \ + veor.64 RT1, RT1, RT4; \ + vshr.u64 RT3, re, #41; \ + vshl.u64 RT4, re, #64 - 41; \ + veor.64 RT1, RT1, RT5; \ + vadd.u64 RT0, RT0, rw0; \ + veor.64 RT1, RT1, RT3; \ + vand.64 RT2, re, rf; \ + veor.64 RT1, RT1, RT4; \ + vbic.64 RT6, rg, re; \ + \ + vadd.u64 RT1, RT1, rh; \ + veor.64 RT2, RT2, RT6; \ + vshr.u64 rh, ra, #28; \ + vshl.u64 RT3, ra, #64 - 28; \ + vadd.u64 RT1, RT1, RT0; \ + vshr.u64 RT4, ra, #34; \ + veor.64 rh, rh, RT3; \ + vshl.u64 RT5, ra, #64 - 34; \ + vadd.u64 RT1, RT1, RT2; \ + \ + /* h = Sum0 (a) + Maj (a, b, c); */ \ + veor.64 rh, rh, RT4; \ + vshr.u64 RT3, ra, #39; \ + vshl.u64 RT4, ra, #64 - 39; \ + vorr.64 RT6, ra, rb; \ + vand.64 RT0, ra, rb; \ + veor.64 rh, rh, RT5; \ + vand.64 RT6, RT6, rc; \ + veor.64 rh, rh, RT3; \ + vorr.64 RT0, RT0, RT6; \ + veor.64 rh, rh, RT4; \ + vshr.u64 RT4, rw14, #19; \ + vadd.u64 rh, rh, RT0; \ + vshl.u64 RT2, rw14, #64 - 19; \ + \ + /* w[0] += S1 (w[14]) + w[9] + S0 (w[1]); */ \ + vshr.u64 RT3, rw14, #61; \ + vshl.u64 RT6, rw14, #64 - 61; \ + veor.64 RT0, RT4, RT2; \ + vshr.u64 RT2, rw14, 6; \ + veor.64 RT0, RT0, RT3; \ + vshr.u64 RT7, rw1, #1; \ + veor.64 RT0, RT0, RT6; \ + vshl.u64 RT4, rw1, #64 - 1; \ + veor.64 RT0, RT0, RT2; \ + vshr.u64 RT5, rw1, #8; \ + vadd.u64 rw0, rw0, RT0; \ + vshl.u64 RT6, rw1, #64 - 8; \ + veor.64 RT7, RT7, RT4; \ + vshr.u64 RT4, rw1, 7; \ + veor.64 RT7, RT7, RT5; \ + vadd.u64 rw0, rw0, rw9; /* w[0]+=w[9]; */\ + veor.64 RT7, RT7, RT6; \ + vadd.u64 rd, rd, RT1; /* d+=t1; */ \ + veor.64 RT7, RT7, RT4; \ + vadd.u64 rh, rh, RT1; /* h+=t1; */ \ + vadd.u64 rw0, rw0, RT7; \ + +#define round_64_79(ra, rb, rc, rd, re, rf, rg, rh, rw0) \ + /* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \ + vld1.64 {RT0}, [RK]!; \ + vshr.u64 RT1, re, #14; \ + vshl.u64 RT3, re, #64 - 14; \ + vshr.u64 RT4, re, #18; \ + vshl.u64 RT5, re, #64 - 18; \ + veor.64 RT1, RT1, RT3; \ + vshr.u64 RT7, ra, #28; \ + veor.64 RT1, RT1, RT4; \ + vshr.u64 RT3, re, #41; \ + vshl.u64 RT4, re, #64 - 41; \ + veor.64 RT1, RT1, RT5; \ + vadd.u64 RT0, RT0, rw0; \ + veor.64 RT1, RT1, RT3; \ + vand.64 RT2, re, rf; \ + veor.64 RT1, RT1, RT4; \ + vbic.64 RT6, rg, re; \ + \ + vadd.u64 RT1, RT1, rh; \ + veor.64 RT2, RT2, RT6; \ + vadd.u64 RT1, RT1, RT0; \ + vshr.u64 RT4, ra, #34; \ + vshl.u64 RT5, ra, #64 - 34; \ + \ + /* t7 = Sum0 (a) + Maj (a, b, c); */ \ + vshl.u64 RT6, ra, #64 - 28; \ + veor.64 RT7, RT7, RT4; \ + vshr.u64 RT3, ra, #39; \ + veor.64 RT7, RT7, RT6; \ + vshl.u64 RT4, ra, #64 - 39; \ + vorr.64 RT6, ra, rb; \ + vand.64 RT0, ra, rb; \ + veor.64 RT7, RT7, RT5; \ + vand.64 RT6, RT6, rc; \ + veor.64 RT7, RT7, RT3; \ + vorr.64 RT0, RT0, RT6; \ + veor.64 RT7, RT7, RT4; \ + vadd.u64 RT1, RT1, RT2; \ + vadd.u64 RT7, RT7, RT0; \ + vadd.u64 rd, rd, RT1; /* d+=t1; */ \ + vadd.u64 rh, RT7, RT1; /* h=t7+t1; */ + +.align 3 +.globl _gcry_sha512_transform_armv7_neon +.type _gcry_sha512_transform_armv7_neon,%function; + +_gcry_sha512_transform_armv7_neon: + /* Input: + * %r0: SHA512_CONTEXT + * %r1: data + * %r2: u64 k[] constants + */ + mov %r3, #0; + + /* Load context to d0-d7 */ + vld1.64 {RA-RD}, [%r0]!; + vld1.64 {RE-RH}, [%r0]; + sub %r0, #(4*8); + + /* Load input to w[16], d16-d31 */ + /* NOTE: Assumes that on ARMv7 unaligned accesses are always allowed. */ + vld1.64 {RW0-RW3}, [%r1]!; + vld1.64 {RW4-RW7}, [%r1]!; + vld1.64 {RW8-RW11}, [%r1]!; + vld1.64 {RW12-RW15}, [%r1]; +#ifdef __ARMEL__ + /* byteswap */ + vrev64.8 RW01q, RW01q; + vrev64.8 RW23q, RW23q; + vrev64.8 RW45q, RW45q; + vrev64.8 RW67q, RW67q; + vrev64.8 RW89q, RW89q; + vrev64.8 RW1011q, RW1011q; + vrev64.8 RW1213q, RW1213q; + vrev64.8 RW1415q, RW1415q; +#endif + + /* EABI says that d8-d15 must be preserved by callee. */ + vpush {RT0-RT7}; + +.Loop: + add %r3, #16; + round_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW14, RW9, RW1); + cmp %r3, #64; + round_0_63(RH, RA, RB, RC, RD, RE, RF, RG, RW1, RW15, RW10, RW2); + round_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW0, RW11, RW3); + round_0_63(RF, RG, RH, RA, RB, RC, RD, RE, RW3, RW1, RW12, RW4); + round_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW2, RW13, RW5); + round_0_63(RD, RE, RF, RG, RH, RA, RB, RC, RW5, RW3, RW14, RW6); + round_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW4, RW15, RW7); + round_0_63(RB, RC, RD, RE, RF, RG, RH, RA, RW7, RW5, RW0, RW8); + round_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW6, RW1, RW9); + round_0_63(RH, RA, RB, RC, RD, RE, RF, RG, RW9, RW7, RW2, RW10); + round_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW8, RW3, RW11); + round_0_63(RF, RG, RH, RA, RB, RC, RD, RE, RW11, RW9, RW4, RW12); + round_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW10, RW5, RW13); + round_0_63(RD, RE, RF, RG, RH, RA, RB, RC, RW13, RW11, RW6, RW14); + round_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW12, RW7, RW15); + round_0_63(RB, RC, RD, RE, RF, RG, RH, RA, RW15, RW13, RW8, RW0); + bne .Loop; + + round_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW0); + round_64_79(RH, RA, RB, RC, RD, RE, RF, RG, RW1); + round_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW2); + round_64_79(RF, RG, RH, RA, RB, RC, RD, RE, RW3); + round_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4); + round_64_79(RD, RE, RF, RG, RH, RA, RB, RC, RW5); + round_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6); + round_64_79(RB, RC, RD, RE, RF, RG, RH, RA, RW7); + round_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8); + round_64_79(RH, RA, RB, RC, RD, RE, RF, RG, RW9); + round_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10); + round_64_79(RF, RG, RH, RA, RB, RC, RD, RE, RW11); + round_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12); + round_64_79(RD, RE, RF, RG, RH, RA, RB, RC, RW13); + round_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14); + round_64_79(RB, RC, RD, RE, RF, RG, RH, RA, RW15); + + /* Load context to d16-d23 */ + vld1.64 {RW0-RW3}, [%r0]!; + vld1.64 {RW4-RW7}, [%r0]; + sub %r0, #(4*8); + + vadd.u64 RA, RW0; + vadd.u64 RB, RW1; + vadd.u64 RC, RW2; + vadd.u64 RD, RW3; + vadd.u64 RE, RW4; + vadd.u64 RF, RW5; + vadd.u64 RG, RW6; + vadd.u64 RH, RW7; + + /* Store the first half of context */ + vst1.64 {RA-RD}, [%r0]!; + + /* Clear used registers */ + /* d16-d31 */ + veor.u64 RW01q, RW01q; + veor.u64 RW23q, RW23q; + veor.u64 RW45q, RW45q; + veor.u64 RW67q, RW67q; + vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */ + veor.u64 RW89q, RW89q; + veor.u64 RW1011q, RW1011q; + veor.u64 RW1213q, RW1213q; + veor.u64 RW1415q, RW1415q; + /* d8-d15 */ + vpop {RT0-RT7}; + /* d0-d7 (q0-q3) */ + veor.u64 %q0, %q0; + veor.u64 %q1, %q1; + veor.u64 %q2, %q2; + veor.u64 %q3, %q3; + + bx %lr; +.size _gcry_sha512_transform_armv7_neon,.-_gcry_sha512_transform_armv7_neon; + +#endif diff --git a/cipher/sha512.c b/cipher/sha512.c index 1bbcd11..fee3e71 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -53,12 +53,26 @@ #include "cipher.h" #include "hash-common.h" + +/* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */ +#undef USE_ARM_NEON_ASM +#if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) +# if defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_NEON) +# define USE_ARM_NEON_ASM 1 +# endif +#endif + + typedef struct { u64 h0, h1, h2, h3, h4, h5, h6, h7; u64 nblocks; byte buf[128]; int count; +#ifdef USE_ARM_NEON_ASM + int use_neon; +#endif } SHA512_CONTEXT; static void @@ -77,6 +91,9 @@ sha512_init (void *context) hd->nblocks = 0; hd->count = 0; +#ifdef USE_ARM_NEON_ASM + hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; +#endif } static void @@ -95,6 +112,9 @@ sha384_init (void *context) hd->nblocks = 0; hd->count = 0; +#ifdef USE_ARM_NEON_ASM + hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; +#endif } @@ -128,58 +148,59 @@ Sum1 (u64 x) return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); } +static const u64 k[] = + { + U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), + U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), + U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), + U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), + U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), + U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), + U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), + U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), + U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), + U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), + U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), + U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), + U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), + U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), + U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), + U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), + U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), + U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), + U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), + U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), + U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), + U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), + U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), + U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), + U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), + U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), + U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), + U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), + U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), + U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), + U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), + U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), + U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), + U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), + U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), + U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), + U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), + U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), + U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), + U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) + }; + /**************** * Transform the message W which consists of 16 64-bit-words */ static void -transform (SHA512_CONTEXT *hd, const unsigned char *data) +__transform (SHA512_CONTEXT *hd, const unsigned char *data) { u64 a, b, c, d, e, f, g, h; u64 w[16]; int t; - static const u64 k[] = - { - U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), - U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), - U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), - U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), - U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), - U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), - U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), - U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), - U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), - U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), - U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), - U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), - U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), - U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), - U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), - U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), - U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), - U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), - U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), - U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), - U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), - U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), - U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), - U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), - U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), - U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), - U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), - U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), - U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), - U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), - U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), - U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), - U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), - U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), - U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), - U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), - U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), - U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), - U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), - U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) - }; /* get values from the chaining vars */ a = hd->h0; @@ -455,6 +476,33 @@ transform (SHA512_CONTEXT *hd, const unsigned char *data) } +#ifdef USE_ARM_NEON_ASM +void _gcry_sha512_transform_armv7_neon (SHA512_CONTEXT *hd, + const unsigned char *data, + const u64 k[]); +#endif + + +static unsigned int +transform (SHA512_CONTEXT *hd, const unsigned char *data) +{ +#ifdef USE_ARM_NEON_ASM + if (hd->use_neon) + { + _gcry_sha512_transform_armv7_neon(hd, data, k); + + /* return stack burn depth */ + return (sizeof(void *) * 3); + } +#endif + + __transform (hd, data); + + /* return stack burn depth */ + return 256; +} + + /* Update the message digest with the contents * of INBUF with length INLEN. */ @@ -463,11 +511,12 @@ sha512_write (void *context, const void *inbuf_arg, size_t inlen) { const unsigned char *inbuf = inbuf_arg; SHA512_CONTEXT *hd = context; + unsigned int stack_burn_depth = 0; if (hd->count == 128) { /* flush the buffer */ - transform (hd, hd->buf); - _gcry_burn_stack (256); + stack_burn_depth = transform (hd, hd->buf); + _gcry_burn_stack (stack_burn_depth); hd->count = 0; hd->nblocks++; } @@ -484,13 +533,13 @@ sha512_write (void *context, const void *inbuf_arg, size_t inlen) while (inlen >= 128) { - transform (hd, inbuf); + stack_burn_depth = transform (hd, inbuf); hd->count = 0; hd->nblocks++; inlen -= 128; inbuf += 128; } - _gcry_burn_stack (256); + _gcry_burn_stack (stack_burn_depth); for (; inlen && hd->count < 128; inlen--) hd->buf[hd->count++] = *inbuf++; } @@ -508,6 +557,7 @@ static void sha512_final (void *context) { SHA512_CONTEXT *hd = context; + unsigned int stack_burn_depth; u64 t, msb, lsb; byte *p; @@ -559,8 +609,8 @@ sha512_final (void *context) hd->buf[125] = lsb >> 16; hd->buf[126] = lsb >> 8; hd->buf[127] = lsb; - transform (hd, hd->buf); - _gcry_burn_stack (256); + stack_burn_depth = transform (hd, hd->buf); + _gcry_burn_stack (stack_burn_depth); p = hd->buf; #ifdef WORDS_BIGENDIAN diff --git a/configure.ac b/configure.ac index 89b9366..959327a 100644 --- a/configure.ac +++ b/configure.ac @@ -1526,6 +1526,11 @@ LIST_MEMBER(sha512, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512.lo" AC_DEFINE(USE_SHA512, 1, [Defined if this module should be included]) + + if test x"$neonsupport" = xyes ; then + # Build with the NEON implementation + GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-armv7-neon.lo" + fi fi LIST_MEMBER(tiger, $enabled_digests) commit 03da7f8ba3ec24d4639a2bcebbc0d9d831734c08 Author: Jussi Kivilinna Date: Sat Aug 31 12:48:30 2013 +0300 sha512: reduce stack use in transform function by 512 bytes * cipher/sha512.c (transform): Change 'u64 w[80]' to 'u64 w[16]' and inline input expansion to first 64 rounds. (sha512_write, sha512_final): Reduce burn_stack depth by 512 bytes. -- The input expansion to w[] array can be inlined with rounds and size of array reduced from u64[80] to u64[16]. On Cortex-A8, this change gives small boost, possibly thanks to reduced burn_stack depth. New vs old (tests/benchmark md sha512 sha384): SHA512 1.09x 1.11x 1.06x 1.09x 1.08x SHA384 1.09x 1.11x 1.06x 1.09x 1.09x Signed-off-by: Jussi Kivilinna diff --git a/cipher/sha512.c b/cipher/sha512.c index 2163e60..1bbcd11 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -135,7 +135,7 @@ static void transform (SHA512_CONTEXT *hd, const unsigned char *data) { u64 a, b, c, d, e, f, g, h; - u64 w[80]; + u64 w[16]; int t; static const u64 k[] = { @@ -215,11 +215,8 @@ transform (SHA512_CONTEXT *hd, const unsigned char *data) #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) - for (t = 16; t < 80; t++) - w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16]; - - for (t = 0; t < 80; ) + for (t = 0; t < 80 - 16; ) { u64 t1, t2; @@ -232,7 +229,125 @@ transform (SHA512_CONTEXT *hd, const unsigned char *data) Unrolled with inline: 330ms */ #if 0 /* Not unrolled. */ - t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16]; + w[t%16] += S1 (w[(t - 2)%16]) + w[(t - 7)%16] + S0 (w[(t - 15)%16]); + t2 = Sum0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + t++; +#else /* Unrolled to interweave the chain variables. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; + w[0] += S1 (w[14]) + w[9] + S0 (w[1]); + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; + w[1] += S1 (w[15]) + w[10] + S0 (w[2]); + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; + w[2] += S1 (w[0]) + w[11] + S0 (w[3]); + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; + w[3] += S1 (w[1]) + w[12] + S0 (w[4]); + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; + w[4] += S1 (w[2]) + w[13] + S0 (w[5]); + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; + w[5] += S1 (w[3]) + w[14] + S0 (w[6]); + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; + w[6] += S1 (w[4]) + w[15] + S0 (w[7]); + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; + w[7] += S1 (w[5]) + w[0] + S0 (w[8]); + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; + w[8] += S1 (w[6]) + w[1] + S0 (w[9]); + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; + w[9] += S1 (w[7]) + w[2] + S0 (w[10]); + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; + w[10] += S1 (w[8]) + w[3] + S0 (w[11]); + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; + w[11] += S1 (w[9]) + w[4] + S0 (w[12]); + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; + w[12] += S1 (w[10]) + w[5] + S0 (w[13]); + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; + w[13] += S1 (w[11]) + w[6] + S0 (w[14]); + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; + w[14] += S1 (w[12]) + w[7] + S0 (w[15]); + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; + w[15] += S1 (w[13]) + w[8] + S0 (w[0]); + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + t += 16; +#endif + } + + for (; t < 80; ) + { + u64 t1, t2; + +#if 0 /* Not unrolled. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16]; t2 = Sum0 (a) + Maj (a, b, c); h = g; g = f; @@ -244,47 +359,87 @@ transform (SHA512_CONTEXT *hd, const unsigned char *data) a = t1 + t2; t++; #else /* Unrolled to interweave the chain variables. */ - t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; - t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1]; + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; - t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2]; + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; - t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3]; + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; - t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4]; + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; - t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5]; + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; - t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6]; + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; - t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7]; + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; - t += 8; + t += 16; #endif } @@ -312,7 +467,7 @@ sha512_write (void *context, const void *inbuf_arg, size_t inlen) if (hd->count == 128) { /* flush the buffer */ transform (hd, hd->buf); - _gcry_burn_stack (768); + _gcry_burn_stack (256); hd->count = 0; hd->nblocks++; } @@ -335,7 +490,7 @@ sha512_write (void *context, const void *inbuf_arg, size_t inlen) inlen -= 128; inbuf += 128; } - _gcry_burn_stack (768); + _gcry_burn_stack (256); for (; inlen && hd->count < 128; inlen--) hd->buf[hd->count++] = *inbuf++; } @@ -405,7 +560,7 @@ sha512_final (void *context) hd->buf[126] = lsb >> 8; hd->buf[127] = lsb; transform (hd, hd->buf); - _gcry_burn_stack (768); + _gcry_burn_stack (256); p = hd->buf; #ifdef WORDS_BIGENDIAN commit 9c95be105f518d18407115c2c06893857c24b116 Author: Jussi Kivilinna Date: Sat Aug 31 12:48:30 2013 +0300 Add ARM HW feature detection module and add NEON detection * configure.ac: Add option --disable-neon-support. (HAVE_GCC_INLINE_ASM_NEON): New. (ENABLE_NEON_SUPPORT): New. [arm]: Add 'hwf-arm.lo' as HW feature module. * src/Makefile.am: Add 'hwf-arm.c'. * src/g10lib.h (HWF_ARM_NEON): New macro. * src/global.c (hwflist): Add HWF_ARM_NEON entry. * src/hwf-arm.c: New file. * src/hwf-common.h (_gcry_hwf_detect_arm): New prototype. * src/hwfeatures.c (_gcry_detect_hw_features) [HAVE_CPU_ARCH_ARM]: Add call to _gcry_hwf_detect_arm. -- Add HW detection module for detecting ARM NEON instruction set. ARM does not have cpuid instruction so we have to rely on OS to pass feature set information to user-space. For linux, NEON support can be detected by parsing '/proc/self/auxv' for hardware capabilities information. For other OSes, NEON can be detected by checking if platform/compiler only supports NEON capable CPUs (by check if __ARM_NEON__ macro is defined). Signed-off-by: Jussi Kivilinna diff --git a/configure.ac b/configure.ac index b54b4d6..89b9366 100644 --- a/configure.ac +++ b/configure.ac @@ -595,6 +595,14 @@ AC_ARG_ENABLE(avx2-support, avx2support=$enableval,avx2support=yes) AC_MSG_RESULT($avx2support) +# Implementation of the --disable-neon-support switch. +AC_MSG_CHECKING([whether NEON support is requested]) +AC_ARG_ENABLE(neon-support, + AC_HELP_STRING([--disable-neon-support], + [Disable support for the ARM NEON instructions]), + neonsupport=$enableval,neonsupport=yes) +AC_MSG_RESULT($neonsupport) + # Implementation of the --disable-O-flag-munging switch. AC_MSG_CHECKING([whether a -O flag munging is requested]) AC_ARG_ENABLE([O-flag-munging], @@ -988,6 +996,30 @@ fi # +# Check whether GCC inline assembler supports NEON instructions +# +AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions], + [gcry_cv_gcc_inline_asm_neon], + [gcry_cv_gcc_inline_asm_neon=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[__asm__( + ".syntax unified\n\t" + ".thumb\n\t" + ".fpu neon\n\t" + "vld1.64 {%q0-%q1}, [%r0]!;\n\t" + "vrev64.8 %q0, %q3;\n\t" + "vadd.u64 %q0, %q1;\n\t" + "vadd.s64 %d3, %d2, %d3;\n\t" + ); + ]])], + [gcry_cv_gcc_inline_asm_neon=yes])]) +if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then + AC_DEFINE(HAVE_GCC_INLINE_ASM_NEON,1, + [Defined if inline assembler supports NEON instructions]) +fi + + +# # Check whether GCC assembler supports features needed for our ARM # implementations # @@ -1269,6 +1301,11 @@ if test x"$avx2support" = xyes ; then avx2support="no (unsupported by compiler)" fi fi +if test x"$neonsupport" = xyes ; then + if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then + neonsupport="no (unsupported by compiler)" + fi +fi if test x"$aesnisupport" = xyes ; then AC_DEFINE(ENABLE_AESNI_SUPPORT, 1, @@ -1282,6 +1319,10 @@ if test x"$avx2support" = xyes ; then AC_DEFINE(ENABLE_AVX2_SUPPORT,1, [Enable support for Intel AVX2 instructions.]) fi +if test x"$neonsupport" = xyes ; then + AC_DEFINE(ENABLE_NEON_SUPPORT,1, + [Enable support for ARM NEON instructions.]) +fi # Define conditional sources and config.h symbols depending on the @@ -1597,6 +1638,7 @@ case "$mpi_cpu_arch" in ;; arm) AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms]) + GCRYPT_HWF_MODULES="hwf-arm.lo" ;; esac AC_SUBST([GCRYPT_HWF_MODULES]) @@ -1660,6 +1702,7 @@ GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport]) GCRY_MSG_SHOW([Try using DRNG (RDRAND): ],[$drngsupport]) GCRY_MSG_SHOW([Try using Intel AVX: ],[$avxsupport]) GCRY_MSG_SHOW([Try using Intel AVX2: ],[$avx2support]) +GCRY_MSG_SHOW([Try using ARM NEON: ],[$neonsupport]) GCRY_MSG_SHOW([],[]) if test "$print_egd_notice" = "yes"; then diff --git a/src/Makefile.am b/src/Makefile.am index 8eb46e6..d4329c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,7 +64,7 @@ libgcrypt_la_SOURCES = \ ec-context.h \ ath.h ath.c -EXTRA_libgcrypt_la_SOURCES = hwf-x86.c +EXTRA_libgcrypt_la_SOURCES = hwf-x86.c hwf-arm.c gcrypt_hwf_modules = @GCRYPT_HWF_MODULES@ diff --git a/src/g10lib.h b/src/g10lib.h index 198ab38..31131a5 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -155,6 +155,8 @@ int _gcry_log_verbosity( int level ); #define HWF_INTEL_AVX 1024 #define HWF_INTEL_AVX2 2048 +#define HWF_ARM_NEON 4096 + unsigned int _gcry_get_hw_features (void); void _gcry_detect_hw_features (unsigned int); diff --git a/src/global.c b/src/global.c index 9c80573..44667cf 100644 --- a/src/global.c +++ b/src/global.c @@ -70,6 +70,7 @@ static struct { HWF_INTEL_RDRAND,"intel-rdrand" }, { HWF_INTEL_AVX, "intel-avx" }, { HWF_INTEL_AVX2, "intel-avx2" }, + { HWF_ARM_NEON, "arm-neon" }, { 0, NULL} }; diff --git a/src/hwf-arm.c b/src/hwf-arm.c new file mode 100644 index 0000000..9ab4cd0 --- /dev/null +++ b/src/hwf-arm.c @@ -0,0 +1,113 @@ +/* hwf-arm.c - Detect hardware features - ARM part + * Copyright ? 2013 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "hwf-common.h" + +#if !defined (__arm__) +# error Module build for wrong CPU. +#endif + +#undef HAS_SYS_AT_HWCAP +#ifdef __linux__ + +#define HAS_SYS_AT_HWCAP 1 + +#define AT_HWCAP 16 +#define HWCAP_NEON 4096 + +static int get_hwcap(unsigned int *hwcap) +{ + struct { unsigned int a_type; unsigned int a_val; } auxv; + FILE *f; + int err = -1; + static int hwcap_initialized = 0; + static unsigned int stored_hwcap; + + if (hwcap_initialized) + { + *hwcap = stored_hwcap; + return 0; + } + + f = fopen("/proc/self/auxv", "r"); + if (!f) + { + *hwcap = stored_hwcap; + return -1; + } + + while (fread(&auxv, sizeof(auxv), 1, f) > 0) + { + if (auxv.a_type != AT_HWCAP) + continue; + + stored_hwcap = auxv.a_val; + hwcap_initialized = 1; + err = 0; + break; + } + + fclose(f); + *hwcap = stored_hwcap; + return err; +} + +static unsigned int detect_arm_at_hwcap(void) +{ + unsigned int hwcap; + unsigned int features = 0; + + if (get_hwcap(&hwcap) < 0) + return features; + +#ifdef ENABLE_NEON_SUPPORT + if (hwcap & HWCAP_NEON) + features |= HWF_ARM_NEON; +#endif + + return features; +} + +#endif /* __linux__ */ + +unsigned int +_gcry_hwf_detect_arm (void) +{ + unsigned int ret = 0; + +#if defined (HAS_SYS_AT_HWCAP) + ret |= detect_arm_at_hwcap (); +#else + ret |= 0; +#endif + +#if defined(__ARM_NEON__) && defined(ENABLE_NEON_SUPPORT) + ret |= HWF_ARM_NEON; +#endif + + return ret; +} diff --git a/src/hwf-common.h b/src/hwf-common.h index 974f47d..8f156b5 100644 --- a/src/hwf-common.h +++ b/src/hwf-common.h @@ -21,6 +21,7 @@ #define HWF_COMMON_H unsigned int _gcry_hwf_detect_x86 (void); +unsigned int _gcry_hwf_detect_arm (void); #endif /*HWF_COMMON_H*/ diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 87d05d8..1e3c27d 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -59,6 +59,11 @@ _gcry_detect_hw_features (unsigned int disabled_features) hw_features = _gcry_hwf_detect_x86 (); } #endif /* HAVE_CPU_ARCH_X86 */ +#if defined (HAVE_CPU_ARCH_ARM) + { + hw_features = _gcry_hwf_detect_arm (); + } +#endif /* HAVE_CPU_ARCH_ARM */ hw_features &= ~disabled_features; } commit 7b0ebe69fe35f2ee13e1e1beb2766a1eaadb7f0c Author: Jussi Kivilinna Date: Sat Aug 31 12:48:30 2013 +0300 Correct mpi_cpu_arch for ARMv6 * mpi/config.links [armv6]: Set mpi_cpu_arch to "arm", instead of "armv6". -- Without this change, HAVE_CPU_ARCH_ARM stays undefined. Signed-off-by: Jussi Kivilinna diff --git a/mpi/config.links b/mpi/config.links index f300255..9fb4f10 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -141,7 +141,7 @@ case "${host}" in if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then echo '/* configured for armv6 */' >>./mpi/asm-syntax.h path="armv6" - mpi_cpu_arch="armv6" + mpi_cpu_arch="arm" else echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h path="" ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 2 +- cipher/sha512-armv7-neon.S | 316 +++++++++++++++++++++++++++++++++++++++++ cipher/sha512.c | 335 +++++++++++++++++++++++++++++++++++--------- configure.ac | 48 +++++++ mpi/config.links | 2 +- src/Makefile.am | 2 +- src/g10lib.h | 2 + src/global.c | 1 + src/hwf-arm.c | 113 +++++++++++++++ src/hwf-common.h | 1 + src/hwfeatures.c | 5 + 11 files changed, 759 insertions(+), 68 deletions(-) create mode 100644 cipher/sha512-armv7-neon.S create mode 100644 src/hwf-arm.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sun Sep 1 16:17:39 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 01 Sep 2013 16:17:39 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-203-gfd6721c 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 fd6721c235a5bdcb332c8eb708fbd4f96e52e824 (commit) from 99d15543b8d94a8f1ef66c6ccb862b0ce82c514d (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 fd6721c235a5bdcb332c8eb708fbd4f96e52e824 Author: Jussi Kivilinna Date: Sun Sep 1 16:46:32 2013 +0300 Fix building for x32 target * mpi/amd64/mpi-asm-defs.h: New file. * random/rndhw.c (poll_padlock) [__x86_64__]: Also check if __LP64__ is defined. [USE_DRNG, __x86_64__]: Also check if __LP64__ is defined. -- In short, x32 is new x86-64 ABI with 32-bit pointers. Adding support is straightforward, small fix for mpi and fixes for random/rndhw.c. AMD64 assembly functions appear to work fine with x32 and 'make check' passes. Signed-off-by: Jussi Kivilinna diff --git a/mpi/amd64/mpi-asm-defs.h b/mpi/amd64/mpi-asm-defs.h new file mode 100644 index 0000000..6519065 --- /dev/null +++ b/mpi/amd64/mpi-asm-defs.h @@ -0,0 +1,4 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG_LONG) diff --git a/random/rndhw.c b/random/rndhw.c index ca99c5f..e625512 100644 --- a/random/rndhw.c +++ b/random/rndhw.c @@ -69,7 +69,7 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), nbytes = 0; while (nbytes < 64) { -#ifdef __x86_64__ +#if defined(__x86_64__) && defined(__LP64__) asm volatile ("movq %1, %%rdi\n\t" /* Set buffer. */ "xorq %%rdx, %%rdx\n\t" /* Request up to 8 bytes. */ @@ -123,7 +123,7 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), #ifdef USE_DRNG # define RDRAND_RETRY_LOOPS 10 # define RDRAND_INT ".byte 0x0f,0xc7,0xf0" -# ifdef __x86_64__ +# if defined(__x86_64__) && defined(__LP64__) # define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0" # else # define RDRAND_LONG RDRAND_INT ----------------------------------------------------------------------- Summary of changes: mpi/{armv6 => amd64}/mpi-asm-defs.h | 2 +- random/rndhw.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) copy mpi/{armv6 => amd64}/mpi-asm-defs.h (73%) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sun Sep 1 20:43:21 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 01 Sep 2013 20:43:21 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-206-gf351524 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 f3515240de9513ead975985c9f8ab714022cac8e (commit) via 8b735cb563dff7aafbf8a970972522b5621e665c (commit) via d12828cd821a4b4428eae19de5aee02cf536e536 (commit) from fd6721c235a5bdcb332c8eb708fbd4f96e52e824 (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 f3515240de9513ead975985c9f8ab714022cac8e Author: Jussi Kivilinna Date: Sun Sep 1 16:50:55 2013 +0300 camellia-aesni-avx2-amd64: Move register clearing to assembly functions * cipher/camellia-aesni-avx2-amd64.S (_gcry_camellia_aesni_avx2_ctr_enc): Add 'vzeroall'. (_gcry_camellia_aesni_avx2_cbc_dec) (_gcry_camellia_aesni_avx2_cfb_dec): Add 'vzeroupper' at head and 'vzeroall' at tail. * cipher/camellia-glue.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec) (_gcry_serpent_avx2_cfb_dec) [USE_AESNI_AVX2]: Remove register clearing. -- Patch moves register clearing with 'vzeroall' to assembly functions and adds missing 'vzeroupper' instructions at head of assembly functions. Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index da427b4..7e31323 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -1104,6 +1104,8 @@ _gcry_camellia_aesni_avx2_ctr_enc: %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9, %ymm8, %rsi); + vzeroall; + ret; .size _gcry_camellia_aesni_avx2_ctr_enc,.-_gcry_camellia_aesni_avx2_ctr_enc; @@ -1119,6 +1121,8 @@ _gcry_camellia_aesni_avx2_cbc_dec: * %rcx: iv */ + vzeroupper; + movq %rcx, %r9; cmpl $128, key_bitlength(CTX); @@ -1171,6 +1175,8 @@ _gcry_camellia_aesni_avx2_cbc_dec: movq %rax, (0)(%r9); movq %rcx, (8)(%r9); + vzeroall; + ret; .size _gcry_camellia_aesni_avx2_cbc_dec,.-_gcry_camellia_aesni_avx2_cbc_dec; @@ -1186,6 +1192,8 @@ _gcry_camellia_aesni_avx2_cfb_dec: * %rcx: iv */ + vzeroupper; + movq %rsp, %r10; subq $(16 * 32), %rsp; andq $~31, %rsp; @@ -1240,6 +1248,8 @@ _gcry_camellia_aesni_avx2_cfb_dec: %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9, %ymm8, %rsi); + vzeroall; + ret; .size _gcry_camellia_aesni_avx2_cfb_dec,.-_gcry_camellia_aesni_avx2_cfb_dec; diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 7d8a4cd..d6d6005 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -314,9 +314,6 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *); - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } @@ -408,9 +405,6 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *); - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } @@ -496,9 +490,6 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv, int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *); - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } commit 8b735cb563dff7aafbf8a970972522b5621e665c Author: Jussi Kivilinna Date: Sun Sep 1 16:50:55 2013 +0300 camellia-aesni-avx-amd64: Move register clearing to assembly functions * cipher/camellia-aesni-avx-amd64.S (_gcry_camellia_aesni_avx_ctr_enc) (_gcry_camellia_aesni_avx_cbc_dec) (_gcry_camellia_aesni_avx_cfb_dec): Add 'vzeroupper' at head and 'vzeroall' at tail. * cipher/camellia-glue.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec) (_gcry_serpent_avx2_cfb_dec) [USE_AESNI_AVX]: Remove register clearing. -- Patch moves register clearing with 'vzeroall' to assembly functions and adds missing 'vzeroupper' instructions at head of assembly functions. Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index b0ef5fd..9873d98 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -958,6 +958,8 @@ _gcry_camellia_aesni_avx_ctr_enc: * %rcx: iv (big endian, 128bit) */ + vzeroupper; + subq $(16 * 16), %rsp; movq %rsp, %rax; @@ -1054,6 +1056,8 @@ _gcry_camellia_aesni_avx_ctr_enc: %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + vzeroall; + ret; .size _gcry_camellia_aesni_avx_ctr_enc,.-_gcry_camellia_aesni_avx_ctr_enc; @@ -1069,6 +1073,8 @@ _gcry_camellia_aesni_avx_cbc_dec: * %rcx: iv */ + vzeroupper; + movq %rcx, %r9; cmpl $128, key_bitlength(CTX); @@ -1114,6 +1120,8 @@ _gcry_camellia_aesni_avx_cbc_dec: movq %r10, (0)(%r9); movq %r11, (8)(%r9); + vzeroall; + ret; .size _gcry_camellia_aesni_avx_cbc_dec,.-_gcry_camellia_aesni_avx_cbc_dec; @@ -1129,6 +1137,8 @@ _gcry_camellia_aesni_avx_cfb_dec: * %rcx: iv */ + vzeroupper; + subq $(16 * 16), %rsp; movq %rsp, %rax; @@ -1179,6 +1189,8 @@ _gcry_camellia_aesni_avx_cfb_dec: %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + vzeroall; + ret; .size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec; diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 6e2319d..7d8a4cd 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -344,9 +344,6 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, if (did_use_aesni_avx) { - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *)) burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *); } @@ -440,9 +437,6 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, if (did_use_aesni_avx) { - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *)) burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *); } @@ -531,9 +525,6 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv, if (did_use_aesni_avx) { - /* clear AVX registers */ - asm volatile ("vzeroall;\n":::); - if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *)) burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *); } commit d12828cd821a4b4428eae19de5aee02cf536e536 Author: Jussi Kivilinna Date: Sun Sep 1 16:50:55 2013 +0300 serpent-avx2-amd64: Move register clearing to assembly * cipher/serpent-avx2-amd64.S (_gcry_serpent_avx2_ctr_enc) (_gcry_serpent_avx2_cbc_dec, _gcry_serpent_avx2_cfb_dec): Change last 'vzeroupper' to 'vzeroall'. * cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec) (_gcry_serpent_avx2_cfb_dec) [USE_AVX2]: Remove register clearing with 'vzeroall'. -- AVX2 implementation was already clearing upper halfs of YMM registers at end of assembly functions to prevent long SSE<->AVX transition stalls present on Intel CPUs. Patch changes these 'vzeroupper' instructions to 'vzeroall' to fully clear YMM registers. After this change register clearing in serpent.c in not needed. Signed-off-by: Jussi Kivilinna diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S index 7586c0c..c726e7b 100644 --- a/cipher/serpent-avx2-amd64.S +++ b/cipher/serpent-avx2-amd64.S @@ -730,7 +730,7 @@ _gcry_serpent_avx2_ctr_enc: vmovdqu RB2, (6 * 32)(%rsi); vmovdqu RB3, (7 * 32)(%rsi); - vzeroupper; + vzeroall; ret .size _gcry_serpent_avx2_ctr_enc,.-_gcry_serpent_avx2_ctr_enc; @@ -799,7 +799,7 @@ _gcry_serpent_avx2_cbc_dec: vmovdqu RB2, (6 * 32)(%rsi); vmovdqu RB3, (7 * 32)(%rsi); - vzeroupper; + vzeroall; ret .size _gcry_serpent_avx2_cbc_dec,.-_gcry_serpent_avx2_cbc_dec; @@ -870,7 +870,7 @@ _gcry_serpent_avx2_cfb_dec: vmovdqu RB2, (6 * 32)(%rsi); vmovdqu RB3, (7 * 32)(%rsi); - vzeroupper; + vzeroall; ret .size _gcry_serpent_avx2_cfb_dec,.-_gcry_serpent_avx2_cfb_dec; diff --git a/cipher/serpent.c b/cipher/serpent.c index bf03fe7..430a7e9 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -845,9 +845,6 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, if (did_use_avx2) { - /* clear avx2 registers used by serpent-sse2 */ - asm volatile ("vzeroall;\n":::); - /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; @@ -937,9 +934,6 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv, if (did_use_avx2) { - /* clear avx2 registers used by serpent-sse2 */ - asm volatile ("vzeroall;\n":::); - /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; @@ -1023,9 +1017,6 @@ _gcry_serpent_cfb_dec(void *context, unsigned char *iv, if (did_use_avx2) { - /* clear avx2 registers used by serpent-sse2 */ - asm volatile ("vzeroall;\n":::); - /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; ----------------------------------------------------------------------- Summary of changes: cipher/camellia-aesni-avx-amd64.S | 12 ++++++++++++ cipher/camellia-aesni-avx2-amd64.S | 10 ++++++++++ cipher/camellia-glue.c | 18 ------------------ cipher/serpent-avx2-amd64.S | 6 +++--- cipher/serpent.c | 9 --------- 5 files changed, 25 insertions(+), 30 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 4 09:32:09 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Wed, 04 Sep 2013 09:32:09 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-208-g4b0edf5 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 4b0edf53440239d3bcc95941980c062a0801a149 (commit) via a3aaa6ad03388ea3eaa24304b604cb864633332f (commit) from f3515240de9513ead975985c9f8ab714022cac8e (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 4b0edf53440239d3bcc95941980c062a0801a149 Author: Jussi Kivilinna Date: Wed Sep 4 10:00:45 2013 +0300 Make _gcry_burn_stack use variable length array * configure.ac (HAVE_VLA): Add check. * src/misc.c (_gcry_burn_stack) [HAVE_VLA]: Add VLA code. -- Some gcc versions convert _gcry_burn_stack into loop that overwrites the same 64-byte stack buffer instead of burn stack deeper. It's argued at GCC bugzilla that _gcry_burn_stack is doing wrong thing here [1] and that this kind of optimization is allowed. So lets fix _gcry_burn_stack by using variable length array when VLAs are supported by compiler. This should ensure proper stack burning to the requested depth and avoid GCC loop optimizations. [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52285 Signed-off-by: Jussi Kivilinna diff --git a/configure.ac b/configure.ac index 959327a..993577b 100644 --- a/configure.ac +++ b/configure.ac @@ -764,6 +764,24 @@ case "${host}" in esac AC_SUBST(FALLBACK_SOCKLEN_T) + +# +# Check for VLA support (variable length arrays). +# +AC_CACHE_CHECK(whether the variable length arrays are supported, + [gcry_cv_have_vla], + [gcry_cv_have_vla=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[void f1(char *, int); + char foo(int i) { + char b[(i < 0 ? 0 : i) + 1]; + f1(b, sizeof b); return b[0];}]])], + [gcry_cv_have_vla=yes])]) +if test "$gcry_cv_have_vla" = "yes" ; then + AC_DEFINE(HAVE_VLA,1, [Defined if variable length arrays are supported]) +fi + + # # Check for ELF visibility support. # diff --git a/src/misc.c b/src/misc.c index 2d9c73a..135aeb4 100644 --- a/src/misc.c +++ b/src/misc.c @@ -290,13 +290,20 @@ _gcry_log_printhex (const char *text, const void *buffer, size_t length) void _gcry_burn_stack (int bytes) { - char buf[64]; +#ifdef HAVE_VLA + int buflen = (((bytes <= 0) ? 1 : bytes) + 63) & ~63; + volatile char buf[buflen]; + + wipememory (buf, sizeof buf); +#else + volatile char buf[64]; wipememory (buf, sizeof buf); bytes -= sizeof buf; if (bytes > 0) _gcry_burn_stack (bytes); +#endif } void commit a3aaa6ad03388ea3eaa24304b604cb864633332f Author: Jussi Kivilinna Date: Wed Sep 4 10:00:45 2013 +0300 Move stack burning from block ciphers to cipher modes * src/gcrypt-module.h (gcry_cipher_encrypt_t) (gcry_cipher_decrypt_t): Return 'unsigned int'. * cipher/cipher.c (dummy_encrypt_block, dummy_decrypt_block): Return zero. (do_ecb_encrypt, do_ecb_decrypt): Get largest stack burn depth from block cipher crypt function and burn stack at end. * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt) (_gcry_cipher_aeswrap_decrypt): Ditto. * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt) (_gcry_cipher_cbc_decrypt): Ditto. * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt) (_gcry_cipher_cfb_decrypt): Ditto. * cipher/cipher-ctr.c (_gcry_cipher_cbc_encrypt): Ditto. * cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt) (_gcry_cipher_ofb_decrypt): Ditto. * cipher/blowfish.c (encrypt_block, decrypt_block): Return burn stack depth. * cipher/camellia-glue.c (camellia_encrypt, camellia_decrypt): Ditto. * cipher/cast5.c (encrypt_block, decrypt_block): Ditto. * cipher/des.c (do_tripledes_encrypt, do_tripledes_decrypt) (do_des_encrypt, do_des_decrypt): Ditto. * cipher/idea.c (idea_encrypt, idea_decrypt): Ditto. * cipher/rijndael.c (rijndael_encrypt, rijndael_decrypt): Ditto. * cipher/seed.c (seed_encrypt, seed_decrypt): Ditto. * cipher/serpent.c (serpent_encrypt, serpent_decrypt): Ditto. * cipher/twofish.c (twofish_encrypt, twofish_decrypt): Ditto. * cipher/rfc2268.c (encrypt_block, decrypt_block): New. (_gcry_cipher_spec_rfc2268_40): Use encrypt_block and decrypt_block. -- Patch moves stack burning from block ciphers and cipher mode loop to end of cipher mode functions. This greatly reduces the overall CPU usage of the problematic _gcry_burn_stack. Internal cipher module API is changed so that encrypt/decrypt functions now return the stack burn depth as unsigned int to cipher mode function. (Note, patch also adds missing burn_stack for RFC2268_40 cipher). _gcry_burn_stack CPU time (looping tests/benchmark cipher blowfish): arch CPU Old New i386 Intel-Haswell 4.1% 0.16% x86_64 Intel-Haswell 3.4% 0.07% armhf Cortex-A8 8.7% 0.14% New vs. old (armhf/Cortex-A8): ECB/Stream CBC CFB OFB CTR --------------- --------------- --------------- --------------- --------------- IDEA 1.05x 1.05x 1.04x 1.04x 1.04x 1.04x 1.07x 1.05x 1.04x 1.04x 3DES 1.04x 1.03x 1.04x 1.03x 1.04x 1.04x 1.04x 1.04x 1.04x 1.04x CAST5 1.19x 1.20x 1.15x 1.00x 1.17x 1.00x 1.15x 1.05x 1.00x 1.00x BLOWFISH 1.21x 1.22x 1.16x 1.00x 1.18x 1.00x 1.16x 1.16x 1.00x 1.00x AES 1.09x 1.09x 1.00x 1.00x 1.00x 1.00x 1.07x 1.07x 1.00x 1.00x AES192 1.11x 1.11x 1.00x 1.00x 1.00x 1.00x 1.08x 1.09x 1.01x 1.00x AES256 1.07x 1.08x 1.01x .99x 1.00x 1.00x 1.07x 1.06x 1.00x 1.00x TWOFISH 1.10x 1.09x 1.09x 1.00x 1.09x 1.00x 1.08x 1.09x 1.00x 1.00x ARCFOUR 1.00x 1.00x DES 1.07x 1.11x 1.06x 1.08x 1.07x 1.07x 1.06x 1.06x 1.06x 1.06x TWOFISH128 1.10x 1.10x 1.09x 1.00x 1.09x 1.00x 1.08x 1.08x 1.00x 1.00x SERPENT128 1.06x 1.07x 1.02x 1.00x 1.06x 1.00x 1.06x 1.05x 1.00x 1.00x SERPENT192 1.07x 1.06x 1.03x 1.00x 1.06x 1.00x 1.06x 1.05x 1.00x 1.00x SERPENT256 1.06x 1.07x 1.02x 1.00x 1.06x 1.00x 1.05x 1.06x 1.00x 1.00x RFC2268_40 0.97x 1.01x 0.99x 0.98x 1.00x 0.97x 0.96x 0.96x 0.97x 0.97x SEED 1.45x 1.54x 1.53x 1.56x 1.50x 1.51x 1.50x 1.50x 1.42x 1.42x CAMELLIA128 1.08x 1.07x 1.06x 1.00x 1.07x 1.00x 1.06x 1.06x 1.00x 1.00x CAMELLIA192 1.08x 1.08x 1.08x 1.00x 1.07x 1.00x 1.07x 1.07x 1.00x 1.00x CAMELLIA256 1.08x 1.09x 1.07x 1.01x 1.08x 1.00x 1.07x 1.07x 1.00x 1.00x SALSA20 .99x 1.00x Raw data: New (armhf/Cortex-A8): Running each test 100 times. ECB/Stream CBC CFB OFB CTR --------------- --------------- --------------- --------------- --------------- IDEA 8620ms 8680ms 9640ms 10010ms 9140ms 8960ms 9630ms 9660ms 9180ms 9180ms 3DES 13990ms 14000ms 14780ms 15300ms 14320ms 14370ms 14780ms 14780ms 14480ms 14480ms CAST5 2980ms 2980ms 3780ms 2300ms 3290ms 2320ms 3770ms 4100ms 2320ms 2320ms BLOWFISH 2740ms 2660ms 3530ms 2060ms 3050ms 2080ms 3530ms 3530ms 2070ms 2070ms AES 2200ms 2330ms 2330ms 2450ms 2270ms 2270ms 2700ms 2690ms 2330ms 2320ms AES192 2550ms 2670ms 2700ms 2910ms 2630ms 2640ms 3060ms 3060ms 2680ms 2690ms AES256 2920ms 3010ms 3040ms 3190ms 3010ms 3000ms 3380ms 3420ms 3050ms 3050ms TWOFISH 2790ms 2840ms 3300ms 2950ms 3010ms 2870ms 3310ms 3280ms 2940ms 2940ms ARCFOUR 2050ms 2050ms DES 5640ms 5630ms 6440ms 6970ms 5960ms 6000ms 6440ms 6440ms 6120ms 6120ms TWOFISH128 2790ms 2840ms 3300ms 2950ms 3010ms 2890ms 3310ms 3290ms 2930ms 2930ms SERPENT128 4530ms 4340ms 5210ms 4470ms 4740ms 4620ms 5020ms 5030ms 4680ms 4680ms SERPENT192 4510ms 4340ms 5190ms 4460ms 4750ms 4620ms 5020ms 5030ms 4680ms 4680ms SERPENT256 4540ms 4330ms 5220ms 4460ms 4730ms 4600ms 5030ms 5020ms 4680ms 4680ms RFC2268_40 10530ms 7790ms 11140ms 9490ms 10650ms 10710ms 11710ms 11690ms 11000ms 11000ms SEED 4530ms 4540ms 5050ms 5380ms 4760ms 4810ms 5060ms 5060ms 4850ms 4860ms CAMELLIA128 2660ms 2630ms 3170ms 2750ms 2880ms 2740ms 3170ms 3170ms 2780ms 2780ms CAMELLIA192 3430ms 3400ms 3930ms 3530ms 3650ms 3500ms 3940ms 3940ms 3570ms 3560ms CAMELLIA256 3430ms 3390ms 3940ms 3500ms 3650ms 3510ms 3930ms 3940ms 3550ms 3550ms SALSA20 1910ms 1900ms Old (armhf/Cortex-A8): Running each test 100 times. ECB/Stream CBC CFB OFB CTR --------------- --------------- --------------- --------------- --------------- IDEA 9030ms 9100ms 10050ms 10410ms 9540ms 9360ms 10350ms 10190ms 9560ms 9570ms 3DES 14580ms 14460ms 15300ms 15720ms 14880ms 14900ms 15350ms 15330ms 15030ms 15020ms CAST5 3560ms 3570ms 4350ms 2300ms 3860ms 2330ms 4340ms 4320ms 2330ms 2320ms BLOWFISH 3320ms 3250ms 4110ms 2060ms 3610ms 2080ms 4100ms 4090ms 2070ms 2070ms AES 2390ms 2530ms 2320ms 2460ms 2280ms 2270ms 2890ms 2880ms 2330ms 2330ms AES192 2830ms 2970ms 2690ms 2900ms 2630ms 2650ms 3320ms 3330ms 2700ms 2690ms AES256 3110ms 3250ms 3060ms 3170ms 3000ms 3000ms 3610ms 3610ms 3050ms 3060ms TWOFISH 3080ms 3100ms 3600ms 2940ms 3290ms 2880ms 3560ms 3570ms 2940ms 2930ms ARCFOUR 2060ms 2050ms DES 6060ms 6230ms 6850ms 7540ms 6380ms 6400ms 6830ms 6840ms 6500ms 6510ms TWOFISH128 3060ms 3110ms 3600ms 2940ms 3290ms 2890ms 3560ms 3560ms 2940ms 2930ms SERPENT128 4820ms 4630ms 5330ms 4460ms 5030ms 4620ms 5300ms 5300ms 4680ms 4680ms SERPENT192 4830ms 4620ms 5320ms 4460ms 5040ms 4620ms 5300ms 5300ms 4680ms 4680ms SERPENT256 4820ms 4640ms 5330ms 4460ms 5030ms 4620ms 5300ms 5300ms 4680ms 4660ms RFC2268_40 10260ms 7850ms 11080ms 9270ms 10620ms 10380ms 11250ms 11230ms 10690ms 10710ms SEED 6580ms 6990ms 7710ms 8370ms 7140ms 7240ms 7600ms 7610ms 6870ms 6900ms CAMELLIA128 2860ms 2820ms 3360ms 2750ms 3080ms 2740ms 3350ms 3360ms 2790ms 2790ms CAMELLIA192 3710ms 3680ms 4240ms 3520ms 3910ms 3510ms 4200ms 4210ms 3560ms 3560ms CAMELLIA256 3700ms 3680ms 4230ms 3520ms 3930ms 3510ms 4200ms 4210ms 3550ms 3560ms SALSA20 1900ms 1900ms Signed-off-by: Jussi Kivilinna diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 2806433..80e1ec7 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -67,8 +67,8 @@ typedef struct { } BLOWFISH_context; static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen); -static void encrypt_block (void *bc, byte *outbuf, const byte *inbuf); -static void decrypt_block (void *bc, byte *outbuf, const byte *inbuf); +static unsigned int encrypt_block (void *bc, byte *outbuf, const byte *inbuf); +static unsigned int decrypt_block (void *bc, byte *outbuf, const byte *inbuf); /* precomputed S boxes */ @@ -298,18 +298,20 @@ do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) _gcry_blowfish_amd64_decrypt_block (context, outbuf, inbuf); } -static void encrypt_block (void *context , byte *outbuf, const byte *inbuf) +static unsigned int +encrypt_block (void *context , byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_encrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (2*8); + return /*burn_stack*/ (2*8); } -static void decrypt_block (void *context, byte *outbuf, const byte *inbuf) +static unsigned int +decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_decrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (2*8); + return /*burn_stack*/ (2*8); } #elif defined(USE_ARMV6_ASM) @@ -352,18 +354,20 @@ do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) _gcry_blowfish_armv6_decrypt_block (context, outbuf, inbuf); } -static void encrypt_block (void *context , byte *outbuf, const byte *inbuf) +static unsigned int +encrypt_block (void *context , byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_encrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (10*4); + return /*burn_stack*/ (10*4); } -static void decrypt_block (void *context, byte *outbuf, const byte *inbuf) +static unsigned int +decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_decrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (10*4); + return /*burn_stack*/ (10*4); } #else /*USE_ARMV6_ASM*/ @@ -553,12 +557,12 @@ do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf ) outbuf[7] = d2 & 0xff; } -static void +static unsigned int encrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *bc = (BLOWFISH_context *) context; do_encrypt_block (bc, outbuf, inbuf); - _gcry_burn_stack (64); + return /*burn_stack*/ (64); } @@ -580,12 +584,12 @@ do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf) outbuf[7] = d2 & 0xff; } -static void +static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *bc = (BLOWFISH_context *) context; do_decrypt_block (bc, outbuf, inbuf); - _gcry_burn_stack (64); + return /*burn_stack*/ (64); } #endif /*!USE_AMD64_ASM&&!USE_ARMV6_ASM*/ diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index d6d6005..2842c3b 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -222,27 +222,27 @@ static void Camellia_DecryptBlock(const int keyBitLength, keyBitLength); } -static void +static unsigned int camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx = c; Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); #define CAMELLIA_encrypt_stack_burn_size (15*4) - _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size); + return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size); } -static void +static unsigned int camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); #define CAMELLIA_decrypt_stack_burn_size (15*4) - _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size); + return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size); } #else /*USE_ARMV6_ASM*/ -static void +static unsigned int camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; @@ -256,10 +256,10 @@ camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) +2*2*sizeof(void*) /* Function calls. */ \ ) - _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size); + return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size); } -static void +static unsigned int camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; @@ -273,7 +273,7 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) +2*2*sizeof(void*) /* Function calls. */ \ ) - _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size); + return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size); } #endif /*!USE_ARMV6_ASM*/ diff --git a/cipher/cast5.c b/cipher/cast5.c index 4377c28..0cd5953 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -71,8 +71,8 @@ typedef struct { } CAST5_context; static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen); -static void encrypt_block (void *c, byte *outbuf, const byte *inbuf); -static void decrypt_block (void *c, byte *outbuf, const byte *inbuf); +static unsigned int encrypt_block (void *c, byte *outbuf, const byte *inbuf); +static unsigned int decrypt_block (void *c, byte *outbuf, const byte *inbuf); @@ -383,18 +383,20 @@ do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) _gcry_cast5_amd64_decrypt_block (context, outbuf, inbuf); } -static void encrypt_block (void *context , byte *outbuf, const byte *inbuf) +static unsigned int +encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (2*8); + return /*burn_stack*/ (2*8); } -static void decrypt_block (void *context, byte *outbuf, const byte *inbuf) +static unsigned int +decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; _gcry_cast5_amd64_decrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (2*8); + return /*burn_stack*/ (2*8); } #elif defined(USE_ARMV6_ASM) @@ -428,18 +430,20 @@ do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) _gcry_cast5_armv6_decrypt_block (context, outbuf, inbuf); } -static void encrypt_block (void *context , byte *outbuf, const byte *inbuf) +static unsigned int +encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (10*4); + return /*burn_stack*/ (10*4); } -static void decrypt_block (void *context, byte *outbuf, const byte *inbuf) +static unsigned int +decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_decrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (10*4); + return /*burn_stack*/ (10*4); } #else /*USE_ARMV6_ASM*/ @@ -519,12 +523,12 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) outbuf[7] = l & 0xff; } -static void +static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (20+4*sizeof(void*)); + return /*burn_stack*/ (20+4*sizeof(void*)); } @@ -569,12 +573,12 @@ do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) outbuf[7] = l & 0xff; } -static void +static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_decrypt_block (c, outbuf, inbuf); - _gcry_burn_stack (20+4*sizeof(void*)); + return /*burn_stack*/ (20+4*sizeof(void*)); } #endif /*!USE_ARMV6_ASM*/ diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index 8e117eb..931dec1 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -42,6 +42,7 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, unsigned int n, i; unsigned char *r, *a, *b; unsigned char t[8]; + unsigned int burn, nburn; #if MAX_BLOCKSIZE < 8 #error Invalid block size @@ -64,6 +65,8 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, if (n < 2) return GPG_ERR_INV_ARG; + burn = 0; + r = outbuf; a = outbuf; /* We store A directly in OUTBUF. */ b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ @@ -87,7 +90,8 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, /* B := AES_k( A | R[i] ) */ memcpy (b, a, 8); memcpy (b+8, r+i*8, 8); - c->cipher->encrypt (&c->context.c, b, b); + nburn = c->cipher->encrypt (&c->context.c, b, b); + burn = nburn > burn ? nburn : burn; /* t := t + 1 */ for (x = 7; x >= 0; x--) { @@ -102,6 +106,9 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, } } + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } @@ -117,6 +124,7 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, unsigned int n, i; unsigned char *r, *a, *b; unsigned char t[8]; + unsigned int burn, nburn; #if MAX_BLOCKSIZE < 8 #error Invalid block size @@ -140,6 +148,8 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, if (n < 3) return GPG_ERR_INV_ARG; + burn = 0; + r = outbuf; a = c->lastiv; /* We use c->LASTIV as buffer for A. */ b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ @@ -163,7 +173,8 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, /* B := AES_k^1( (A ^ t)| R[i] ) */ buf_xor(b, a, t, 8); memcpy (b+8, r+(i-1)*8, 8); - c->cipher->decrypt (&c->context.c, b, b); + nburn = c->cipher->decrypt (&c->context.c, b, b); + burn = nburn > burn ? nburn : burn; /* t := t - 1 */ for (x = 7; x >= 0; x--) { @@ -191,5 +202,9 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, break; } } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return j? GPG_ERR_CHECKSUM : 0; } diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c index 0d30f63..55a1c74 100644 --- a/cipher/cipher-cbc.c +++ b/cipher/cipher-cbc.c @@ -42,6 +42,7 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, int i; size_t blocksize = c->cipher->blocksize; unsigned nblocks = inbuflen / blocksize; + unsigned int burn, nburn; if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) return GPG_ERR_BUFFER_TOO_SHORT; @@ -51,6 +52,8 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, && (c->flags & GCRY_CIPHER_CBC_CTS))) return GPG_ERR_INV_LENGTH; + burn = 0; + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { if ((inbuflen % blocksize) == 0) @@ -70,7 +73,8 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, for (n=0; n < nblocks; n++ ) { buf_xor(outbuf, inbuf, c->u_iv.iv, blocksize); - c->cipher->encrypt ( &c->context.c, outbuf, outbuf ); + nburn = c->cipher->encrypt ( &c->context.c, outbuf, outbuf ); + burn = nburn > burn ? nburn : burn; memcpy (c->u_iv.iv, outbuf, blocksize ); inbuf += blocksize; if (!(c->flags & GCRY_CIPHER_CBC_MAC)) @@ -100,10 +104,14 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, for (; i < blocksize; i++) outbuf[i] = 0 ^ *ivp++; - c->cipher->encrypt (&c->context.c, outbuf, outbuf); + nburn = c->cipher->encrypt (&c->context.c, outbuf, outbuf); + burn = nburn > burn ? nburn : burn; memcpy (c->u_iv.iv, outbuf, blocksize); } + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } @@ -117,6 +125,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, int i; size_t blocksize = c->cipher->blocksize; unsigned int nblocks = inbuflen / blocksize; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -126,6 +135,8 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, && (c->flags & GCRY_CIPHER_CBC_CTS))) return GPG_ERR_INV_LENGTH; + burn = 0; + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { nblocks--; @@ -148,7 +159,8 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, * save the original ciphertext block. We use LASTIV for * this here because it is not used otherwise. */ memcpy (c->lastiv, inbuf, blocksize); - c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + nburn = c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + burn = nburn > burn ? nburn : burn; buf_xor(outbuf, outbuf, c->u_iv.iv, blocksize); memcpy(c->u_iv.iv, c->lastiv, blocksize ); inbuf += c->cipher->blocksize; @@ -168,16 +180,21 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ - c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + nburn = c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + burn = nburn > burn ? nburn : burn; buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes); memcpy(outbuf + blocksize, outbuf, restbytes); for(i=restbytes; i < blocksize; i++) c->u_iv.iv[i] = outbuf[i]; - c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv); + nburn = c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv); + burn = nburn > burn ? nburn : burn; buf_xor(outbuf, outbuf, c->lastiv, blocksize); /* c->lastiv is now really lastlastiv, does this matter? */ } + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index ed84b75..f772280 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -39,6 +39,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, unsigned char *ivp; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -53,6 +54,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, return 0; } + burn = 0; + if ( c->unused ) { /* XOR the input with the IV and store input into IV */ @@ -80,7 +83,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, while ( inbuflen >= blocksize_x_2 ) { /* Encrypt the IV. */ - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; @@ -93,7 +97,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, { /* Save the current IV and then encrypt the IV. */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; @@ -104,7 +109,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, { /* Save the current IV and then encrypt the IV. */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; c->unused = blocksize; /* Apply the XOR. */ c->unused -= inbuflen; @@ -113,6 +119,10 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, inbuf += inbuflen; inbuflen = 0; } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } @@ -125,6 +135,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, unsigned char *ivp; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -139,6 +150,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, return 0; } + burn = 0; + if (c->unused) { /* XOR the input with the IV and store input into IV. */ @@ -166,7 +179,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, while (inbuflen >= blocksize_x_2 ) { /* Encrypt the IV. */ - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; @@ -179,7 +193,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; @@ -191,7 +206,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; c->unused = blocksize; /* Apply the XOR. */ c->unused -= inbuflen; @@ -200,5 +216,9 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, inbuf += inbuflen; inbuflen = 0; } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c index 6bc6ffc..ff1742c 100644 --- a/cipher/cipher-ctr.c +++ b/cipher/cipher-ctr.c @@ -40,10 +40,13 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, int i; unsigned int blocksize = c->cipher->blocksize; unsigned int nblocks; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; + burn = 0; + /* First process a left over encrypted counter. */ if (c->unused) { @@ -57,7 +60,6 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, inbuflen -= n; } - /* Use a bulk method if available. */ nblocks = inbuflen / blocksize; if (nblocks && c->bulk.ctr_enc) @@ -75,7 +77,8 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, unsigned char tmp[MAX_BLOCKSIZE]; do { - c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + nburn = c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + burn = nburn > burn ? nburn : burn; for (i = blocksize; i > 0; i--) { @@ -100,5 +103,8 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, wipememory (tmp, sizeof tmp); } + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c index e194976..3fb9b0d 100644 --- a/cipher/cipher-ofb.c +++ b/cipher/cipher-ofb.c @@ -38,6 +38,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, { unsigned char *ivp; size_t blocksize = c->cipher->blocksize; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -52,6 +53,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, return 0; } + burn = 0; + if( c->unused ) { inbuflen -= c->unused; @@ -67,7 +70,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, { /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; @@ -76,7 +80,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, if ( inbuflen ) { /* process the remaining bytes */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; c->unused = blocksize; c->unused -= inbuflen; buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen); @@ -84,6 +89,10 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, inbuf += inbuflen; inbuflen = 0; } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } @@ -95,6 +104,7 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c, { unsigned char *ivp; size_t blocksize = c->cipher->blocksize; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -108,6 +118,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c, return 0; } + burn = 0; + if ( c->unused ) { inbuflen -= c->unused; @@ -123,7 +135,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c, { /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; @@ -133,7 +146,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c, { /* Process the remaining bytes. */ /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); - c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; c->unused = blocksize; c->unused -= inbuflen; buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen); @@ -141,5 +155,9 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c, inbuf += inbuflen; inbuflen = 0; } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } diff --git a/cipher/cipher.c b/cipher/cipher.c index 08d6165..2337c09 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -150,7 +150,7 @@ dummy_setkey (void *c, const unsigned char *key, unsigned int keylen) return GPG_ERR_NO_ERROR; } -static void +static unsigned int dummy_encrypt_block (void *c, unsigned char *outbuf, const unsigned char *inbuf) { @@ -158,9 +158,10 @@ dummy_encrypt_block (void *c, (void)outbuf; (void)inbuf; BUG(); + return 0; } -static void +static unsigned int dummy_decrypt_block (void *c, unsigned char *outbuf, const unsigned char *inbuf) { @@ -168,6 +169,7 @@ dummy_decrypt_block (void *c, (void)outbuf; (void)inbuf; BUG(); + return 0; } static void @@ -902,6 +904,7 @@ do_ecb_encrypt (gcry_cipher_hd_t c, { unsigned int blocksize = c->cipher->blocksize; unsigned int n, nblocks; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; @@ -909,13 +912,19 @@ do_ecb_encrypt (gcry_cipher_hd_t c, return GPG_ERR_INV_LENGTH; nblocks = inbuflen / c->cipher->blocksize; + burn = 0; for (n=0; n < nblocks; n++ ) { - c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + nburn = c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + burn = nburn > burn ? nburn : burn; inbuf += blocksize; outbuf += blocksize; } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } @@ -926,20 +935,27 @@ do_ecb_decrypt (gcry_cipher_hd_t c, { unsigned int blocksize = c->cipher->blocksize; unsigned int n, nblocks; + unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; if ((inbuflen % blocksize)) return GPG_ERR_INV_LENGTH; + nblocks = inbuflen / c->cipher->blocksize; + burn = 0; for (n=0; n < nblocks; n++ ) { - c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + nburn = c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + burn = nburn > burn ? nburn : burn; inbuf += blocksize; outbuf += blocksize; } + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + return 0; } diff --git a/cipher/des.c b/cipher/des.c index 96b06ae..7db9e5d 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -1054,21 +1054,21 @@ do_tripledes_set_extra_info (void *context, int what, } -static void +static unsigned int do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); - _gcry_burn_stack (32); + return /*burn_stack*/ (32); } -static void +static unsigned int do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); - _gcry_burn_stack (32); + return /*burn_stack*/ (32); } static gcry_err_code_t @@ -1091,22 +1091,22 @@ do_des_setkey (void *context, const byte *key, unsigned keylen) } -static void +static unsigned int do_des_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_encrypt ( ctx, inbuf, outbuf ); - _gcry_burn_stack (32); + return /*burn_stack*/ (32); } -static void +static unsigned int do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_decrypt ( ctx, inbuf, outbuf ); - _gcry_burn_stack (32); + return /*burn_stack*/ (32); } diff --git a/cipher/idea.c b/cipher/idea.c index c025c95..6e81e84 100644 --- a/cipher/idea.c +++ b/cipher/idea.c @@ -272,12 +272,12 @@ encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) cipher( outbuf, inbuf, c->ek ); } -static void +static unsigned int idea_encrypt (void *context, byte *out, const byte *in) { IDEA_context *ctx = context; encrypt_block (ctx, out, in); - _gcry_burn_stack (24+3*sizeof (void*)); + return /*burn_stack*/ (24+3*sizeof (void*)); } static void @@ -290,12 +290,12 @@ decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) cipher( outbuf, inbuf, c->dk ); } -static void +static unsigned int idea_decrypt (void *context, byte *out, const byte *in) { IDEA_context *ctx = context; decrypt_block (ctx, out, in); - _gcry_burn_stack (24+3*sizeof (void*)); + return /*burn_stack*/ (24+3*sizeof (void*)); } diff --git a/cipher/rfc2268.c b/cipher/rfc2268.c index 1c9c8d4..130be9b 100644 --- a/cipher/rfc2268.c +++ b/cipher/rfc2268.c @@ -136,6 +136,13 @@ do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) outbuf[7] = word3 >> 8; } +static unsigned int +encrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + do_encrypt (context, outbuf, inbuf); + return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); +} + static void do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) { @@ -188,6 +195,13 @@ do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) outbuf[7] = word3 >> 8; } +static unsigned int +decrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + do_decrypt (context, outbuf, inbuf); + return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); +} + static gpg_err_code_t setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) @@ -340,5 +354,5 @@ static gcry_cipher_oid_spec_t oids_rfc2268_40[] = gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { "RFC2268_40", NULL, oids_rfc2268_40, RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), - do_setkey, do_encrypt, do_decrypt + do_setkey, encrypt_block, decrypt_block }; diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 314f106..190d0f9 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1450,10 +1450,11 @@ do_aesni (RIJNDAEL_context *ctx, int decrypt_flag, #endif /*USE_AESNI*/ -static void +static unsigned int rijndael_encrypt (void *context, byte *b, const byte *a) { RIJNDAEL_context *ctx = context; + unsigned int burn_stack; if (0) ; @@ -1461,7 +1462,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a) else if (ctx->use_padlock) { do_padlock (ctx, 0, b, a); - _gcry_burn_stack (48 + 15 /* possible padding for alignment */); + burn_stack = (48 + 15 /* possible padding for alignment */); } #endif /*USE_PADLOCK*/ #ifdef USE_AESNI @@ -1470,13 +1471,16 @@ rijndael_encrypt (void *context, byte *b, const byte *a) aesni_prepare (); do_aesni (ctx, 0, b, a); aesni_cleanup (); + burn_stack = 0; } #endif /*USE_AESNI*/ else { do_encrypt (ctx, b, a); - _gcry_burn_stack (56 + 2*sizeof(int)); + burn_stack = (56 + 2*sizeof(int)); } + + return burn_stack; } @@ -1820,10 +1824,11 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) -static void +static unsigned int rijndael_decrypt (void *context, byte *b, const byte *a) { RIJNDAEL_context *ctx = context; + unsigned int burn_stack; if (0) ; @@ -1831,7 +1836,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a) else if (ctx->use_padlock) { do_padlock (ctx, 1, b, a); - _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */); + burn_stack = (48 + 2*sizeof(int) /* FIXME */); } #endif /*USE_PADLOCK*/ #ifdef USE_AESNI @@ -1840,13 +1845,16 @@ rijndael_decrypt (void *context, byte *b, const byte *a) aesni_prepare (); do_aesni (ctx, 1, b, a); aesni_cleanup (); + burn_stack = 0; } #endif /*USE_AESNI*/ else { do_decrypt (ctx, b, a); - _gcry_burn_stack (56+2*sizeof(int)); + burn_stack = (56+2*sizeof(int)); } + + return burn_stack; } diff --git a/cipher/seed.c b/cipher/seed.c index ae26e67..1600c55 100644 --- a/cipher/seed.c +++ b/cipher/seed.c @@ -371,13 +371,13 @@ do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) PUTU32 (outbuf+12, x2); } -static void +static unsigned int seed_encrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_encrypt (ctx, outbuf, inbuf); - _gcry_burn_stack (4*6); + return /*burn_stack*/ (4*6); } @@ -417,13 +417,13 @@ do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) PUTU32 (outbuf+12, x2); } -static void +static unsigned int seed_decrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_decrypt (ctx, outbuf, inbuf); - _gcry_burn_stack (4*6); + return /*burn_stack*/ (4*6); } diff --git a/cipher/serpent.c b/cipher/serpent.c index 430a7e9..72895ed 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -792,22 +792,22 @@ serpent_decrypt_internal (serpent_context_t *context, memcpy (output, b_next, sizeof (b_next)); } -static void +static unsigned int serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_encrypt_internal (context, buffer_in, buffer_out); - _gcry_burn_stack (2 * sizeof (serpent_block_t)); + return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } -static void +static unsigned int serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_decrypt_internal (context, buffer_in, buffer_out); - _gcry_burn_stack (2 * sizeof (serpent_block_t)); + return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } diff --git a/cipher/twofish.c b/cipher/twofish.c index 07a4ebe..70cdb47 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -819,12 +819,12 @@ do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) _gcry_twofish_amd64_encrypt_block(ctx, out, in); } -static void +static unsigned int twofish_encrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; _gcry_twofish_amd64_encrypt_block(ctx, out, in); - _gcry_burn_stack (4*sizeof (void*)); + return /*burn_stack*/ (4*sizeof (void*)); } #else /*!USE_AMD64_ASM*/ @@ -861,12 +861,12 @@ do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) OUTUNPACK (3, b, 7); } -static void +static unsigned int twofish_encrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; do_twofish_encrypt (ctx, out, in); - _gcry_burn_stack (24+3*sizeof (void*)); + return /*burn_stack*/ (24+3*sizeof (void*)); } #endif /*!USE_AMD64_ASM*/ @@ -882,12 +882,12 @@ do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) _gcry_twofish_amd64_decrypt_block(ctx, out, in); } -static void +static unsigned int twofish_decrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; _gcry_twofish_amd64_decrypt_block(ctx, out, in); - _gcry_burn_stack (4*sizeof (void*)); + return /*burn_stack*/ (4*sizeof (void*)); } #else /*!USE_AMD64_ASM*/ @@ -924,13 +924,13 @@ do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) OUTUNPACK (3, d, 3); } -static void +static unsigned int twofish_decrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; do_twofish_decrypt (ctx, out, in); - _gcry_burn_stack (24+3*sizeof (void*)); + return /*burn_stack*/ (24+3*sizeof (void*)); } #endif /*!USE_AMD64_ASM*/ diff --git a/src/gcrypt-module.h b/src/gcrypt-module.h index cd55207..5276e8f 100644 --- a/src/gcrypt-module.h +++ b/src/gcrypt-module.h @@ -52,14 +52,14 @@ typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c, unsigned keylen); /* Type for the cipher_encrypt function. */ -typedef void (*gcry_cipher_encrypt_t) (void *c, - unsigned char *outbuf, - const unsigned char *inbuf); +typedef unsigned int (*gcry_cipher_encrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); /* Type for the cipher_decrypt function. */ -typedef void (*gcry_cipher_decrypt_t) (void *c, - unsigned char *outbuf, - const unsigned char *inbuf); +typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); /* Type for the cipher_stencrypt function. */ typedef void (*gcry_cipher_stencrypt_t) (void *c, ----------------------------------------------------------------------- Summary of changes: cipher/blowfish.c | 32 ++++++++++++++++++-------------- cipher/camellia-glue.c | 16 ++++++++-------- cipher/cast5.c | 32 ++++++++++++++++++-------------- cipher/cipher-aeswrap.c | 19 +++++++++++++++++-- cipher/cipher-cbc.c | 27 ++++++++++++++++++++++----- cipher/cipher-cfb.c | 32 ++++++++++++++++++++++++++------ cipher/cipher-ctr.c | 10 ++++++++-- cipher/cipher-ofb.c | 26 ++++++++++++++++++++++---- cipher/cipher.c | 24 ++++++++++++++++++++---- cipher/des.c | 16 ++++++++-------- cipher/idea.c | 8 ++++---- cipher/rfc2268.c | 16 +++++++++++++++- cipher/rijndael.c | 20 ++++++++++++++------ cipher/seed.c | 8 ++++---- cipher/serpent.c | 8 ++++---- cipher/twofish.c | 16 ++++++++-------- configure.ac | 18 ++++++++++++++++++ src/gcrypt-module.h | 12 ++++++------ src/misc.c | 9 ++++++++- 19 files changed, 248 insertions(+), 101 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 4 16:01:21 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 04 Sep 2013 16:01:21 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-1-4, updated. gnupg-1.4.14-4-g45efde9 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 Privacy Guard". The branch, STABLE-BRANCH-1-4 has been updated via 45efde9557661ea071a01bcb938f1591ed4ec1a3 (commit) from 6ed7056197e7ede1305b25457e4633c4ac4301d4 (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 45efde9557661ea071a01bcb938f1591ed4ec1a3 Author: Werner Koch Date: Wed Sep 4 15:25:18 2013 +0200 mpicalc: Change copyright notice. -- Except for a minor change by David Shaw, all code has been written by me. After termination of my copyright assignment, I change that notice to reflect the new legal state. Signed-off-by: Werner Koch diff --git a/tools/mpicalc.c b/tools/mpicalc.c index 8cfde49..46e5fc8 100644 --- a/tools/mpicalc.c +++ b/tools/mpicalc.c @@ -1,11 +1,14 @@ -/* mpitest.c - test the mpi functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* mpicalc.c - test the mpi functions + * Copyright (C) 1997, 1998, 1999, 2004, 2006 Werner Koch * * This is an RPN calculator; values must be given in hex. * Operation is like dc(1) except that the input/output radix is * always 16 and you can use a '-' to prefix a negative number. * Addition operators: ++ and --. All operators must be delimited by a blank * + * WARNING: This is an old test utility which is not anymore + * maintained as part of GnuPG. However, Libgcrypt has a + * copy of it which uses the libgcrypt functions. * * This file is part of GnuPG. * ----------------------------------------------------------------------- Summary of changes: tools/mpicalc.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 4 18:49:30 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 04 Sep 2013 18:49:30 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-215-g1d23040 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 1d23040b659661b4086c079cb9fd5f37189a7020 (commit) via 603fe44ef4eb44836f0eb472a1aaabbcfa2819c2 (commit) via a70c46e29c480fa0f56ab4814666a5b115f84fd7 (commit) via c47d4001033f68212d2847b3074a0bdda990342e (commit) via c26be7a337d0bf98193bc58e043209e46d0769bb (commit) via 8698530b2f9ef95542f1dd550961de7af86cc256 (commit) via b28b1f732e1b4f9c62a9de87c22c6bb0d3f8fdb8 (commit) from 4b0edf53440239d3bcc95941980c062a0801a149 (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 1d23040b659661b4086c079cb9fd5f37189a7020 Author: Werner Koch Date: Wed Sep 4 17:51:30 2013 +0200 Change mpicalc to use Libgcrypt and install it. * src/mpicalc.c: Make use of gcry_ functions. (MPICALC_VERSION): New. Set to 2.0. (strusage): Remove. (scan_mpi): New. Replaces mpi_fromstr. (print_mpi): New. Replaces mpi_print. (my_getc): New. (print_help): New. (main): Use simple option parser and print version info. * src/Makefile.am (bin_PROGRAMS): Add mpicalc. (mpicalc_SOURCES, mpicalc_CFLAGS, mpicalc_LDADD): New. Signed-off-by: Werner Koch diff --git a/src/Makefile.am b/src/Makefile.am index d4329c9..507fcd0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,7 @@ m4data_DATA = libgcrypt.m4 include_HEADERS = gcrypt.h lib_LTLIBRARIES = libgcrypt.la -bin_PROGRAMS = dumpsexp hmac256 +bin_PROGRAMS = dumpsexp hmac256 mpicalc if USE_RANDOM_DAEMON sbin_PROGRAMS = gcryptrnd bin_PROGRAMS += getrandom @@ -128,6 +128,10 @@ dumpsexp_SOURCES = dumpsexp.c dumpsexp_CFLAGS = $(arch_gpg_error_cflags) dumpsexp_LDADD = $(arch_gpg_error_libs) +mpicalc_SOURCES = mpicalc.c +mpicalc_CFLAGS = $(arch_gpg_error_cflags) +mpicalc_LDADD = ../src/libgcrypt.la $(arch_gpg_error_libs) + hmac256_SOURCES = hmac256.c hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags) hmac256_LDADD = $(arch_gpg_error_libs) diff --git a/src/mpicalc.c b/src/mpicalc.c index 7043a4a..762d7c8 100644 --- a/src/mpicalc.c +++ b/src/mpicalc.c @@ -21,53 +21,64 @@ hex. Operation is like dc(1) except that the input/output radix is always 16 and you can use a '-' to prefix a negative number. Addition operators: ++ and --. All operators must be delimited by - a blank + a blank. */ -#include +#ifdef HAVE_CONFIG_H +# include +#endif #include #include #include -#include "util.h" -#include "mpi.h" +#ifdef _GCRYPT_IN_LIBGCRYPT +# undef _GCRYPT_IN_LIBGCRYPT +# include "gcrypt.h" +#else +# include +#endif +#define MPICALC_VERSION "2.0" + #define STACKSIZE 500 static gcry_mpi_t stack[STACKSIZE]; static int stackidx; -const char * -strusage (int level) +static int +scan_mpi (gcry_mpi_t retval, const char *string) { - const char *p; - switch (level) + gpg_error_t err; + gcry_mpi_t val; + + err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL); + if (err) { - case 10: - case 0: - p = "mpicalc - v" VERSION "; " "Copyright 1997 Werner Koch (dd9jn)"; - break; - case 13: - p = "mpicalc"; - break; - case 14: - p = VERSION; - break; - case 1: - case 11: - p = "Usage: mpicalc (-h for help)"; - break; - case 2: - case 12: - p = - "\nSyntax: mpicalc [options] [files]\n" - "Simple big integer RPN calculator\n"; - break; - default: - p = default_strusage (level); + fprintf (stderr, "scanning input failed: %s\n", gpg_strerror (err)); + return -1; + } + mpi_set (retval, val); + mpi_release (val); + return 0; +} + + +static void +print_mpi (gcry_mpi_t a) +{ + gpg_error_t err; + char *buf; + void *bufaddr = &buf; + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); + if (err) + fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (err)); + else + { + fputs (buf, stdout); + gcry_free (buf); } - return p; } @@ -151,7 +162,8 @@ do_div (void) fputs ("stack underflow\n", stderr); return; } - mpi_fdiv_q (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + mpi_fdiv (stack[stackidx - 2], NULL, + stack[stackidx - 2], stack[stackidx - 1]); stackidx--; } @@ -163,22 +175,23 @@ do_rem (void) fputs ("stack underflow\n", stderr); return; } - mpi_fdiv_r (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + mpi_mod (stack[stackidx - 2], + stack[stackidx - 2], stack[stackidx - 1]); stackidx--; } static void do_powm (void) { - MPI a; + gcry_mpi_t a; if (stackidx < 3) { fputs ("stack underflow\n", stderr); return; } - a = mpi_alloc (10); + a = mpi_new (0); mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]); - mpi_free (stack[stackidx - 3]); + mpi_release (stack[stackidx - 3]); stack[stackidx - 3] = a; stackidx -= 2; } @@ -186,7 +199,7 @@ do_powm (void) static void do_inv (void) { - MPI a = mpi_alloc (40); + gcry_mpi_t a = mpi_new (0); if (stackidx < 2) { fputs ("stack underflow\n", stderr); @@ -194,14 +207,14 @@ do_inv (void) } mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]); mpi_set (stack[stackidx - 2], a); - mpi_free (a); + mpi_release (a); stackidx--; } static void do_gcd (void) { - MPI a = mpi_alloc (40); + gcry_mpi_t a = mpi_new (0); if (stackidx < 2) { fputs ("stack underflow\n", stderr); @@ -209,7 +222,7 @@ do_gcd (void) } mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]); mpi_set (stack[stackidx - 2], a); - mpi_free (a); + mpi_release (a); stackidx--; } @@ -225,43 +238,123 @@ do_rshift (void) } + +static int +my_getc (void) +{ + static int shown; + int c; + + for (;;) + { + if ((c = getc (stdin)) == EOF) + return EOF; + if (!(c & 0x80)) + return c; + + if (!shown) + { + shown = 1; + fputs ("note: Non ASCII characters are ignored\n", stderr); + } + } +} + + +static void +print_help (void) +{ + fputs ("+ add [0] := [1] + [0] {-1}\n" + "- subtract [0] := [1] - [0] {-1}\n" + "* multiply [0] := [1] * [0] {-1}\n" + "/ divide [0] := [1] - [0] {-1}\n" + "% modulo [0] := [1] % [0] {-1}\n" + "> right shift [0] := [0] >> 1 {0}\n" + "++ increment [0] := [0]++ {0}\n" + "-- decrement [0] := [0]-- {0}\n" + "m multiply mod [0] := [2] * [1] mod [0] {-2}\n" + "^ power mod [0] := [2] ^ [1] mod [0] {-2}\n" + "I inverse mod [0] := [1]^-1 mod [0] {-1}\n" + "G gcd [0] := gcd([1],[0]) {-1}\n" + "i remove item [0] := [1] {-1}\n" + "d dup item [-1] := [0] {+1}\n" + "r reverse [0] := [1], [1] := [0] {0}\n" + "c clear stack\n" + "p print top item\n" + "f print the stack\n" + "# ignore until end of line\n" + "? print this help\n" + , stdout); +} + + + int main (int argc, char **argv) { - static ARGPARSE_OPTS opts[] = { - {0} - }; - ARGPARSE_ARGS pargs; + const char *pgm; + int last_argc = -1; int i, c; int state = 0; char strbuf[1000]; int stridx = 0; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 0; + if (argc) + { + pgm = strrchr (*argv, '/'); + if (pgm) + pgm++; + else + pgm = *argv; + argc--; argv++; + } + else + pgm = "?"; - while (arg_parse (&pargs, opts)) + while (argc && last_argc != argc ) { - switch (pargs.r_opt) - { - default: - pargs.err = 2; - break; - } + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version") + || !strcmp (*argv, "--help")) + { + printf ("%s " MPICALC_VERSION "\n" + "libgcrypt %s\n" + "Copyright (C) 1997, 2013 Werner Koch\n" + "License LGPLv2.1+: GNU LGPL version 2.1 or later " + "\n" + "This is free software: you are free to change and " + "redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n" + "\n" + "Syntax: mpicalc [options]\n" + "Simple interactive big integer RPN calculator\n" + "\n" + "Options:\n" + " --version print version information\n", + pgm, gcry_check_version (NULL)); + exit (0); + } } - if (argc) - usage (1); + if (argc) + { + fprintf (stderr, "usage: %s [options] (--help for help)\n", pgm); + exit (1); + } for (i = 0; i < STACKSIZE; i++) stack[i] = NULL; stackidx = 0; - while ((c = getc (stdin)) != EOF) + while ((c = my_getc ()) != EOF) { - if (!state) - { /* waiting */ + if (!state) /* waiting */ + { if (isdigit (c)) { state = 1; @@ -276,8 +369,11 @@ main (int argc, char **argv) { switch (c) { + case '#': + state = 2; + break; case '+': - if ((c = getc (stdin)) == '+') + if ((c = my_getc ()) == '+') do_inc (); else { @@ -286,7 +382,7 @@ main (int argc, char **argv) } break; case '-': - if ((c = getc (stdin)) == '-') + if ((c = my_getc ()) == '-') do_dec (); else if (isdigit (c) || (c >= 'A' && c <= 'F')) { @@ -318,21 +414,21 @@ main (int argc, char **argv) case '^': do_powm (); break; + case '>': + do_rshift (); + break; case 'I': do_inv (); break; case 'G': do_gcd (); break; - case '>': - do_rshift (); - break; case 'i': /* dummy */ if (!stackidx) fputs ("stack underflow\n", stderr); else { - mpi_free (stack[stackidx - 1]); + mpi_release (stack[stackidx - 1]); stackidx--; } break; @@ -341,16 +437,28 @@ main (int argc, char **argv) fputs ("stack underflow\n", stderr); else if (stackidx < STACKSIZE) { - mpi_free (stack[stackidx]); + mpi_release (stack[stackidx]); stack[stackidx] = mpi_copy (stack[stackidx - 1]); stackidx++; } else fputs ("stack overflow\n", stderr); break; + case 'r': /* swap top elements */ + if (stackidx < 2) + fputs ("stack underflow\n", stderr); + else if (stackidx < STACKSIZE) + { + gcry_mpi_t tmp = stack[stackidx-1]; + stack[stackidx-1] = stack[stackidx - 2]; + stack[stackidx-2] = tmp; + } + break; case 'c': for (i = 0; i < stackidx; i++) - mpi_free (stack[i]), stack[i] = NULL; + { + mpi_release (stack[i]); stack[i] = NULL; + } stackidx = 0; break; case 'p': /* print the tos */ @@ -358,7 +466,7 @@ main (int argc, char **argv) puts ("stack is empty"); else { - mpi_print (stdout, stack[stackidx - 1], 1); + print_mpi (stack[stackidx - 1]); putchar ('\n'); } break; @@ -366,29 +474,33 @@ main (int argc, char **argv) for (i = stackidx - 1; i >= 0; i--) { printf ("[%2d]: ", i); - mpi_print (stdout, stack[i], 1); + print_mpi (stack[i]); putchar ('\n'); } break; + case '?': + print_help (); + break; default: fputs ("invalid operator\n", stderr); } } } - else if (state == 1) - { /* in a number */ + else if (state == 1) /* In a number. */ + { if (!isxdigit (c)) - { /* store the number */ + { + /* Store the number */ state = 0; ungetc (c, stdin); - if (stridx < 1000) + if (stridx < sizeof strbuf) strbuf[stridx] = 0; if (stackidx < STACKSIZE) { if (!stack[stackidx]) - stack[stackidx] = mpi_alloc (10); - if (mpi_fromstr (stack[stackidx], strbuf)) + stack[stackidx] = mpi_new (0); + if (scan_mpi (stack[stackidx], strbuf)) fputs ("invalid number\n", stderr); else stackidx++; @@ -397,20 +509,26 @@ main (int argc, char **argv) fputs ("stack overflow\n", stderr); } else - { /* store digit */ - if (stridx < 999) + { /* Store a digit. */ + if (stridx < sizeof strbuf - 1) strbuf[stridx++] = c; - else if (stridx == 999) + else if (stridx == sizeof strbuf - 1) { strbuf[stridx] = 0; - fputs ("string too large - truncated\n", stderr); + fputs ("input too large - truncated\n", stderr); stridx++; } } } + else if (state == 2) /* In a comment. */ + { + if (c == '\n') + state = 0; + } } + for (i = 0; i < stackidx; i++) - mpi_free (stack[i]); + mpi_release (stack[i]); return 0; } commit 603fe44ef4eb44836f0eb472a1aaabbcfa2819c2 Author: Werner Koch Date: Wed Sep 4 16:17:11 2013 +0200 Re-indent mpicalc.c and change license. -- Changed license to LGPLv2.1+. Signed-off-by: Werner Koch diff --git a/src/mpicalc.c b/src/mpicalc.c index 46e5fc8..7043a4a 100644 --- a/src/mpicalc.c +++ b/src/mpicalc.c @@ -1,29 +1,27 @@ -/* mpicalc.c - test the mpi functions - * Copyright (C) 1997, 1998, 1999, 2004, 2006 Werner Koch +/* mpicalc.c - Simple RPN calculator using gcry_mpi functions + * Copyright (C) 1997, 1998, 1999, 2004, 2006, 2013 Werner Koch * - * This is an RPN calculator; values must be given in hex. - * Operation is like dc(1) except that the input/output radix is - * always 16 and you can use a '-' to prefix a negative number. - * Addition operators: ++ and --. All operators must be delimited by a blank + * This program 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. * - * WARNING: This is an old test utility which is not anymore - * maintained as part of GnuPG. However, Libgcrypt has a - * copy of it which uses the libgcrypt functions. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +/* + This program is a simple RPN calculator which was originally used + to develop the mpi functions of GnuPG. Values must be given in + hex. Operation is like dc(1) except that the input/output radix is + always 16 and you can use a '-' to prefix a negative number. + Addition operators: ++ and --. All operators must be delimited by + a blank */ #include @@ -33,354 +31,386 @@ #include "util.h" #include "mpi.h" -#include "i18n.h" -#define STACKSIZE 100 -static MPI stack[STACKSIZE]; + +#define STACKSIZE 500 +static gcry_mpi_t stack[STACKSIZE]; static int stackidx; const char * -strusage( int level ) +strusage (int level) { - const char *p; - switch( level ) { - case 10: - case 0: p = "mpicalc - v" VERSION "; " - "Copyright 1997 Werner Koch (dd9jn)" ; break; - case 13: p = "mpicalc"; break; - case 14: p = VERSION; break; - case 1: - case 11: p = "Usage: mpicalc (-h for help)"; - break; - case 2: - case 12: p = - "\nSyntax: mpicalc [options] [files]\n" - "MPI RPN calculator\n"; - break; - default: p = default_strusage(level); + const char *p; + switch (level) + { + case 10: + case 0: + p = "mpicalc - v" VERSION "; " "Copyright 1997 Werner Koch (dd9jn)"; + break; + case 13: + p = "mpicalc"; + break; + case 14: + p = VERSION; + break; + case 1: + case 11: + p = "Usage: mpicalc (-h for help)"; + break; + case 2: + case 12: + p = + "\nSyntax: mpicalc [options] [files]\n" + "Simple big integer RPN calculator\n"; + break; + default: + p = default_strusage (level); } - return p; + return p; } -static void -i18n_init(void) -{ -#ifdef ENABLE_NLS - setlocale( LC_ALL, "" ); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain( PACKAGE ); -#endif -} - static void -do_add(void) +do_add (void) { - if( stackidx < 2 ) { - fputs("stack underflow\n",stderr); - return; + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; + mpi_add (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + stackidx--; } static void -do_sub(void) +do_sub (void) { - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; + mpi_sub (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + stackidx--; } static void -do_inc(void) +do_inc (void) { - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 1) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 ); + mpi_add_ui (stack[stackidx - 1], stack[stackidx - 1], 1); } static void -do_dec(void) +do_dec (void) { - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 1) + { + fputs ("stack underflow\n", stderr); + return; } - /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */ + /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */ } static void -do_mul(void) +do_mul (void) { - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; + mpi_mul (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + stackidx--; } static void -do_mulm(void) +do_mulm (void) { - if( stackidx < 3 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 3) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_mulm( stack[stackidx-3], stack[stackidx-3], - stack[stackidx-2], stack[stackidx-1] ); - stackidx -= 2; + mpi_mulm (stack[stackidx - 3], stack[stackidx - 3], + stack[stackidx - 2], stack[stackidx - 1]); + stackidx -= 2; } static void -do_div(void) +do_div (void) { - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; + mpi_fdiv_q (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + stackidx--; } static void -do_rem(void) +do_rem (void) { - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; + mpi_fdiv_r (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]); + stackidx--; } static void -do_powm(void) +do_powm (void) { - MPI a; - if( stackidx < 3 ) { - fputs("stack underflow\n", stderr); - return; + MPI a; + if (stackidx < 3) + { + fputs ("stack underflow\n", stderr); + return; } - a= mpi_alloc(10); - mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] ); - mpi_free(stack[stackidx-3]); - stack[stackidx-3] = a; - stackidx -= 2; + a = mpi_alloc (10); + mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]); + mpi_free (stack[stackidx - 3]); + stack[stackidx - 3] = a; + stackidx -= 2; } static void -do_inv(void) +do_inv (void) { - MPI a = mpi_alloc(40); - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + MPI a = mpi_alloc (40); + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_invm( a, stack[stackidx-2], stack[stackidx-1] ); - mpi_set(stack[stackidx-2],a); - mpi_free(a); - stackidx--; + mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]); + mpi_set (stack[stackidx - 2], a); + mpi_free (a); + stackidx--; } static void -do_gcd(void) +do_gcd (void) { - MPI a = mpi_alloc(40); - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; + MPI a = mpi_alloc (40); + if (stackidx < 2) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] ); - mpi_set(stack[stackidx-2],a); - mpi_free(a); - stackidx--; + mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]); + mpi_set (stack[stackidx - 2], a); + mpi_free (a); + stackidx--; } static void -do_rshift(void) +do_rshift (void) { - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; + if (stackidx < 1) + { + fputs ("stack underflow\n", stderr); + return; } - mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 ); + mpi_rshift (stack[stackidx - 1], stack[stackidx - 1], 1); } int -main(int argc, char **argv) +main (int argc, char **argv) { - static ARGPARSE_OPTS opts[] = { - {0} }; - ARGPARSE_ARGS pargs; - int i, c; - int state = 0; - char strbuf[1000]; - int stridx=0; + static ARGPARSE_OPTS opts[] = { + {0} + }; + ARGPARSE_ARGS pargs; + int i, c; + int state = 0; + char strbuf[1000]; + int stridx = 0; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 0; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 0; - i18n_init(); - while( arg_parse( &pargs, opts) ) { - switch( pargs.r_opt ) { - default : pargs.err = 2; break; + while (arg_parse (&pargs, opts)) + { + switch (pargs.r_opt) + { + default: + pargs.err = 2; + break; } } - if( argc ) - usage(1); + if (argc) + usage (1); - for(i=0; i < STACKSIZE; i++ ) - stack[i] = NULL; - stackidx =0; + for (i = 0; i < STACKSIZE; i++) + stack[i] = NULL; + stackidx = 0; - while( (c=getc(stdin)) != EOF ) { - if( !state ) { /* waiting */ - if( isdigit(c) ) { - state = 1; - ungetc(c, stdin); - strbuf[0] = '0'; - strbuf[1] = 'x'; - stridx=2; + while ((c = getc (stdin)) != EOF) + { + if (!state) + { /* waiting */ + if (isdigit (c)) + { + state = 1; + ungetc (c, stdin); + strbuf[0] = '0'; + strbuf[1] = 'x'; + stridx = 2; } - else if( isspace(c) ) - ; - else { - switch(c) { - case '+': - if( (c=getc(stdin)) == '+' ) - do_inc(); - else { - ungetc(c, stdin); - do_add(); + else if (isspace (c)) + ; + else + { + switch (c) + { + case '+': + if ((c = getc (stdin)) == '+') + do_inc (); + else + { + ungetc (c, stdin); + do_add (); } - break; - case '-': - if( (c=getc(stdin)) == '-' ) - do_dec(); - else if( isdigit(c) || (c >='A' && c <= 'F') ) { - state = 1; - ungetc(c, stdin); - strbuf[0] = '-'; - strbuf[1] = '0'; - strbuf[2] = 'x'; - stridx=3; + break; + case '-': + if ((c = getc (stdin)) == '-') + do_dec (); + else if (isdigit (c) || (c >= 'A' && c <= 'F')) + { + state = 1; + ungetc (c, stdin); + strbuf[0] = '-'; + strbuf[1] = '0'; + strbuf[2] = 'x'; + stridx = 3; } - else { - ungetc(c, stdin); - do_sub(); + else + { + ungetc (c, stdin); + do_sub (); } - break; - case '*': - do_mul(); - break; - case 'm': - do_mulm(); - break; - case '/': - do_div(); - break; - case '%': - do_rem(); - break; - case '^': - do_powm(); - break; - case 'I': - do_inv(); - break; - case 'G': - do_gcd(); - break; - case '>': - do_rshift(); - break; - case 'i': /* dummy */ - if( !stackidx ) - fputs("stack underflow\n", stderr); - else { - mpi_free(stack[stackidx-1]); - stackidx--; + break; + case '*': + do_mul (); + break; + case 'm': + do_mulm (); + break; + case '/': + do_div (); + break; + case '%': + do_rem (); + break; + case '^': + do_powm (); + break; + case 'I': + do_inv (); + break; + case 'G': + do_gcd (); + break; + case '>': + do_rshift (); + break; + case 'i': /* dummy */ + if (!stackidx) + fputs ("stack underflow\n", stderr); + else + { + mpi_free (stack[stackidx - 1]); + stackidx--; } - break; - case 'd': /* duplicate the tos */ - if( !stackidx ) - fputs("stack underflow\n", stderr); - else if( stackidx < STACKSIZE ) { - mpi_free(stack[stackidx]); - stack[stackidx] = mpi_copy( stack[stackidx-1] ); - stackidx++; + break; + case 'd': /* duplicate the tos */ + if (!stackidx) + fputs ("stack underflow\n", stderr); + else if (stackidx < STACKSIZE) + { + mpi_free (stack[stackidx]); + stack[stackidx] = mpi_copy (stack[stackidx - 1]); + stackidx++; } - else - fputs("stack overflow\n", stderr); - break; - case 'c': - for(i=0; i < stackidx; i++ ) - mpi_free(stack[i]), stack[i] = NULL; - stackidx = 0; - break; - case 'p': /* print the tos */ - if( !stackidx ) - puts("stack is empty"); - else { - mpi_print(stdout, stack[stackidx-1], 1 ); - putchar('\n'); + else + fputs ("stack overflow\n", stderr); + break; + case 'c': + for (i = 0; i < stackidx; i++) + mpi_free (stack[i]), stack[i] = NULL; + stackidx = 0; + break; + case 'p': /* print the tos */ + if (!stackidx) + puts ("stack is empty"); + else + { + mpi_print (stdout, stack[stackidx - 1], 1); + putchar ('\n'); } - break; - case 'f': /* print the stack */ - for( i = stackidx-1 ; i >= 0; i-- ) { - printf("[%2d]: ", i ); - mpi_print(stdout, stack[i], 1 ); - putchar('\n'); + break; + case 'f': /* print the stack */ + for (i = stackidx - 1; i >= 0; i--) + { + printf ("[%2d]: ", i); + mpi_print (stdout, stack[i], 1); + putchar ('\n'); } - break; - default: - fputs("invalid operator\n", stderr); + break; + default: + fputs ("invalid operator\n", stderr); } } } - else if( state == 1 ) { /* in a number */ - if( !isxdigit(c) ) { /* store the number */ - state = 0; - ungetc(c, stdin); - if( stridx < 1000 ) - strbuf[stridx] = 0; + else if (state == 1) + { /* in a number */ + if (!isxdigit (c)) + { /* store the number */ + state = 0; + ungetc (c, stdin); + if (stridx < 1000) + strbuf[stridx] = 0; - if( stackidx < STACKSIZE ) { - if( !stack[stackidx] ) - stack[stackidx] = mpi_alloc(10); - if( mpi_fromstr(stack[stackidx], strbuf) ) - fputs("invalid number\n", stderr); - else - stackidx++; + if (stackidx < STACKSIZE) + { + if (!stack[stackidx]) + stack[stackidx] = mpi_alloc (10); + if (mpi_fromstr (stack[stackidx], strbuf)) + fputs ("invalid number\n", stderr); + else + stackidx++; } - else - fputs("stack overflow\n", stderr); + else + fputs ("stack overflow\n", stderr); } - else { /* store digit */ - if( stridx < 999 ) - strbuf[stridx++] = c; - else if( stridx == 999 ) { - strbuf[stridx] = 0; - fputs("string too large - truncated\n", stderr); - stridx++; + else + { /* store digit */ + if (stridx < 999) + strbuf[stridx++] = c; + else if (stridx == 999) + { + strbuf[stridx] = 0; + fputs ("string too large - truncated\n", stderr); + stridx++; } } } } - for(i=0; i < stackidx; i++ ) - mpi_free(stack[i]); - return 0; + for (i = 0; i < stackidx; i++) + mpi_free (stack[i]); + return 0; } commit a70c46e29c480fa0f56ab4814666a5b115f84fd7 Author: Werner Koch Date: Wed Sep 4 15:37:01 2013 +0200 Add mpicalc.c to help with testing. * src/mpicalc.c: Take from GnuPG 1.4 -- Taken from GnuPG commit 45efde9557661ea071a01bcb938f1591ed4ec1a3 diff --git a/src/mpicalc.c b/src/mpicalc.c new file mode 100644 index 0000000..46e5fc8 --- /dev/null +++ b/src/mpicalc.c @@ -0,0 +1,386 @@ +/* mpicalc.c - test the mpi functions + * Copyright (C) 1997, 1998, 1999, 2004, 2006 Werner Koch + * + * This is an RPN calculator; values must be given in hex. + * Operation is like dc(1) except that the input/output radix is + * always 16 and you can use a '-' to prefix a negative number. + * Addition operators: ++ and --. All operators must be delimited by a blank + * + * WARNING: This is an old test utility which is not anymore + * maintained as part of GnuPG. However, Libgcrypt has a + * copy of it which uses the libgcrypt functions. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "util.h" +#include "mpi.h" +#include "i18n.h" + +#define STACKSIZE 100 +static MPI stack[STACKSIZE]; +static int stackidx; + + +const char * +strusage( int level ) +{ + const char *p; + switch( level ) { + case 10: + case 0: p = "mpicalc - v" VERSION "; " + "Copyright 1997 Werner Koch (dd9jn)" ; break; + case 13: p = "mpicalc"; break; + case 14: p = VERSION; break; + case 1: + case 11: p = "Usage: mpicalc (-h for help)"; + break; + case 2: + case 12: p = + "\nSyntax: mpicalc [options] [files]\n" + "MPI RPN calculator\n"; + break; + default: p = default_strusage(level); + } + return p; +} + + +static void +i18n_init(void) +{ +#ifdef ENABLE_NLS + setlocale( LC_ALL, "" ); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain( PACKAGE ); +#endif +} + + +static void +do_add(void) +{ + if( stackidx < 2 ) { + fputs("stack underflow\n",stderr); + return; + } + mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); + stackidx--; +} + +static void +do_sub(void) +{ + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); + stackidx--; +} + +static void +do_inc(void) +{ + if( stackidx < 1 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 ); +} + +static void +do_dec(void) +{ + if( stackidx < 1 ) { + fputs("stack underflow\n", stderr); + return; + } + /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */ +} + +static void +do_mul(void) +{ + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); + stackidx--; +} + +static void +do_mulm(void) +{ + if( stackidx < 3 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_mulm( stack[stackidx-3], stack[stackidx-3], + stack[stackidx-2], stack[stackidx-1] ); + stackidx -= 2; +} + +static void +do_div(void) +{ + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); + stackidx--; +} + +static void +do_rem(void) +{ + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); + stackidx--; +} + +static void +do_powm(void) +{ + MPI a; + if( stackidx < 3 ) { + fputs("stack underflow\n", stderr); + return; + } + a= mpi_alloc(10); + mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] ); + mpi_free(stack[stackidx-3]); + stack[stackidx-3] = a; + stackidx -= 2; +} + +static void +do_inv(void) +{ + MPI a = mpi_alloc(40); + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_invm( a, stack[stackidx-2], stack[stackidx-1] ); + mpi_set(stack[stackidx-2],a); + mpi_free(a); + stackidx--; +} + +static void +do_gcd(void) +{ + MPI a = mpi_alloc(40); + if( stackidx < 2 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] ); + mpi_set(stack[stackidx-2],a); + mpi_free(a); + stackidx--; +} + +static void +do_rshift(void) +{ + if( stackidx < 1 ) { + fputs("stack underflow\n", stderr); + return; + } + mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 ); +} + + +int +main(int argc, char **argv) +{ + static ARGPARSE_OPTS opts[] = { + {0} }; + ARGPARSE_ARGS pargs; + int i, c; + int state = 0; + char strbuf[1000]; + int stridx=0; + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 0; + + i18n_init(); + while( arg_parse( &pargs, opts) ) { + switch( pargs.r_opt ) { + default : pargs.err = 2; break; + } + } + if( argc ) + usage(1); + + + for(i=0; i < STACKSIZE; i++ ) + stack[i] = NULL; + stackidx =0; + + while( (c=getc(stdin)) != EOF ) { + if( !state ) { /* waiting */ + if( isdigit(c) ) { + state = 1; + ungetc(c, stdin); + strbuf[0] = '0'; + strbuf[1] = 'x'; + stridx=2; + } + else if( isspace(c) ) + ; + else { + switch(c) { + case '+': + if( (c=getc(stdin)) == '+' ) + do_inc(); + else { + ungetc(c, stdin); + do_add(); + } + break; + case '-': + if( (c=getc(stdin)) == '-' ) + do_dec(); + else if( isdigit(c) || (c >='A' && c <= 'F') ) { + state = 1; + ungetc(c, stdin); + strbuf[0] = '-'; + strbuf[1] = '0'; + strbuf[2] = 'x'; + stridx=3; + } + else { + ungetc(c, stdin); + do_sub(); + } + break; + case '*': + do_mul(); + break; + case 'm': + do_mulm(); + break; + case '/': + do_div(); + break; + case '%': + do_rem(); + break; + case '^': + do_powm(); + break; + case 'I': + do_inv(); + break; + case 'G': + do_gcd(); + break; + case '>': + do_rshift(); + break; + case 'i': /* dummy */ + if( !stackidx ) + fputs("stack underflow\n", stderr); + else { + mpi_free(stack[stackidx-1]); + stackidx--; + } + break; + case 'd': /* duplicate the tos */ + if( !stackidx ) + fputs("stack underflow\n", stderr); + else if( stackidx < STACKSIZE ) { + mpi_free(stack[stackidx]); + stack[stackidx] = mpi_copy( stack[stackidx-1] ); + stackidx++; + } + else + fputs("stack overflow\n", stderr); + break; + case 'c': + for(i=0; i < stackidx; i++ ) + mpi_free(stack[i]), stack[i] = NULL; + stackidx = 0; + break; + case 'p': /* print the tos */ + if( !stackidx ) + puts("stack is empty"); + else { + mpi_print(stdout, stack[stackidx-1], 1 ); + putchar('\n'); + } + break; + case 'f': /* print the stack */ + for( i = stackidx-1 ; i >= 0; i-- ) { + printf("[%2d]: ", i ); + mpi_print(stdout, stack[i], 1 ); + putchar('\n'); + } + break; + default: + fputs("invalid operator\n", stderr); + } + } + } + else if( state == 1 ) { /* in a number */ + if( !isxdigit(c) ) { /* store the number */ + state = 0; + ungetc(c, stdin); + if( stridx < 1000 ) + strbuf[stridx] = 0; + + if( stackidx < STACKSIZE ) { + if( !stack[stackidx] ) + stack[stackidx] = mpi_alloc(10); + if( mpi_fromstr(stack[stackidx], strbuf) ) + fputs("invalid number\n", stderr); + else + stackidx++; + } + else + fputs("stack overflow\n", stderr); + } + else { /* store digit */ + if( stridx < 999 ) + strbuf[stridx++] = c; + else if( stridx == 999 ) { + strbuf[stridx] = 0; + fputs("string too large - truncated\n", stderr); + stridx++; + } + } + } + + } + for(i=0; i < stackidx; i++ ) + mpi_free(stack[i]); + return 0; +} commit c47d4001033f68212d2847b3074a0bdda990342e Author: Werner Koch Date: Wed Sep 4 11:20:57 2013 +0200 Prepare support for EdDSA. * src/cipher.h (PUBKEY_FLAG_EDDSA): New. * cipher/pubkey.c (pubkey_verify): Repalce args CMP and OPAQUEV by CTX. Pass flags and hash algo to the verify function. Change all verify functions to accept these args. (sexp_data_to_mpi): Implement new flag "eddsa". (gcry_pk_verify): Pass CTX instead of the compare function to pubkey_verify. * cipher/ecc.c (sign): Rename to sign_ecdsa. Change all callers. (verify): Rename to verify_ecdsa. Change all callers. (sign_eddsa, verify_eddsa): New stub functions. (ecc_sign): Divert to sign_ecdsa or sign_eddsa. (ecc_verify): Divert to verify_ecdsa or verify_eddsa. diff --git a/cipher/dsa.c b/cipher/dsa.c index ac2dee1..3a64dda 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -1004,7 +1004,8 @@ dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, static gcry_err_code_t dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), void *opaquev) + int (*cmp) (void *, gcry_mpi_t), void *opaquev, + int flags, int hashalgo) { gcry_err_code_t err = GPG_ERR_NO_ERROR; DSA_public_key pk; @@ -1012,6 +1013,8 @@ dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, (void)algo; (void)cmp; (void)opaquev; + (void)flags; + (void)hashalgo; if ((! data[0]) || (! data[1]) || (! hash) || (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3])) diff --git a/cipher/ecc.c b/cipher/ecc.c index 8a7ca0b..0cb279f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -77,12 +77,11 @@ static void *progress_cb_data; /* Local prototypes. */ static void test_keys (ECC_secret_key * sk, unsigned int nbits); static int check_secret_key (ECC_secret_key * sk); -static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey, - gcry_mpi_t r, gcry_mpi_t s, - int flags, int hashalgo); -static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey, - gcry_mpi_t r, gcry_mpi_t s); - +static gpg_err_code_t sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, + gcry_mpi_t r, gcry_mpi_t s, + int flags, int hashalgo); +static gpg_err_code_t verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey, + gcry_mpi_t r, gcry_mpi_t s); static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base); @@ -284,10 +283,10 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); - if (sign (test, sk, r, s, 0, 0) ) + if (sign_ecdsa (test, sk, r, s, 0, 0) ) log_fatal ("ECDSA operation: sign failed\n"); - if (verify (test, &pk, r, s)) + if (verify_ecdsa (test, &pk, r, s)) { log_fatal ("ECDSA operation: sign, verify failed\n"); } @@ -411,13 +410,13 @@ check_secret_key (ECC_secret_key * sk) } -/* +/* Compute an ECDSA signature. * Return the signature struct (r,s) from the message hash. The caller * must have allocated R and S. */ static gpg_err_code_t -sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, - int flags, int hashalgo) +sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, + int flags, int hashalgo) { gpg_err_code_t err = 0; int extraloops = 0; @@ -532,11 +531,12 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, } -/* +/* Verify an ECDSA signature. * Check if R and S verifies INPUT. */ static gpg_err_code_t -verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) +verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey, + gcry_mpi_t r, gcry_mpi_t s) { gpg_err_code_t err = 0; gcry_mpi_t h, h1, h2, x; @@ -615,6 +615,59 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) +/* Compute an EdDSA signature. See: + * [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja + * Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security + * signatures. Journal of Cryptographic Engineering 2 (2012), 77-89. + * Document ID: a1a62a2f76d23f65d622484ddd09caf8. + * URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26. + * + * Despite that this function requires the specification of a hash + * algorithm, we only support what has been specified by the paper. + * This may change in the future. Note that we don't check the used + * curve; the user is responsible to use Ed25519. + * + * Return the signature struct (r,s) from the message hash. The caller + * must have allocated R and S. + */ +static gpg_err_code_t +sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, + gcry_mpi_t r, gcry_mpi_t s, int hashalgo) +{ + (void)skey; + (void)r; + (void)s; + + if (!mpi_is_opaque (input)) + return GPG_ERR_INV_DATA; + if (hashalgo != GCRY_MD_SHA512) + return GPG_ERR_DIGEST_ALGO; + + return GPG_ERR_NOT_IMPLEMENTED; +} + + +/* Verify an EdDSA signature. See sign_eddsa for the reference. + * Check if R and S verifies INPUT. + */ +static gpg_err_code_t +verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey, + gcry_mpi_t r, gcry_mpi_t s, int hashalgo) +{ + (void)pkey; + (void)r; + (void)s; + + if (!mpi_is_opaque (input)) + return GPG_ERR_INV_DATA; + if (hashalgo != GCRY_MD_SHA512) + return GPG_ERR_DIGEST_ALGO; + + return GPG_ERR_NOT_IMPLEMENTED; +} + + + /********************************************* ************** interface ****************** *********************************************/ @@ -796,7 +849,10 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); - err = sign (data, &sk, resarr[0], resarr[1], flags, hashalgo); + if ((flags & PUBKEY_FLAG_EDDSA)) + err = sign_eddsa (data, &sk, resarr[0], resarr[1], hashalgo); + else + err = sign_ecdsa (data, &sk, resarr[0], resarr[1], flags, hashalgo); if (err) { mpi_free (resarr[0]); @@ -810,7 +866,8 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, static gcry_err_code_t ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp)(void *, gcry_mpi_t), void *opaquev) + int (*cmp)(void *, gcry_mpi_t), void *opaquev, + int flags, int hashalgo) { gpg_err_code_t err; ECC_public_key pk; @@ -843,7 +900,11 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, return err; } - if (mpi_is_opaque (hash)) + if ((flags & PUBKEY_FLAG_EDDSA)) + { + err = verify_eddsa (hash, &pk, data[0], data[1], hashalgo); + } + else if (mpi_is_opaque (hash)) { const void *abuf; unsigned int abits, qbits; @@ -858,12 +919,12 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, if (abits > qbits) gcry_mpi_rshift (a, a, abits - qbits); - err = verify (a, &pk, data[0], data[1]); + err = verify_ecdsa (a, &pk, data[0], data[1]); gcry_mpi_release (a); } } else - err = verify (hash, &pk, data[0], data[1]); + err = verify_ecdsa (hash, &pk, data[0], data[1]); point_free (&pk.E.G); point_free (&pk.Q); diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 7540e3f..d105cb4 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -789,7 +789,8 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, static gcry_err_code_t elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), void *opaquev) + int (*cmp) (void *, gcry_mpi_t), void *opaquev, + int flags, int hashalgo) { gcry_err_code_t err = GPG_ERR_NO_ERROR; ELG_public_key pk; @@ -797,6 +798,8 @@ elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, (void)algo; (void)cmp; (void)opaquev; + (void)flags; + (void)hashalgo; if (mpi_is_opaque (hash)) return GPG_ERR_INV_DATA; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index e6c1cf6..fb8de14 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -41,8 +41,7 @@ static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr, struct pk_encoding_ctx *ctx); static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), - void *opaque); + struct pk_encoding_ctx *ctx); /* A dummy extraspec so that we do not need to tests the extraspec @@ -179,7 +178,8 @@ dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, static gcry_err_code_t dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), void *opaquev) + int (*cmp) (void *, gcry_mpi_t), void *opaquev, + int flags, int hashalgo) { (void)algorithm; (void)hash; @@ -187,6 +187,8 @@ dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, (void)pkey; (void)cmp; (void)opaquev; + (void)flags; + (void)hashalgo; fips_signal_error ("using dummy public key function"); return GPG_ERR_NOT_IMPLEMENTED; } @@ -757,8 +759,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, */ static gcry_err_code_t pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, - gcry_mpi_t *pkey, - int (*cmp)(void *, gcry_mpi_t), void *opaquev) + gcry_mpi_t *pkey, struct pk_encoding_ctx *ctx) { gcry_pk_spec_t *pubkey; gcry_module_t module; @@ -780,7 +781,9 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, if (module) { pubkey = (gcry_pk_spec_t *) module->spec; - rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev); + rc = pubkey->verify (algorithm, hash, data, pkey, + ctx->verify_cmp, ctx, + ctx->flags, ctx->hash_algo); _gcry_module_release (module); goto ready; } @@ -2484,7 +2487,7 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, () or (data - [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979])] + [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])] [(hash )] [(value )] [(hash-algo )] @@ -2496,7 +2499,9 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, Either the VALUE or the HASH element must be present for use with signatures. VALUE is used for encryption. - HASH-ALGO and LABEL are specific to OAEP. + HASH-ALGO is specific to OAEP and EDDSA. + + LABEL is specific to OAEP. SALT-LENGTH is for PSS. @@ -2533,8 +2538,13 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, s = gcry_sexp_nth_data (lflags, i, &n); if (!s) ; /* not a data element*/ - else if (n == 7 && ! memcmp (s, "rfc6979", 7)) + else if (n == 7 && !memcmp (s, "rfc6979", 7)) parsed_flags |= PUBKEY_FLAG_RFC6979; + else if (n == 5 && !memcmp (s, "eddsa", 5)) + { + ctx->encoding = PUBKEY_ENC_RAW; + parsed_flags |= PUBKEY_FLAG_EDDSA; + } else if ( n == 3 && !memcmp (s, "raw", 3) && ctx->encoding == PUBKEY_ENC_UNKNOWN) { @@ -2570,6 +2580,54 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, rc = GPG_ERR_INV_OBJ; /* none or both given */ else if (unknown_flag) rc = GPG_ERR_INV_FLAG; + else if (ctx->encoding == PUBKEY_ENC_RAW + && (parsed_flags & PUBKEY_FLAG_EDDSA)) + { + /* Prepare for EdDSA. */ + gcry_sexp_t list; + void *value; + size_t valuelen; + + if (lvalue) + { + rc = GPG_ERR_INV_OBJ; + goto leave; + } + /* Get HASH-ALGO. */ + list = gcry_sexp_find_token (ldata, "hash-algo", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else + { + ctx->hash_algo = get_hash_algo (s, n); + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + } + gcry_sexp_release (list); + } + else + rc = GPG_ERR_INV_OBJ; + if (rc) + goto leave; + + /* Get VALUE. */ + value = gcry_sexp_nth_buffer (lvalue, 1, &valuelen); + if (!value) + rc = GPG_ERR_INV_OBJ; + else if ((valuelen * 8) < valuelen) + { + gcry_free (value); + rc = GPG_ERR_TOO_LARGE; + } + if (rc) + goto leave; + + /* Note that mpi_set_opaque takes ownership of VALUE. */ + *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8); + } else if (ctx->encoding == PUBKEY_ENC_RAW && lhash && (explicit_raw || (parsed_flags & PUBKEY_FLAG_RFC6979))) { @@ -3406,8 +3464,7 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) if (rc) goto leave; - rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, - ctx.verify_cmp, &ctx); + rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, &ctx); leave: if (pkey) diff --git a/cipher/rsa.c b/cipher/rsa.c index c9fcebf..bb22d05 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -1020,8 +1020,8 @@ rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, static gcry_err_code_t rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *opaque, gcry_mpi_t tmp), - void *opaquev) + int (*cmp) (void *opaque, gcry_mpi_t tmp), void *opaquev, + int flags, int hashalgo) { RSA_public_key pk; gcry_mpi_t result; @@ -1030,6 +1030,8 @@ rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, (void)algo; (void)cmp; (void)opaquev; + (void)flags; + (void)hashalgo; if (mpi_is_opaque (hash)) return GPG_ERR_INV_DATA; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 770a245..4c8cdb1 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2364,6 +2364,7 @@ Here, the data to be signed is directly given as an @var{MPI}. @noindent For DSA the input data is expected in this format: + @example (data (flags raw) @@ -2411,11 +2412,28 @@ S-expression returned is: @end example Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign -operation. For Elgamal signing (which is slow, yields large numbers -and probably is not as secure as the other algorithms), the same format is -used with "elg" replacing "dsa"; for ECDSA signing, the same format is used +operation. + +For Elgamal signing (which is slow, yields large numbers and probably +is not as secure as the other algorithms), the same format is used +with "elg" replacing "dsa"; for ECDSA signing, the same format is used with "ecdsa" replacing "dsa". +For the EdDSA algorithm (cf. Ed25515) the required input parameters are: + + at example +(data + (flags eddsa) + (hash-algo sha-512) + (value @var{message})) + at end example + +Note that the @var{message} may be of any length; hashing is part of +the algorithm. Using a large data block for @var{message} is not +suggested; in that case the used protocol should better require that a +hash of the message is used as input to the EdDSA algorithm. + + @end deftypefun @c end gcry_pk_sign diff --git a/src/cipher.h b/src/cipher.h index bb92758..3674c2d 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -28,6 +28,7 @@ #define PUBKEY_FLAG_NO_BLINDING (1 << 0) #define PUBKEY_FLAG_RFC6979 (1 << 1) +#define PUBKEY_FLAG_EDDSA (1 << 2) enum pk_operation { diff --git a/src/gcrypt-module.h b/src/gcrypt-module.h index 5276e8f..75ca8ab 100644 --- a/src/gcrypt-module.h +++ b/src/gcrypt-module.h @@ -137,7 +137,9 @@ typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo, gcry_mpi_t *data, gcry_mpi_t *pkey, int (*cmp) (void *, gcry_mpi_t), - void *opaquev); + void *opaquev, + int flags, + int hashalgo); /* Type for the pk_get_nbits function. */ typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey); commit c26be7a337d0bf98193bc58e043209e46d0769bb Author: Werner Koch Date: Tue Sep 3 12:01:15 2013 +0200 Prepare support for non-Weierstrass EC equations. * src/mpi.h (gcry_mpi_ec_models): New. * src/ec-context.h (mpi_ec_ctx_s): Add MODEL. * cipher/ecc-common.h (elliptic_curve_t): Ditto. * cipher/ecc-curves.c (ecc_domain_parms_t): Ditto. (domain_parms): Mark als as Weierstrass. (_gcry_ecc_fill_in_curve): Check model. (_gcry_ecc_get_curve): Set model to Weierstrass. * cipher/ecc-misc.c (_gcry_ecc_model2str): New. * cipher/ecc.c (generate_key, ecc_generate_ext): Print model in the debug output. * mpi/ec.c (_gcry_mpi_ec_dup_point): Switch depending on model. Factor code out to ... (dup_point_weierstrass): new. (dup_point_montgomery, dup_point_twistededwards): New stub functions. (_gcry_mpi_ec_add_points): Switch depending on model. Factor code out to ... (add_points_weierstrass): new. (add_points_montgomery, add_points_twistededwards): New stub functions. * tests/Makefile.am (TESTS): Reorder tests. Signed-off-by: Werner Koch diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h index 94da73e..614baae 100644 --- a/cipher/ecc-common.h +++ b/cipher/ecc-common.h @@ -23,9 +23,11 @@ /* Definition of a curve. */ typedef struct { + enum gcry_mpi_ec_models model;/* The model descrinbing this curve. */ gcry_mpi_t p; /* Prime specifying the field GF(p). */ gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ - gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ + gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. + or d as used by Twisted Edwards curves. */ mpi_point_struct G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ const char *name; /* Name of the curve or NULL. */ @@ -73,6 +75,7 @@ gcry_sexp_t _gcry_ecc_get_param_sexp (const char *name); /*-- ecc-misc.c --*/ void _gcry_ecc_curve_free (elliptic_curve_t *E); elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E); +const char *_gcry_ecc_model2str (enum gcry_mpi_ec_models model); gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p); gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value); diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index e813b6b..e956dad 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -77,8 +77,12 @@ typedef struct const char *desc; /* Description of the curve. */ unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ + + enum gcry_mpi_ec_models model;/* The model describing this curve. */ + const char *p; /* Order of the prime field. */ - const char *a, *b; /* The coefficients. */ + const char *a, *b; /* The coefficients. For Twisted Edwards + Curves b is used for d. */ const char *n; /* The order of the base point. */ const char *g_x, *g_y; /* Base point. */ } ecc_domain_parms_t; @@ -89,6 +93,7 @@ static const ecc_domain_parms_t domain_parms[] = { { "NIST P-192", 192, 1, + MPI_EC_WEIERSTRASS, "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xfffffffffffffffffffffffffffffffefffffffffffffffc", "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", @@ -99,6 +104,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-224", 224, 1, + MPI_EC_WEIERSTRASS, "0xffffffffffffffffffffffffffffffff000000000000000000000001", "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", @@ -109,6 +115,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-256", 256, 1, + MPI_EC_WEIERSTRASS, "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", @@ -119,6 +126,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-384", 384, 1, + MPI_EC_WEIERSTRASS, "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" "ffffffff0000000000000000ffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" @@ -135,6 +143,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-521", 521, 1, + MPI_EC_WEIERSTRASS, "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -151,6 +160,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP160r1", 160, 0, + MPI_EC_WEIERSTRASS, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -160,6 +170,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP192r1", 192, 0, + MPI_EC_WEIERSTRASS, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -169,6 +180,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP224r1", 224, 0, + MPI_EC_WEIERSTRASS, "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", @@ -178,6 +190,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP256r1", 256, 0, + MPI_EC_WEIERSTRASS, "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", @@ -187,6 +200,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP320r1", 320, 0, + MPI_EC_WEIERSTRASS, "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" "fcd412b1f1b32e27", "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" @@ -202,6 +216,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP384r1", 384, 0, + MPI_EC_WEIERSTRASS, "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" "acd3a729901d1a71874700133107ec53", "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" @@ -217,6 +232,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP512r1", 512, 0, + MPI_EC_WEIERSTRASS, "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" @@ -231,7 +247,7 @@ static const ecc_domain_parms_t domain_parms[] = "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" }, - { NULL, 0, 0, NULL, NULL, NULL, NULL } + { NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; @@ -302,10 +318,23 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, possible to bypass this check by specifying the curve parameters directly. */ if (fips_mode () && !domain_parms[idx].fips ) + return GPG_ERR_NOT_SUPPORTED; + switch (domain_parms[idx].model) + { + case MPI_EC_WEIERSTRASS: + break; + case MPI_EC_TWISTEDEDWARDS: + case MPI_EC_MONTGOMERY: + return GPG_ERR_NOT_SUPPORTED; + default: + return GPG_ERR_BUG; + } + if (r_nbits) *r_nbits = domain_parms[idx].nbits; + curve->p = scanval (domain_parms[idx].p); curve->a = scanval (domain_parms[idx].a); curve->b = scanval (domain_parms[idx].b); @@ -319,7 +348,8 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, } -/* Return the name matching the parameters in PKEY. */ +/* Return the name matching the parameters in PKEY. This works only + with curves described by the Weierstrass equation. */ const char * _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) { @@ -347,6 +377,7 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4]) return NULL; + E.model = MPI_EC_WEIERSTRASS; E.p = pkey[0]; E.a = pkey[1]; E.b = pkey[2]; @@ -505,7 +536,7 @@ point_from_keyparam (gcry_mpi_point_t *r_a, /* This function creates a new context for elliptic curve operations. Either KEYPARAM or CURVENAME must be given. If both are given and - KEYPARAM has no curve parameter CURVENAME is used to add missing + KEYPARAM has no curve parameter, CURVENAME is used to add missing parameters. On success 0 is returned and the new context stored at R_CTX. On error NULL is stored at R_CTX and an error code is returned. The context needs to be released using diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 5e06bef..5c86121 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -64,6 +64,25 @@ _gcry_ecc_curve_copy (elliptic_curve_t E) } +/* + * Return a description of the curve model. + */ +const char * +_gcry_ecc_model2str (enum gcry_mpi_ec_models model) +{ + const char *str = "?"; + switch (model) + { + case MPI_EC_WEIERSTRASS: str = "Weierstrass"; break; + case MPI_EC_MONTGOMERY: str = "Montgomery"; break; + case MPI_EC_TWISTEDEDWARDS: str = "Twisted Edwards"; break; + } + return str; +} + + + + gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) { diff --git a/cipher/ecc.c b/cipher/ecc.c index 9174f9b..8a7ca0b 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -108,8 +108,8 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *, -/**************** - * Solve the right side of the equation that defines a curve. +/* + * Solve the right side of the Weierstrass equation. */ static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) @@ -158,6 +158,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (DBG_CIPHER) { + log_debug ("ecgen curve model: %s\n", _gcry_ecc_model2str (E.model)); log_mpidump ("ecgen curve p", E.p); log_mpidump ("ecgen curve a", E.a); log_mpidump ("ecgen curve b", E.b); @@ -166,7 +167,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, log_mpidump ("ecgen curve Gy", E.G.y); log_mpidump ("ecgen curve Gz", E.G.z); if (E.name) - log_debug ("ecgen curve used: %s\n", E.name); + log_debug ("ecgen curve used: %s\n", E.name); } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -696,6 +697,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (DBG_CIPHER) { + log_debug ("ecgen result model: %s\n", _gcry_ecc_model2str (sk.E.model)); log_mpidump ("ecgen result p", skey[0]); log_mpidump ("ecgen result a", skey[1]); log_mpidump ("ecgen result b", skey[2]); diff --git a/mpi/ec.c b/mpi/ec.c index 8fb47a3..54fa028 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -684,9 +684,9 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point, -/* RESULT = 2 * POINT */ -void -_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) +/* RESULT = 2 * POINT (Weierstrass version). */ +static void +dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) { #define x3 (result->x) #define y3 (result->y) @@ -767,12 +767,48 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) } +/* RESULT = 2 * POINT (Montgomery version). */ +static void +dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) +{ + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_dup_point", "Montgomery"); +} + -/* RESULT = P1 + P2 */ +/* RESULT = 2 * POINT (Twisted Edwards version). */ +static void +dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) +{ + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_dup_point", "Twisted Edwards"); +} + + +/* RESULT = 2 * POINT */ void -_gcry_mpi_ec_add_points (mpi_point_t result, - mpi_point_t p1, mpi_point_t p2, - mpi_ec_t ctx) +_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) +{ + switch (ctx->model) + { + case MPI_EC_WEIERSTRASS: + dup_point_weierstrass (result, point, ctx); + break; + case MPI_EC_MONTGOMERY: + dup_point_montgomery (result, point, ctx); + break; + case MPI_EC_TWISTEDEDWARDS: + dup_point_twistededwards (result, point, ctx); + break; + } +} + + +/* RESULT = P1 + P2 (Weierstrass version).*/ +static void +add_points_weierstrass (mpi_point_t result, + mpi_point_t p1, mpi_point_t p2, + mpi_ec_t ctx) { #define x1 (p1->x ) #define y1 (p1->y ) @@ -910,6 +946,48 @@ _gcry_mpi_ec_add_points (mpi_point_t result, } +/* RESULT = P1 + P2 (Montgomery version).*/ +static void +add_points_montgomery (mpi_point_t result, + mpi_point_t p1, mpi_point_t p2, + mpi_ec_t ctx) +{ + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_add_points", "Montgomery"); +} + + +/* RESULT = P1 + P2 (Twisted Edwards version).*/ +static void +add_points_twistededwards (mpi_point_t result, + mpi_point_t p1, mpi_point_t p2, + mpi_ec_t ctx) +{ + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_add_points", "Twisted Edwards"); +} + + +/* RESULT = P1 + P2 */ +void +_gcry_mpi_ec_add_points (mpi_point_t result, + mpi_point_t p1, mpi_point_t p2, + mpi_ec_t ctx) +{ + switch (ctx->model) + { + case MPI_EC_WEIERSTRASS: + add_points_weierstrass (result, p1, p2, ctx); + break; + case MPI_EC_MONTGOMERY: + add_points_montgomery (result, p1, p2, ctx); + break; + case MPI_EC_TWISTEDEDWARDS: + add_points_twistededwards (result, p1, p2, ctx); + break; + } +} + /* Scalar point multiplication - the main function for ECC. If takes an integer SCALAR and a POINT as well as the usual context CTX. diff --git a/src/ec-context.h b/src/ec-context.h index 7002d47..7df3576 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -23,8 +23,10 @@ /* This context is used with all our EC functions. */ struct mpi_ec_ctx_s { + enum gcry_mpi_ec_models model; /* The model describing this curve. */ + /* Domain parameters. Note that they may not all be set and if set - the MPIs may be flaged as constant.*/ + the MPIs may be flaged as constant. */ gcry_mpi_t p; /* Prime specifying the field GF(p). */ gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ diff --git a/src/mpi.h b/src/mpi.h index fd265bf..0114dba 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -272,6 +272,18 @@ void _gcry_mpi_get_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z, void _gcry_mpi_snatch_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z, mpi_point_t point); +/* Models describing an elliptic curve. */ +enum gcry_mpi_ec_models + { + + MPI_EC_WEIERSTRASS = 0, + MPI_EC_MONTGOMERY, + MPI_EC_TWISTEDEDWARDS + /* The equation for Twisted Edwards curves is + ax^2 + y^2 = 1 + bx^2y^2 + Note that we use 'b' instead of the commonly used 'd'. */ + }; + /* Context used with elliptic curve functions. */ struct mpi_ec_ctx_s; typedef struct mpi_ec_ctx_s *mpi_ec_t; diff --git a/tests/Makefile.am b/tests/Makefile.am index 35bcd60..4cbc34b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -18,9 +18,10 @@ ## Process this file with automake to produce Makefile.in -TESTS = version t-convert t-mpi-bit t-mpi-point prime basic \ - mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap \ - curves t-kdf pkcs1v2 random dsa-rfc6979 +TESTS = version mpitests tsexp t-convert \ + t-mpi-bit t-mpi-point curves \ + prime basic keygen pubkey hmac t-kdf keygrip \ + fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 # The last test to run. commit 8698530b2f9ef95542f1dd550961de7af86cc256 Author: Werner Koch Date: Fri Aug 30 17:56:35 2013 +0200 mpi: Suppress newer gcc warnings. * src/g10lib.h (GCC_ATTR_UNUSED): Define for gcc >= 3.5. * mpi/mpih-div.c (_gcry_mpih_mod_1, _gcry_mpih_divmod_1): Mark dummy as unused. * mpi/mpi-internal.h (UDIV_QRNND_PREINV): Mark _ql as unused. -- Due to the use of macros and longlong.h, we use variables which are only used by some architectures. At least gcc 4.7.2 prints new warnings abot set but not used variables. This patch silences them. Signed-off-by: Werner Koch diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index e75b7c6..178378f 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -145,7 +145,8 @@ typedef int mpi_size_t; /* (must be a signed type) */ */ #define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ do { \ - mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _ql GCC_ATTR_UNUSED; \ + mpi_limb_t _q, _r; \ mpi_limb_t _xh, _xl; \ umul_ppmm (_q, _ql, (nh), (di)); \ _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c index b33dcbf..0bddd22 100644 --- a/mpi/mpih-div.c +++ b/mpi/mpih-div.c @@ -48,7 +48,7 @@ _gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, { mpi_size_t i; mpi_limb_t n1, n0, r; - int dummy; + int dummy GCC_ATTR_UNUSED; /* Botch: Should this be handled at all? Rely on callers? */ if( !dividend_size ) @@ -396,7 +396,7 @@ _gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, { mpi_size_t i; mpi_limb_t n1, n0, r; - int dummy; + int dummy GCC_ATTR_UNUSED; if( !dividend_size ) return 0; diff --git a/src/g10lib.h b/src/g10lib.h index 31131a5..2d84dd3 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -67,6 +67,13 @@ #endif +#if __GNUC__ > 2 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 ) +#define GCC_ATTR_UNUSED __attribute__ ((unused)) +#else +#define GCC_ATTR_UNUSED +#endif + + /* Gettext macros. */ #define _(a) _gcry_gettext(a) commit b28b1f732e1b4f9c62a9de87c22c6bb0d3f8fdb8 Author: Werner Koch Date: Fri Aug 30 17:52:17 2013 +0200 Do not check with cpp for typedefed constants. * src/gcrypt-int.h: Include error code replacements depeding on the version of libgpg-error. Signed-off-by: Werner Koch diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index 33969fe..295328b 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -28,7 +28,7 @@ /* These error codes are used but not defined in the required libgpg-error 1.11. Define them here. */ -#ifndef GPG_ERR_NO_CRYPT_CTX +#if GPG_ERROR_VERSION_NUMBER < 0x010c00 /* 1.12 */ # define GPG_ERR_NO_CRYPT_CTX 191 # define GPG_ERR_WRONG_CRYPT_CTX 192 # define GPG_ERR_BAD_CRYPT_CTX 193 ----------------------------------------------------------------------- Summary of changes: cipher/dsa.c | 5 +- cipher/ecc-common.h | 5 +- cipher/ecc-curves.c | 39 ++++- cipher/ecc-misc.c | 19 ++ cipher/ecc.c | 105 ++++++++-- cipher/elgamal.c | 5 +- cipher/pubkey.c | 79 +++++++- cipher/rsa.c | 6 +- doc/gcrypt.texi | 24 ++- mpi/ec.c | 92 ++++++++- mpi/mpi-internal.h | 3 +- mpi/mpih-div.c | 4 +- src/Makefile.am | 6 +- src/cipher.h | 1 + src/ec-context.h | 4 +- src/g10lib.h | 7 + src/gcrypt-int.h | 2 +- src/gcrypt-module.h | 4 +- src/mpi.h | 12 ++ src/mpicalc.c | 534 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 7 +- 21 files changed, 902 insertions(+), 61 deletions(-) create mode 100644 src/mpicalc.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Thu Sep 5 09:38:07 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Thu, 05 Sep 2013 09:38:07 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-217-ge0ae31f 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 e0ae31fcce3bd57b24751ff3c82cba820e493c3a (commit) via 50ec983666f0ca9d50c84aa1afad0d7bd5810779 (commit) from 1d23040b659661b4086c079cb9fd5f37189a7020 (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 e0ae31fcce3bd57b24751ff3c82cba820e493c3a Author: Jussi Kivilinna Date: Thu Sep 5 09:34:25 2013 +0300 Change _gcry_burn_stack take burn depth as unsigned integer * src/misc.c (_gcry_burn_stack): Change to handle 'unsigned int' bytes. -- Unsigned integer is better here for code generation because we can now avoid possible branching caused by (bytes <= 0) check. Signed-off-by: Jussi Kivilinna diff --git a/src/g10lib.h b/src/g10lib.h index 2d84dd3..4c34ae5 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -242,7 +242,7 @@ int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE; /* Stack burning. */ -void _gcry_burn_stack (int bytes); +void _gcry_burn_stack (unsigned int bytes); /* To avoid that a compiler optimizes certain memset calls away, these diff --git a/src/misc.c b/src/misc.c index 135aeb4..dece1d0 100644 --- a/src/misc.c +++ b/src/misc.c @@ -288,10 +288,11 @@ _gcry_log_printhex (const char *text, const void *buffer, size_t length) void -_gcry_burn_stack (int bytes) +_gcry_burn_stack (unsigned int bytes) { #ifdef HAVE_VLA - int buflen = (((bytes <= 0) ? 1 : bytes) + 63) & ~63; + /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */ + unsigned int buflen = ((!bytes + bytes) + 63) & ~63; volatile char buf[buflen]; wipememory (buf, sizeof buf); @@ -300,9 +301,8 @@ _gcry_burn_stack (int bytes) wipememory (buf, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - _gcry_burn_stack (bytes); + if (bytes > sizeof buf) + _gcry_burn_stack (bytes - sizeof buf); #endif } commit 50ec983666f0ca9d50c84aa1afad0d7bd5810779 Author: Jussi Kivilinna Date: Thu Sep 5 09:46:29 2013 +0300 mpicalc: fix building on linux and win32 * src/Makefile.am (mpicalc): Adjust CFLAGS and LDADD. -- Building libgcrypt is now failing on Ubuntu 13.04 machine. Patch changes src/Makefile.am for 'mpicalc' to correct this issue. $ make distclean; ./configure --enable-maintainer-mode; make ... libtool: link: gcc -g -O2 -fvisibility=hidden -Wall -Wcast-align -Wshadow -Wstrict-prototypes -Wformat -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast -Wwrite-strings -Wdeclaration-after-statement -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith -o .libs/mpicalc mpicalc-mpicalc.o ../src/.libs/libgcrypt.so /usr/bin/ld: mpicalc-mpicalc.o: undefined reference to symbol 'gpg_strerror' /usr/bin/ld: note: 'gpg_strerror' is defined in DSO /lib/x86_64-linux-gnu/libgpg-error.so.0 so try adding it to the linker command line /lib/x86_64-linux-gnu/libgpg-error.so.0: could not read symbols: Invalid operation With win32 target, gpg-error.h is not found. $ make distclean; ./autogen.sh --build-w32; make ... i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -Wall -Wcast-align -Wshadow -Wstrict-prototypes -Wformat -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast -Wwrite-strings -Wdeclaration-after-statement -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith -MT mpicalc-mpicalc.o -MD -MP -MF .deps/mpicalc-mpicalc.Tpo -c -o mpicalc-mpicalc.o `test -f 'mpicalc.c' || echo './'`mpicalc.c In file included from mpicalc.c:36:0: gcrypt.h:32:23: fatal error: gpg-error.h: No such file or directory Signed-off-by: Jussi Kivilinna diff --git a/src/Makefile.am b/src/Makefile.am index 507fcd0..3bc27c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -129,8 +129,8 @@ dumpsexp_CFLAGS = $(arch_gpg_error_cflags) dumpsexp_LDADD = $(arch_gpg_error_libs) mpicalc_SOURCES = mpicalc.c -mpicalc_CFLAGS = $(arch_gpg_error_cflags) -mpicalc_LDADD = ../src/libgcrypt.la $(arch_gpg_error_libs) +mpicalc_CFLAGS = $(GPG_ERROR_CFLAGS) +mpicalc_LDADD = libgcrypt.la $(GPG_ERROR_LIBS) hmac256_SOURCES = hmac256.c hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags) ----------------------------------------------------------------------- Summary of changes: src/Makefile.am | 4 ++-- src/g10lib.h | 2 +- src/misc.c | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Sep 6 11:45:53 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Fri, 06 Sep 2013 11:45:53 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-218-g4e44401 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 4e4440153258e2f0dfdcaa8443820af06984ecb1 (commit) from e0ae31fcce3bd57b24751ff3c82cba820e493c3a (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 4e4440153258e2f0dfdcaa8443820af06984ecb1 Author: Jussi Kivilinna Date: Fri Sep 6 11:11:37 2013 +0300 Tune armv6 mpi assembly * mpi/armv6/mpih-mul1.S: Tune assembly for Cortex-A8. * mpi/armv6/mpih-mul2.S: Ditto. * mpi/armv6/mpih-mul3.S: Ditto. -- Little bit of tuning of assembly functions with help of Cortex-A8 profiler. Old (armhf/Cortex-A8 1Ghz): Algorithm generate 100*sign 100*verify ------------------------------------------------ RSA 1024 bit 350ms 2230ms 50ms RSA 2048 bit 3500ms 11890ms 150ms RSA 3072 bit 23900ms 32540ms 280ms RSA 4096 bit 15750ms 69420ms 450ms Algorithm generate 100*sign 100*verify ------------------------------------------------ DSA 1024/160 - 990ms 930ms DSA 2048/224 - 3840ms 3400ms DSA 3072/256 - 8280ms 7620ms Algorithm generate 100*sign 100*verify ------------------------------------------------ ECDSA 192 bit 60ms 1760ms 3300ms ECDSA 224 bit 80ms 2240ms 4300ms ECDSA 256 bit 110ms 2740ms 5420ms ECDSA 384 bit 230ms 5680ms 11300ms ECDSA 521 bit 540ms 13590ms 26890ms New: Algorithm generate 100*sign 100*verify ------------------------------------------------ RSA 1024 bit 350ms 2190ms 60ms RSA 2048 bit 8910ms 11800ms 150ms RSA 3072 bit 11000ms 31810ms 270ms RSA 4096 bit 50290ms 68690ms 450ms Algorithm generate 100*sign 100*verify ------------------------------------------------ DSA 1024/160 - 980ms 920ms DSA 2048/224 - 3780ms 3370ms DSA 3072/256 - 8100ms 7060ms Algorithm generate 100*sign 100*verify ------------------------------------------------ ECDSA 192 bit 70ms 1730ms 3200ms ECDSA 224 bit 90ms 2180ms 4220ms ECDSA 256 bit 110ms 2660ms 5200ms ECDSA 384 bit 220ms 5660ms 10910ms ECDSA 521 bit 530ms 13420ms 26000ms Signed-off-by: Jussi Kivilinna diff --git a/mpi/armv6/mpih-mul1.S b/mpi/armv6/mpih-mul1.S index ae19a15..0aa41ef 100644 --- a/mpi/armv6/mpih-mul1.S +++ b/mpi/armv6/mpih-mul1.S @@ -60,18 +60,18 @@ _gcry_mpih_mul_1: beq .Lend; .Large_loop: - mov %r9, #0; ldm %r1!, {%r5, %r6, %r7, %r8}; + mov %r9, #0; mov %r10, #0; umlal %r4, %r9, %r5, %r3; mov %r11, #0; umlal %r9, %r10, %r6, %r3; - mov %lr, #0; + str %r4, [%r0], #4; + mov %r4, #0; umlal %r10, %r11, %r7, %r3; subs %r2, #4; - umlal %r11, %lr, %r8, %r3; - stm %r0!, {%r4, %r9, %r10, %r11}; - mov %r4, %lr; + umlal %r11, %r4, %r8, %r3; + stm %r0!, {%r9, %r10, %r11}; bne .Large_loop; .Lend: diff --git a/mpi/armv6/mpih-mul2.S b/mpi/armv6/mpih-mul2.S index 02f7c07..a7eb8a1 100644 --- a/mpi/armv6/mpih-mul2.S +++ b/mpi/armv6/mpih-mul2.S @@ -61,8 +61,8 @@ _gcry_mpih_addmul_1: beq .Lend; .Large_loop: - ldm %r0, {%r4, %r6, %r8, %r10}; ldr %r5, [%r1], #4; + ldm %r0, {%r4, %r6, %r8, %r10}; sub %r2, #4; adcs %r4, %lr; diff --git a/mpi/armv6/mpih-mul3.S b/mpi/armv6/mpih-mul3.S index e42fc30..034929e 100644 --- a/mpi/armv6/mpih-mul3.S +++ b/mpi/armv6/mpih-mul3.S @@ -63,20 +63,23 @@ _gcry_mpih_submul_1: .Large_loop: ldr %r5, [%r1], #4; - ldm %r0, {%r4, %r6, %r8, %r10}; - mov %r9, #0; + ldr %r4, [%r0, #0]; + umlal %lr, %r9, %r5, %r3; + ldr %r6, [%r0, #4]; ldr %r5, [%r1], #4; sbcs %r4, %r4, %lr; mov %lr, #0; umlal %r9, %lr, %r5, %r3; + ldr %r8, [%r0, #8]; ldr %r5, [%r1], #4; sbcs %r6, %r6, %r9; mov %r9, #0; umlal %lr, %r9, %r5, %r3; + ldr %r10, [%r0, #12]; ldr %r5, [%r1], #4; sbcs %r8, %r8, %lr; ----------------------------------------------------------------------- Summary of changes: mpi/armv6/mpih-mul1.S | 10 +++++----- mpi/armv6/mpih-mul2.S | 2 +- mpi/armv6/mpih-mul3.S | 7 +++++-- 3 files changed, 11 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 7 10:49:02 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Sat, 07 Sep 2013 10:49:02 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-222-g49d5b9d 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 49d5b9dcd622cdc87fb02a211bd51e3d46345bf2 (commit) via 4d8c8c7aa88cddb1624301957e6245405f46d027 (commit) via ddfefe429660cc5d798f3517208936449247ae5c (commit) via 1bd2c67aa55b40589654d3fa5dea05cf1ed7dc5f (commit) from 4e4440153258e2f0dfdcaa8443820af06984ecb1 (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 49d5b9dcd622cdc87fb02a211bd51e3d46345bf2 Author: Werner Koch Date: Sat Sep 7 09:50:44 2013 +0200 Add configure option --disable-amd64-as-feature-detection. * configure.ac: Implement new disable flag. -- Doing a static build of Libgcrypt currently throws an as error on my box. Adding this configure option as a workaround Signed-off-by: Werner Koch diff --git a/configure.ac b/configure.ac index 993577b..8deb448 100644 --- a/configure.ac +++ b/configure.ac @@ -613,6 +613,14 @@ AC_ARG_ENABLE([O-flag-munging], AC_MSG_RESULT($enable_o_flag_munging) AM_CONDITIONAL(ENABLE_O_FLAG_MUNGING, test "$enable_o_flag_munging" = "yes") +# Implementation of the --disable-amd64-as-feature-detection switch. +AC_MSG_CHECKING([whether to enable AMD64 as(1) feature detection]) +AC_ARG_ENABLE(amd64-as-feature-detection, + AC_HELP_STRING([--disable-amd64-as-feature-detection], + [Disable the auto-detection of AMD64 as(1) features]), + amd64_as_feature_detection=$enableval, + amd64_as_feature_detection=yes) +AC_MSG_RESULT($amd64_as_feature_detection) AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", @@ -964,7 +972,8 @@ fi # Check whether GCC assembler supports features needed for our amd64 # implementations # -AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations], +if test $amd64_as_feature_detection = yes; then + AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations], [gcry_cv_gcc_amd64_platform_as_ok], [gcry_cv_gcc_amd64_platform_as_ok=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( @@ -984,9 +993,10 @@ AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implement ".type asmfunc, at function;\n\t" );]])], [gcry_cv_gcc_amd64_platform_as_ok=yes])]) -if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then - AC_DEFINE(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS,1, - [Defined if underlying assembler is compatible with amd64 assembly implementations]) + if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then + AC_DEFINE(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS,1, + [Defined if underlying assembler is compatible with amd64 assembly implementations]) + fi fi commit 4d8c8c7aa88cddb1624301957e6245405f46d027 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 mpi: Improve support for non-Weierstrass support. * mpi/ec.c (ec_p_init): Add args MODEL and P. Change all callers. (_gcry_mpi_ec_p_internal_new): Ditto. (_gcry_mpi_ec_p_new): Ditto. * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Return GPG_ERR_UNKNOWN_CURVE instead of invalid value. Init curve model. * cipher/ecc.c (ecc_verify, ecc_encrypt_raw): Ditto. * cipher/pubkey.c (sexp_data_to_mpi): Fix EDDSA flag error checking. -- (fixes commit c26be7a337d0bf98193bc58e043209e46d0769bb) diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index e956dad..89a4d87 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -312,29 +312,30 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, break; } if (!domain_parms[idx].desc) - return GPG_ERR_INV_VALUE; + return GPG_ERR_UNKNOWN_CURVE; /* In fips mode we only support NIST curves. Note that it is possible to bypass this check by specifying the curve parameters directly. */ if (fips_mode () && !domain_parms[idx].fips ) - return GPG_ERR_NOT_SUPPORTED; switch (domain_parms[idx].model) { case MPI_EC_WEIERSTRASS: - break; case MPI_EC_TWISTEDEDWARDS: + break; case MPI_EC_MONTGOMERY: return GPG_ERR_NOT_SUPPORTED; default: return GPG_ERR_BUG; } + if (r_nbits) *r_nbits = domain_parms[idx].nbits; + curve->model = domain_parms[idx].model; curve->p = scanval (domain_parms[idx].p); curve->a = scanval (domain_parms[idx].a); curve->b = scanval (domain_parms[idx].b); @@ -547,6 +548,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, { gpg_err_code_t errc; gcry_ctx_t ctx = NULL; + enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS; gcry_mpi_t p = NULL; gcry_mpi_t a = NULL; gcry_mpi_t b = NULL; @@ -626,6 +628,8 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, goto leave; } + model = E->model; + if (!p) { p = E->p; @@ -657,7 +661,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_free (E); } - errc = _gcry_mpi_ec_p_new (&ctx, p, a); + errc = _gcry_mpi_ec_p_new (&ctx, model, p, a, b); if (!errc) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); @@ -719,7 +723,7 @@ _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey) g_x = mpi_new (0); g_y = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a); + ctx = _gcry_mpi_ec_p_internal_new (0, E.p, E.a, NULL); if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx)) log_fatal ("ecc get param: Failed to get affine coordinates\n"); _gcry_mpi_ec_free (ctx); diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 5c86121..6c34902 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -53,6 +53,7 @@ _gcry_ecc_curve_copy (elliptic_curve_t E) { elliptic_curve_t R; + R.model = E.model; R.p = mpi_copy (E.p); R.a = mpi_copy (E.a); R.b = mpi_copy (E.b); diff --git a/cipher/ecc.c b/cipher/ecc.c index 0cb279f..9d318cc 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -174,10 +174,11 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, /* Compute Q. */ point_init (&Q); - ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a); + ctx = _gcry_mpi_ec_p_internal_new (E.model, E.p, E.a, E.b); _gcry_mpi_ec_mul_point (&Q, sk->d, &E.G, ctx); /* Copy the stuff to the key structures. */ + sk->E.model = E.model; sk->E.p = mpi_copy (E.p); sk->E.a = mpi_copy (E.a); sk->E.b = mpi_copy (E.b); @@ -343,7 +344,7 @@ check_secret_key (ECC_secret_key * sk) goto leave; } - ctx = _gcry_mpi_ec_p_internal_new (sk->E.p, sk->E.a); + ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.p, sk->E.a, sk->E.b); _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); if (mpi_cmp_ui (Q.z, 0)) @@ -457,7 +458,8 @@ sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, mpi_set_ui (s, 0); mpi_set_ui (r, 0); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.p, skey->E.a); + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, + skey->E.p, skey->E.a, skey->E.b); while (!mpi_cmp_ui (s, 0)) /* s == 0 */ { @@ -556,7 +558,8 @@ verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey, point_init (&Q1); point_init (&Q2); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.p, pkey->E.a); + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, + pkey->E.p, pkey->E.a, pkey->E.b); /* h = s^(-1) (mod n) */ mpi_invm (h, s, pkey->E.n); @@ -786,6 +789,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) || !skey[6]) return GPG_ERR_BAD_MPI; + sk.E.model = MPI_EC_WEIERSTRASS; sk.E.p = skey[0]; sk.E.a = skey[1]; sk.E.b = skey[2]; @@ -833,6 +837,9 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, || !skey[6] ) return GPG_ERR_BAD_MPI; + sk.E.model = ((flags & PUBKEY_FLAG_EDDSA) + ? MPI_EC_TWISTEDEDWARDS + : MPI_EC_WEIERSTRASS); sk.E.p = skey[0]; sk.E.a = skey[1]; sk.E.b = skey[2]; @@ -880,6 +887,9 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, || !pkey[3] || !pkey[4] || !pkey[5] ) return GPG_ERR_BAD_MPI; + pk.E.model = ((flags & PUBKEY_FLAG_EDDSA) + ? MPI_EC_TWISTEDEDWARDS + : MPI_EC_WEIERSTRASS); pk.E.p = pkey[0]; pk.E.a = pkey[1]; pk.E.b = pkey[2]; @@ -976,6 +986,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) return GPG_ERR_BAD_MPI; + pk.E.model = MPI_EC_WEIERSTRASS; pk.E.p = pkey[0]; pk.E.a = pkey[1]; pk.E.b = pkey[2]; @@ -996,7 +1007,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, return err; } - ctx = _gcry_mpi_ec_p_internal_new (pk.E.p, pk.E.a); + ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.p, pk.E.a, pk.E.b); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { @@ -1084,7 +1095,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, return err; } - + sk.E.model = MPI_EC_WEIERSTRASS; sk.E.p = skey[0]; sk.E.a = skey[1]; sk.E.b = skey[2]; @@ -1108,7 +1119,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, } sk.d = skey[6]; - ctx = _gcry_mpi_ec_p_internal_new (sk.E.p, sk.E.a); + ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.p, sk.E.a, sk.E.b); /* R = dkG */ point_init (&R); diff --git a/cipher/pubkey.c b/cipher/pubkey.c index fb8de14..141d656 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -2588,7 +2588,7 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, void *value; size_t valuelen; - if (lvalue) + if (!lvalue) { rc = GPG_ERR_INV_OBJ; goto leave; diff --git a/mpi/ec.c b/mpi/ec.c index 7da2e3b..049afa9 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -386,14 +386,18 @@ ec_get_two_inv_p (mpi_ec_t ec) field GF(p). P is the prime specifying this field, A is the first coefficient. CTX is expected to be zeroized. */ static void -ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a) +ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, + gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { int i; /* Fixme: Do we want to check some constraints? e.g. a < p */ + ctx->model = model; ctx->p = mpi_copy (p); ctx->a = mpi_copy (a); + if (b && model == MPI_EC_TWISTEDEDWARDS) + ctx->b = mpi_copy (b); ec_get_reset (ctx); @@ -461,41 +465,35 @@ ec_deinit (void *opaque) /* This function returns a new context for elliptic curve based on the field GF(p). P is the prime specifying this field, A is the first - coefficient. This function is only used within Libgcrypt and not + coefficient, B is the second coefficient, and MODEL is the model + for the curve. This function is only used within Libgcrypt and not part of the public API. This context needs to be released using _gcry_mpi_ec_free. */ mpi_ec_t -_gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a) +_gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, + gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { mpi_ec_t ctx; ctx = gcry_xcalloc (1, sizeof *ctx); - ec_p_init (ctx, p, a); + ec_p_init (ctx, model, p, a, b); return ctx; } -void -_gcry_mpi_ec_free (mpi_ec_t ctx) -{ - if (ctx) - { - ec_deinit (ctx); - gcry_free (ctx); - } -} +/* This is a variant of _gcry_mpi_ec_p_internal_new which returns an + public contect and does some error checking on the supplied + arguments. On success the new context is stored at R_CTX and 0 is + returned; on error NULL is stored at R_CTX and an error code is + returned. - -/* This function returns a new context for elliptic curve operations - based on the field GF(p). P is the prime specifying this field, A - is the first coefficient. On success the new context is stored at - R_CTX and 0 is returned; on error NULL is stored at R_CTX and an - error code is returned. The context needs to be released using - gcry_ctx_release. This is an internal fucntions. */ + The context needs to be released using gcry_ctx_release. */ gpg_err_code_t -_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a) +_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, + enum gcry_mpi_ec_models model, + gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { gcry_ctx_t ctx; mpi_ec_t ec; @@ -508,12 +506,24 @@ _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a) if (!ctx) return gpg_err_code_from_syserror (); ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - ec_p_init (ec, p, a); + ec_p_init (ec, model, p, a, b); *r_ctx = ctx; return 0; } + +void +_gcry_mpi_ec_free (mpi_ec_t ctx) +{ + if (ctx) + { + ec_deinit (ctx); + gcry_free (ctx); + } +} + + gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy) { @@ -772,6 +782,9 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) static void dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) { + (void)result; + (void)point; + (void)ctx; log_fatal ("%s: %s not yet supported\n", "_gcry_mpi_ec_dup_point", "Montgomery"); } @@ -953,6 +966,10 @@ add_points_montgomery (mpi_point_t result, mpi_point_t p1, mpi_point_t p2, mpi_ec_t ctx) { + (void)result; + (void)p1; + (void)p2; + (void)ctx; log_fatal ("%s: %s not yet supported\n", "_gcry_mpi_ec_add_points", "Montgomery"); } diff --git a/src/mpi.h b/src/mpi.h index 09ba717..6406112 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -291,8 +291,13 @@ enum gcry_mpi_ec_models struct mpi_ec_ctx_s; typedef struct mpi_ec_ctx_s *mpi_ec_t; -mpi_ec_t _gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a); +mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, + gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); +gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, + enum gcry_mpi_ec_models model, + gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); void _gcry_mpi_ec_free (mpi_ec_t ctx); + int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point, mpi_ec_t ctx); void _gcry_mpi_ec_dup_point (mpi_point_t result, @@ -303,11 +308,10 @@ void _gcry_mpi_ec_add_points (mpi_point_t result, void _gcry_mpi_ec_mul_point (mpi_point_t result, gcry_mpi_t scalar, mpi_point_t point, mpi_ec_t ctx); +int _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx); gcry_mpi_t _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx); -gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, - gcry_mpi_t p, gcry_mpi_t a); gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_sexp_t keyparam, const char *curvename); gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy); commit ddfefe429660cc5d798f3517208936449247ae5c Author: Werner Koch Date: Fri Sep 6 20:07:07 2013 +0200 mpi: Add gcry_mpi_ec_curve_point. * mpi/ec.c (_gcry_mpi_ec_curve_point): New. (ec_powm): Return the absolute value. * src/visibility.c, src/visibility.c: Add wrappers. * src/libgcrypt.def, src/libgcrypt.vers: Export them. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index ba9bb02..d187de9 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -4197,6 +4197,13 @@ Multiply the point @var{u} of the elliptic curve described by @var{ctx} by @var{n} and store the result into @var{w}. @end deftypefun + at deftypefun int gcry_mpi_ec_curve_point ( @ + @w{gcry_mpi_point_t @var{point}}, @w{gcry_ctx_t @var{ctx}}) + +Return true if @var{point} is on the elliptic curve described by + at var{ctx}. + at end deftypefun + @node Miscellaneous @section Miscellaneous diff --git a/mpi/ec.c b/mpi/ec.c index 478416f..7da2e3b 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -328,6 +328,7 @@ ec_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e, mpi_ec_t ctx) { mpi_powm (w, b, e, ctx->p); + _gcry_mpi_abs (w); } static void @@ -1104,3 +1105,52 @@ _gcry_mpi_ec_mul_point (mpi_point_t result, mpi_free (k); #endif } + + +/* Return true if POINT is on the curve described by CTX. */ +int +_gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) +{ + int res = 0; + gcry_mpi_t x, y, w; + + x = mpi_new (0); + y = mpi_new (0); + w = mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) + return 0; + + switch (ctx->model) + { + case MPI_EC_WEIERSTRASS: + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_curve_point", "Weierstrass"); + break; + case MPI_EC_MONTGOMERY: + log_fatal ("%s: %s not yet supported\n", + "_gcry_mpi_ec_curve_point", "Montgomery"); + break; + case MPI_EC_TWISTEDEDWARDS: + { + /* a ? x^2 + y^2 - 1 - b ? x^2 ? y^2 == 0 */ + ec_powm (x, x, mpi_const (MPI_C_TWO), ctx); + ec_powm (y, y, mpi_const (MPI_C_TWO), ctx); + ec_mulm (w, ctx->a, x, ctx); + ec_addm (w, w, y, ctx); + ec_subm (w, w, mpi_const (MPI_C_ONE), ctx); + ec_mulm (x, x, y, ctx); + ec_mulm (x, x, ctx->b, ctx); + ec_subm (w, w, x, ctx); + if (!mpi_cmp_ui (w, 0)) + res = 1; + } + break; + } + + gcry_mpi_release (w); + gcry_mpi_release (x); + gcry_mpi_release (y); + + return res; +} diff --git a/src/libgcrypt.def b/src/libgcrypt.def index 9539d39..9c691ec 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -239,11 +239,12 @@ EXPORTS gcry_sexp_nth_buffer @214 - gcry_mpi_ec_curve_point @215 + gcry_mpi_is_neg @215 + gcry_mpi_neg @216 + gcry_mpi_abs @217 + + gcry_mpi_ec_curve_point @218 - gcry_mpi_is_neg @216 - gcry_mpi_neg @217 - gcry_mpi_abs @218 ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 9bb7ae2..beb691e 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -97,7 +97,8 @@ GCRYPT_1.6 { gcry_mpi_ec_get_mpi; gcry_mpi_ec_get_point; gcry_mpi_ec_set_mpi; gcry_mpi_ec_set_point; gcry_mpi_ec_get_affine; - gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul; gcry_mpi_ec_curve_point; + gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul; + gcry_mpi_ec_curve_point; _gcry_mpi_get_const; diff --git a/src/visibility.c b/src/visibility.c index 0e24411..404da20 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -547,6 +547,13 @@ gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); } +int +gcry_mpi_ec_curve_point (gcry_mpi_point_t point, gcry_ctx_t ctx) +{ + return _gcry_mpi_ec_curve_point + (point, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); +} + unsigned int gcry_mpi_get_nbits (gcry_mpi_t a) { diff --git a/src/visibility.h b/src/visibility.h index a6cb3dc..b4da48e 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -550,6 +550,7 @@ MARK_VISIBLE (gcry_mpi_copy) MARK_VISIBLE (gcry_mpi_div) MARK_VISIBLE (gcry_mpi_dump) MARK_VISIBLEX(gcry_mpi_ec_add) +MARK_VISIBLEX(gcry_mpi_ec_curve_point) MARK_VISIBLEX(gcry_mpi_ec_dup) MARK_VISIBLEX(gcry_mpi_ec_get_affine) MARK_VISIBLEX(gcry_mpi_ec_mul) commit 1bd2c67aa55b40589654d3fa5dea05cf1ed7dc5f Author: Werner Koch Date: Fri Sep 6 19:58:50 2013 +0200 mpi: Add functions to manipulate the sign. * src/gcrypt.h.in (gcry_mpi_is_neg): New. (gcry_mpi_neg, gcry_mpi_abs): New. * mpi/mpiutil.c (_gcry_mpi_is_neg): New. (_gcry_mpi_neg, _gcry_mpi_abs): New. * src/visibility.c, src/visibility.h: Add wrappers. * src/libgcrypt.def, src/libgcrypt.vers: Export them. * src/mpi.h (mpi_is_neg): New. Rename old macro to mpi_has_sign. * mpi/mpi-mod.c (_gcry_mpi_mod_barrett): Use mpi_has_sign. * mpi/mpi-mpow.c (calc_barrett): Ditto. * cipher/primegen.c (_gcry_derive_x931_prime): Ditto * cipher/rsa.c (secret): Ditto. diff --git a/NEWS b/NEWS index ee737f9..e4fe1eb 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,9 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRY_RNG_TYPE_STANDARD NEW. GCRY_RNG_TYPE_FIPS NEW. GCRY_RNG_TYPE_SYSTEM NEW. + gcry_mpi_is_neg NEW. + gcry_mpi_neg NEW. + gcry_mpi_abs NEW. gcry_mpi_snatch NEW. gcry_mpi_point_t NEW. gcry_mpi_point_new NEW. @@ -65,6 +68,7 @@ Noteworthy changes in version 1.6.0 (unreleased) gcry_mpi_ec_dup NEW. gcry_mpi_ec_add NEW. gcry_mpi_ec_mul NEW. + gcry_mpi_ec_curve_point NEW. GCRYMPI_FLAG_IMMUTABLE NEW. GCRYMPI_FLAG_CONST NEW. GCRYMPI_CONST_ONE NEW. diff --git a/cipher/primegen.c b/cipher/primegen.c index d0cf20c..3610ae7 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -1351,7 +1351,7 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, mpi_sub (r1, r1, tmp); /* Fixup a negative value. */ - if (mpi_is_neg (r1)) + if (mpi_has_sign (r1)) mpi_add (r1, r1, p1p2); /* yp0 = xp + (r1 - xp mod p1*p2) */ diff --git a/cipher/rsa.c b/cipher/rsa.c index bb22d05..8d17129 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -722,7 +722,7 @@ secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey ) mpi_powm( m2, input, h, skey->q ); /* h = u * ( m2 - m1 ) mod q */ mpi_sub( h, m2, m1 ); - if ( mpi_is_neg( h ) ) + if ( mpi_has_sign ( h ) ) mpi_add ( h, h, skey->q ); mpi_mulm( h, skey->u, h, skey->q ); /* m = m2 + h * p */ diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 4c8cdb1..ba9bb02 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2424,7 +2424,7 @@ For the EdDSA algorithm (cf. Ed25515) the required input parameters are: @example (data (flags eddsa) - (hash-algo sha-512) + (hash-algo sha512) (value @var{message})) @end example @@ -3763,6 +3763,17 @@ Set @var{u} into @var{w} and release @var{u}. If @var{w} is @code{NULL} only @var{u} will be released. @end deftypefun + at deftypefun void gcry_mpi_neg (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}) + +Set the sign of @var{w} to the negative of @var{u}. + at end deftypefun + + at deftypefun void gcry_mpi_abs (@w{gcry_mpi_t @var{w}}) + +Clear the sign of @var{w}. + at end deftypefun + + @node MPI formats @section MPI formats @@ -3949,6 +3960,11 @@ integer @var{v} returning 0 for equality, a positive value for @var{u} > @var{v} and a negative for @var{u} < @var{v}. @end deftypefun + at deftypefun int gcry_mpi_is_neg (@w{const gcry_mpi_t @var{a}}) + +Return 1 if @var{a} is less than zero; return 0 if zero or positive. + at end deftypefun + @node Bit manipulations @section Bit manipulations diff --git a/mpi/ec.c b/mpi/ec.c index 54fa028..478416f 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -1025,7 +1025,7 @@ _gcry_mpi_ec_mul_point (mpi_point_t result, k = mpi_copy (scalar); yy = mpi_copy (point->y); - if ( mpi_is_neg (k) ) + if ( mpi_has_sign (k) ) { k->sign = 0; ec_invm (yy, yy, ctx); diff --git a/mpi/mpi-mod.c b/mpi/mpi-mod.c index 7ebfe6d..795826e 100644 --- a/mpi/mpi-mod.c +++ b/mpi/mpi-mod.c @@ -157,7 +157,7 @@ _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) r2->nlimbs = k+1; mpi_sub ( r, r1, r2 ); - if ( mpi_is_neg( r ) ) + if ( mpi_has_sign ( r ) ) { if (!ctx->r3) { diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c index ca5b3f1..ec677fe 100644 --- a/mpi/mpi-mpow.c +++ b/mpi/mpi-mpow.c @@ -204,7 +204,7 @@ calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcr r2->nlimbs = k+1; mpi_sub( r, r1, r2 ); - if( mpi_is_neg( r ) ) { + if( mpi_has_sign (r) ) { gcry_mpi_t tmp; tmp = mpi_alloc( k + 2 ); diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index a65d236..433dda6 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -324,6 +324,45 @@ gcry_mpi_copy( gcry_mpi_t a ) } +/* Return true if A is negative. */ +int +_gcry_mpi_is_neg (gcry_mpi_t a) +{ + if (a->sign && _gcry_mpi_cmp_ui (a, 0)) + return 1; + else + return 0; +} + + +/* W = - U */ +void +_gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u) +{ + if (mpi_is_immutable (w)) + { + mpi_immutable_failed (); + return; + } + + w->sign = !u->sign; +} + + +/* W = [W] */ +void +_gcry_mpi_abs (gcry_mpi_t w) +{ + if (mpi_is_immutable (w)) + { + mpi_immutable_failed (); + return; + } + + w->sign = 0; +} + + /**************** * This function allocates an MPI which is optimized to hold * a value as large as the one given in the argument and allocates it diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 06d6663..71c50ab 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -508,6 +508,15 @@ gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u); /* Swap the values of A and B. */ void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b); +/* Return 1 if A is negative; 0 if zero or positive. */ +int gcry_mpi_is_neg (gcry_mpi_t a); + +/* W = - U */ +void gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u); + +/* W = [W] */ +void gcry_mpi_abs (gcry_mpi_t w); + /* Compare the big integer number U and V returning 0 for equality, a positive value for U > V and a negative for U < V. */ int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v); @@ -661,6 +670,8 @@ void gcry_mpi_ec_add (gcry_mpi_point_t w, void gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u, gcry_ctx_t ctx); +/* Return true if POINT is on the curve described by CTX. */ +int gcry_mpi_ec_curve_point (gcry_mpi_point_t w, gcry_ctx_t ctx); /* Return the number of bits required to represent A. */ unsigned int gcry_mpi_get_nbits (gcry_mpi_t a); @@ -728,8 +739,11 @@ gcry_mpi_t _gcry_mpi_get_const (int no); #define mpi_snatch( w, u) gcry_mpi_snatch( (w), (u) ) #define mpi_set( w, u) gcry_mpi_set( (w), (u) ) #define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) ) +#define mpi_abs( w ) gcry_mpi_abs( (w) ) +#define mpi_neg( w, u) gcry_mpi_neg( (w), (u) ) #define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) ) #define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) ) +#define mpi_is_neg( a ) gcry_mpi_is_new ((a)) #define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) #define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) diff --git a/src/libgcrypt.def b/src/libgcrypt.def index f275ae9..9539d39 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -239,5 +239,11 @@ EXPORTS gcry_sexp_nth_buffer @214 + gcry_mpi_ec_curve_point @215 + + gcry_mpi_is_neg @216 + gcry_mpi_neg @217 + gcry_mpi_abs @218 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 473ee68..9bb7ae2 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -77,6 +77,7 @@ GCRYPT_1.6 { gcry_sexp_sprint; gcry_sexp_sscan; gcry_sexp_vlist; gcry_sexp_nth_string; + gcry_mpi_is_neg; gcry_mpi_neg; gcry_mpi_abs; gcry_mpi_add; gcry_mpi_add_ui; gcry_mpi_addm; gcry_mpi_aprint; gcry_mpi_clear_bit; gcry_mpi_clear_flag; gcry_mpi_clear_highbit; gcry_mpi_cmp; gcry_mpi_cmp_ui; gcry_mpi_copy; gcry_mpi_div; @@ -96,7 +97,7 @@ GCRYPT_1.6 { gcry_mpi_ec_get_mpi; gcry_mpi_ec_get_point; gcry_mpi_ec_set_mpi; gcry_mpi_ec_set_point; gcry_mpi_ec_get_affine; - gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul; + gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul; gcry_mpi_ec_curve_point; _gcry_mpi_get_const; diff --git a/src/mpi.h b/src/mpi.h index 0114dba..09ba717 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -78,7 +78,7 @@ struct gcry_mpi #define MPI_NULL NULL #define mpi_get_nlimbs(a) ((a)->nlimbs) -#define mpi_is_neg(a) ((a)->sign) +#define mpi_has_sign(a) ((a)->sign) /*-- mpiutil.c --*/ @@ -134,6 +134,9 @@ void _gcry_mpi_m_check( gcry_mpi_t a ); void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); gcry_mpi_t _gcry_mpi_new (unsigned int nbits); gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); +int _gcry_mpi_is_neg (gcry_mpi_t a); +void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u); +void _gcry_mpi_abs (gcry_mpi_t w); /* Constants used to return constant MPIs. See _gcry_mpi_init if you want to add more constants. */ diff --git a/src/visibility.c b/src/visibility.c index bb51d58..0e24411 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -293,6 +293,24 @@ gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b) } int +gcry_mpi_is_neg (gcry_mpi_t a) +{ + return _gcry_mpi_is_neg (a); +} + +void +gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u) +{ + _gcry_mpi_neg (w, u); +} + +void +gcry_mpi_abs (gcry_mpi_t w) +{ + _gcry_mpi_abs (w); +} + +int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v) { return _gcry_mpi_cmp (u, v); diff --git a/src/visibility.h b/src/visibility.h index 54da016..a6cb3dc 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -536,6 +536,7 @@ MARK_VISIBLE (gcry_sexp_sprint) MARK_VISIBLE (gcry_sexp_sscan) MARK_VISIBLE (gcry_sexp_vlist) +MARK_VISIBLEX(gcry_mpi_abs) MARK_VISIBLE (gcry_mpi_add) MARK_VISIBLE (gcry_mpi_add_ui) MARK_VISIBLE (gcry_mpi_addm) @@ -561,12 +562,14 @@ MARK_VISIBLE (gcry_mpi_gcd) MARK_VISIBLE (gcry_mpi_get_flag) MARK_VISIBLE (gcry_mpi_get_nbits) MARK_VISIBLE (gcry_mpi_get_opaque) +MARK_VISIBLEX(gcry_mpi_is_neg) MARK_VISIBLE (gcry_mpi_invm) MARK_VISIBLE (gcry_mpi_mod) MARK_VISIBLE (gcry_mpi_mul) MARK_VISIBLE (gcry_mpi_mul_2exp) MARK_VISIBLE (gcry_mpi_mul_ui) MARK_VISIBLE (gcry_mpi_mulm) +MARK_VISIBLEX(gcry_mpi_neg) MARK_VISIBLE (gcry_mpi_new) MARK_VISIBLE (gcry_mpi_point_get) MARK_VISIBLE (gcry_mpi_point_new) ----------------------------------------------------------------------- Summary of changes: NEWS | 4 ++ cipher/ecc-curves.c | 14 ++++-- cipher/ecc-misc.c | 1 + cipher/ecc.c | 25 ++++++++--- cipher/primegen.c | 2 +- cipher/pubkey.c | 2 +- cipher/rsa.c | 2 +- configure.ac | 18 ++++++-- doc/gcrypt.texi | 25 +++++++++++- mpi/ec.c | 113 ++++++++++++++++++++++++++++++++++++++++---------- mpi/mpi-mod.c | 2 +- mpi/mpi-mpow.c | 2 +- mpi/mpiutil.c | 39 +++++++++++++++++ src/gcrypt.h.in | 14 ++++++ src/libgcrypt.def | 7 +++ src/libgcrypt.vers | 2 + src/mpi.h | 15 +++++-- src/visibility.c | 25 +++++++++++ src/visibility.h | 4 ++ 19 files changed, 267 insertions(+), 49 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 7 10:58:23 2013 From: cvs at cvs.gnupg.org (by Dmitry Eremin-Solenikov) Date: Sat, 07 Sep 2013 10:58:23 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-223-gae6f6c4 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 ae6f6c47d2e0c536f3eab0823b5f23d26956cda2 (commit) from 49d5b9dcd622cdc87fb02a211bd51e3d46345bf2 (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 ae6f6c47d2e0c536f3eab0823b5f23d26956cda2 Author: Dmitry Eremin-Solenikov Date: Thu Sep 5 13:42:11 2013 +0400 Add support for Salsa20/12 - 12 round version of Salsa20 * src/gcrypt.h.in (GCRY_CIPHER_SALSA20R12): New. * src/salsa20.c (salsa20_core, salsa20_do_encrypt_stream): Add support for reduced round versions. (salsa20r12_encrypt_stream, _gcry_cipher_spec_salsa20r12): Implement Salsa20/12 - a 12 round version of Salsa20 selected by eStream. * src/cipher.h: Declsare Salsa20/12 definition. * cipher/cipher.c: Register Salsa20/12 * tests/basic.c: (check_stream_cipher, check_stream_cipher_large_block): Populate Salsa20/12 tests with test vectors from ecrypt (check_ciphers): Add simple test for Salsa20/12 -- Salsa20/12 is a reduced round version of Salsa20 that is amongst ciphers selected by eSTREAM for Phase 3 of Profile 1 algorithm. Moreover it is one of proposed ciphers for TLS (draft-josefsson-salsa20-tls-02). Signed-off-by: Dmitry Eremin-Solenikov diff --git a/NEWS b/NEWS index e4fe1eb..5a39a38 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ Noteworthy changes in version 1.6.0 (unreleased) * Added support for the IDEA cipher algorithm. - * Added support for the Salsa20 stream cipher. + * Added support for the Salsa20 and reduced Salsa20/12 stream ciphers. * Added a random number generator to directly use the system's RNG. Also added an interface to prefer the use of a specified RNG. @@ -83,6 +83,7 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRYCTL_DISABLE_PRIV_DROP NEW. GCRY_CIPHER_SALSA20 NEW. gcry_sexp_nth_buffer NEW. + GCRY_CIPHER_SALSA20R12 NEW. Noteworthy changes in version 1.5.0 (2011-06-29) diff --git a/cipher/cipher.c b/cipher/cipher.c index 2337c09..6ddd58b 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -107,6 +107,8 @@ static struct cipher_table_entry #if USE_SALSA20 { &_gcry_cipher_spec_salsa20, &_gcry_cipher_extraspec_salsa20, GCRY_CIPHER_SALSA20 }, + { &_gcry_cipher_spec_salsa20r12, + &_gcry_cipher_extraspec_salsa20, GCRY_CIPHER_SALSA20R12 }, #endif { NULL } }; diff --git a/cipher/salsa20.c b/cipher/salsa20.c index e26c328..37f2989 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -49,6 +49,7 @@ /* Number of rounds. The standard uses 20 rounds. In any case the number of rounds must be even. */ #define SALSA20_ROUNDS 20 +#define SALSA20R12_ROUNDS 12 typedef struct @@ -120,13 +121,13 @@ static const char *selftest (void); } while(0) static void -salsa20_core (u32 *dst, const u32 *src) +salsa20_core (u32 *dst, const u32 *src, unsigned rounds) { u32 pad[SALSA20_INPUT_LENGTH]; unsigned int i; memcpy (pad, src, sizeof(pad)); - for (i = 0; i < SALSA20_ROUNDS; i += 2) + for (i = 0; i < rounds; i += 2) { SALSA20_CORE_DEBUG (i); QROUND (pad[0], pad[4], pad[8], pad[12]); @@ -253,7 +254,7 @@ salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) static void salsa20_do_encrypt_stream (SALSA20_context_t *ctx, byte *outbuf, const byte *inbuf, - unsigned int length) + unsigned int length, unsigned rounds) { if (ctx->unused) { @@ -280,7 +281,7 @@ salsa20_do_encrypt_stream (SALSA20_context_t *ctx, /* Create the next pad and bump the block counter. Note that it is the user's duty to change to another nonce not later than after 2^70 processed bytes. */ - salsa20_core (ctx->pad, ctx->input); + salsa20_core (ctx->pad, ctx->input, rounds); if (!++ctx->input[8]) ctx->input[9]++; @@ -306,7 +307,30 @@ salsa20_encrypt_stream (void *context, if (length) { - salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length); + salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS); + _gcry_burn_stack (/* salsa20_do_encrypt_stream: */ + 2*sizeof (void*) + + 3*sizeof (void*) + sizeof (unsigned int) + /* salsa20_core: */ + + 2*sizeof (void*) + + 2*sizeof (void*) + + 64 + + sizeof (unsigned int) + + sizeof (u32) + ); + } +} + + +static void +salsa20r12_encrypt_stream (void *context, + byte *outbuf, const byte *inbuf, unsigned int length) +{ + SALSA20_context_t *ctx = (SALSA20_context_t *)context; + + if (length) + { + salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS); _gcry_burn_stack (/* salsa20_do_encrypt_stream: */ 2*sizeof (void*) + 3*sizeof (void*) + sizeof (unsigned int) @@ -372,6 +396,21 @@ gcry_cipher_spec_t _gcry_cipher_spec_salsa20 = salsa20_encrypt_stream }; +gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12 = + { + "SALSA20R12", /* name */ + NULL, /* aliases */ + NULL, /* oids */ + 1, /* blocksize in bytes. */ + SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */ + sizeof (SALSA20_context_t), + salsa20_setkey, + NULL, + NULL, + salsa20r12_encrypt_stream, + salsa20r12_encrypt_stream + }; + cipher_extra_spec_t _gcry_cipher_extraspec_salsa20 = { NULL, diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index d187de9..09501f0 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1579,6 +1579,10 @@ The Camellia cipher by NTT. See @cindex Salsa20 This is the Salsa20 stream cipher. + at item GCRY_CIPHER_SALSA20R12 + at cindex Salsa20/12 +This is the Salsa20/12 - reduced round version of Salsa20 stream cipher. + @end table @node Available cipher modes diff --git a/src/cipher.h b/src/cipher.h index 3674c2d..ea8ba2a 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -197,6 +197,7 @@ extern gcry_cipher_spec_t _gcry_cipher_spec_camellia192; extern gcry_cipher_spec_t _gcry_cipher_spec_camellia256; extern gcry_cipher_spec_t _gcry_cipher_spec_idea; extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20; +extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12; extern cipher_extra_spec_t _gcry_cipher_extraspec_tripledes; extern cipher_extra_spec_t _gcry_cipher_extraspec_aes; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 71c50ab..5d30ced 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -834,7 +834,8 @@ enum gcry_cipher_algos GCRY_CIPHER_CAMELLIA128 = 310, GCRY_CIPHER_CAMELLIA192 = 311, GCRY_CIPHER_CAMELLIA256 = 312, - GCRY_CIPHER_SALSA20 = 313 + GCRY_CIPHER_SALSA20 = 313, + GCRY_CIPHER_SALSA20R12 = 314 }; /* The Rijndael algorithm is basically AES, so provide some macros. */ diff --git a/tests/basic.c b/tests/basic.c index 46e213c..4fbca43 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1241,6 +1241,91 @@ check_stream_cipher (void) "\x2B\xB2\x55\x71\xE1\xAA\x85\x93\x75\x8F\xC3\x82\xB1\x28\x0B\x71" } } + }, + { + "Salsa20/12 128 bit, test 1", + GCRY_CIPHER_SALSA20R12, 16, 8, + "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\xFC\x20\x7D\xBF\xC7\x6C\x5E\x17" + } + } + }, + { + "Salsa20/12 128 bit, test 2", + GCRY_CIPHER_SALSA20R12, 16, 8, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x80\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x08\x28\x39\x9A\x6F\xEF\x20\xDA" + } + } + }, + { + "Salsa20/12 128 bit, test 3", + GCRY_CIPHER_SALSA20R12, 16, 8, + "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD", + "\x0D\x74\xDB\x42\xA9\x10\x77\xDE", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\xAD\x9E\x60\xE6\xD2\xA2\x64\xB8" + } + } + }, + { + "Salsa20/12 256 bit, test 1", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\xAF\xE4\x11\xED\x1C\x4E\x07\xE4" + } + } + }, + { + "Salsa20/12 256 bit, test 2", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x80\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x17\x2C\x51\x92\xCB\x6E\x64\x5B" + } + } + }, + { + "Salsa20/12 256 bit, ecrypt verified, set 6, vector 0", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD" + "\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D", + "\x0D\x74\xDB\x42\xA9\x10\x77\xDE", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x52\xE2\x0C\xF8\x77\x5A\xE8\x82" + }, + { 64, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x52\xE2\x0C\xF8\x77\x5A\xE8\x82\xF2\x00\xC2\x99\x9F\xE4\xBA\x31" + "\xA7\xA1\x8F\x1D\x5C\x97\x16\x19\x1D\x12\x31\x75\xE1\x47\xBD\x4E" + "\x8C\xA6\xED\x16\x6C\xE0\xFC\x8E\x65\xA5\xCA\x60\x84\x20\xFC\x65" + "\x44\xC9\x70\x0A\x0F\x21\x38\xE8\xC1\xA2\x86\xFB\x8C\x1F\xBF\xA0" + } + } } #endif /*USE_SALSA20*/ }; @@ -1543,6 +1628,138 @@ check_stream_cipher_large_block (void) "\xEB\x31\x4E\xD4\x70\xB1\xAF\x6B\x9F\x8D\x69\xDD\x79\xA9\xD7\x50" } } + }, + { + "Salsa20/12 256 bit, ecrypt verified, set 6, vector 0", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD" + "\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D", + "\x0D\x74\xDB\x42\xA9\x10\x77\xDE", + { + { 0, 64, + "\x52\xE2\x0C\xF8\x77\x5A\xE8\x82\xF2\x00\xC2\x99\x9F\xE4\xBA\x31" + "\xA7\xA1\x8F\x1D\x5C\x97\x16\x19\x1D\x12\x31\x75\xE1\x47\xBD\x4E" + "\x8C\xA6\xED\x16\x6C\xE0\xFC\x8E\x65\xA5\xCA\x60\x84\x20\xFC\x65" + "\x44\xC9\x70\x0A\x0F\x21\x38\xE8\xC1\xA2\x86\xFB\x8C\x1F\xBF\xA0" + }, + { 65472, 64, + "\x8F\xBC\x9F\xE8\x69\x1B\xD4\xF0\x82\xB4\x7F\x54\x05\xED\xFB\xC1" + "\x6F\x4D\x5A\x12\xDD\xCB\x2D\x75\x4E\x8A\x99\x98\xD0\xB2\x19\x55" + "\x7D\xFE\x29\x84\xF4\xA1\xD2\xDD\xA7\x6B\x95\x96\x92\x8C\xCE\x05" + "\x56\xF5\x00\x66\xCD\x59\x9E\x44\xEF\x5C\x14\xB2\x26\x68\x3A\xEF" + }, + { 65536, 64, + "\xBC\xBD\x01\xDD\x28\x96\x1C\xC7\xAD\x30\x47\x38\x6C\xBC\xC6\x7C" + "\x10\x8D\x6A\xF1\x11\x67\xE4\x0D\x7A\xE1\xB2\xFC\x45\x18\xA8\x67" + "\xEF\xE4\x02\x65\x1D\x1D\x88\x51\xC4\xFD\x23\x30\xC5\x97\xB3\x6A" + "\x46\xD5\x68\x9E\x00\xFC\x96\xFE\xCF\x9C\xE3\xE2\x21\x1D\x44\xBE" + }, + { 131008, 64, + "\x91\x66\xF3\x1C\xD8\x5B\x5B\xB1\x8F\xC6\x14\xE5\x4E\x4A\xD6\x7F" + "\xB8\x65\x8E\x3B\xF9\xFB\x19\xB7\xA8\x2F\x0F\xE7\xDC\x90\x2D\xF5" + "\x63\xC6\xAC\x4F\x44\x67\x48\xC4\xBC\x3E\x14\x05\xE1\x24\x82\x0D" + "\xC4\x09\x41\x99\x8F\x44\xA8\x10\xE7\x22\x78\x7F\xCD\x47\x78\x4C" + } + } + }, + { + "Salsa20/12 256 bit, ecrypt verified, set 6, vector 1", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x05\x58\xAB\xFE\x51\xA4\xF7\x4A\x9D\xF0\x43\x96\xE9\x3C\x8F\xE2" + "\x35\x88\xDB\x2E\x81\xD4\x27\x7A\xCD\x20\x73\xC6\x19\x6C\xBF\x12", + "\x16\x7D\xE4\x4B\xB2\x19\x80\xE7", + { + { 0, 64, + "\xC0\x75\x60\xB3\xE7\x76\xB4\x71\xC5\xE2\x93\x14\x26\xCA\xF1\xED" + "\x3A\xE4\xB8\x67\x08\x76\x82\xCA\x9D\xFD\xC2\xBA\xE8\x93\x50\xBD" + "\x84\x82\x1C\xAE\xFF\x85\xAA\xC4\x9D\x74\x35\xA7\xD9\x88\x93\x52" + "\xF5\x27\x9E\x36\x12\x3F\x41\x72\x8A\x14\xEF\x26\x9F\xCB\x94\x4B" + }, + { 65472, 64, + "\xEE\xD1\xBB\x58\xF9\x0C\x89\xE0\x5C\xC6\x8B\x2D\xB6\x05\x58\x49" + "\xB3\xD2\xB1\x87\xB7\xF0\x2F\x9A\x24\xCE\x34\x2A\xF0\xFC\x47\xA3" + "\x74\xBD\x75\x90\xFB\xF4\xFD\x9E\xE5\x9B\x1A\x38\x1E\xBF\xD2\x29" + "\xAD\x2A\x29\x01\xB3\xFB\x61\x08\x12\x90\x0B\x92\x30\xE6\x22\xE9" + }, + { 65536, 64, + "\x70\xF0\x49\x3A\x1B\x62\x53\xCC\x5E\xD3\x45\x0A\x31\xCF\x37\x7D" + "\x83\x4B\xAD\x20\x72\x30\x29\x27\xCC\xD8\x30\x10\x4B\xD3\x05\xFF" + "\x59\xD2\x94\x17\xB2\x32\x88\x4E\xC9\x59\x19\x4D\x60\x47\xC3\xDD" + "\x66\x56\xC4\x7E\x32\x00\x64\xEB\x01\x44\xF7\x34\x1B\xC3\xD6\x97" + }, + { 131008, 64, + "\xD2\xCC\xF7\xC1\xAF\x2A\xB4\x66\xE6\x27\xDB\x44\x08\x40\x96\x9A" + "\xBD\xAB\x68\xD8\x86\xAE\x6A\x38\xA1\x3F\xEE\x17\x50\xCA\x97\xB5" + "\xD3\x31\x5B\x84\x08\x47\x28\x86\x2F\xBC\xC7\xD4\xA9\x7C\x75\xC8" + "\x65\x5F\xF9\xD6\xBB\xC2\x61\x88\x63\x6F\x3E\xDF\xE1\x5C\x7D\x30" + } + } + }, + { + "Salsa20/12 256 bit, ecrypt verified, set 6, vector 2", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x0A\x5D\xB0\x03\x56\xA9\xFC\x4F\xA2\xF5\x48\x9B\xEE\x41\x94\xE7" + "\x3A\x8D\xE0\x33\x86\xD9\x2C\x7F\xD2\x25\x78\xCB\x1E\x71\xC4\x17", + "\x1F\x86\xED\x54\xBB\x22\x89\xF0", + { + { 0, 64, + "\x51\x22\x52\x91\x01\x90\xD1\x54\xD1\x4D\x0B\x92\x32\xB8\x84\x31" + "\x8C\xCB\x43\x81\x9B\xD5\x42\x19\x32\xC0\x3A\x13\xF0\x7B\x40\x10" + "\x83\xD7\x89\x72\x5A\xA9\xDA\x0B\x41\xCB\x62\x24\x94\x5E\xDC\xB0" + "\xFB\x6F\xD7\xC2\x34\x22\x35\xC9\x70\xF6\x4E\x10\x1C\x25\x68\x64" + }, + { 65472, 64, + "\x97\x96\x74\x55\x84\x0A\x4A\xE5\xC1\xCA\xCE\x49\x15\x19\x13\x8A" + "\xA3\x5E\x5F\x02\x40\x7D\x4A\x1F\xE5\x08\x6D\x35\xF3\x55\x1E\xF4" + "\x77\xD9\x28\x9D\x17\x23\x79\x7C\x1A\x49\xEC\x26\x62\x9A\xFA\xDC" + "\x56\xA0\x38\xA3\x8C\x75\x88\x1B\x62\x17\xFD\x74\x67\x25\x59\x09" + }, + { 65536, 64, + "\x1B\xF8\x2E\x3D\x5C\x54\xDA\xAB\xCF\x84\x15\xF8\xA2\xA1\xA2\x2E" + "\x86\x88\x06\x33\x4F\xF3\x11\x36\x04\x74\x1C\x1D\xF2\xB9\x84\x0F" + "\x87\xDE\xEF\xB0\x07\x23\xA8\xA1\xB2\x4A\x4D\xA1\x7E\xCD\xAD\x00" + "\x01\xF9\x79\xDD\xAE\x2D\xF0\xC5\xE1\xE5\x32\xC4\x8F\x8E\x0D\x34" + }, + { 131008, 64, + "\x06\xD8\x4F\x6A\x71\x34\x84\x20\x32\x9F\xCD\x0C\x41\x75\x9A\xD1" + "\x8F\x99\x57\xA3\x8F\x22\x89\x3B\xA5\x58\xC5\x05\x11\x97\x28\x5C" + "\x6B\xE2\xFD\x6C\x96\xA5\xC6\x62\xAF\xD3\x11\x78\xE7\x0F\x96\x0A" + "\xAB\x3F\x47\x96\x23\xA4\x44\xB6\x81\x91\xE4\xC5\x28\x46\x93\x88" + } + } + }, + { + "Salsa20/12 256 bit, ecrypt verified, set 6, vector 3", + GCRY_CIPHER_SALSA20R12, 32, 8, + "\x0F\x62\xB5\x08\x5B\xAE\x01\x54\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC" + "\x3F\x92\xE5\x38\x8B\xDE\x31\x84\xD7\x2A\x7D\xD0\x23\x76\xC9\x1C", + "\x28\x8F\xF6\x5D\xC4\x2B\x92\xF9", + { + { 0, 64, + "\x99\xDB\x33\xAD\x11\xCE\x0C\xCB\x3B\xFD\xBF\x8D\x0C\x18\x16\x04" + "\x52\xD0\x14\xCD\xE9\x89\xB4\xC4\x11\xA5\x59\xFF\x7C\x20\xA1\x69" + "\xE6\xDC\x99\x09\xD8\x16\xBE\xCE\xDC\x40\x63\xCE\x07\xCE\xA8\x28" + "\xF4\x4B\xF9\xB6\xC9\xA0\xA0\xB2\x00\xE1\xB5\x2A\xF4\x18\x59\xC5" + }, + { 65472, 64, + "\x2F\xF2\x02\x64\xEE\xAF\x47\xAB\x7D\x57\xC3\x62\x24\x53\x54\x51" + "\x73\x5A\xC8\x36\xD3\x2D\xD2\x8A\xE6\x36\x45\xCE\x95\x2F\x7F\xDB" + "\xE6\x68\x9C\x69\x59\x77\xB1\xC7\x6E\x60\xDD\x5B\x27\xAC\xA4\x76" + "\xD2\x62\x0F\xDC\x93\x13\xE8\x48\x9B\xA5\x6A\x70\xC9\xF4\xC3\xA8" + }, + { 65536, 64, + "\xEB\x30\xCD\xA7\x27\xC0\xF8\xB7\xE4\x5D\x5E\xF3\x0D\xB7\xCB\xE0" + "\x21\xF2\x29\x1E\x5F\x56\x93\x8D\x56\xF6\x87\xB7\x37\xC3\xB4\x27" + "\x54\x5C\x56\xA6\xD3\xA0\xBF\x2B\x2F\x47\xB4\x84\x93\xFA\xE4\x5E" + "\xD5\x0C\x2E\x9B\xBE\x49\xFD\x92\xD6\x7C\x76\x49\x05\x5F\x06\xFD" + }, + { 131008, 64, + "\x0E\xBF\x6C\xC3\xCB\xCB\xE7\x4E\x6E\xE8\x07\x47\x1B\x49\x2A\x67" + "\x39\xA5\x2F\x57\x11\x31\xA2\x50\xBC\xDF\xA0\x76\xA2\x65\x90\xD7" + "\xED\xE6\x75\x1C\x03\x26\xA0\x2C\xB1\x1C\x58\x77\x35\x52\x80\x4F" + "\xD8\x68\x67\x15\x35\x5C\x5A\x5C\xC5\x91\x96\x3A\x75\xE9\x94\xB4" + } + } } #endif /*USE_SALSA20*/ }; @@ -2170,6 +2387,7 @@ check_ciphers (void) #endif #if USE_SALSA20 GCRY_CIPHER_SALSA20, + GCRY_CIPHER_SALSA20R12, #endif 0 }; ----------------------------------------------------------------------- Summary of changes: NEWS | 3 +- cipher/cipher.c | 2 + cipher/salsa20.c | 49 +++++++++++- doc/gcrypt.texi | 4 + src/cipher.h | 1 + src/gcrypt.h.in | 3 +- tests/basic.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 273 insertions(+), 7 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 7 11:04:11 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Sat, 07 Sep 2013 11:04:11 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-224-gf7135e2 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 f7135e299e659d78906aac3dfdf30f380b5cf9c6 (commit) from ae6f6c47d2e0c536f3eab0823b5f23d26956cda2 (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 f7135e299e659d78906aac3dfdf30f380b5cf9c6 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 Use gcc "unused" attribute only with gcc >= 3.5. * src/g10lib.h (GCC_ATTR_UNUSED): Fix gcc version detection. -- Reported-by: Dmitry Eremin-Solenikov Signed-off-by: Werner Koch diff --git a/src/g10lib.h b/src/g10lib.h index 4c34ae5..6023c60 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -67,7 +67,10 @@ #endif -#if __GNUC__ > 2 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 ) +/* I am not sure since when the unused attribute is really supported. + In any case it it only needed for gcc versions which print a + warning. Thus let us require gcc >= 3.5. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 ) #define GCC_ATTR_UNUSED __attribute__ ((unused)) #else #define GCC_ATTR_UNUSED ----------------------------------------------------------------------- Summary of changes: src/g10lib.h | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 7 11:28:34 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 07 Sep 2013 11:28:34 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-226-g90fdf25 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 90fdf25f0dcc5feac7195ede55bd15948a11363e (commit) via 38a038a135d82231eff9d84f1ae3c4a25c6a5e75 (commit) from f7135e299e659d78906aac3dfdf30f380b5cf9c6 (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 90fdf25f0dcc5feac7195ede55bd15948a11363e Author: Jussi Kivilinna Date: Sat Sep 7 11:55:19 2013 +0300 Fix static build on AMD64 * cipher/rijndael-amd64.S: Correct 'RIP' macro for non-PIC build. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/rijndael-amd64.S b/cipher/rijndael-amd64.S index 2519ada..2a7dd90 100644 --- a/cipher/rijndael-amd64.S +++ b/cipher/rijndael-amd64.S @@ -23,7 +23,7 @@ #if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && defined(USE_AES) #ifdef __PIC__ -# define RIP %rip +# define RIP (%rip) #else # define RIP #endif @@ -177,7 +177,7 @@ _gcry_aes_amd64_encrypt_block: movq %rbx, (3 * 8)(%rsp); movq %r12, (4 * 8)(%rsp); - leaq .LtableE0(RIP), RTAB; + leaq .LtableE0 RIP, RTAB; /* read input block */ movl 0 * 4(%rdx), RAd; @@ -298,7 +298,7 @@ _gcry_aes_amd64_decrypt_block: movq %rbx, (3 * 8)(%rsp); movq %r12, (4 * 8)(%rsp); - leaq .LtableD0(RIP), RTAB; + leaq .LtableD0 RIP, RTAB; /* read input block */ movl 0 * 4(%rdx), RAd; commit 38a038a135d82231eff9d84f1ae3c4a25c6a5e75 Author: Jussi Kivilinna Date: Sat Sep 7 11:52:05 2013 +0300 scrypt: fix for big-endian systems * cipher/scrypt.c (_salsa20_core): Fix endianess issues. -- On big-endian systems 'tests/t-kdf' was failing scrypt tests. Patch fixes the issue. Signed-off-by: Jussi Kivilinna diff --git a/cipher/scrypt.c b/cipher/scrypt.c index 06196d6..9e29288 100644 --- a/cipher/scrypt.c +++ b/cipher/scrypt.c @@ -107,7 +107,9 @@ _salsa20_core(u32 *dst, const u32 *src, unsigned rounds) assert ( (rounds & 1) == 0); - memcpy (x, src, sizeof(x)); + for (i = 0; i < SALSA20_INPUT_LENGTH; i++) + x[i] = LE_SWAP32(src[i]); + for (i = 0; i < rounds;i += 2) { QROUND(x[0], x[4], x[8], x[12]); @@ -123,8 +125,8 @@ _salsa20_core(u32 *dst, const u32 *src, unsigned rounds) for (i = 0; i < SALSA20_INPUT_LENGTH; i++) { - u32 t = x[i] + src[i]; - dst[i] = LE_SWAP32 (t); + u32 t = x[i] + LE_SWAP32(src[i]); + dst[i] = LE_SWAP32(t); } } ----------------------------------------------------------------------- Summary of changes: cipher/rijndael-amd64.S | 6 +++--- cipher/scrypt.c | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Tue Sep 10 22:44:33 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 10 Sep 2013 22:44:33 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-229-gf3bca0c 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 f3bca0c77c4979504f95fdbc618f7458e61e3e45 (commit) via 0a28b2d2c9181a536fc894e24626714832619923 (commit) via 0fb7c2cd345f3d3e9715c7fbc7a3e91d3c5c150d (commit) from 90fdf25f0dcc5feac7195ede55bd15948a11363e (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 f3bca0c77c4979504f95fdbc618f7458e61e3e45 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 md: Add function gcry_md_hash_buffers. * src/gcrypt.h.in (gcry_buffer_t): new. (gcry_md_hash_buffers): New. * src/visibility.c, src/visibility.h: Add wrapper for new function. * src/libgcrypt.def, src/libgcrypt.vers: Export new function. * cipher/md.c (gcry_md_hash_buffers): New. * cipher/sha1.c (_gcry_sha1_hash_buffers): New. * tests/basic.c (check_one_md_multi): New. (check_digests): Run that test. * tests/hmac.c (check_hmac_multi): New. (main): Run that test. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 5a39a38..e5ea856 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ Noteworthy changes in version 1.6.0 (unreleased) * Support Deterministic DSA as per RFC-6969. + * Added a scatter gather hash convenience function. + + * Added several MPI helper functions. + * Interface changes relative to the 1.5.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_ac_* REMOVED. @@ -40,6 +44,8 @@ Noteworthy changes in version 1.6.0 (unreleased) gcry_md_list REMOVED. gcry_md_start_debug REMOVED (macro). gcry_md_stop_debug REMOVED (macro). + gcry_md_hash_buffers NEW. + gcry_buffer_t NEW. GCRYCTL_SET_ENFORCED_FIPS_FLAG NEW. GCRYCTL_SET_PREFERRED_RNG_TYPE NEW. GCRYCTL_GET_CURRENT_RNG_TYPE NEW. diff --git a/cipher/md.c b/cipher/md.c index 46567a1..44dc6dc 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1,6 +1,7 @@ /* md.c - message digest dispatcher * Copyright (C) 1998, 1999, 2002, 2003, 2006, * 2008 Free Software Foundation, Inc. + * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * @@ -1035,6 +1036,83 @@ gcry_md_hash_buffer (int algo, void *digest, } } + +/* Shortcut function to hash multiple buffers with a given algo. In + contrast to gcry_md_hash_buffer, this function returns an error on + invalid arguments or on other problems; disabled algorithms are + _not_ ignored but flagged as an error. + + The data to sign is taken from the array IOV which has IOVCNT items. + + The only supported flag in FLAGS is GCRY_MD_FLAG_HMAC which turns + this function into a HMAC function; the first item in IOV is then + used as the key. + + On success 0 is returned and resulting hash or HMAC is stored at + DIGEST which must have been provided by the caller with an + appropriate length. */ +gpg_err_code_t +gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, + const gcry_buffer_t *iov, int iovcnt) +{ + int hmac; + + if (!iov || iovcnt < 0) + return GPG_ERR_INV_ARG; + if (flags & ~(GCRY_MD_FLAG_HMAC)) + return GPG_ERR_INV_ARG; + + hmac = !!(flags & GCRY_MD_FLAG_HMAC); + if (hmac && iovcnt < 1) + return GPG_ERR_INV_ARG; + + if (algo == GCRY_MD_SHA1 && !hmac) + _gcry_sha1_hash_buffers (digest, iov, iovcnt); + else + { + /* For the others we do not have a fast function, so we use the + normal functions. */ + gcry_md_hd_t h; + gpg_err_code_t rc; + + if (algo == GCRY_MD_MD5 && fips_mode ()) + { + _gcry_inactivate_fips_mode ("MD5 used"); + if (_gcry_enforced_fips_mode () ) + { + /* We should never get to here because we do not register + MD5 in enforced fips mode. */ + _gcry_fips_noreturn (); + } + } + + rc = md_open (&h, algo, 0, hmac); + if (rc) + return rc; + + if (hmac) + { + rc = gcry_err_code + (gcry_md_setkey (h, (const char*)iov[0].data + iov[0].off, + iov[0].len)); + if (rc) + { + md_close (h); + return rc; + } + iov++; iovcnt--; + } + for (;iovcnt; iov++, iovcnt--) + md_write (h, (const char*)iov[0].data + iov[0].off, iov[0].len); + md_final (h); + memcpy (digest, md_read (h, algo), md_digest_length (algo)); + md_close (h); + } + + return 0; +} + + static int md_get_algo (gcry_md_hd_t a) { diff --git a/cipher/sha1.c b/cipher/sha1.c index 4b784ac..c29f488 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -373,6 +373,20 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) } +/* Variant of the above shortcut function using a multiple buffers. */ +void +_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +{ + SHA1_CONTEXT hd; + + sha1_init (&hd); + for (;iovcnt > 0; iov++, iovcnt--) + sha1_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); + sha1_final (&hd); + memcpy (outbuf, hd.buf, 20); +} + + /* Self-test section. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 09501f0..afef7f7 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3115,8 +3115,36 @@ The function does return @code{NULL} if the requested algorithm has not been enabled. @end deftypefun -Because it is often necessary to get the message digest of one block of -memory, a fast convenience function is available for this task: +Because it is often necessary to get the message digest of blocks of +memory, two fast convenience function are available for this task: + + at deftypefun gpg_err_code_t gcry_md_hash_buffers ( @ + @w{int @var{algo}}, @w{unsigned int @var{flags}}, @ + @w{void *@var{digest}}, @ + @w{const gcry_buffer_t *@var{iov}}, @w{int @var{iovcnt}} ) + + at code{gcry_md_hash_buffers} is a shortcut function to calculate a +message digest from several buffers. This function does not require a +context and immediately returns the message digest of of the data +described by @var{iov} and @var{iovcnt}. @var{digest} must be +allocated by the caller, large enough to hold the message digest +yielded by the the specified algorithm @var{algo}. This required size +may be obtained by using the function @code{gcry_md_get_algo_dlen}. + + at var{iov} is an array of buffer descriptions with @var{iovcnt} items. +The caller should zero out the structures in this array and for each +array item set the fields @code{.data} to the address of the data to +be hashed, @code{.len} to number of bytes to be hashed. If @var{.off} +is also set, the data is taken starting at @var{.off} bytes from the +begin of the buffer. The field @code{.size} is not used. + +The only supported flag value for @var{flags} is + at var{GCRY_MD_FLAG_HMAC} which turns this function into a HMAC +function; the first item in @var{iov} is then used as the key. + +On success the function returns 0 and stores the resulting hash or MAC +at @var{digest}. + at end deftypefun @deftypefun void gcry_md_hash_buffer (int @var{algo}, void *@var{digest}, const void *@var{buffer}, size_t @var{length}); @@ -3128,8 +3156,8 @@ enough to hold the message digest yielded by the the specified algorithm @var{algo}. This required size may be obtained by using the function @code{gcry_md_get_algo_dlen}. -Note that this function will abort the process if an unavailable -algorithm is used. +Note that in contrast to @code{gcry_md_hash_buffers} this function +will abort the process if an unavailable algorithm is used. @end deftypefun @c *********************************** @@ -4359,8 +4387,10 @@ wrong. @menu * Memory allocation:: Functions related with memory allocation. * Context management:: Functions related with context management. +* Buffer description:: A data type to describe buffers. @end menu + @node Memory allocation @section Memory allocation @@ -4418,6 +4448,31 @@ Release the context object @var{ctx} and all associated resources. A @code{NULL} passed as @var{ctx} is ignored. @end deftypefun + at node Buffer description + at section Buffer description + +To help hashing non-contiguous areas of memory a general purpose data +type is defined: + + at deftp {Data type} {gcry_buffer_t} +This type is a structure to describe a buffer. The user should make +sure that this structure is initialized to zero. The available fields +of this structure are: + + at table @code + @item .size + This is either 0 for no information available or indicates the + allocated length of the buffer. + @item .off + This is the offset into the buffer. + @item .len + This is the valid length of the buffer starting at @code{.off}. + @item .data + This is the address of the buffer. + @end table + at end deftp + + @c ********************************************************** @c ********************* Tools **************************** diff --git a/src/cipher.h b/src/cipher.h index ea8ba2a..7791083 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -79,6 +79,8 @@ void _gcry_rmd160_hash_buffer (void *outbuf, /*-- sha1.c --*/ void _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length); +void _gcry_sha1_hash_buffers (void *outbuf, + const gcry_buffer_t *iov, int iovcnt); /*-- rijndael.c --*/ void _gcry_aes_cfb_enc (void *context, unsigned char *iv, diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 5d30ced..71ea073 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -232,6 +232,16 @@ typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED; typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED; #endif +/* A structure used for scatter gather hashing. */ +typedef struct +{ + size_t size; /* The allocated size of the buffer or 0. */ + size_t off; /* Offset into the buffer. */ + size_t len; /* The used length of the buffer. */ + void *data; /* The buffer. */ +} gcry_buffer_t; + + /* Check that the library fulfills the version requirement. */ @@ -1151,6 +1161,10 @@ unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo); void gcry_md_hash_buffer (int algo, void *digest, const void *buffer, size_t length); +/* Convenience function to hash multiple buffers. */ +gpg_error_t gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, + const gcry_buffer_t *iov, int iovcnt); + /* Retrieve the algorithm used with HD. This does not work reliable if more than one algorithm is enabled in HD. */ int gcry_md_get_algo (gcry_md_hd_t hd); diff --git a/src/libgcrypt.def b/src/libgcrypt.def index 9c691ec..9fa4245 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -245,6 +245,7 @@ EXPORTS gcry_mpi_ec_curve_point @218 + gcry_md_hash_buffers @219 ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index beb691e..904ab41 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -39,6 +39,7 @@ GCRYPT_1.6 { gcry_md_algo_info; gcry_md_algo_name; gcry_md_close; gcry_md_copy; gcry_md_ctl; gcry_md_enable; gcry_md_get; gcry_md_get_algo; gcry_md_get_algo_dlen; gcry_md_hash_buffer; + gcry_md_hash_buffers; gcry_md_info; gcry_md_is_enabled; gcry_md_is_secure; gcry_md_map_name; gcry_md_open; gcry_md_read; gcry_md_reset; gcry_md_setkey; diff --git a/src/visibility.c b/src/visibility.c index 404da20..48725ff 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -997,6 +997,18 @@ gcry_md_hash_buffer (int algo, void *digest, _gcry_md_hash_buffer (algo, digest, buffer, length); } +gpg_error_t +gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, + const gcry_buffer_t *iov, int iovcnt) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_error ("called in non-operational state"); + } + return _gcry_md_hash_buffers (algo, flags, digest, iov, iovcnt); +} + int gcry_md_get_algo (gcry_md_hd_t hd) { diff --git a/src/visibility.h b/src/visibility.h index b4da48e..5e3556c 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -63,6 +63,7 @@ #define gcry_md_get_algo _gcry_md_get_algo #define gcry_md_get_algo_dlen _gcry_md_get_algo_dlen #define gcry_md_hash_buffer _gcry_md_hash_buffer +#define gcry_md_hash_buffers _gcry_md_hash_buffers #define gcry_md_info _gcry_md_info #define gcry_md_is_enabled _gcry_md_is_enabled #define gcry_md_is_secure _gcry_md_is_secure @@ -279,6 +280,7 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo, #undef gcry_md_get_algo #undef gcry_md_get_algo_dlen #undef gcry_md_hash_buffer +#undef gcry_md_hash_buffers #undef gcry_md_info #undef gcry_md_is_enabled #undef gcry_md_is_secure @@ -455,6 +457,7 @@ MARK_VISIBLE (gcry_md_get) MARK_VISIBLE (gcry_md_get_algo) MARK_VISIBLE (gcry_md_get_algo_dlen) MARK_VISIBLE (gcry_md_hash_buffer) +MARK_VISIBLE (gcry_md_hash_buffers) MARK_VISIBLE (gcry_md_info) MARK_VISIBLE (gcry_md_is_enabled) MARK_VISIBLE (gcry_md_is_secure) diff --git a/tests/basic.c b/tests/basic.c index 4fbca43..26c85ca 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -2522,6 +2522,72 @@ check_one_md (int algo, const char *data, int len, const char *expect) static void +check_one_md_multi (int algo, const char *data, int len, const char *expect) +{ + gpg_error_t err; + gcry_buffer_t iov[3]; + int iovcnt; + char digest[64]; + int mdlen; + int i; + + mdlen = gcry_md_get_algo_dlen (algo); + if (mdlen < 1 || mdlen > 64) + { + fail ("check_one_md_multi: algo %d, gcry_md_get_algo_dlen failed: %d\n", + algo, mdlen); + return; + } + + if (*data == '!' && !data[1]) + return; /* We can't do that here. */ + + memset (iov, 0, sizeof iov); + + iov[0].data = (void*)data; + if (len) + { + iov[0].len = 1; + len--; + data++; + } + iovcnt = 1; + if (len >= 4) + { + iov[iovcnt].data = (void*)data; + iov[iovcnt].len = 4; + iovcnt++; + data += 4; + len -= 4; + } + iov[iovcnt].data = (void*)data; + iov[iovcnt].len = len; + iovcnt++; + assert (iovcnt <= DIM (iov)); + + err = gcry_md_hash_buffers (algo, 0, digest, iov, iovcnt); + if (err) + { + fail ("check_one_md_multi: algo %d, gcry_hash_buffers failed: %s\n", + algo, gpg_strerror (err)); + return; + } + if (memcmp (digest, expect, mdlen)) + { + printf ("computed: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", digest[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("check_one_md_multi: algo %d, digest mismatch\n", algo); + } +} + + +static void check_digests (void) { static struct algos @@ -2742,11 +2808,11 @@ check_digests (void) "\x08\xEB\xA2\x66\x29\x12\x9D\x8F\xB7\xCB\x57\x21\x1B\x92\x81\xA6" "\x55\x17\xCC\x87\x9D\x7B\x96\x21\x42\xC6\x5F\x5A\x7A\xF0\x14\x67" }, { GCRY_MD_WHIRLPOOL, - "!", - "\x0C\x99\x00\x5B\xEB\x57\xEF\xF5\x0A\x7C\xF0\x05\x56\x0D\xDF\x5D" - "\x29\x05\x7F\xD8\x6B\x20\xBF\xD6\x2D\xEC\xA0\xF1\xCC\xEA\x4A\xF5" - "\x1F\xC1\x54\x90\xED\xDC\x47\xAF\x32\xBB\x2B\x66\xC3\x4F\xF9\xAD" - "\x8C\x60\x08\xAD\x67\x7F\x77\x12\x69\x53\xB2\x26\xE4\xED\x8B\x01" }, + "!", + "\x0C\x99\x00\x5B\xEB\x57\xEF\xF5\x0A\x7C\xF0\x05\x56\x0D\xDF\x5D" + "\x29\x05\x7F\xD8\x6B\x20\xBF\xD6\x2D\xEC\xA0\xF1\xCC\xEA\x4A\xF5" + "\x1F\xC1\x54\x90\xED\xDC\x47\xAF\x32\xBB\x2B\x66\xC3\x4F\xF9\xAD" + "\x8C\x60\x08\xAD\x67\x7F\x77\x12\x69\x53\xB2\x26\xE4\xED\x8B\x01" }, { 0 }, }; int i; @@ -2773,6 +2839,8 @@ check_digests (void) check_one_md (algos[i].md, algos[i].data, strlen (algos[i].data), algos[i].expect); + check_one_md_multi (algos[i].md, algos[i].data, strlen (algos[i].data), + algos[i].expect); } if (verbose) diff --git a/tests/hmac.c b/tests/hmac.c index 5d695ea..f4dc945 100644 --- a/tests/hmac.c +++ b/tests/hmac.c @@ -148,6 +148,63 @@ check_hmac (void) } + +static void +check_hmac_multi (void) +{ + gpg_error_t err; + unsigned char key[128]; + const char msg[] = "Sample #1"; + const char mac[] = ("\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12" + "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a"); + gcry_buffer_t iov[4]; + char digest[64]; + int i; + int algo; + int maclen; + + if (verbose) + fprintf (stderr, "checking HMAC using multiple buffers\n"); + for (i=0; i < 64; i++) + key[i] = i; + + memset (iov, 0, sizeof iov); + iov[0].data = key; + iov[0].len = 64; + iov[1].data = (void*)msg; + iov[1].off = 0; + iov[1].len = 3; + iov[2].data = (void*)msg; + iov[2].off = 3; + iov[2].len = 1; + iov[3].data = (void*)msg; + iov[3].off = 4; + iov[3].len = 5; + + algo = GCRY_MD_SHA1; + maclen = gcry_md_get_algo_dlen (algo); + err = gcry_md_hash_buffers (algo, GCRY_MD_FLAG_HMAC, digest, iov, 4); + if (err) + { + fail ("gcry_md_hash_buffers failed: %s\n", algo, gpg_strerror (err)); + return; + } + + if (memcmp (digest, mac, maclen)) + { + printf ("computed: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", digest[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", mac[i] & 0xFF); + printf ("\n"); + + fail ("gcry_md_hash_buffers, algo %d, MAC does not match\n", algo); + } +} + + int main (int argc, char **argv) { @@ -166,6 +223,7 @@ main (int argc, char **argv) if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); check_hmac (); + check_hmac_multi (); return error_count ? 1 : 0; } commit 0a28b2d2c9181a536fc894e24626714832619923 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 md: Fix Whirlpool flaw. * cipher/whirlpool.c (whirlpool_add): Remove shortcut return so that byte counter is always properly updated. -- Using the forthcoming gcry_md_hash_buffers() and its test suite, I found that a message of size 62 won't yield the correct hash if it is fed into Whirlpool into in chunks. The fix is obvious. The wrong code was likely due to using similar structure as SHA-1 but neglecting that bytes and not blocks are counted. diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index f99aa89..2c3beb7 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1315,9 +1315,6 @@ whirlpool_add (whirlpool_context_t *context, buffer_n--; } whirlpool_add (context, NULL, 0); - if (!buffer_n) - /* Done. */ - return; } /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ commit 0fb7c2cd345f3d3e9715c7fbc7a3e91d3c5c150d Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 md: Update URL of the Whirlpool specs. -- diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index c89a572..f99aa89 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -14,20 +14,19 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * + * License along with this program; if not, see . */ /* This is an implementation of the Whirlpool hashing algorithm, which has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; it's homepage is located at: - http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html. + http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html The S-Boxes and the structure of the main transformation function, which implements an optimized version of the algorithm, is taken from the reference implementation available from - http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip. */ + http://www.larc.usp.br/~pbarreto/whirlpool.zip + */ #include #include ----------------------------------------------------------------------- Summary of changes: NEWS | 6 ++++ cipher/md.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cipher/sha1.c | 14 +++++++++ cipher/whirlpool.c | 12 ++----- doc/gcrypt.texi | 63 +++++++++++++++++++++++++++++++++++++++-- src/cipher.h | 2 + src/gcrypt.h.in | 14 +++++++++ src/libgcrypt.def | 1 + src/libgcrypt.vers | 1 + src/visibility.c | 12 ++++++++ src/visibility.h | 3 ++ tests/basic.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++--- tests/hmac.c | 58 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 325 insertions(+), 17 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 11 18:32:54 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 11 Sep 2013 18:32:54 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-230-ge35ed61 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 e35ed615acc624a8b6c07576ea0650aac2bdb0db (commit) from f3bca0c77c4979504f95fdbc618f7458e61e3e45 (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 e35ed615acc624a8b6c07576ea0650aac2bdb0db Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 Streamline the use of the internal mpi and hex debug functions. * mpi/mpicoder.c (gcry_mpi_dump): Remove. (_gcry_log_mpidump): Remove. * src/misc.c (_gcry_log_printhex): Factor all code out to ... (do_printhex): new. Add line wrapping a and compact printing. (_gcry_log_printmpi): New. * src/mpi.h (log_mpidump): Remove macro. * src/g10lib.h (log_mpidump): Add compatibility macro. (log_printmpi): New macro * src/visibility.c (gcry_mpi_dump): Call _gcry_log_printmpi. * cipher/primegen.c (prime_generate_internal): Replace gcry_mpi_dump by log_printmpi. (gcry_prime_group_generator): Ditto. * cipher/pubkey.c: Remove extra colons from log_mpidump call. * cipher/rsa.c (stronger_key_check): Use log_printmpi. -- The values to debug get longer and longer and the different debug functions made it hard to check them out. Now MPIs and hex buffers are printed very similar. Lines may now wrap with an backslash as indicator. MPIs are distinguished from plain buffers in the output by always using a sign. Signed-off-by: Werner Koch diff --git a/cipher/primegen.c b/cipher/primegen.c index 3610ae7..3c9f14b 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -655,11 +655,7 @@ prime_generate_internal (int need_q_factor, { mpi_add_ui (g, g, 1); if (DBG_CIPHER) - { - log_debug ("checking g:"); - gcry_mpi_dump (g); - log_printf ("\n"); - } + log_printmpi ("checking g", g); else progress('^'); for (i = 0; i < n + 2; i++) @@ -1242,11 +1238,7 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, gcry_mpi_add_ui (g, g, 1); if (DBG_CIPHER) - { - log_debug ("checking g:"); - gcry_mpi_dump (g); - log_debug ("\n"); - } + log_printmpi ("checking g", g); else progress('^'); @@ -1835,9 +1827,9 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 12: Save p, q, counter and seed. */ log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); - log_printhex("fips186-3 seed:", seed, seedlen); - log_mpidump ("fips186-3 prime p", prime_p); - log_mpidump ("fips186-3 prime q", prime_q); + log_printhex ("fips186-3 seed", seed, seedlen); + log_printmpi ("fips186-3 p", prime_p); + log_printmpi ("fips186-3 q", prime_q); if (r_q) { *r_q = prime_q; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 141d656..98e3074 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -632,8 +632,8 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, { log_debug ("pubkey_encrypt: algo=%d\n", algorithm); for(i = 0; i < pubkey_get_npkey (algorithm); i++) - log_mpidump (" pkey:", pkey[i]); - log_mpidump (" data:", data); + log_mpidump (" pkey", pkey[i]); + log_mpidump (" data", data); } ath_mutex_lock (&pubkeys_registered_lock); @@ -653,7 +653,7 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, if (!rc && DBG_CIPHER && !fips_mode ()) { for(i = 0; i < pubkey_get_nenc (algorithm); i++) - log_mpidump(" encr:", resarr[i] ); + log_mpidump(" encr", resarr[i] ); } return rc; } @@ -680,9 +680,9 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, { log_debug ("pubkey_decrypt: algo=%d\n", algorithm); for(i = 0; i < pubkey_get_nskey (algorithm); i++) - log_mpidump (" skey:", skey[i]); + log_mpidump (" skey", skey[i]); for(i = 0; i < pubkey_get_nenc (algorithm); i++) - log_mpidump (" data:", data[i]); + log_mpidump (" data", data[i]); } ath_mutex_lock (&pubkeys_registered_lock); @@ -701,7 +701,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, ath_mutex_unlock (&pubkeys_registered_lock); if (!rc && DBG_CIPHER && !fips_mode ()) - log_mpidump (" plain:", *result); + log_mpidump (" plain", *result); return rc; } @@ -726,8 +726,8 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, { log_debug ("pubkey_sign: algo=%d\n", algorithm); for(i = 0; i < pubkey_get_nskey (algorithm); i++) - log_mpidump (" skey:", skey[i]); - log_mpidump(" data:", data ); + log_mpidump (" skey", skey[i]); + log_mpidump(" data", data ); } ath_mutex_lock (&pubkeys_registered_lock); @@ -748,7 +748,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, if (!rc && DBG_CIPHER && !fips_mode ()) for (i = 0; i < pubkey_get_nsig (algorithm); i++) - log_mpidump (" sig:", resarr[i]); + log_mpidump (" sig", resarr[i]); return rc; } @@ -1038,7 +1038,7 @@ pkcs1_decode_for_encryption (unsigned char **r_result, size_t *r_resultlen, *r_resultlen = nframe - n; if (DBG_CIPHER) - log_printhex ("value extracted from PKCS#1 block type 2 encoded data:", + log_printhex ("value extracted from PKCS#1 block type 2 encoded data", *r_result, *r_resultlen); return 0; @@ -1481,7 +1481,7 @@ oaep_decode (unsigned char **r_result, size_t *r_resultlen, seed = NULL; if (DBG_CIPHER) - log_printhex ("value extracted from OAEP encoded data:", + log_printhex ("value extracted from OAEP encoded data", *r_result, *r_resultlen); return 0; diff --git a/cipher/rsa.c b/cipher/rsa.c index 8d17129..e7c880d 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -662,7 +662,7 @@ stronger_key_check ( RSA_secret_key *skey ) { log_info ( "RSA Oops: d is wrong - fixed\n"); mpi_set (skey->d, t); - _gcry_log_mpidump (" fixed d", skey->d); + log_printmpi (" fixed d", skey->d); } /* check for correctness of u */ @@ -671,7 +671,7 @@ stronger_key_check ( RSA_secret_key *skey ) { log_info ( "RSA Oops: u is wrong - fixed\n"); mpi_set (skey->u, t); - _gcry_log_mpidump (" fixed u", skey->u); + log_printmpi (" fixed u", skey->u); } log_info ( "RSA secret key check finished\n"); @@ -1043,8 +1043,8 @@ rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, #ifdef IS_DEVELOPMENT_VERSION if (DBG_CIPHER) { - log_mpidump ("rsa verify result:", result ); - log_mpidump (" hash:", hash ); + log_mpidump ("rsa verify result", result ); + log_mpidump (" hash", hash ); } #endif /*IS_DEVELOPMENT_VERSION*/ if (cmp) diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c index a925922..ffe6538 100644 --- a/mpi/mpicoder.c +++ b/mpi/mpicoder.c @@ -176,65 +176,6 @@ mpi_fromstr (gcry_mpi_t val, const char *str) } -/* Dump the value of A in a format suitable for debugging to - Libgcrypt's logging stream. Note that one leading space but no - trailing space or linefeed will be printed. It is okay to pass - NULL for A. Note that this function prints the sign as it is used - internally and won't map -0 to 0. */ -void -gcry_mpi_dump (const gcry_mpi_t a) -{ - int i; - - log_printf (" "); - if (!a) - log_printf ("[MPI_NULL]"); - else if (mpi_is_opaque (a)) - { - unsigned int nbits; - const unsigned char *p; - - p = gcry_mpi_get_opaque (a, &nbits); - log_printf ("[%u bit: ", nbits); - for (i=0; i < (nbits + 7)/8; i++) - log_printf ("%02x", p[i]); - log_printf ("]"); - } - else - { - if (a->sign) - log_printf ( "-"); -#if BYTES_PER_MPI_LIMB == 2 -# define X "4" -#elif BYTES_PER_MPI_LIMB == 4 -# define X "8" -#elif BYTES_PER_MPI_LIMB == 8 -# define X "16" -#elif BYTES_PER_MPI_LIMB == 16 -# define X "32" -#else -# error please define the format here -#endif - for (i=a->nlimbs; i > 0 ; i-- ) - { - log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); - } -#undef X - if (!a->nlimbs) - log_printf ("0"); - } -} - -/* Convience function used internally. */ -void -_gcry_log_mpidump (const char *text, gcry_mpi_t a) -{ - log_printf ("%s:", text); - gcry_mpi_dump (a); - log_printf ("\n"); -} - - /* Return an allocated buffer with the MPI (msb first). NBYTES receives the length of this buffer. Caller must free the return string. This function returns an allocated buffer with NBYTES set diff --git a/src/g10lib.h b/src/g10lib.h index 6023c60..f8953e7 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -125,6 +125,7 @@ int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printhex (const char *text, const void *buffer, size_t length); +void _gcry_log_printmpi (const char *text, gcry_mpi_t mpi); void _gcry_set_log_verbosity( int level ); int _gcry_log_verbosity( int level ); @@ -151,6 +152,10 @@ int _gcry_log_verbosity( int level ); #define log_debug _gcry_log_debug #define log_printf _gcry_log_printf #define log_printhex _gcry_log_printhex +#define log_printmpi _gcry_log_printmpi + +/* Compatibility macro. */ +#define log_mpidump _gcry_log_printmpi /*-- src/hwfeatures.c --*/ diff --git a/src/misc.c b/src/misc.c index dece1d0..d7a7a65 100644 --- a/src/misc.c +++ b/src/misc.c @@ -28,6 +28,7 @@ #include "g10lib.h" #include "secmem.h" +#include "mpi.h" static int verbosity_level = 0; @@ -267,26 +268,97 @@ _gcry_log_printf (const char *fmt, ...) } } -/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw - dump, with TEXT an empty string, print a trailing linefeed, - otherwise print an entire debug line. */ -void -_gcry_log_printhex (const char *text, const void *buffer, size_t length) + +/* Helper for _gcry_log_printhex and _gcry_log_printmpi. */ +static void +do_printhex (const char *text, const char *text2, + const void *buffer, size_t length) { + int wrap = 0; + int cnt = 0; + if (text && *text) - log_debug ("%s ", text); + { + wrap = 1; + log_debug ("%s:%s", text, text2); + if (text2[1] == '[' && length && buffer) + { + /* Start with a new line so that we get nice output for + opaque MPIS: + "value: [31 bit]" + " 01020300" */ + log_printf ("\n"); + text2 = " "; + log_debug ("%*s ", (int)strlen(text), ""); + } + } if (length) { const unsigned char *p = buffer; - log_printf ("%02X", *p); - for (length--, p++; length--; p++) - log_printf (" %02X", *p); + for (; length--; p++) + { + log_printf ("%02x", *p); + if (wrap && ++cnt == 32 && length) + { + cnt = 0; + log_printf (" \\\n"); + log_debug ("%*s %*s", + (int)strlen(text), "", (int)strlen(text2), ""); + } + } } if (text) log_printf ("\n"); } +/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw + dump without any wrappping, with TEXT an empty string, print a + trailing linefeed, otherwise print an entire debug line. */ +void +_gcry_log_printhex (const char *text, const void *buffer, size_t length) +{ + do_printhex (text, " ", buffer, length); +} + + +/* Print MPI in hex notation. To make clear that the output is an MPI + a sign is always printed. With TEXT of NULL print just the raw dump + without any wrapping, with TEXT an empty string, print a trailing + linefeed, otherwise print an entire debug line. */ +void +_gcry_log_printmpi (const char *text, gcry_mpi_t mpi) +{ + unsigned char *rawmpi; + unsigned int rawmpilen; + int sign; + + if (!mpi) + do_printhex (text? text:" ", " (null)", NULL, 0); + else if (mpi_is_opaque (mpi)) + { + unsigned int nbits; + const unsigned char *p; + char prefix[30]; + + p = gcry_mpi_get_opaque (mpi, &nbits); + snprintf (prefix, sizeof prefix, " [%u bit]", nbits); + do_printhex (text? text:" ", prefix, p, (nbits+7)/8); + } + else + { + rawmpi = _gcry_mpi_get_buffer (mpi, &rawmpilen, &sign); + if (!rawmpi) + do_printhex (text? text:" ", " [out of core]", NULL, 0); + else + { + do_printhex (text, sign? "-":"+", rawmpi, rawmpilen); + gcry_free (rawmpi); + } + } +} + + void _gcry_burn_stack (unsigned int bytes) { diff --git a/src/mpi.h b/src/mpi.h index 6406112..13d843a 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -163,8 +163,6 @@ byte *_gcry_mpi_get_secure_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign ); void _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer, unsigned int nbytes, int sign ); -#define log_mpidump _gcry_log_mpidump - /*-- mpi-add.c --*/ #define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) #define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) diff --git a/src/visibility.c b/src/visibility.c index 48725ff..3c8041a 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -350,7 +350,7 @@ gcry_mpi_aprint (enum gcry_mpi_format format, void gcry_mpi_dump (const gcry_mpi_t a) { - _gcry_mpi_dump (a); + _gcry_log_printmpi (NULL, a); } void ----------------------------------------------------------------------- Summary of changes: cipher/primegen.c | 18 +++-------- cipher/pubkey.c | 22 ++++++------ cipher/rsa.c | 8 ++-- mpi/mpicoder.c | 59 ---------------------------------- src/g10lib.h | 5 +++ src/misc.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++----- src/mpi.h | 2 - src/visibility.c | 2 +- 8 files changed, 107 insertions(+), 99 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 16 16:28:18 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 16 Sep 2013 16:28:18 +0200 Subject: [git] GCRYPT - branch, LIBGCRYPT-1-5-BRANCH, updated. libgcrypt-1.5.3-2-g497478c 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, LIBGCRYPT-1-5-BRANCH has been updated via 497478c79711eee5a032ea91e9d7ad02a5a961cd (commit) from 64b8f6b7d5d8fd40df2561dedf21729466d0412a (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 497478c79711eee5a032ea91e9d7ad02a5a961cd Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 Fix bug in _gcry_mpi_tdiv_q_2exp. * mpi/mpi-internal.h (MPN_COPY_INCR): Make it work. -- This bug has been with us since the version 0.0.0 of GnuPG. Fortunately it only affects an optimized code path which is rarely used in practice: If the shift size matches the size of a limb (i.e.. 32 or 64); this is is_prime in primegen.c. Over there the Rabin-Miller test may fail with a probability of 2^-31 (that is if the to be tested prime - 1 has the low 32 bits cleared). In practice the probability is even much less because we first do a Fermat test on the randomly generated candidates which sorts out the majority of composite numbers. The bug in MPN_COPY_INCR was found by Sven Bjorn. Signed-off-by: Werner Koch (cherry picked from commit a7a9cdcaaf3979baa18dad51e722882581349f45) diff --git a/THANKS b/THANKS index 0f47d4f..6a44ead 100644 --- a/THANKS +++ b/THANKS @@ -135,6 +135,7 @@ Steffen Ullrich ccrlphr at xensei.com Steffen Zahn zahn at berlin.snafu.de Steven Bakker steven at icoe.att.com Susanne Schultz schultz at hsp.de +Sven Bjorn Szakats Istvan szaki.ms at gmail.com Thiago Jung Bauermann jungmann at cwb.matrix.com.br Thomas Roessler roessler at guug.de diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index e75b7c6..8ba1d79 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -92,7 +92,7 @@ typedef int mpi_size_t; /* (must be a signed type) */ do { \ mpi_size_t _i; \ for( _i = 0; _i < (n); _i++ ) \ - (d)[_i] = (d)[_i]; \ + (d)[_i] = (s)[_i]; \ } while (0) #define MPN_COPY_DECR( d, s, n ) \ ----------------------------------------------------------------------- Summary of changes: THANKS | 1 + mpi/mpi-internal.h | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 16 16:36:25 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 16 Sep 2013 16:36:25 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-1-4, updated. gnupg-1.4.14-5-g9dc6dd0 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 Privacy Guard". The branch, STABLE-BRANCH-1-4 has been updated via 9dc6dd0572102a2fa27df28ba4d66728827eb03d (commit) from 45efde9557661ea071a01bcb938f1591ed4ec1a3 (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 9dc6dd0572102a2fa27df28ba4d66728827eb03d Author: Werner Koch Date: Mon Sep 16 15:57:01 2013 +0200 Fix bug in mpi_tdiv_q_2exp. * mpi/mpi-internal.h (MPN_COPY_INCR): Make it work. -- This bug has been with us since the version 0.0.0 of GnuPG. Fortunately it only affects an optimized code path which is rarely used in practice: If the shift size matches the size of a limb (i.e.. 32 or 64); this is is_prime in primegen.c. Over there the Rabin-Miller test may fail with a probability of 2^-31 (that is if the to be tested prime - 1 has the low 32 bits cleared). In practice the probability is even much less because we first do a Fermat test on the randomly generated candidates which sorts out the majority of composite numbers. The bug in MPN_COPY_INCR was found by Sven Bjorn. Signed-off-by: Werner Koch (back ported from Libgcrypt commit 7f7a5ef59962ae1a819b5060f9b781469bfe27d5) diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index c1df30a..46da08d 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -104,7 +104,7 @@ typedef int mpi_size_t; /* (must be a signed type) */ do { \ mpi_size_t _i; \ for( _i = 0; _i < (n); _i++ ) \ - (d)[_i] = (d)[_i]; \ + (d)[_i] = (s)[_i]; \ } while (0) #define MPN_COPY_DECR( d, s, n ) \ ----------------------------------------------------------------------- Summary of changes: mpi/mpi-internal.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 18 09:06:17 2013 From: cvs at cvs.gnupg.org (by Marcus Brinkmann) Date: Wed, 18 Sep 2013 09:06:17 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.21-10-g801ea11 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 Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via 801ea11f21e4c29ab7220b0741691c1964b76854 (commit) from 0f18295ac83e0533f30b65a14bb04bd94f1627fe (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 801ea11f21e4c29ab7220b0741691c1964b76854 Author: Marcus Brinkmann Date: Tue Nov 10 09:04:17 2009 +0000 2009-11-10 Marcus Brinkmann * server.c (cmd_getauditlog): Don't dup FD for es_fdopen_nc as this leaks the FD here. (cherry picked from commit b3cda3f45cdbf3c66538589c7e108cbf73adc850) Resolved Conflicts: sm/ChangeLog-2011 - Removed. GnuPG-bug-id: 1535 diff --git a/sm/server.c b/sm/server.c index fcf47a7..6ba5e58 100644 --- a/sm/server.c +++ b/sm/server.c @@ -1050,7 +1050,7 @@ cmd_getauditlog (assuan_context_t ctx, char *line) if (out_fd == -1) return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); - out_stream = es_fdopen_nc ( dup (out_fd), "w"); + out_stream = es_fdopen_nc (out_fd, "w"); if (!out_stream) { return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen() failed"); ----------------------------------------------------------------------- Summary of changes: sm/server.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 18 13:45:56 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 18 Sep 2013 13:45:56 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-238-g63cd347 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 63cd3474425cb5a7ec4d1a56be15b248ecda4680 (commit) via 89fe2173649a72019d75e059e6c6938efd10421f (commit) from a7a9cdcaaf3979baa18dad51e722882581349f45 (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 63cd3474425cb5a7ec4d1a56be15b248ecda4680 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ecc: Add Ed25519 key generation and prepare for optimizations. * src/mpi.h (enum ecc_dialects): New. * src/ec-context.h (mpi_ec_ctx_s): Add field DIALECT. * cipher/ecc-common.h (elliptic_curve_t): Ditto. * cipher/ecc-curves.c (ecc_domain_parms_t): Ditto. (domain_parms): Add dialect values. (_gcry_ecc_fill_in_curve): Set dialect. (_gcry_ecc_get_curve): Ditto. (_gcry_mpi_ec_new): Ditto. (_gcry_ecc_get_param): Use ECC_DIALECT_STANDARD for now. * cipher/ecc-misc.c (_gcry_ecc_curve_copy): Copy dialect. (_gcry_ecc_dialect2str): New. * mpi/ec.c (ec_p_init): Add arg DIALECT. (_gcry_mpi_ec_p_internal_new): Ditto. (_gcry_mpi_ec_p_new): Ditto. * mpi/mpiutil.c (gcry_mpi_set_opaque): Set the secure flag. (_gcry_mpi_set_opaque_copy): New. * cipher/ecc-misc.c (_gcry_ecc_os2ec): Take care of an opaque MPI. * cipher/ecc.c (eddsa_generate_key): New. (generate_key): Rename to nist_generate_key and factor some code out to ... (ecc_generate_ext): here. Divert to eddsa_generate_key if desired. (eddsa_decodepoint): Take care of an opaque MPI. (ecc_check_secret_key): Ditto. (ecc_sign): Ditto. * cipher/pubkey.c (sexp_elements_extract_ecc): Store public and secret key as opaque MPIs. (gcry_pk_genkey): Add the curve_name also to the private key part of the result. * tests/benchmark.c (ecc_bench): Support Ed25519. (main): Add option --debug. * tests/curves.c (sample_key_2): Make sure that P and N are positive. * tests/keygen.c (show): New. (check_ecc_keys): Support Ed25519. -- There are two main purposes of this patch: Add a key generation feature for Ed25519 and add the "dialect" thingy which will eventually be used to add curve specific optimization. Note that the entire way of how we interface between the public key modules and pubkey.c is overly complex and probably also the cause for a lot of performance overhead. Given that we don't have the loadable module system anymore, we should entirely get rid of the MPI-array based internal interface and move parts of the s-expression handling direct into the pubkey modules. This needs to be fixed or we are turning Libgcrypt into another software incarnation of Heathrow Airport. Signed-off-by: Werner Koch diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h index 614baae..e806059 100644 --- a/cipher/ecc-common.h +++ b/cipher/ecc-common.h @@ -20,10 +20,12 @@ #ifndef GCRY_ECC_COMMON_H #define GCRY_ECC_COMMON_H + /* Definition of a curve. */ typedef struct { enum gcry_mpi_ec_models model;/* The model descrinbing this curve. */ + enum ecc_dialects dialect; /* The dialect used with the curve. */ gcry_mpi_t p; /* Prime specifying the field GF(p). */ gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. @@ -76,6 +78,7 @@ gcry_sexp_t _gcry_ecc_get_param_sexp (const char *name); void _gcry_ecc_curve_free (elliptic_curve_t *E); elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E); const char *_gcry_ecc_model2str (enum gcry_mpi_ec_models model); +const char *_gcry_ecc_dialect2str (enum ecc_dialects dialect); gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p); gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value); diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index c17c7fe..49c0959 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -78,7 +78,13 @@ typedef struct unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ - enum gcry_mpi_ec_models model;/* The model describing this curve. */ + /* The model describing this curve. This is mainly used to select + the group equation. */ + enum gcry_mpi_ec_models model; + + /* The actual ECC dialect used. This is used for curve specific + optimizations and to select encodings etc. */ + enum ecc_dialects dialect; const char *p; /* The prime defining the field. */ const char *a, *b; /* The coefficients. For Twisted Edwards @@ -94,7 +100,7 @@ static const ecc_domain_parms_t domain_parms[] = { /* (-x^2 + y^2 = 1 + dx^2y^2) */ "Ed25519", 256, 0, - MPI_EC_TWISTEDEDWARDS, + MPI_EC_TWISTEDEDWARDS, ECC_DIALECT_ED25519, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", "-0x01", "-0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4", @@ -104,7 +110,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-192", 192, 1, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xfffffffffffffffffffffffffffffffefffffffffffffffc", "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", @@ -115,7 +121,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-224", 224, 1, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xffffffffffffffffffffffffffffffff000000000000000000000001", "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", @@ -126,7 +132,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-256", 256, 1, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", @@ -137,7 +143,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-384", 384, 1, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" "ffffffff0000000000000000ffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" @@ -154,7 +160,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "NIST P-521", 521, 1, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -171,7 +177,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP160r1", 160, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -181,7 +187,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP192r1", 192, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -191,7 +197,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP224r1", 224, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", @@ -201,7 +207,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP256r1", 256, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", @@ -211,7 +217,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP320r1", 320, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" "fcd412b1f1b32e27", "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" @@ -227,7 +233,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP384r1", 384, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" "acd3a729901d1a71874700133107ec53", "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" @@ -243,7 +249,7 @@ static const ecc_domain_parms_t domain_parms[] = }, { "brainpoolP512r1", 512, 0, - MPI_EC_WEIERSTRASS, + MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" @@ -258,7 +264,7 @@ static const ecc_domain_parms_t domain_parms[] = "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" }, - { NULL, 0, 0, 0, NULL, NULL, NULL, NULL } + { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL } }; @@ -348,6 +354,7 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, *r_nbits = domain_parms[idx].nbits; curve->model = domain_parms[idx].model; + curve->dialect = domain_parms[idx].dialect; curve->p = scanval (domain_parms[idx].p); curve->a = scanval (domain_parms[idx].a); curve->b = scanval (domain_parms[idx].b); @@ -391,6 +398,8 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) return NULL; E.model = MPI_EC_WEIERSTRASS; + E.dialect = ECC_DIALECT_STANDARD; + E.name = NULL; E.p = pkey[0]; E.a = pkey[1]; E.b = pkey[2]; @@ -561,6 +570,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gpg_err_code_t errc; gcry_ctx_t ctx = NULL; enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS; + enum ecc_dialects dialect = ECC_DIALECT_STANDARD; gcry_mpi_t p = NULL; gcry_mpi_t a = NULL; gcry_mpi_t b = NULL; @@ -641,6 +651,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, } model = E->model; + dialect = E->dialect; if (!p) { @@ -673,7 +684,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_free (E); } - errc = _gcry_mpi_ec_p_new (&ctx, model, p, a, b); + errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, p, a, b); if (!errc) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); @@ -735,7 +746,7 @@ _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey) g_x = mpi_new (0); g_y = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (0, E.p, E.a, NULL); + ctx = _gcry_mpi_ec_p_internal_new (0, ECC_DIALECT_STANDARD, E.p, E.a, NULL); if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx)) log_fatal ("ecc get param: Failed to get affine coordinates\n"); _gcry_mpi_ec_free (ctx); diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 6c34902..f8db81a 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -54,6 +54,7 @@ _gcry_ecc_curve_copy (elliptic_curve_t E) elliptic_curve_t R; R.model = E.model; + R.dialect = E.dialect; R.p = mpi_copy (E.p); R.a = mpi_copy (E.a); R.b = mpi_copy (E.b); @@ -82,6 +83,20 @@ _gcry_ecc_model2str (enum gcry_mpi_ec_models model) } +/* + * Return a description of the curve dialect. + */ +const char * +_gcry_ecc_dialect2str (enum ecc_dialects dialect) +{ + const char *str = "?"; + switch (dialect) + { + case ECC_DIALECT_STANDARD: str = "Standard"; break; + case ECC_DIALECT_ED25519: str = "Ed25519"; break; + } + return str; +} gcry_mpi_t @@ -151,41 +166,57 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) { gcry_error_t err; size_t n; - unsigned char *buf; + const unsigned char *buf; + unsigned char *buf_memory; gcry_mpi_t x, y; - n = (mpi_get_nbits (value)+7)/8; - buf = gcry_xmalloc (n); - err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value); - if (err) + if (mpi_is_opaque (value)) { - gcry_free (buf); - return err; + unsigned int nbits; + + buf = gcry_mpi_get_opaque (value, &nbits); + if (!buf) + return GPG_ERR_INV_OBJ; + n = (nbits + 7)/8; + buf_memory = NULL; + } + else + { + n = (mpi_get_nbits (value)+7)/8; + buf_memory= gcry_xmalloc (n); + err = gcry_mpi_print (GCRYMPI_FMT_USG, buf_memory, n, &n, value); + if (err) + { + gcry_free (buf_memory); + return err; + } + buf = buf_memory; } + if (n < 1) { - gcry_free (buf); + gcry_free (buf_memory); return GPG_ERR_INV_OBJ; } if (*buf != 4) { - gcry_free (buf); + gcry_free (buf_memory); return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ } if ( ((n-1)%2) ) { - gcry_free (buf); + gcry_free (buf_memory); return GPG_ERR_INV_OBJ; } n = (n-1)/2; err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); if (err) { - gcry_free (buf); + gcry_free (buf_memory); return err; } err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); - gcry_free (buf); + gcry_free (buf_memory); if (err) { mpi_free (x); diff --git a/cipher/ecc.c b/cipher/ecc.c index 7d468ee..9766e9e 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -132,59 +132,30 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) } -/* - * First obtain the setup. Over the finite field randomize an scalar - * secret value, and calculate the public point. - */ +/* Standard version of the key generation. */ static gpg_err_code_t -generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, - int transient_key, - gcry_mpi_t g_x, gcry_mpi_t g_y, - gcry_mpi_t q_x, gcry_mpi_t q_y, - const char **r_usedcurve) +nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, + gcry_random_level_t random_level, unsigned int nbits) { - gpg_err_code_t err; - elliptic_curve_t E; mpi_point_struct Q; - mpi_ec_t ctx; - gcry_random_level_t random_level; - - *r_usedcurve = NULL; - err = _gcry_ecc_fill_in_curve (nbits, name, &E, &nbits); - if (err) - return err; - - if (DBG_CIPHER) - { - log_debug ("ecgen curve model: %s\n", _gcry_ecc_model2str (E.model)); - log_mpidump ("ecgen curve p", E.p); - log_mpidump ("ecgen curve a", E.a); - log_mpidump ("ecgen curve b", E.b); - log_mpidump ("ecgen curve n", E.n); - log_mpidump ("ecgen curve Gx", E.G.x); - log_mpidump ("ecgen curve Gy", E.G.y); - log_mpidump ("ecgen curve Gz", E.G.z); - if (E.name) - log_debug ("ecgen curve used: %s\n", E.name); - } + point_init (&Q); - random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; - sk->d = _gcry_dsa_gen_k (E.n, random_level); + /* Generate a secret. */ + sk->d = _gcry_dsa_gen_k (E->n, random_level); /* Compute Q. */ - point_init (&Q); - ctx = _gcry_mpi_ec_p_internal_new (E.model, E.p, E.a, E.b); - _gcry_mpi_ec_mul_point (&Q, sk->d, &E.G, ctx); + _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx); /* Copy the stuff to the key structures. */ - sk->E.model = E.model; - sk->E.p = mpi_copy (E.p); - sk->E.a = mpi_copy (E.a); - sk->E.b = mpi_copy (E.b); + sk->E.model = E->model; + sk->E.dialect = E->dialect; + sk->E.p = mpi_copy (E->p); + sk->E.a = mpi_copy (E->a); + sk->E.b = mpi_copy (E->b); point_init (&sk->E.G); - point_set (&sk->E.G, &E.G); - sk->E.n = mpi_copy (E.n); + point_set (&sk->E.G, &E->G); + sk->E.n = mpi_copy (E->n); point_init (&sk->Q); /* We want the Q=(x,y) be a "compliant key" in terms of the @@ -196,7 +167,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, * possibilities without any loss of security. */ { gcry_mpi_t x, y, p_y; - const unsigned int pbits = mpi_get_nbits (E.p); + const unsigned int pbits = mpi_get_nbits (E->p); x = mpi_new (pbits); y = mpi_new (pbits); @@ -205,22 +176,22 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx)) log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q"); - mpi_sub (p_y, E.p, y); /* p_y = p - y */ + mpi_sub (p_y, E->p, y); /* p_y = p - y */ if (mpi_cmp (p_y, y) < 0) /* p - y < p */ { /* We need to end up with -Q; this assures that new Q's y is the smallest one */ - mpi_sub (sk->d, E.n, sk->d); /* d = order - d */ - gcry_mpi_point_snatch_set (&sk->Q, x, p_y, mpi_alloc_set_ui (1)); + mpi_sub (sk->d, E->n, sk->d); /* d = order - d */ + gcry_mpi_point_snatch_set (&sk->Q, x, p_y, mpi_alloc_set_ui (1)); - if (DBG_CIPHER) - log_debug ("ecgen converted Q to a compliant point\n"); + if (DBG_CIPHER) + log_debug ("ecgen converted Q to a compliant point\n"); } else /* p - y >= p */ { /* No change is needed exactly 50% of the time: just copy. */ - point_set (&sk->Q, &Q); + point_set (&sk->Q, &Q); if (DBG_CIPHER) log_debug ("ecgen didn't need to convert Q to a compliant point\n"); @@ -230,25 +201,6 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, mpi_free (y); } - /* We also return copies of G and Q in affine coordinates if - requested. */ - if (g_x && g_y) - { - if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) - log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G"); - } - if (q_x && q_y) - { - if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) - log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q"); - } - _gcry_mpi_ec_free (ctx); - - point_free (&Q); - - *r_usedcurve = E.name; - _gcry_ecc_curve_free (&E); - /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); @@ -344,7 +296,8 @@ check_secret_key (ECC_secret_key * sk) goto leave; } - ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.p, sk->E.a, sk->E.b); + ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, + sk->E.p, sk->E.a, sk->E.b); _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); if (mpi_cmp_ui (Q.z, 0)) @@ -458,7 +411,7 @@ sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, mpi_set_ui (s, 0); mpi_set_ui (r, 0); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); while (!mpi_cmp_ui (s, 0)) /* s == 0 */ @@ -558,7 +511,7 @@ verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey, point_init (&Q1); point_init (&Q2); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, pkey->E.p, pkey->E.a, pkey->E.b); /* h = s^(-1) (mod n) */ @@ -700,9 +653,27 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, gcry_mpi_t yy, t, x, p1, p2, p3; int sign; - rawmpi = _gcry_mpi_get_buffer (pk, len, &rawmpilen, NULL); - if (!rawmpi) - return gpg_err_code_from_syserror (); + if (mpi_is_opaque (pk)) + { + const void *buf; + + buf = gcry_mpi_get_opaque (pk, &rawmpilen); + if (!buf) + return GPG_ERR_INV_OBJ; + rawmpilen = (rawmpilen + 7)/8; + rawmpi = gcry_malloc (rawmpilen? rawmpilen:1); + if (!rawmpi) + return gpg_err_code_from_syserror (); + memcpy (rawmpi, buf, rawmpilen); + reverse_buffer (rawmpi, rawmpilen); + } + else + { + rawmpi = _gcry_mpi_get_buffer (pk, len, &rawmpilen, NULL); + if (!rawmpi) + return gpg_err_code_from_syserror (); + } + if (rawmpilen) { sign = !!(rawmpi[0] & 0x80); @@ -781,6 +752,78 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, } +/* Ed25519 version of the key generation. */ +static gpg_err_code_t +eddsa_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, + gcry_random_level_t random_level) +{ + gpg_err_code_t rc; + int b = 256/8; /* The only size we currently support. */ + gcry_mpi_t a, x, y; + mpi_point_struct Q; + char *dbuf; + size_t dlen; + gcry_buffer_t hvec[1]; + unsigned char *hash_d = NULL; + + point_init (&Q); + memset (hvec, 0, sizeof hvec); + + a = mpi_snew (0); + x = mpi_new (0); + y = mpi_new (0); + + /* Generate a secret. */ + hash_d = gcry_malloc_secure (2*b); + if (!hash_d) + { + rc = gpg_error_from_syserror (); + goto leave; + } + dlen = b; + dbuf = gcry_random_bytes_secure (dlen, random_level); + + /* Compute the A value. */ + hvec[0].data = dbuf; + hvec[0].len = dlen; + rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1); + if (rc) + goto leave; + sk->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8); + dbuf = NULL; + reverse_buffer (hash_d, 32); /* Only the first half of the hash. */ + hash_d[0] = (hash_d[0] & 0x7f) | 0x40; + hash_d[31] &= 0xf8; + _gcry_mpi_set_buffer (a, hash_d, 32, 0); + gcry_free (hash_d); hash_d = NULL; + /* log_printmpi ("ecgen a", a); */ + + /* Compute Q. */ + _gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx); + if (DBG_CIPHER) + log_printpnt ("ecgen pk", &Q, ctx); + + /* Copy the stuff to the key structures. */ + sk->E.model = E->model; + sk->E.dialect = E->dialect; + sk->E.p = mpi_copy (E->p); + sk->E.a = mpi_copy (E->a); + sk->E.b = mpi_copy (E->b); + point_init (&sk->E.G); + point_set (&sk->E.G, &E->G); + sk->E.n = mpi_copy (E->n); + point_init (&sk->Q); + point_set (&sk->Q, &Q); + + leave: + gcry_mpi_release (a); + gcry_mpi_release (x); + gcry_mpi_release (y); + gcry_free (hash_d); + return rc; +} + + /* Compute an EdDSA signature. See: * [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja * Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security @@ -831,7 +874,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, x = mpi_new (0); y = mpi_new (0); r = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); /* Hash the secret key. We clear DIGEST so we can use it to left @@ -998,7 +1041,7 @@ verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey, h = mpi_new (0); s = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, pkey->E.p, pkey->E.a, pkey->E.b); /* Decode and check the public key. */ @@ -1116,13 +1159,16 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_mpi_t *skey, gcry_mpi_t **retfactors, gcry_sexp_t *r_extrainfo) { - gpg_err_code_t ec; + gpg_err_code_t rc; + elliptic_curve_t E; ECC_secret_key sk; - gcry_mpi_t g_x, g_y, q_x, q_y; + gcry_mpi_t x = NULL; + gcry_mpi_t y = NULL; char *curve_name = NULL; gcry_sexp_t l1; int transient_key = 0; - const char *usedcurve = NULL; + gcry_random_level_t random_level; + mpi_ec_t ctx = NULL; (void)algo; (void)evalue; @@ -1152,52 +1198,106 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (!nbits && !curve_name) return GPG_ERR_NO_OBJ; /* No NBITS parameter. */ - g_x = mpi_new (0); - g_y = mpi_new (0); - q_x = mpi_new (0); - q_y = mpi_new (0); - ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y, - &usedcurve); - gcry_free (curve_name); - if (ec) - return ec; - if (usedcurve) /* Fixme: No error return checking. */ - gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve); - - skey[0] = sk.E.p; - skey[1] = sk.E.a; - skey[2] = sk.E.b; - skey[3] = _gcry_ecc_ec2os (g_x, g_y, sk.E.p); - skey[4] = sk.E.n; - skey[5] = _gcry_ecc_ec2os (q_x, q_y, sk.E.p); - skey[6] = sk.d; - - mpi_free (g_x); - mpi_free (g_y); - mpi_free (q_x); - mpi_free (q_y); + rc = _gcry_ecc_fill_in_curve (nbits, curve_name, &E, &nbits); + gcry_free (curve_name); curve_name = NULL; + if (rc) + goto leave; - point_free (&sk.E.G); - point_free (&sk.Q); + if (DBG_CIPHER) + { + log_debug ("ecgen curve info: %s/%s\n", + _gcry_ecc_model2str (E.model), + _gcry_ecc_dialect2str (E.dialect)); + if (E.name) + log_debug ("ecgen curve used: %s\n", E.name); + log_printmpi ("ecgen curve p", E.p); + log_printmpi ("ecgen curve a", E.a); + log_printmpi ("ecgen curve b", E.b); + log_printmpi ("ecgen curve n", E.n); + log_printpnt ("ecgen curve G", &E.G, NULL); + } + + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, E.p, E.a, E.b); + x = mpi_new (0); + y = mpi_new (0); + + switch (E.dialect) + { + case ECC_DIALECT_STANDARD: + rc = nist_generate_key (&sk, &E, ctx, random_level, nbits); + break; + case ECC_DIALECT_ED25519: + rc = eddsa_generate_key (&sk, &E, ctx, random_level); + break; + default: + rc = GPG_ERR_INTERNAL; + break; + } + if (rc) + goto leave; + + /* Copy data to the result. */ + if (_gcry_mpi_ec_get_affine (x, y, &sk.E.G, ctx)) + log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G"); + skey[3] = _gcry_ecc_ec2os (x, y, sk.E.p); + if (sk.E.dialect == ECC_DIALECT_ED25519) + { + unsigned char *encpk; + unsigned int encpklen; + + rc = eddsa_encodepoint (&sk.Q, 256/8, ctx, x, y, &encpk, &encpklen); + if (rc) + return rc; + skey[5] = mpi_new (0); + gcry_mpi_set_opaque (skey[5], encpk, encpklen*8); + encpk = NULL; + if (DBG_CIPHER) + log_printmpi ("ecgen e_pk", skey[5]); + } + else + { + if (_gcry_mpi_ec_get_affine (x, y, &sk.Q, ctx)) + log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q"); + skey[5] = _gcry_ecc_ec2os (x, y, sk.E.p); + } + skey[0] = sk.E.p; sk.E.p = NULL; + skey[1] = sk.E.a; sk.E.a = NULL; + skey[2] = sk.E.b; sk.E.b = NULL; + skey[4] = sk.E.n; sk.E.n = NULL; + skey[6] = sk.d; sk.d = NULL; - /* Make an empty list of factors. */ + if (E.name) /* Fixme: No error return checking. */ + gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", E.name); + + /* Make an dummy list of factors. */ *retfactors = gcry_calloc ( 1, sizeof **retfactors ); if (!*retfactors) - return gpg_err_code_from_syserror (); /* Fixme: relase mem? */ + { + rc = gpg_err_code_from_syserror (); + goto leave; + } if (DBG_CIPHER) { - log_debug ("ecgen result model: %s\n", _gcry_ecc_model2str (sk.E.model)); - log_mpidump ("ecgen result p", skey[0]); - log_mpidump ("ecgen result a", skey[1]); - log_mpidump ("ecgen result b", skey[2]); - log_mpidump ("ecgen result G", skey[3]); - log_mpidump ("ecgen result n", skey[4]); - log_mpidump ("ecgen result Q", skey[5]); - log_mpidump ("ecgen result d", skey[6]); + log_printmpi ("ecgen result p", skey[0]); + log_printmpi ("ecgen result a", skey[1]); + log_printmpi ("ecgen result b", skey[2]); + log_printmpi ("ecgen result G", skey[3]); + log_printmpi ("ecgen result n", skey[4]); + log_printmpi ("ecgen result Q", skey[5]); + log_printmpi ("ecgen result d", skey[6]); } + rc = 0; - return 0; + leave: + point_free (&sk.E.G); + point_free (&sk.Q); + _gcry_mpi_ec_free (ctx); + _gcry_ecc_curve_free (&E); + gcry_mpi_release (x); + gcry_mpi_release (y); + return rc; } @@ -1244,17 +1344,33 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) return err; } - sk.d = skey[6]; + { + const unsigned char *buf; + unsigned int n; + + gcry_assert (mpi_is_opaque (skey[6])); + + buf = gcry_mpi_get_opaque (skey[6], &n); + if (!buf) + err = GPG_ERR_INV_OBJ; + else + { + n = (n + 7)/8; + sk.d = NULL; + err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL); + if (!err) + { + if (check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + gcry_mpi_release (sk.d); + sk.d = NULL; + } + } + } - if (check_secret_key (&sk)) - { - point_free (&sk.E.G); - point_free (&sk.Q); - return GPG_ERR_BAD_SECKEY; - } point_free (&sk.E.G); point_free (&sk.Q); - return 0; + return err; } @@ -1288,14 +1404,36 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, return err; } sk.E.n = skey[4]; - sk.d = skey[6]; resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); - if ((flags & PUBKEY_FLAG_EDDSA)) - err = sign_eddsa (data, &sk, resarr[0], resarr[1], hashalgo, skey[5]); - else - err = sign_ecdsa (data, &sk, resarr[0], resarr[1], flags, hashalgo); + { + const unsigned char *buf; + unsigned int n; + + gcry_assert (mpi_is_opaque (skey[6])); + + buf = gcry_mpi_get_opaque (skey[6], &n); + if (!buf) + err = GPG_ERR_INV_OBJ; + else + { + n = (n + 7)/8; + sk.d = NULL; + err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL); + if (!err) + { + if ((flags & PUBKEY_FLAG_EDDSA)) + err = sign_eddsa (data, &sk, resarr[0], resarr[1], + hashalgo, skey[5]); + else + err = sign_ecdsa (data, &sk, resarr[0], resarr[1], + flags, hashalgo); + gcry_mpi_release (sk.d); + sk.d = NULL; + } + } + } if (err) { mpi_free (resarr[0]); @@ -1453,7 +1591,8 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, return err; } - ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.p, pk.E.a, pk.E.b); + ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, + pk.E.p, pk.E.a, pk.E.b); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { @@ -1565,7 +1704,8 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, } sk.d = skey[6]; - ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.p, sk.E.a, sk.E.b); + ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, + sk.E.p, sk.E.a, sk.E.b); /* R = dkG */ point_init (&R); diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 949c538..8fa7ebf 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -1903,7 +1903,16 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, elements[idx] = NULL; else { - elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); + switch (idx) + { + case 5: /* The public and */ + case 6: /* the secret key must to be passed opaque. */ + elements[idx] = _gcry_sexp_nth_opaque_mpi (list, 1); + break; + default: + elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_STD); + break; + } gcry_sexp_release (list); if (!elements[idx]) { @@ -3706,6 +3715,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) size_t nelem=0, nelem_cp = 0, needed=0; gcry_mpi_t mpis[30]; int percent_s_idx = -1; + int percent_s_idx2 = -1; /* Estimate size of format string. */ nelem = strlen (pub_elems) + strlen (sec_elems); @@ -3714,11 +3724,13 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) for (i = 0; factors[i]; i++) nelem++; } + if (extrainfo) + nelem += 2; nelem_cp = nelem; needed += nelem * 10; - /* (+5 is for EXTRAINFO ("%S")). */ - needed += 2 * strlen (algo_name) + 300 + 5; + /* (+10 for two times EXTRAINFO ("%S")). */ + needed += 2 * strlen (algo_name) + 300 + 10; if (nelem > DIM (mpis)) BUG (); @@ -3744,7 +3756,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) { /* Very ugly hack to insert the used curve parameter into the list of public key parameters. */ - percent_s_idx = nelem; + percent_s_idx = nelem++; p = stpcpy (p, "%S"); } p = stpcpy (p, "))"); @@ -3757,15 +3769,24 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) p = stpcpy (p, "%m)"); mpis[nelem++] = skey[i]; } + if (extrainfo && (algo == GCRY_PK_ECDSA || algo == GCRY_PK_ECDH)) + { + percent_s_idx2 = nelem++; + p = stpcpy (p, "%S"); + } p = stpcpy (p, "))"); /* Hack to make release_mpi_array() work. */ skey[i] = NULL; - if (extrainfo && percent_s_idx == -1) + if (extrainfo) { /* If we have extrainfo we should not have any factors. */ - p = stpcpy (p, "%S"); + if (percent_s_idx == -1) + { + percent_s_idx = nelem++; + p = stpcpy (p, "%S"); + } } else if (factors && factors[0]) { @@ -3787,8 +3808,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) int elem_n = strlen (pub_elems) + strlen (sec_elems); void **arg_list; - /* Allocate one extra for EXTRAINFO ("%S"). */ - arg_list = gcry_calloc (nelem_cp+1, sizeof *arg_list); + if (percent_s_idx != -1) + elem_n++; + if (percent_s_idx2 != -1) + elem_n++; + + arg_list = gcry_calloc (nelem_cp, sizeof *arg_list); if (!arg_list) { rc = gpg_err_code_from_syserror (); @@ -3798,10 +3823,13 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) { if (i == percent_s_idx) arg_list[j++] = &extrainfo; - arg_list[j++] = mpis + i; + else if (i == percent_s_idx2) + arg_list[j++] = &extrainfo; + else + arg_list[j++] = mpis + i; } - if (extrainfo && percent_s_idx == -1) - arg_list[j] = &extrainfo; + if (extrainfo) + ; else if (factors && factors[0]) { for (; i < nelem_cp; i++) diff --git a/mpi/ec.c b/mpi/ec.c index cb86ade..730f766 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -431,6 +431,7 @@ ec_get_two_inv_p (mpi_ec_t ec) coefficient. CTX is expected to be zeroized. */ static void ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, + enum ecc_dialects dialect, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { int i; @@ -438,6 +439,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, /* Fixme: Do we want to check some constraints? e.g. a < p */ ctx->model = model; + ctx->dialect = dialect; ctx->p = mpi_copy (p); ctx->a = mpi_copy (a); if (b && model == MPI_EC_TWISTEDEDWARDS) @@ -516,12 +518,13 @@ ec_deinit (void *opaque) This context needs to be released using _gcry_mpi_ec_free. */ mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, + enum ecc_dialects dialect, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { mpi_ec_t ctx; ctx = gcry_xcalloc (1, sizeof *ctx); - ec_p_init (ctx, model, p, a, b); + ec_p_init (ctx, model, dialect, p, a, b); return ctx; } @@ -537,6 +540,7 @@ _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, enum gcry_mpi_ec_models model, + enum ecc_dialects dialect, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { gcry_ctx_t ctx; @@ -550,7 +554,7 @@ _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, if (!ctx) return gpg_err_code_from_syserror (); ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - ec_p_init (ec, model, p, a, b); + ec_p_init (ec, model, dialect, p, a, b); *r_ctx = ctx; return 0; diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 57fe72a..3855dc4 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -276,10 +276,25 @@ gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits ) a->nlimbs = 0; a->sign = nbits; a->flags = 4; + if (gcry_is_secure (a->d)) + a->flags |= 1; return a; } +gcry_mpi_t +_gcry_mpi_set_opaque_copy (gcry_mpi_t a, void *p, unsigned int nbits) +{ + void *d; + unsigned int n; + + n = (nbits+7)/8; + d = gcry_is_secure (p)? gcry_malloc_secure (n) : gcry_malloc (n); + memcpy (d, p, n); + return gcry_mpi_set_opaque (a, d, nbits); +} + + void * gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits ) { diff --git a/src/ec-context.h b/src/ec-context.h index 7df3576..f2ad19b 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -25,6 +25,8 @@ struct mpi_ec_ctx_s { enum gcry_mpi_ec_models model; /* The model describing this curve. */ + enum ecc_dialects dialect; /* The ECC dialect used with the curve. */ + /* Domain parameters. Note that they may not all be set and if set the MPIs may be flaged as constant. */ gcry_mpi_t p; /* Prime specifying the field GF(p). */ diff --git a/src/mpi.h b/src/mpi.h index bd93168..f24e968 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -134,6 +134,8 @@ void _gcry_mpi_m_check( gcry_mpi_t a ); void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); gcry_mpi_t _gcry_mpi_new (unsigned int nbits); gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); +gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a, + void *p, unsigned int nbits); void *_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits); int _gcry_mpi_is_neg (gcry_mpi_t a); void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u); @@ -289,6 +291,15 @@ enum gcry_mpi_ec_models Note that we use 'b' instead of the commonly used 'd'. */ }; +/* Dialects used with elliptic curves. It is easier to keep the + definition here than in ecc-common.h. */ +enum ecc_dialects + { + ECC_DIALECT_STANDARD = 0, + ECC_DIALECT_ED25519 + }; + + /* Context used with elliptic curve functions. */ struct mpi_ec_ctx_s; typedef struct mpi_ec_ctx_s *mpi_ec_t; @@ -297,9 +308,11 @@ void _gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx); #define log_printpnt(a,p,c) _gcry_mpi_point_log ((a), (p), (c)) mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, + enum ecc_dialects dialect, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, enum gcry_mpi_ec_models model, + enum ecc_dialects dialect, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); void _gcry_mpi_ec_free (mpi_ec_t ctx); diff --git a/tests/benchmark.c b/tests/benchmark.c index ea472a1..1fa2676 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -883,7 +883,7 @@ ecc_bench (int iterations, int print_header) { #if USE_ECC gpg_error_t err; - int p_sizes[] = { 192, 224, 256, 384, 521 }; + const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519" }; int testno; if (print_header) @@ -897,12 +897,29 @@ ecc_bench (int iterations, int print_header) gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; + int p_size; + int is_ed25519; - printf ("ECDSA %3d bit ", p_sizes[testno]); + is_ed25519 = !strcmp (p_sizes[testno], "Ed25519"); + if (is_ed25519) + { + p_size = 256; + printf ("EdDSA Ed25519 "); + fflush (stdout); + } + else + { + p_size = atoi (p_sizes[testno]); + printf ("ECDSA %3d bit ", p_size); + } fflush (stdout); - err = gcry_sexp_build (&key_spec, NULL, - "(genkey (ECDSA (nbits %d)))", p_sizes[testno]); + if (is_ed25519) + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (ecdsa (curve \"Ed25519\")))"); + else + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (ECDSA (nbits %d)))", p_size); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); @@ -910,7 +927,7 @@ ecc_bench (int iterations, int print_header) err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit ECC key failed: %s\n", - p_sizes[testno], gcry_strerror (err)); + p_size, gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) @@ -925,10 +942,16 @@ ecc_bench (int iterations, int print_header) printf (" %s", elapsed_time ()); fflush (stdout); - x = gcry_mpi_new (p_sizes[testno]); - gcry_mpi_randomize (x, p_sizes[testno], GCRY_WEAK_RANDOM); - err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); + x = gcry_mpi_new (p_size); + gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM); + if (is_ed25519) + err = gcry_sexp_build (&data, NULL, + "(data (flags eddsa)(hash-algo sha512)" + " (value %m))", x); + else + err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); + if (err) die ("converting data failed: %s\n", gcry_strerror (err)); @@ -1041,6 +1064,7 @@ main( int argc, char **argv ) int no_blinding = 0; int use_random_daemon = 0; int with_progress = 0; + int debug = 0; buffer_alignment = 1; @@ -1067,6 +1091,12 @@ main( int argc, char **argv ) verbose++; argc--; argv++; } + else if (!strcmp (*argv, "--debug")) + { + verbose += 2; + debug++; + argc--; argv++; + } else if (!strcmp (*argv, "--use-random-daemon")) { use_random_daemon = 1; @@ -1167,6 +1197,9 @@ main( int argc, char **argv ) exit (1); } + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + if (gcry_fips_mode_active ()) in_fips_mode = 1; else diff --git a/tests/curves.c b/tests/curves.c index af2b368..2c3ae53 100644 --- a/tests/curves.c +++ b/tests/curves.c @@ -51,12 +51,12 @@ static unsigned int sample_key_1_nbits = 256; static char const sample_key_2[] = "(public-key\n" " (ecdh\n" -" (p #e95e4a5f737059dc60dfc7ad95b3d8139515620f#)\n" +" (p #00e95e4a5f737059dc60dfc7ad95b3d8139515620f#)\n" " (a #340e7be2a280eb74e2be61bada745d97e8f7c300#)\n" " (b #1e589a8595423412134faa2dbdec95c8d8675e58#)\n" " (g #04bed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3" "1667cb477a1a8ec338f94741669c976316da6321#)\n" -" (n #e95e4a5f737059dc60df5991d45029409e60fc09#)\n" +" (n #00e95e4a5f737059dc60df5991d45029409e60fc09#)\n" " (q #041111111111111111111111111111111111111111" "2222222222222222222222222222222222222222#)\n" " ))"; diff --git a/tests/keygen.c b/tests/keygen.c index 1d1b43e..eed62e1 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -34,6 +34,16 @@ static int debug; static int error_count; static void +show ( const char *format, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); +} + +static void fail ( const char *format, ... ) { va_list arg_ptr ; @@ -266,7 +276,8 @@ check_generated_ecc_key (gcry_sexp_t key) static void check_ecc_keys (void) { - const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256", NULL }; + const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256", + "Ed25519", NULL }; int testno; gcry_sexp_t keyparm, key; int rc; @@ -285,7 +296,11 @@ check_ecc_keys (void) die ("error generating ECC key using curve %s: %s\n", curves[testno], gpg_strerror (rc)); - check_generated_ecc_key (key); + if (!strcmp (curves[testno], "Ed25519")) + show ("Note: gcry_pk_testkey does not yet work for Ed25519\n"); + else + check_generated_ecc_key (key); + gcry_sexp_release (key); } } @@ -306,13 +321,13 @@ check_nonce (void) { gcry_create_nonce (b, sizeof b); if (!memcmp (a, b, sizeof a)) - die ("identical nounce found\n"); + die ("identical nonce found\n"); } for (i=0; i < 10; i++) { gcry_create_nonce (a, sizeof a); if (!memcmp (a, b, sizeof a)) - die ("identical nounce found\n"); + die ("identical nonce found\n"); } again: commit 89fe2173649a72019d75e059e6c6938efd10421f Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 mpi: Support printing of negative numbers. * mpi/mpicoder.c (twocompl, onecompl): New. (gcry_mpi_print): Use it for STD and SSH. (gcry_mpi_scan): Use it for STD and SSH. Always set NSCANNED. (gcry_mpi_aprint): Clear the extra allocated byte. * tests/t-convert.c (showhex, showmpi): New. (mpi2bitstr_nlz): New. (check_formats): New. (main): Call new test. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index e5ea856..46b5297 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,9 @@ Noteworthy changes in version 1.6.0 (unreleased) * Added several MPI helper functions. + * Added support for negative numbers to gcry_mpi_print, + gcry_mpi_aprint and gcry_mpi_scan. + * Interface changes relative to the 1.5.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_ac_* REMOVED. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index afef7f7..63fd596 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3826,7 +3826,8 @@ bytes actually scanned unless @var{nscanned} was given as @table @code @item GCRYMPI_FMT_STD -2-complement stored without a length header. +2-complement stored without a length header. Note that + at code{gcry_mpi_print} stores a @code{0} as a string of zero length. @item GCRYMPI_FMT_PGP As used by OpenPGP (only defined as unsigned). This is basically @@ -3837,8 +3838,10 @@ As used in the Secure Shell protocol. This is @code{GCRYMPI_FMT_STD} with a 4 byte big endian header. @item GCRYMPI_FMT_HEX -Stored as a C style string with each byte of the MPI encoded as 2 hex -digits. When using this format, @var{buflen} must be zero. +Stored as a string with each byte of the MPI encoded as 2 hex digits. +Negative numbers are prefix with a minus sign and in addition the +high bit is always zero to make clear that an explicit sign ist used. +When using this format, @var{buflen} must be zero. @item GCRYMPI_FMT_USG Simple unsigned integer. @@ -3866,6 +3869,12 @@ Convert the MPI @var{a} into an external representation described by address will be stored in the variable @var{buffer} points to. The number of bytes stored in this buffer will be stored in the variable @var{nbytes} points to, unless @var{nbytes} is @code{NULL}. + +Even if @var{nbytes} is zero, the function allocates at least one byte +and store a zero there. Thus with formats @code{GCRYMPI_FMT_STD} and + at code{GCRYMPI_FMT_USG} the caller may safely set a returned length of +0 to 1 to represent a zero as a 1 byte string. + @end deftypefun @deftypefun void gcry_mpi_dump (@w{const gcry_mpi_t @var{a}}) diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c index 19c8de9..07e91c6 100644 --- a/mpi/mpicoder.c +++ b/mpi/mpicoder.c @@ -353,6 +353,65 @@ _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg, } +static void +onecompl (gcry_mpi_t a) +{ + mpi_ptr_t ap; + mpi_size_t n; + unsigned int i; + unsigned int nbits = mpi_get_nbits (a); + + if (mpi_is_immutable (a)) + { + mpi_immutable_failed (); + return; + } + + mpi_normalize (a); + ap = a->d; + n = a->nlimbs; + + for( i = 0; i < n; i++ ) + ap[i] ^= (mpi_limb_t)(-1); + + a->sign = 0; + mpi_clear_highbit (a, nbits-1); +} + + +/* Perform a two's complement operation on buffer P of size N bytes. */ +static void +twocompl (unsigned char *p, unsigned int n) +{ + int i; + + for (i=n-1; i >= 0 && !p[i]; i--) + ; + if (i >= 0) + { + if ((p[i] & 0x01)) + p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff); + else if ((p[i] & 0x02)) + p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe); + else if ((p[i] & 0x04)) + p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc); + else if ((p[i] & 0x08)) + p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8); + else if ((p[i] & 0x10)) + p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0); + else if ((p[i] & 0x20)) + p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0); + else if ((p[i] & 0x40)) + p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0); + else + p[i] = 0x80; + + for (i--; i >= 0; i--) + p[i] ^= 0xff; + } +} + + /* Convert the external representation of an integer stored in BUFFER with a length of BUFLEN into a newly create MPI returned in RET_MPI. If NBYTES is not NULL, it will receive the number of @@ -380,15 +439,14 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (len) { + _gcry_mpi_set_buffer (a, s, len, 0); a->sign = !!(*s & 0x80); if (a->sign) { - /* FIXME: we have to convert from 2compl to magnitude format */ - mpi_free (a); - return gcry_error (GPG_ERR_INTERNAL); + onecompl (a); + mpi_add_ui (a, a, 1); + a->sign = 1; } - else - _gcry_mpi_set_buffer (a, s, len, 0); } if (ret_mpi) { @@ -397,6 +455,8 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, } else mpi_free(a); + if (nscanned) + *nscanned = len; return 0; } else if (format == GCRYMPI_FMT_USG) @@ -414,6 +474,8 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, } else mpi_free(a); + if (nscanned) + *nscanned = len; return 0; } else if (format == GCRYMPI_FMT_PGP) @@ -458,14 +520,13 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, if (n) { a->sign = !!(*s & 0x80); + _gcry_mpi_set_buffer( a, s, n, 0 ); if (a->sign) { - /* FIXME: we have to convert from 2compl to magnitude format */ - mpi_free(a); - return gcry_error (GPG_ERR_INTERNAL); + onecompl (a); + mpi_add_ui (a, a, 1); + a->sign = 1; } - else - _gcry_mpi_set_buffer( a, s, n, 0 ); } if (nscanned) *nscanned = n+4; @@ -497,6 +558,8 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, } else mpi_free(a); + if (nscanned) + *nscanned = strlen ((const char*)buffer); return 0; } else @@ -541,18 +604,25 @@ gcry_mpi_print (enum gcry_mpi_format format, int extra = 0; unsigned int n; - if (negative) - return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ - tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); if (!tmp) return gpg_error_from_syserror (); - /* If the high bit of the returned buffer is set, we need to - print an extra leading 0x00 so that the output is interpreted - as a positive number. */ - if (n && (*tmp & 0x80)) + if (negative) { + twocompl (tmp, n); + if (!(*tmp & 0x80)) + { + /* Need to extend the sign. */ + n++; + extra = 2; + } + } + else if (n && (*tmp & 0x80)) + { + /* Positive but the high bit of the returned buffer is set. + Thus we need to print an extra leading 0x00 so that the + output is interpreted as a positive number. */ n++; extra = 1; } @@ -567,9 +637,11 @@ gcry_mpi_print (enum gcry_mpi_format format, { unsigned char *s = buffer; - if (extra) + if (extra == 1) *s++ = 0; - memcpy (s, tmp, n-extra); + else if (extra) + *s++ = 0xff; + memcpy (s, tmp, n-!!extra); } gcry_free(tmp); *nwritten = n; @@ -632,13 +704,21 @@ gcry_mpi_print (enum gcry_mpi_format format, int extra = 0; unsigned int n; - if (negative) - return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ - tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); if (!tmp) return gpg_error_from_syserror (); - if (n && (*tmp & 0x80)) + + if (negative) + { + twocompl (tmp, n); + if (!(*tmp & 0x80)) + { + /* Need to extend the sign. */ + n++; + extra = 2; + } + } + else if (n && (*tmp & 0x80)) { n++; extra=1; @@ -658,10 +738,11 @@ gcry_mpi_print (enum gcry_mpi_format format, *s++ = n >> 16; *s++ = n >> 8; *s++ = n; - if (extra) + if (extra == 1) *s++ = 0; - - memcpy (s, tmp, n-extra); + else if (extra) + *s++ = 0xff; + memcpy (s, tmp, n-!!extra); } gcry_free (tmp); *nwritten = 4+n; @@ -741,6 +822,10 @@ gcry_mpi_aprint (enum gcry_mpi_format format, *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n?n:1) : gcry_malloc (n?n:1); if (!*buffer) return gpg_error_from_syserror (); + /* If the returned buffer will have a length of 0, we nevertheless + allocated 1 byte (malloc needs it anyway) and store a 0. */ + if (!n) + **buffer = 0; rc = gcry_mpi_print( format, *buffer, n, &n, a ); if (rc) { diff --git a/tests/t-convert.c b/tests/t-convert.c index b7f97fa..d44c439 100644 --- a/tests/t-convert.c +++ b/tests/t-convert.c @@ -28,7 +28,10 @@ #include "../src/gcrypt-int.h" -#define PGM "t-mpi-point" +#define PGM "t-convert" + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) static const char *wherestr; static int verbose; @@ -55,6 +58,61 @@ show (const char *format, ...) } static void +showhex (const char *prefix, const void *buffer, size_t buflen) +{ + const unsigned char *s; + + if (!verbose) + return; + fprintf (stderr, "%s: %s ", PGM, prefix); + for (s= buffer; buflen; buflen--, s++) + fprintf (stderr, "%02x", *s); + putc ('\n', stderr); +} + + +/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do + not return any leading zero bits. Caller needs to gcry_free the + result. */ +static char * +mpi2bitstr_nlz (gcry_mpi_t a) +{ + char *p, *buf; + size_t length = gcry_mpi_get_nbits (a); + + if (!length) + { + buf = p = xmalloc (3); + *p++ = ' '; + *p++ = '0'; + } + else + { + buf = p = xmalloc (length + 1 + 1); + *p++ = gcry_mpi_is_neg (a)? '-':' '; + while (length-- > 1) + *p++ = gcry_mpi_test_bit (a, length) ? '1':'0'; + *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0'; + } + *p = 0; + return buf; +} + + +static void +showmpi (const char *prefix, gcry_mpi_t a) +{ + char *bitstr; + + if (!verbose) + return; + bitstr = mpi2bitstr_nlz (a); + fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr); + xfree (bitstr); +} + + +static void fail (const char *format, ...) { va_list arg_ptr; @@ -95,10 +153,10 @@ negative_zero (void) void *bufaddr = &buf; struct { const char *name; enum gcry_mpi_format format; } fmts[] = { - { "STD", GCRYMPI_FMT_STD }, - { "PGP", GCRYMPI_FMT_PGP }, - { "SSH", GCRYMPI_FMT_SSH }, - { "HEX", GCRYMPI_FMT_HEX }, + /* { "STD", GCRYMPI_FMT_STD }, */ + /* { "PGP", GCRYMPI_FMT_PGP }, */ + /* { "SSH", GCRYMPI_FMT_SSH }, */ + /* { "HEX", GCRYMPI_FMT_HEX }, */ { "USG", GCRYMPI_FMT_USG }, { NULL, 0 } }; @@ -134,6 +192,311 @@ negative_zero (void) } +static void +check_formats (void) +{ + static struct { + int value; + struct { + const char *hex; + size_t stdlen; + const char *std; + size_t sshlen; + const char *ssh; + size_t usglen; + const char *usg; + } a; + } data[] = { + { 0, { "00", + 0, "", + 4, "\x00\x00\x00\x00", + 0, "" } + }, + { 1, { "01", + 1, "\x01", + 5, "\x00\x00\x00\x01\x01", + 1, "\x01" } + }, + { 2, { "02", + 1, "\x02", + 5, "\x00\x00\x00\x01\x02", + 1, "\x02", } + }, + { 127, { "7F", + 1, "\x7f", + 5, "\x00\x00\x00\x01\x7f", + 1, "\x7f" } + }, + { 128, { "0080", + 2, "\x00\x80", + 6, "\x00\x00\x00\x02\x00\x80", + 1, "\x80" } + }, + { 129, { "0081", + 2, "\x00\x81", + 6, "\x00\x00\x00\x02\x00\x81", + 1, "\x81" } + }, + { 255, { "00FF", + 2, "\x00\xff", + 6, "\x00\x00\x00\x02\x00\xff", + 1, "\xff" } + }, + { 256, { "0100", + 2, "\x01\x00", + 6, "\x00\x00\x00\x02\x01\x00", + 2, "\x01\x00" } + }, + { 257, { "0101", + 2, "\x01\x01", + 6, "\x00\x00\x00\x02\x01\x01", + 2, "\x01\x01" } + }, + { -1, { "-01", + 1, "\xff", + 5, "\x00\x00\x00\x01\xff", + 1,"\x01" } + }, + { -2, { "-02", + 1, "\xfe", + 5, "\x00\x00\x00\x01\xfe", + 1, "\x02" } + }, + { -127, { "-7F", + 1, "\x81", + 5, "\x00\x00\x00\x01\x81", + 1, "\x7f" } + }, + { -128, { "-0080", + 1, "\x80", + 5, "\x00\x00\x00\x01\x80", + 1, "\x80" } + }, + { -129, { "-0081", + 2, "\xff\x7f", + 6, "\x00\x00\x00\x02\xff\x7f", + 1, "\x81" } + }, + { -255, { "-00FF", + 2, "\xff\x01", + 6, "\x00\x00\x00\x02\xff\x01", + 1, "\xff" } + }, + { -256, { "-0100", + 2, "\xff\x00", + 6, "\x00\x00\x00\x02\xff\x00", + 2, "\x01\x00" } + }, + { -257, { "-0101", + 2, "\xfe\xff", + 6, "\x00\x00\x00\x02\xfe\xff", + 2, "\x01\x01" } + }, + { 65535, { "00FFFF", + 3, "\x00\xff\xff", + 7, "\x00\x00\x00\x03\x00\xff\xff", + 2, "\xff\xff" } + }, + { 65536, { "010000", + 3, "\x01\00\x00", + 7, "\x00\x00\x00\x03\x01\x00\x00", + 3, "\x01\x00\x00" } + }, + { 65537, { "010001", + 3, "\x01\00\x01", + 7, "\x00\x00\x00\x03\x01\x00\x01", + 3, "\x01\x00\x01" } + }, + { -65537, { "-010001", + 3, "\xfe\xff\xff", + 7, "\x00\x00\x00\x03\xfe\xff\xff", + 3, "\x01\x00\x01" } + }, + { -65536, { "-010000", + 3, "\xff\x00\x00", + 7, "\x00\x00\x00\x03\xff\x00\x00", + 3, "\x01\x00\x00" } + }, + { -65535, { "-00FFFF", + 3, "\xff\x00\x01", + 7, "\x00\x00\x00\x03\xff\x00\x01", + 2, "\xff\xff" } + } + }; + gpg_error_t err; + gcry_mpi_t a, b; + char *buf; + void *bufaddr = &buf; + int idx; + size_t buflen; + + a = gcry_mpi_new (0); + for (idx=0; idx < DIM(data); idx++) + { + if (debug) + show ("print test %d\n", data[idx].value); + + if (data[idx].value < 0) + { + gcry_mpi_set_ui (a, -data[idx].value); + gcry_mpi_neg (a, a); + } + else + gcry_mpi_set_ui (a, data[idx].value); + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "HEX", gpg_strerror (err)); + else + { + if (strcmp (buf, data[idx].a.hex)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "HEX", "wrong result"); + show ("expected: '%s'\n", data[idx].a.hex); + show (" got: '%s'\n", buf); + } + gcry_free (buf); + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "STD", gpg_strerror (err)); + else + { + if (buflen != data[idx].a.stdlen + || memcmp (buf, data[idx].a.std, data[idx].a.stdlen)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "STD", "wrong result"); + showhex ("expected:", data[idx].a.std, data[idx].a.stdlen); + showhex (" got:", buf, buflen); + } + gcry_free (buf); + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "SSH", gpg_strerror (err)); + else + { + if (buflen != data[idx].a.sshlen + || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "SSH", "wrong result"); + showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen); + showhex (" got:", buf, buflen); + } + gcry_free (buf); + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "USG", gpg_strerror (err)); + else + { + if (buflen != data[idx].a.usglen + || memcmp (buf, data[idx].a.usg, data[idx].a.usglen)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "USG", "wrong result"); + showhex ("expected:", data[idx].a.usg, data[idx].a.usglen); + showhex (" got:", buf, buflen); + } + gcry_free (buf); + } + } + + + /* Now for the other direction. */ + for (idx=0; idx < DIM(data); idx++) + { + if (debug) + show ("scan test %d\n", data[idx].value); + + if (data[idx].value < 0) + { + gcry_mpi_set_ui (a, -data[idx].value); + gcry_mpi_neg (a, a); + } + else + gcry_mpi_set_ui (a, data[idx].value); + + err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen); + if (err) + fail ("error scanning value %d from %s: %s\n", + data[idx].value, "HEX", gpg_strerror (err)); + else + { + if (gcry_mpi_cmp (a, b)) + { + fail ("error scanning value %d from %s: %s\n", + data[idx].value, "HEX", "wrong result"); + showmpi ("expected:", a); + showmpi (" got:", b); + } + gcry_mpi_release (b); + } + + err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD, + data[idx].a.std, data[idx].a.stdlen, &buflen); + if (err) + fail ("error scanning value %d as %s: %s\n", + data[idx].value, "STD", gpg_strerror (err)); + else + { + if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen) + { + fail ("error scanning value %d from %s: %s (%u)\n", + data[idx].value, "STD", "wrong result", buflen); + showmpi ("expected:", a); + showmpi (" got:", b); + } + gcry_mpi_release (b); + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "SSH", gpg_strerror (err)); + else + { + if (buflen != data[idx].a.sshlen + || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "SSH", "wrong result"); + showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen); + showhex (" got:", buf, buflen); + } + gcry_free (buf); + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a); + if (err) + fail ("error printing value %d as %s: %s\n", + data[idx].value, "USG", gpg_strerror (err)); + else + { + if (buflen != data[idx].a.usglen + || memcmp (buf, data[idx].a.usg, data[idx].a.usglen)) + { + fail ("error printing value %d as %s: %s\n", + data[idx].value, "USG", "wrong result"); + showhex ("expected:", data[idx].a.usg, data[idx].a.usglen); + showhex (" got:", buf, buflen); + } + gcry_free (buf); + } + } + + gcry_mpi_release (a); +} int @@ -154,6 +517,7 @@ main (int argc, char **argv) gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); negative_zero (); + check_formats (); show ("All tests completed. Errors: %d\n", error_count); return error_count ? 1 : 0; ----------------------------------------------------------------------- Summary of changes: NEWS | 3 + cipher/ecc-common.h | 3 + cipher/ecc-curves.c | 45 ++++-- cipher/ecc-misc.c | 55 ++++++-- cipher/ecc.c | 404 ++++++++++++++++++++++++++++++++++----------------- cipher/pubkey.c | 50 +++++-- doc/gcrypt.texi | 15 ++- mpi/ec.c | 8 +- mpi/mpicoder.c | 137 ++++++++++++++---- mpi/mpiutil.c | 15 ++ src/ec-context.h | 2 + src/mpi.h | 13 ++ tests/benchmark.c | 49 +++++- tests/curves.c | 4 +- tests/keygen.c | 23 +++- tests/t-convert.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++- 16 files changed, 978 insertions(+), 222 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 18 13:54:02 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 18 Sep 2013 13:54:02 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-248-g6466db1 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 Privacy Guard". The branch, master has been updated via 6466db10fb22a4f24df4edad9c5cb33ec67321bd (commit) from 244587ea41d4c75cb5570356f09a6705864a7e8d (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 6466db10fb22a4f24df4edad9c5cb33ec67321bd Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 Switch to deterministic DSA. * agent/pksign.c (rfc6979_hash_algo_string): New. (do_encode_dsa) [Libgcrypt >= 1.6]: Make use of RFC-6979. -- Now that we have a good (and not NSA/NIST demanded ;-) specification on how to use DSA without a random nonce, we take advantage of it and thus avoid pitfalls related to a misbehaving RNG during signature creation. Note that OpenPGP has the option of using a longer hash algorithm but truncated to what is suitable for the used DSA key size. The hash used as input to RFC-6979 will also be one with an appropriate digest length but not a truncated one. This is allowed by RFC-6979. Signed-off-by: Werner Koch diff --git a/agent/pksign.c b/agent/pksign.c index 8518730..ad783ce 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -1,5 +1,6 @@ /* pksign.c - public key signing (well, actually using a secret key) * Copyright (C) 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch * * This file is part of GnuPG. * @@ -111,6 +112,25 @@ get_dsa_qbits (gcry_sexp_t key) } +/* Return an appropriate hash algorithm to be used with RFC-6979 for a + message digest of length MDLEN. Although a fallback of SHA-256 is + used the current implementation in Libgcrypt will reject a hash + algorithm which does not match the length of the message. */ +static const char * +rfc6979_hash_algo_string (size_t mdlen) +{ + switch (mdlen) + { + case 20: return "sha1"; + case 28: return "sha224"; + case 32: return "sha256"; + case 48: return "sha384"; + case 64: return "sha512"; + default: return "sha256"; + } +} + + /* Encode a message digest for use with an DSA algorithm. */ static gpg_error_t do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, @@ -177,11 +197,20 @@ do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, if (mdlen > qbits/8) mdlen = qbits/8; - /* Create the S-expression. We need to convert to an MPI first - because we want an unsigned integer. Using %b directly is not - possible because libgcrypt assumes an mpi and uses - GCRYMPI_FMT_STD for parsing and thus possible yielding a negative - value. */ + /* Create the S-expression. If we are using Libgcrypt 1.6 we make + use of Deterministic DSA. Libgcrypt < 1.6 does not implement + RFC-6979 and also requires us to convert to an MPI because it + expects an unsigned integer. Using %b directly is not possible + because Libgcrypt assumes an MPI and uses GCRYMPI_FMT_STD for + parsing and thus possible yielding a negative value. */ +#if GCRYPT_VERSION_NUMBER >= 0x010600 /* Libgcrypt >= 1.6 */ + { + err = gcry_sexp_build (&hash, NULL, + "(data (flags rfc6979) (hash %s %b))", + rfc6979_hash_algo_string (mdlen), + (int)mdlen, md); + } +#else /* Libgcrypt < 1.6 */ { gcry_mpi_t mpi; @@ -193,6 +222,7 @@ do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gcry_mpi_release (mpi); } } +#endif /* Libgcrypt < 1.6 */ if (!err) *r_hash = hash; return err; ----------------------------------------------------------------------- Summary of changes: agent/pksign.c | 40 +++++++++++++++++++++++++++++++++++----- 1 files changed, 35 insertions(+), 5 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 18 17:50:58 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Wed, 18 Sep 2013 17:50:58 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-245-g2ad7ea9 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 2ad7ea9cb388fd31e4b0852b68d77f599ef4adce (commit) from fd84b63ddd825431f557c002608a6c8d1bcc54c8 (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 2ad7ea9cb388fd31e4b0852b68d77f599ef4adce Author: Jussi Kivilinna Date: Wed Sep 18 17:13:53 2013 +0300 Fix encryption/decryption return type for GOST28147 * cipher/gost.h (_gcry_gost_enc_one): Change return type to 'unsigned int'. * cipher/gost28147.c (max): New macro. (gost_encrypt_block, gost_decrypt_block): Return burn stack depth. (_gcry_gost_enc_one): Return burn stack depth from gost_encrypt_block. -- Return type for block cipher functions was lately changed from 'void' to 'unsigned int' to pass burn stack depth to cipher mode code. Patch fixes gost28147 to return stack burn value. Signed-off-by: Jussi Kivilinna diff --git a/cipher/gost.h b/cipher/gost.h index e1cf033..42021aa 100644 --- a/cipher/gost.h +++ b/cipher/gost.h @@ -27,7 +27,7 @@ typedef struct { } GOST28147_context; /* This is a simple interface that will be used by GOST R 34.11-94 */ -extern void _gcry_gost_enc_one (GOST28147_context *c, const byte *key, +extern unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key, byte *out, byte *in); #endif diff --git a/cipher/gost28147.c b/cipher/gost28147.c index 5d6d1e7..862e7d6 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -35,6 +35,9 @@ #include "cipher.h" +#define max(a, b) (((a) > (b)) ? (a) : (b)) + + /* This is an s-box from RFC4357, named GostR3411-94-TestParamSet * For now it is the only s-box supported, as libgcrypt lacks mechanism * for passing parameters to cipher in a usefull way. */ @@ -107,7 +110,7 @@ gost_val (GOST28147_context *ctx, u32 cm1, int subkey) return (cm1 << 11) | (cm1 >> 21); } -static void +static unsigned int gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; @@ -153,16 +156,22 @@ gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff; outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff; outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff; + + return /* burn_stack */ 4*sizeof(void*) /* func call */ + + 3*sizeof(void*) /* stack */ + + max( 4*sizeof(void*) /* gost_val call */, + 3*sizeof(void*) /* gost_set_subst call */ + + 2*sizeof(void*) /* gost_set subst stack*/ ); } -void _gcry_gost_enc_one (GOST28147_context *c, const byte *key, +unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key, byte *out, byte *in) { gost_setkey (c, key, 32); - gost_encrypt_block (c, out, in); + return gost_encrypt_block (c, out, in); } -static void +static unsigned int gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; @@ -208,6 +217,12 @@ gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff; outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff; outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff; + + return /* burn_stack */ 4*sizeof(void*) /* func call */ + + 3*sizeof(void*) /* stack */ + + max( 4*sizeof(void*) /* gost_val call */, + 3*sizeof(void*) /* gost_set_subst call */ + + 2*sizeof(void*) /* gost_set subst stack*/ ); } gcry_cipher_spec_t _gcry_cipher_spec_gost28147 = ----------------------------------------------------------------------- Summary of changes: cipher/gost.h | 2 +- cipher/gost28147.c | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 18 21:35:07 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 18 Sep 2013 21:35:07 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-247-g85722af 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 85722afb379f7a392a8117b895de273fd88c4ebc (commit) via 89103ce00e862cc709e80fa41f2ee13d54093ec5 (commit) from 2ad7ea9cb388fd31e4b0852b68d77f599ef4adce (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 85722afb379f7a392a8117b895de273fd88c4ebc Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 pk: Simplify the public key dispatcher pubkey.c. * src/cipher-proto.h (gcry_pk_spec_t): Add fields ALGO and FLAGS. * cipher/dsa.c (_gcry_pubkey_spec_dsa): Set these fields. * cipher/ecc.c (_gcry_pubkey_spec_ecdsa): Ditto. (_gcry_pubkey_spec_ecdh): Ditto. * cipher/rsa.c (_gcry_pubkey_spec_rsa): Ditto. * cipher/elgamal.c (_gcry_pubkey_spec_elg): Ditto (_gcry_pubkey_spec_elg_e): New. * cipher/pubkey.c: Change most code to replace the former module system by a simpler system to gain information about the algorithms. (disable_pubkey_algo): SImplified. Not anymore thread-safe, though. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 1c8793b..678805d 100644 --- a/NEWS +++ b/NEWS @@ -102,6 +102,7 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRY_MD_GOSTR3411_94 NEW. GCRY_MD_STRIBOG256 NEW. GCRY_MD_STRIBOG512 NEW. + GCRYCTL_DISABLE_ALGO CHANGED: Not anymore thread-safe. Noteworthy changes in version 1.5.0 (2011-06-29) diff --git a/cipher/dsa.c b/cipher/dsa.c index 4a7ceee..ca9a4f6 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -1205,9 +1205,10 @@ static const char *dsa_names[] = gcry_pk_spec_t _gcry_pubkey_spec_dsa = { + GCRY_PK_DSA, { 0, 1 }, + GCRY_PK_USAGE_SIGN, "DSA", dsa_names, "pqgy", "pqgyx", "", "rs", "pqgy", - GCRY_PK_USAGE_SIGN, dsa_generate, dsa_check_secret_key, NULL, diff --git a/cipher/ecc.c b/cipher/ecc.c index 5340d57..66cd342 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -2003,9 +2003,10 @@ static const char *ecdh_names[] = gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { + GCRY_PK_ECDSA, { 0, 0 }, + GCRY_PK_USAGE_SIGN, "ECDSA", ecdsa_names, "pabgnq", "pabgnqd", "", "rs", "pabgnq", - GCRY_PK_USAGE_SIGN, ecc_generate, ecc_check_secret_key, NULL, @@ -2023,9 +2024,10 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = gcry_pk_spec_t _gcry_pubkey_spec_ecdh = { + GCRY_PK_ECDH, { 0, 0 }, + GCRY_PK_USAGE_ENCR, "ECDH", ecdh_names, "pabgnq", "pabgnqd", "se", "", "pabgnq", - GCRY_PK_USAGE_ENCR, ecc_generate, ecc_check_secret_key, ecc_encrypt_raw, diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 44990aa..65448e0 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -840,9 +840,27 @@ static const char *elg_names[] = gcry_pk_spec_t _gcry_pubkey_spec_elg = { + GCRY_PK_ELG, { 0, 0 }, + (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), + "ELG", elg_names, + "pgy", "pgyx", "ab", "rs", "pgy", + elg_generate, + elg_check_secret_key, + elg_encrypt, + elg_decrypt, + elg_sign, + elg_verify, + elg_get_nbits, + NULL, + elg_generate_ext + }; + +gcry_pk_spec_t _gcry_pubkey_spec_elg_e = + { + GCRY_PK_ELG_E, { 0, 0 }, + (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), "ELG", elg_names, "pgy", "pgyx", "ab", "rs", "pgy", - GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, elg_generate, elg_check_secret_key, elg_encrypt, diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 5be6b85..c755729 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -44,253 +44,80 @@ static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, struct pk_encoding_ctx *ctx); -/* This is the list of the default public-key ciphers included in - libgcrypt. FIPS_ALLOWED indicated whether the algorithm is used in - FIPS mode. */ -static struct pubkey_table_entry -{ - gcry_pk_spec_t *pubkey; - unsigned int algorithm; - int fips_allowed; -} pubkey_table[] = +/* This is the list of the public-key algorithms included in + Libgcrypt. */ +static gcry_pk_spec_t *pubkey_list[] = { -#if USE_RSA - { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA, 1}, +#if USE_ECC + &_gcry_pubkey_spec_ecdsa, + &_gcry_pubkey_spec_ecdh, #endif -#if USE_ELGAMAL - { &_gcry_pubkey_spec_elg, GCRY_PK_ELG }, - { &_gcry_pubkey_spec_elg, GCRY_PK_ELG_E }, +#if USE_RSA + &_gcry_pubkey_spec_rsa, #endif #if USE_DSA - { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA, 1 }, + &_gcry_pubkey_spec_dsa, #endif -#if USE_ECC - { &_gcry_pubkey_spec_ecdsa, GCRY_PK_ECDSA, 0 }, - { &_gcry_pubkey_spec_ecdh, GCRY_PK_ECDH, 0 }, +#if USE_ELGAMAL + &_gcry_pubkey_spec_elg, + &_gcry_pubkey_spec_elg, #endif - { NULL, 0 } + NULL }; -/* List of registered ciphers. */ -static gcry_module_t pubkeys_registered; - -/* This is the lock protecting PUBKEYS_REGISTERED. */ -static ath_mutex_t pubkeys_registered_lock; - -/* Flag to check whether the default pubkeys have already been - registered. */ -static int default_pubkeys_registered; - -/* Convenient macro for registering the default digests. */ -#define REGISTER_DEFAULT_PUBKEYS \ - do \ - { \ - ath_mutex_lock (&pubkeys_registered_lock); \ - if (! default_pubkeys_registered) \ - { \ - pk_register_default (); \ - default_pubkeys_registered = 1; \ - } \ - ath_mutex_unlock (&pubkeys_registered_lock); \ - } \ - while (0) - -/* These dummy functions are used in case a cipher implementation - refuses to provide it's own functions. */ - -static gcry_err_code_t -dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy, - gcry_mpi_t *skey, gcry_mpi_t **retfactors) -{ - (void)algorithm; - (void)nbits; - (void)dummy; - (void)skey; - (void)retfactors; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; -} - -static gcry_err_code_t -dummy_check_secret_key (int algorithm, gcry_mpi_t *skey) -{ - (void)algorithm; - (void)skey; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; -} - -static gcry_err_code_t -dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, - gcry_mpi_t *pkey, int flags) -{ - (void)algorithm; - (void)resarr; - (void)data; - (void)pkey; - (void)flags; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; -} -static gcry_err_code_t -dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, - gcry_mpi_t *skey, int flags) +/* Return the spec structure for the public key algorithm ALGO. For + an unknown algorithm NULL is returned. */ +static gcry_pk_spec_t * +spec_from_algo (int algo) { - (void)algorithm; - (void)result; - (void)data; - (void)skey; - (void)flags; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; -} - -static gcry_err_code_t -dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, - gcry_mpi_t *skey, - int flags, int hashalgo) - -{ - (void)algorithm; - (void)resarr; - (void)data; - (void)skey; - (void)flags; - (void)hashalgo; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; -} + int idx; + gcry_pk_spec_t *spec; -static gcry_err_code_t -dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, - gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), void *opaquev, - int flags, int hashalgo) -{ - (void)algorithm; - (void)hash; - (void)data; - (void)pkey; - (void)cmp; - (void)opaquev; - (void)flags; - (void)hashalgo; - fips_signal_error ("using dummy public key function"); - return GPG_ERR_NOT_IMPLEMENTED; + for (idx = 0; (spec = pubkey_list[idx]); idx++) + if (algo == spec->algo) + return spec; + return NULL; } -static unsigned -dummy_get_nbits (int algorithm, gcry_mpi_t *pkey) -{ - (void)algorithm; - (void)pkey; - fips_signal_error ("using dummy public key function"); - return 0; -} -/* Internal function. Register all the pubkeys included in - PUBKEY_TABLE. Returns zero on success or an error code. */ -static void -pk_register_default (void) +/* Return the spec structure for the public key algorithm with NAME. + For an unknown name NULL is returned. */ +static gcry_pk_spec_t * +spec_from_name (const char *name) { - gcry_err_code_t err = 0; - int i; + gcry_pk_spec_t *spec; + int idx; + const char **aliases; - for (i = 0; (! err) && pubkey_table[i].pubkey; i++) + for (idx=0; (spec = pubkey_list[idx]); idx++) { -#define pubkey_use_dummy(func) \ - if (! pubkey_table[i].pubkey->func) \ - pubkey_table[i].pubkey->func = dummy_##func; - - pubkey_use_dummy (generate); - pubkey_use_dummy (check_secret_key); - pubkey_use_dummy (encrypt); - pubkey_use_dummy (decrypt); - pubkey_use_dummy (sign); - pubkey_use_dummy (verify); - pubkey_use_dummy (get_nbits); -#undef pubkey_use_dummy - - err = _gcry_module_add (&pubkeys_registered, - pubkey_table[i].algorithm, - (void *) pubkey_table[i].pubkey, - NULL, - NULL); + if (!stricmp (name, spec->name)) + return spec; + for (aliases = spec->aliases; *aliases; aliases++) + if (!stricmp (name, *aliases)) + return spec; } - if (err) - BUG (); + return NULL; } -/* Internal callback function. Used via _gcry_module_lookup. */ -static int -gcry_pk_lookup_func_name (void *spec, void *data) -{ - gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec; - char *name = (char *) data; - const char **aliases = pubkey->aliases; - int ret = stricmp (name, pubkey->name); - - while (ret && *aliases) - ret = stricmp (name, *aliases++); - - return ! ret; -} -/* Internal function. Lookup a pubkey entry by it's name. */ -static gcry_module_t -gcry_pk_lookup_name (const char *name) +/* Disable the use of the algorithm ALGO. This is not thread safe and + should thus be called early. */ +static void +disable_pubkey_algo (int algo) { - gcry_module_t pubkey; + gcry_pk_spec_t *spec = spec_from_algo (algo); - pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name, - gcry_pk_lookup_func_name); - - return pubkey; + if (spec) + spec->flags.disabled = 1; } -/* Register a new pubkey module whose specification can be found in - PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID - and a pointer representhing this module is stored in MODULE. */ -gcry_error_t -_gcry_pk_register (gcry_pk_spec_t *pubkey, - unsigned int *algorithm_id, - gcry_module_t *module) -{ - gcry_err_code_t err = GPG_ERR_NO_ERROR; - gcry_module_t mod; - - /* We do not support module loading in fips mode. */ - if (fips_mode ()) - return gpg_error (GPG_ERR_NOT_SUPPORTED); - - ath_mutex_lock (&pubkeys_registered_lock); - err = _gcry_module_add (&pubkeys_registered, 0, - (void *) pubkey, - NULL, - &mod); - ath_mutex_unlock (&pubkeys_registered_lock); - - if (! err) - { - *module = mod; - *algorithm_id = mod->mod_id; - } - - return err; -} - -/* Unregister the pubkey identified by ID, which must have been - registered with gcry_pk_register. */ -void -_gcry_pk_unregister (gcry_module_t module) -{ - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); -} + +/* Free the MPIs stored in the NULL terminated ARRAY of MPIs and set + the slots to NULL. */ static void release_mpi_array (gcry_mpi_t *array) { @@ -301,30 +128,24 @@ release_mpi_array (gcry_mpi_t *array) } } -/**************** + + +/* * Map a string to the pubkey algo */ int gcry_pk_map_name (const char *string) { - gcry_module_t pubkey; - int algorithm = 0; + gcry_pk_spec_t *spec; if (!string) return 0; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = gcry_pk_lookup_name (string); - if (pubkey) - { - algorithm = pubkey->mod_id; - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); - - return algorithm; + spec = spec_from_name (string); + if (!spec) + return 0; + if (spec->flags.disabled) + return 0; + return spec->algo; } @@ -332,25 +153,14 @@ gcry_pk_map_name (const char *string) a string representation of the algorithm name. For unknown algorithm IDs this functions returns "?". */ const char * -gcry_pk_algo_name (int algorithm) +gcry_pk_algo_name (int algo) { - gcry_module_t pubkey; - const char *name; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - name = ((gcry_pk_spec_t *) pubkey->spec)->name; - _gcry_module_release (pubkey); - } - else - name = "?"; - ath_mutex_unlock (&pubkeys_registered_lock); + gcry_pk_spec_t *spec; - return name; + spec = spec_from_algo (algo); + if (spec) + return spec->name; + return "?"; } @@ -358,77 +168,44 @@ gcry_pk_algo_name (int algorithm) name of the algorithm. This is required to adhere to the spki specs where the algorithm names are lowercase. */ const char * -_gcry_pk_aliased_algo_name (int algorithm) +_gcry_pk_aliased_algo_name (int algo) { - const char *name = NULL; - gcry_module_t module; - - REGISTER_DEFAULT_PUBKEYS; + gcry_pk_spec_t *spec; + const char *name; - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) + spec = spec_from_algo (algo); + if (spec) { - gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec; - - name = pubkey->aliases? *pubkey->aliases : NULL; + name = spec->aliases? *spec->aliases : NULL; if (!name || !*name) - name = pubkey->name; - _gcry_module_release (module); + name = spec->name; } - ath_mutex_unlock (&pubkeys_registered_lock); - + else + name = NULL; return name; } -static void -disable_pubkey_algo (int algorithm) -{ - gcry_module_t pubkey; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - if (! (pubkey-> flags & FLAG_MODULE_DISABLED)) - pubkey->flags |= FLAG_MODULE_DISABLED; - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); -} - - /**************** * A USE of 0 means: don't care. */ static gcry_err_code_t -check_pubkey_algo (int algorithm, unsigned use) +check_pubkey_algo (int algo, unsigned use) { - gcry_err_code_t err = GPG_ERR_NO_ERROR; - gcry_pk_spec_t *pubkey; - gcry_module_t module; - - REGISTER_DEFAULT_PUBKEYS; + gcry_err_code_t err = 0; + gcry_pk_spec_t *spec; - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) + spec = spec_from_algo (algo); + if (spec) { - pubkey = (gcry_pk_spec_t *) module->spec; - if (((use & GCRY_PK_USAGE_SIGN) - && (! (pubkey->use & GCRY_PK_USAGE_SIGN))) + && (! (spec->use & GCRY_PK_USAGE_SIGN))) || ((use & GCRY_PK_USAGE_ENCR) - && (! (pubkey->use & GCRY_PK_USAGE_ENCR)))) + && (! (spec->use & GCRY_PK_USAGE_ENCR)))) err = GPG_ERR_WRONG_PUBKEY_ALGO; - else if (module->flags & FLAG_MODULE_DISABLED) - err = GPG_ERR_PUBKEY_ALGO; - _gcry_module_release (module); } else err = GPG_ERR_PUBKEY_ALGO; - ath_mutex_unlock (&pubkeys_registered_lock); return err; } @@ -438,96 +215,50 @@ check_pubkey_algo (int algorithm, unsigned use) * Return the number of public key material numbers */ static int -pubkey_get_npkey (int algorithm) +pubkey_get_npkey (int algo) { - gcry_module_t pubkey; - int npkey = 0; + gcry_pk_spec_t *spec = spec_from_algo (algo); - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey); - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); - - return npkey; + return spec? strlen (spec->elements_pkey) : 0; } + /**************** * Return the number of secret key material numbers */ static int -pubkey_get_nskey (int algorithm) +pubkey_get_nskey (int algo) { - gcry_module_t pubkey; - int nskey = 0; + gcry_pk_spec_t *spec = spec_from_algo (algo); - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey); - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); - - return nskey; + return spec? strlen (spec->elements_skey) : 0; } + /**************** * Return the number of signature material numbers */ static int -pubkey_get_nsig (int algorithm) +pubkey_get_nsig (int algo) { - gcry_module_t pubkey; - int nsig = 0; + gcry_pk_spec_t *spec = spec_from_algo (algo); - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig); - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); - - return nsig; + return spec? strlen (spec->elements_sig) : 0; } /**************** * Return the number of encryption material numbers */ static int -pubkey_get_nenc (int algorithm) +pubkey_get_nenc (int algo) { - gcry_module_t pubkey; - int nenc = 0; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc); - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); + gcry_pk_spec_t *spec = spec_from_algo (algo); - return nenc; + return spec? strlen (spec->elements_enc) : 0; } -/* Generate a new public key with algorithm ALGORITHM of size NBITS +/* Generate a new public key with algorithm ALGO of size NBITS and return it at SKEY. USE_E depends on the ALGORITHM. GENPARMS is passed to the algorithm module if it features an extended generation function. RETFACTOR is used by some algorithms to @@ -536,62 +267,44 @@ pubkey_get_nenc (int algorithm) The function returns the error code number or 0 on success. */ static gcry_err_code_t -pubkey_generate (int algorithm, +pubkey_generate (int algo, unsigned int nbits, unsigned long use_e, gcry_sexp_t genparms, gcry_mpi_t *skey, gcry_mpi_t **retfactors, gcry_sexp_t *r_extrainfo) { - gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO; - gcry_module_t pubkey; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - if (((gcry_pk_spec_t *) pubkey->spec)->ext_generate) - { - - /* Use the extended generate function. */ - ec = ((gcry_pk_spec_t *) pubkey->spec)->ext_generate - (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo); - } - else - { - /* Use the standard generate function. */ - ec = ((gcry_pk_spec_t *) pubkey->spec)->generate - (algorithm, nbits, use_e, skey, retfactors); - } - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); + gcry_err_code_t rc; + gcry_pk_spec_t *spec = spec_from_algo (algo); + + if (spec && spec->ext_generate) + rc = spec->ext_generate (algo, nbits, use_e, genparms, + skey, retfactors, r_extrainfo); + else if (spec && spec->generate) + rc = spec->generate (algo, nbits, use_e, skey, retfactors); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; - return ec; + return rc; } static gcry_err_code_t -pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey) +pubkey_check_secret_key (int algo, gcry_mpi_t *skey) { - gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; - gcry_module_t pubkey; - - REGISTER_DEFAULT_PUBKEYS; + gcry_err_code_t rc; + gcry_pk_spec_t *spec = spec_from_algo (algo); - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key - (algorithm, skey); - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); + if (spec && spec->check_secret_key) + rc = spec->check_secret_key (algo, skey); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; - return err; + return rc; } @@ -602,12 +315,11 @@ pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey) * check with pubkey_get_nenc() ) */ static gcry_err_code_t -pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, +pubkey_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags) { - gcry_pk_spec_t *pubkey; - gcry_module_t module; gcry_err_code_t rc; + gcry_pk_spec_t *spec; int i; /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as @@ -615,29 +327,23 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, here. */ if (DBG_CIPHER && !fips_mode ()) { - log_debug ("pubkey_encrypt: algo=%d\n", algorithm); - for(i = 0; i < pubkey_get_npkey (algorithm); i++) + log_debug ("pubkey_encrypt: algo=%d\n", algo); + for(i = 0; i < pubkey_get_npkey (algo); i++) log_mpidump (" pkey", pkey[i]); log_mpidump (" data", data); } - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) - { - pubkey = (gcry_pk_spec_t *) module->spec; - rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags); - _gcry_module_release (module); - goto ready; - } - rc = GPG_ERR_PUBKEY_ALGO; - - ready: - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_algo (algo); + if (spec && spec->encrypt) + rc = spec->encrypt (algo, resarr, data, pkey, flags); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; if (!rc && DBG_CIPHER && !fips_mode ()) { - for(i = 0; i < pubkey_get_nenc (algorithm); i++) + for(i = 0; i < pubkey_get_nenc (algo); i++) log_mpidump(" encr", resarr[i] ); } return rc; @@ -652,38 +358,30 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, * newly allocated mpi or NULL in case of an error. */ static gcry_err_code_t -pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, +pubkey_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) { - gcry_pk_spec_t *pubkey; - gcry_module_t module; gcry_err_code_t rc; + gcry_pk_spec_t *spec; int i; - *result = NULL; /* so the caller can always do a mpi_free */ + *result = NULL; /* So the caller can always do a mpi_free. */ if (DBG_CIPHER && !fips_mode ()) { - log_debug ("pubkey_decrypt: algo=%d\n", algorithm); - for(i = 0; i < pubkey_get_nskey (algorithm); i++) + log_debug ("pubkey_decrypt: algo=%d\n", algo); + for(i = 0; i < pubkey_get_nskey (algo); i++) log_mpidump (" skey", skey[i]); - for(i = 0; i < pubkey_get_nenc (algorithm); i++) + for(i = 0; i < pubkey_get_nenc (algo); i++) log_mpidump (" data", data[i]); } - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) - { - pubkey = (gcry_pk_spec_t *) module->spec; - rc = pubkey->decrypt (algorithm, result, data, skey, flags); - _gcry_module_release (module); - goto ready; - } - - rc = GPG_ERR_PUBKEY_ALGO; - - ready: - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_algo (algo); + if (spec && spec->decrypt) + rc = spec->decrypt (algo, result, data, skey, flags); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; if (!rc && DBG_CIPHER && !fips_mode ()) log_mpidump (" plain", *result); @@ -699,84 +397,68 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, * algorithm allows this - check with pubkey_get_nsig() ) */ static gcry_err_code_t -pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, +pubkey_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, struct pk_encoding_ctx *ctx) { - gcry_pk_spec_t *pubkey; - gcry_module_t module; gcry_err_code_t rc; + gcry_pk_spec_t *spec; int i; if (DBG_CIPHER && !fips_mode ()) { - log_debug ("pubkey_sign: algo=%d\n", algorithm); - for(i = 0; i < pubkey_get_nskey (algorithm); i++) + log_debug ("pubkey_sign: algo=%d\n", algo); + for(i = 0; i < pubkey_get_nskey (algo); i++) log_mpidump (" skey", skey[i]); log_mpidump(" data", data ); } - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) - { - pubkey = (gcry_pk_spec_t *) module->spec; - rc = pubkey->sign (algorithm, resarr, data, skey, - ctx->flags, ctx->hash_algo); - _gcry_module_release (module); - goto ready; - } - - rc = GPG_ERR_PUBKEY_ALGO; - - ready: - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_algo (algo); + if (spec && spec->sign) + rc = spec->sign (algo, resarr, data, skey, ctx->flags, ctx->hash_algo); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; if (!rc && DBG_CIPHER && !fips_mode ()) - for (i = 0; i < pubkey_get_nsig (algorithm); i++) + for (i = 0; i < pubkey_get_nsig (algo); i++) log_mpidump (" sig", resarr[i]); return rc; } + /**************** * Verify a public key signature. * Return 0 if the signature is good */ static gcry_err_code_t -pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, +pubkey_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, struct pk_encoding_ctx *ctx) { - gcry_pk_spec_t *pubkey; - gcry_module_t module; gcry_err_code_t rc; + gcry_pk_spec_t *spec; int i; if (DBG_CIPHER && !fips_mode ()) { - log_debug ("pubkey_verify: algo=%d\n", algorithm); - for (i = 0; i < pubkey_get_npkey (algorithm); i++) + log_debug ("pubkey_verify: algo=%d\n", algo); + for (i = 0; i < pubkey_get_npkey (algo); i++) log_mpidump (" pkey", pkey[i]); - for (i = 0; i < pubkey_get_nsig (algorithm); i++) + for (i = 0; i < pubkey_get_nsig (algo); i++) log_mpidump (" sig", data[i]); log_mpidump (" hash", hash); } - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (module) - { - pubkey = (gcry_pk_spec_t *) module->spec; - rc = pubkey->verify (algorithm, hash, data, pkey, - ctx->verify_cmp, ctx, - ctx->flags, ctx->hash_algo); - _gcry_module_release (module); - goto ready; - } - - rc = GPG_ERR_PUBKEY_ALGO; + spec = spec_from_algo (algo); + if (spec && spec->verify) + rc = spec->verify (algo, hash, data, pkey, + ctx->verify_cmp, ctx, ctx->flags, ctx->hash_algo); + else if (spec) + rc = GPG_ERR_NOT_IMPLEMENTED; + else + rc = GPG_ERR_PUBKEY_ALGO; - ready: - ath_mutex_unlock (&pubkeys_registered_lock); return rc; } @@ -2014,15 +1696,14 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, static gcry_err_code_t sexp_to_key (gcry_sexp_t sexp, int want_private, int use, const char *override_elems, - gcry_mpi_t **retarray, gcry_module_t *retalgo, int *r_is_ecc) + gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, int *r_is_ecc) { gcry_err_code_t err = 0; gcry_sexp_t list, l2; char *name; const char *elems; gcry_mpi_t *array; - gcry_module_t module; - gcry_pk_spec_t *pubkey; + gcry_pk_spec_t *spec; int is_ecc; /* Check that the first element is valid. If we are looking for a @@ -2062,43 +1743,37 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, else is_ecc = 0; - ath_mutex_lock (&pubkeys_registered_lock); if (is_ecc == 2 && (use & GCRY_PK_USAGE_SIGN)) - module = gcry_pk_lookup_name ("ecdsa"); + spec = spec_from_name ("ecdsa"); else if (is_ecc == 2 && (use & GCRY_PK_USAGE_ENCR)) - module = gcry_pk_lookup_name ("ecdh"); + spec = spec_from_name ("ecdh"); else - module = gcry_pk_lookup_name (name); - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_name (name); gcry_free (name); - if (!module) + if (!spec) { gcry_sexp_release (list); return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ } - else - { - pubkey = (gcry_pk_spec_t *) module->spec; - } if (override_elems) elems = override_elems; else if (want_private) - elems = pubkey->elements_skey; + elems = spec->elements_skey; else - elems = pubkey->elements_pkey; + elems = spec->elements_pkey; array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); if (!array) err = gpg_err_code_from_syserror (); if (!err) { if (is_ecc) - err = sexp_elements_extract_ecc (list, elems, array, pubkey, + err = sexp_elements_extract_ecc (list, elems, array, spec, want_private); else - err = sexp_elements_extract (list, elems, array, pubkey->name, 0); + err = sexp_elements_extract (list, elems, array, spec->name, 0); } gcry_sexp_release (list); @@ -2106,15 +1781,11 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, if (err) { gcry_free (array); - - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); } else { *retarray = array; - *retalgo = module; + *r_spec = spec; if (r_is_ecc) *r_is_ecc = is_ecc; } @@ -2128,15 +1799,14 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, MPI as opaque data. */ static gcry_err_code_t sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, - gcry_module_t *retalgo, int opaque) + gcry_pk_spec_t **r_spec, int opaque) { gcry_err_code_t err = 0; gcry_sexp_t list, l2; char *name; const char *elems; gcry_mpi_t *array; - gcry_module_t module; - gcry_pk_spec_t *pubkey; + gcry_pk_spec_t *spec; /* Check that the first element is valid. */ list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); @@ -2171,22 +1841,18 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, name = _gcry_sexp_nth_string (l2, 0); } - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name (name); - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_name (name); gcry_free (name); name = NULL; - if (!module) + if (!spec) { gcry_sexp_release (l2); gcry_sexp_release (list); return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ } - else - pubkey = (gcry_pk_spec_t *) module->spec; - elems = pubkey->elements_sig; + elems = spec->elements_sig; array = gcry_calloc (strlen (elems) + 1 , sizeof *array ); if (!array) err = gpg_err_code_from_syserror (); @@ -2199,16 +1865,12 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, if (err) { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); - gcry_free (array); } else { *retarray = array; - *retalgo = module; + *r_spec = spec; } return err; @@ -2284,13 +1946,13 @@ get_hash_algo (const char *s, size_t n) * case raw encoding is used. */ static gcry_err_code_t -sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, +sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, int *ret_modern, int *flags, struct pk_encoding_ctx *ctx) { gcry_err_code_t err = 0; - gcry_sexp_t list = NULL, l2 = NULL; - gcry_pk_spec_t *pubkey = NULL; - gcry_module_t module = NULL; + gcry_sexp_t list = NULL; + gcry_sexp_t l2 = NULL; + gcry_pk_spec_t *spec = NULL; char *name = NULL; size_t n; int parsed_flags = 0; @@ -2435,18 +2097,14 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, l2 = NULL; } - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name (name); - ath_mutex_unlock (&pubkeys_registered_lock); - - if (!module) + spec = spec_from_name (name); + if (!spec) { err = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ goto leave; } - pubkey = (gcry_pk_spec_t *) module->spec; - elems = pubkey->elements_enc; + elems = spec->elements_enc; array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); if (!array) { @@ -2463,9 +2121,6 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, if (err) { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); gcry_free (array); gcry_free (ctx->label); ctx->label = NULL; @@ -2473,7 +2128,7 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, else { *retarray = array; - *retalgo = module; + *r_spec = spec; *flags = parsed_flags; } @@ -2995,31 +2650,27 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) const char *algo_name, *algo_elems; struct pk_encoding_ctx ctx; gcry_err_code_t rc; - gcry_pk_spec_t *pubkey = NULL; - gcry_module_t module = NULL; + gcry_pk_spec_t *spec = NULL; *r_ciph = NULL; - REGISTER_DEFAULT_PUBKEYS; - /* Get the key. */ - rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_ENCR, NULL, &pkey, &module, NULL); + rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_ENCR, NULL, &pkey, &spec, NULL); if (rc) goto leave; - gcry_assert (module); - pubkey = (gcry_pk_spec_t *) module->spec; + gcry_assert (spec); /* If aliases for the algorithm name exists, take the first one instead of the regular name to adhere to SPKI conventions. We assume that the first alias name is the lowercase version of the regular one. This change is required for compatibility with 1.1.12 generated S-expressions. */ - algo_name = pubkey->aliases? *pubkey->aliases : NULL; + algo_name = spec->aliases? *spec->aliases : NULL; if (!algo_name || !*algo_name) - algo_name = pubkey->name; + algo_name = spec->name; - algo_elems = pubkey->elements_enc; + algo_elems = spec->elements_enc; /* Get the stuff we want to encrypt. */ init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey)); @@ -3034,7 +2685,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) rc = gpg_err_code_from_syserror (); goto leave; } - rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, ctx.flags); + rc = pubkey_encrypt (spec->algo, ciph, data, pkey, ctx.flags); mpi_free (data); data = NULL; if (rc) @@ -3120,18 +2771,12 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) gcry_free (ciph); } - if (module) - { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); - } - gcry_free (ctx.label); return gcry_error (rc); } + /* Do a PK decrypt operation @@ -3163,36 +2808,37 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) gcry_error_t gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) { - gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL; + gcry_err_code_t rc; + gcry_mpi_t *skey = NULL; + gcry_mpi_t *data = NULL; + gcry_mpi_t plain = NULL; unsigned char *unpad = NULL; size_t unpadlen = 0; int modern, flags; struct pk_encoding_ctx ctx; - gcry_err_code_t rc; - gcry_module_t module_enc = NULL, module_key = NULL; + gcry_pk_spec_t *spec_enc = NULL; + gcry_pk_spec_t *spec_key = NULL; *r_plain = NULL; ctx.label = NULL; - REGISTER_DEFAULT_PUBKEYS; - rc = sexp_to_key (s_skey, 1, GCRY_PK_USAGE_ENCR, NULL, - &skey, &module_key, NULL); + &skey, &spec_key, NULL); if (rc) goto leave; init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, gcry_pk_get_nbits (s_skey)); - rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &flags, &ctx); + rc = sexp_to_enc (s_data, &data, &spec_enc, &modern, &flags, &ctx); if (rc) goto leave; - if (module_key->mod_id != module_enc->mod_id) + if (spec_key->algo != spec_enc->algo) { rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */ goto leave; } - rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags); + rc = pubkey_decrypt (spec_key->algo, &plain, data, skey, flags); if (rc) goto leave; @@ -3245,16 +2891,6 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) gcry_free (data); } - if (module_key || module_enc) - { - ath_mutex_lock (&pubkeys_registered_lock); - if (module_key) - _gcry_module_release (module_key); - if (module_enc) - _gcry_module_release (module_enc); - ath_mutex_unlock (&pubkeys_registered_lock); - } - gcry_free (ctx.label); return gcry_error (rc); @@ -3293,9 +2929,10 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) gcry_error_t gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) { - gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL; - gcry_pk_spec_t *pubkey = NULL; - gcry_module_t module = NULL; + gcry_mpi_t *skey = NULL; + gcry_mpi_t hash = NULL; + gcry_mpi_t *result = NULL; + gcry_pk_spec_t *spec = NULL; const char *algo_name, *algo_elems; struct pk_encoding_ctx ctx; int i; @@ -3304,20 +2941,17 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) *r_sig = NULL; - REGISTER_DEFAULT_PUBKEYS; - rc = sexp_to_key (s_skey, 1, GCRY_PK_USAGE_SIGN, NULL, - &skey, &module, &is_ecc); + &skey, &spec, &is_ecc); if (rc) goto leave; - gcry_assert (module); - pubkey = (gcry_pk_spec_t *) module->spec; - algo_name = pubkey->aliases? *pubkey->aliases : NULL; + gcry_assert (spec); + algo_name = spec->aliases? *spec->aliases : NULL; if (!algo_name || !*algo_name) - algo_name = pubkey->name; + algo_name = spec->name; - algo_elems = pubkey->elements_sig; + algo_elems = spec->elements_sig; /* Get the stuff we want to sign. Note that pk_get_nbits does also work on a private key. We don't need the number of bits for ECC @@ -3334,7 +2968,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) rc = gpg_err_code_from_syserror (); goto leave; } - rc = pubkey_sign (module->mod_id, result, hash, skey, &ctx); + rc = pubkey_sign (spec->algo, result, hash, skey, &ctx); if (rc) goto leave; @@ -3443,15 +3077,16 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) gcry_error_t gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) { - gcry_module_t module_key = NULL, module_sig = NULL; - gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL; - struct pk_encoding_ctx ctx; gcry_err_code_t rc; - - REGISTER_DEFAULT_PUBKEYS; + gcry_pk_spec_t *spec_key = NULL; + gcry_pk_spec_t *spec_sig = NULL; + gcry_mpi_t *pkey = NULL; + gcry_mpi_t hash = NULL; + gcry_mpi_t *sig = NULL; + struct pk_encoding_ctx ctx; rc = sexp_to_key (s_pkey, 0, GCRY_PK_USAGE_SIGN, NULL, - &pkey, &module_key, NULL); + &pkey, &spec_key, NULL); if (rc) goto leave; @@ -3462,20 +3097,20 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) goto leave; /* Get the signature. */ - rc = sexp_to_sig (s_sig, &sig, &module_sig, + rc = sexp_to_sig (s_sig, &sig, &spec_sig, !!(ctx.flags & PUBKEY_FLAG_EDDSA)); if (rc) goto leave; /* Fixme: Check that the algorithm of S_SIG is compatible to the one of S_PKEY. */ - if (module_key->mod_id != module_sig->mod_id) + if (spec_key->algo != spec_sig->algo) { rc = GPG_ERR_CONFLICT; goto leave; } - rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, &ctx); + rc = pubkey_verify (spec_key->algo, hash, sig, pkey, &ctx); leave: if (pkey) @@ -3491,16 +3126,6 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) if (hash) mpi_free (hash); - if (module_key || module_sig) - { - ath_mutex_lock (&pubkeys_registered_lock); - if (module_key) - _gcry_module_release (module_key); - if (module_sig) - _gcry_module_release (module_sig); - ath_mutex_unlock (&pubkeys_registered_lock); - } - return gcry_error (rc); } @@ -3517,17 +3142,15 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) gcry_error_t gcry_pk_testkey (gcry_sexp_t s_key) { - gcry_module_t module = NULL; + gcry_pk_spec_t *spec = NULL; gcry_mpi_t *key = NULL; gcry_err_code_t rc; - REGISTER_DEFAULT_PUBKEYS; - /* Note we currently support only secret key checking. */ - rc = sexp_to_key (s_key, 1, 0, NULL, &key, &module, NULL); - if (! rc) + rc = sexp_to_key (s_key, 1, 0, NULL, &key, &spec, NULL); + if (!rc) { - rc = pubkey_check_secret_key (module->mod_id, key); + rc = pubkey_check_secret_key (spec->algo, key); release_mpi_array (key); gcry_free (key); } @@ -3571,8 +3194,7 @@ gcry_pk_testkey (gcry_sexp_t s_key) gcry_error_t gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) { - gcry_pk_spec_t *pubkey = NULL; - gcry_module_t module = NULL; + gcry_pk_spec_t *spec = NULL; gcry_sexp_t list = NULL; gcry_sexp_t l2 = NULL; gcry_sexp_t l3 = NULL; @@ -3581,7 +3203,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) gcry_err_code_t rc = GPG_ERR_NO_ERROR; int i, j; const char *algo_name = NULL; - int algo; const char *sec_elems = NULL, *pub_elems = NULL; gcry_mpi_t skey[12]; gcry_mpi_t *factors = NULL; @@ -3592,8 +3213,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) skey[0] = NULL; *r_key = NULL; - REGISTER_DEFAULT_PUBKEYS; - list = gcry_sexp_find_token (s_parms, "genkey", 0); if (!list) { @@ -3618,24 +3237,20 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) goto leave; } - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name (name); - ath_mutex_unlock (&pubkeys_registered_lock); + spec = spec_from_name (name); gcry_free (name); name = NULL; - if (!module) + if (!spec) { rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ goto leave; } - pubkey = (gcry_pk_spec_t *) module->spec; - algo = module->mod_id; - algo_name = pubkey->aliases? *pubkey->aliases : NULL; + algo_name = spec->aliases? *spec->aliases : NULL; if (!algo_name || !*algo_name) - algo_name = pubkey->name; - pub_elems = pubkey->elements_pkey; - sec_elems = pubkey->elements_skey; + algo_name = spec->name; + pub_elems = spec->elements_pkey; + sec_elems = spec->elements_skey; if (strlen (sec_elems) >= DIM(skey)) BUG (); @@ -3686,7 +3301,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) nbits = 0; /* Pass control to the algorithm module. */ - rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey, + rc = pubkey_generate (spec->algo, nbits, use_e, list, skey, &factors, &extrainfo); gcry_sexp_release (list); list = NULL; if (rc) @@ -3735,7 +3350,8 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) p = stpcpy (p, "%m)"); mpis[nelem++] = skey[i]; } - if (extrainfo && (algo == GCRY_PK_ECDSA || algo == GCRY_PK_ECDH)) + if (extrainfo + && (spec->algo == GCRY_PK_ECDSA || spec->algo == GCRY_PK_ECDH)) { /* Very ugly hack to insert the used curve parameter into the list of public key parameters. */ @@ -3752,7 +3368,8 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) p = stpcpy (p, "%m)"); mpis[nelem++] = skey[i]; } - if (extrainfo && (algo == GCRY_PK_ECDSA || algo == GCRY_PK_ECDH)) + if (extrainfo + && (spec->algo == GCRY_PK_ECDSA || spec->algo == GCRY_PK_ECDH)) { percent_s_idx2 = nelem++; p = stpcpy (p, "%S"); @@ -3845,13 +3462,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) gcry_sexp_release (l2); gcry_sexp_release (list); - if (module) - { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); - } - return gcry_error (rc); } @@ -3864,30 +3474,22 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) unsigned int gcry_pk_get_nbits (gcry_sexp_t key) { - gcry_module_t module = NULL; - gcry_pk_spec_t *pubkey; + gcry_pk_spec_t *spec; gcry_mpi_t *keyarr = NULL; unsigned int nbits = 0; gcry_err_code_t rc; - REGISTER_DEFAULT_PUBKEYS; - /* FIXME: Parsing KEY is often too much overhead. For example for ECC we would only need to look at P and stop parsing right away. */ - rc = sexp_to_key (key, 0, 0, NULL, &keyarr, &module, NULL); + rc = sexp_to_key (key, 0, 0, NULL, &keyarr, &spec, NULL); if (rc == GPG_ERR_INV_OBJ) - rc = sexp_to_key (key, 1, 0, NULL, &keyarr, &module, NULL); + rc = sexp_to_key (key, 1, 0, NULL, &keyarr, &spec, NULL); if (rc) return 0; /* Error - 0 is a suitable indication for that. */ - pubkey = (gcry_pk_spec_t *) module->spec; - nbits = (*pubkey->get_nbits) (module->mod_id, keyarr); - - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); + nbits = spec->get_nbits (spec->algo, keyarr); release_mpi_array (keyarr); gcry_free (keyarr); @@ -3906,9 +3508,9 @@ gcry_pk_get_nbits (gcry_sexp_t key) unsigned char * gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) { - gcry_sexp_t list = NULL, l2 = NULL; - gcry_pk_spec_t *pubkey = NULL; - gcry_module_t module = NULL; + gcry_sexp_t list = NULL; + gcry_sexp_t l2 = NULL; + gcry_pk_spec_t *spec = NULL; const char *s; char *name = NULL; int idx; @@ -3916,8 +3518,6 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) gcry_md_hd_t md = NULL; int okay = 0; - REGISTER_DEFAULT_PUBKEYS; - /* Check that the first element is valid. */ list = gcry_sexp_find_token (key, "public-key", 0); if (! list) @@ -3938,26 +3538,21 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) if (!name) goto fail; /* Invalid structure of object. */ - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name (name); - ath_mutex_unlock (&pubkeys_registered_lock); - - if (!module) + spec = spec_from_name (name); + if (!spec) goto fail; /* Unknown algorithm. */ - pubkey = (gcry_pk_spec_t *) module->spec; - - elems = pubkey->elements_grip; + elems = spec->elements_grip; if (!elems) goto fail; /* No grip parameter. */ if (gcry_md_open (&md, GCRY_MD_SHA1, 0)) goto fail; - if (pubkey->comp_keygrip) + if (spec->comp_keygrip) { /* Module specific method to compute a keygrip. */ - if (pubkey->comp_keygrip (md, list)) + if (spec->comp_keygrip (md, list)) goto fail; } else @@ -4011,17 +3606,14 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) gcry_mpi_t *pkey = NULL; gcry_sexp_t list = NULL; gcry_sexp_t l2; - gcry_module_t module = NULL; char *name = NULL; const char *result = NULL; int want_private = 1; - gcry_pk_spec_t *spec; + gcry_pk_spec_t *spec = NULL; if (r_nbits) *r_nbits = 0; - REGISTER_DEFAULT_PUBKEYS; - if (key) { iterator = 0; @@ -4047,19 +3639,16 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) /* Get the key. We pass the names of the parameters for override_elems; this allows to call this function without the actual public key parameter. */ - if (sexp_to_key (key, want_private, 0, "pabgn", &pkey, &module, NULL)) + if (sexp_to_key (key, want_private, 0, "pabgn", &pkey, &spec, NULL)) goto leave; } else { - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name ("ecc"); - ath_mutex_unlock (&pubkeys_registered_lock); - if (!module) + spec = spec_from_name ("ecc"); + if (!spec) goto leave; } - spec = module->spec; if (!spec || !spec->get_curve) goto leave; @@ -4071,12 +3660,6 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) release_mpi_array (pkey); gcry_free (pkey); } - if (module) - { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); - } gcry_free (name); gcry_sexp_release (list); return result; @@ -4087,27 +3670,17 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) gcry_sexp_t gcry_pk_get_param (int algo, const char *name) { - gcry_module_t module = NULL; gcry_sexp_t result = NULL; - gcry_pk_spec_t *spec; + gcry_pk_spec_t *spec = NULL; if (algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH) return NULL; - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pk_lookup_name ("ecc"); - ath_mutex_unlock (&pubkeys_registered_lock); - if (module) + spec = spec_from_name ("ecc"); + if (spec) { - spec = module->spec; if (spec && spec->get_curve_param) result = spec->get_curve_param (name); - - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); } return result; } @@ -4119,8 +3692,6 @@ gcry_pk_ctl (int cmd, void *buffer, size_t buflen) { gcry_err_code_t err = GPG_ERR_NO_ERROR; - REGISTER_DEFAULT_PUBKEYS; - switch (cmd) { case GCRYCTL_DISABLE_ALGO: @@ -4180,23 +3751,10 @@ gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) case GCRYCTL_GET_ALGO_USAGE: { - gcry_module_t pubkey; - int use = 0; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); - if (pubkey) - { - use = ((gcry_pk_spec_t *) pubkey->spec)->use; - _gcry_module_release (pubkey); - } - ath_mutex_unlock (&pubkeys_registered_lock); - - /* FIXME? */ - *nbytes = use; + gcry_pk_spec_t *spec; + spec = spec_from_algo (algorithm); + *nbytes = spec? spec->use : 0; break; } @@ -4283,15 +3841,7 @@ _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx) gcry_err_code_t _gcry_pk_init (void) { - gcry_err_code_t err; - - err = ath_mutex_init (&pubkeys_registered_lock); - if (err) - return gpg_err_code_from_errno (err); - - REGISTER_DEFAULT_PUBKEYS; - - return err; + return 0; } @@ -4300,18 +3850,9 @@ _gcry_pk_init (void) gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { - gcry_module_t module = NULL; - gcry_err_code_t ec = 0; - gcry_pk_spec_t *spec = NULL; - - REGISTER_DEFAULT_PUBKEYS; + gcry_err_code_t ec; + gcry_pk_spec_t *spec = spec_from_algo (algo); - ath_mutex_lock (&pubkeys_registered_lock); - module = _gcry_module_lookup_id (pubkeys_registered, algo); - if (module && !(module->flags & FLAG_MODULE_DISABLED)) - spec = module->spec; - - ath_mutex_unlock (&pubkeys_registered_lock); if (spec && spec->selftest) ec = spec->selftest (algo, extended, report); else @@ -4319,16 +3860,11 @@ _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) ec = GPG_ERR_PUBKEY_ALGO; if (report) report ("pubkey", algo, "module", - module && !(module->flags & FLAG_MODULE_DISABLED)? + spec && !spec->flags.disabled? "no selftest available" : - module? "algorithm disabled" : "algorithm not found"); + spec? "algorithm disabled" : + "algorithm not found"); } - if (module) - { - ath_mutex_lock (&pubkeys_registered_lock); - _gcry_module_release (module); - ath_mutex_unlock (&pubkeys_registered_lock); - } return gpg_error (ec); } diff --git a/cipher/rsa.c b/cipher/rsa.c index f4d3ca1..e495cd8 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -1382,9 +1382,10 @@ static const char *rsa_names[] = gcry_pk_spec_t _gcry_pubkey_spec_rsa = { + GCRY_PK_RSA, { 0, 1 }, + (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), "RSA", rsa_names, "ne", "nedpqu", "a", "s", "n", - GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, rsa_generate, rsa_check_secret_key, rsa_encrypt, diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index fd7680e..4c1485c 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2589,8 +2589,10 @@ operations. @var{cmd} controls what is to be done. The return value is @table @code @item GCRYCTL_DISABLE_ALGO Disable the algorithm given as an algorithm id in @var{buffer}. - at var{buffer} must point to an @code{int} variable with the algorithm id -and @var{buflen} must have the value @code{sizeof (int)}. + at var{buffer} must point to an @code{int} variable with the algorithm +id and @var{buflen} must have the value @code{sizeof (int)}. This +fucntion is not thread safe and should thus be used before any other +threads are started. @end table @end deftypefun diff --git a/src/cipher-proto.h b/src/cipher-proto.h index eec3d35..a641a07 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -122,6 +122,12 @@ typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); /* Module specification structure for public key algoritms. */ typedef struct gcry_pk_spec { + int algo; + struct { + unsigned int disabled:1; + unsigned int fips:1; + } flags; + int use; const char *name; const char **aliases; const char *elements_pkey; @@ -129,7 +135,6 @@ typedef struct gcry_pk_spec const char *elements_enc; const char *elements_sig; const char *elements_grip; - int use; gcry_pk_generate_t generate; gcry_pk_check_secret_key_t check_secret_key; gcry_pk_encrypt_t encrypt; @@ -181,9 +186,6 @@ gcry_error_t _gcry_md_register (gcry_md_spec_t *cipher, md_extra_spec_t *extraspec, unsigned int *algorithm_id, gcry_module_t *module); -gcry_error_t _gcry_pk_register (gcry_pk_spec_t *cipher, - unsigned int *algorithm_id, - gcry_module_t *module); /* The selftest functions. */ gcry_error_t _gcry_cipher_selftest (int algo, int extended, diff --git a/src/cipher.h b/src/cipher.h index 7f10aee..8d3afbf 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -237,6 +237,7 @@ extern md_extra_spec_t _gcry_digest_extraspec_sha512; /* Declarations for the pubkey cipher specifications. */ extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; extern gcry_pk_spec_t _gcry_pubkey_spec_elg; +extern gcry_pk_spec_t _gcry_pubkey_spec_elg_e; extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; commit 89103ce00e862cc709e80fa41f2ee13d54093ec5 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 pk: Merge extraspecs struct with standard specs struct. * src/gcrypt-module.h (gcry_pk_spec_t): Move this typedef and the corresponding function typedefs to ... * src/cipher-proto.h: here. (pk_extra_spec_t): Remove typedef and merge fields into gcry_pk_spec_t. * cipher/rsa.c, cipher/dsa.c, cipher/elg.c, cipher/ecc.c: Ditto. * cipher/pubkey.c: Change accordingly. * src/cipher.h (_gcry_pubkey_extraspec_rsa): Remove. (_gcry_pubkey_extraspec_dsa): Remove. (_gcry_pubkey_extraspec_elg): Remove. (_gcry_pubkey_extraspec_ecdsa): Remove. -- Now that we don't have loadable modules anymore, we don't need to keep the internal API between the modules and thus can simplify the code. Signed-off-by: Werner Koch diff --git a/cipher/dsa.c b/cipher/dsa.c index 3a64dda..4a7ceee 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -1214,10 +1214,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa = NULL, dsa_sign, dsa_verify, - dsa_get_nbits - }; -pk_extra_spec_t _gcry_pubkey_extraspec_dsa = - { + dsa_get_nbits, run_selftests, dsa_generate_ext }; diff --git a/cipher/ecc.c b/cipher/ecc.c index 9766e9e..5340d57 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -2012,7 +2012,13 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = NULL, ecc_sign, ecc_verify, - ecc_get_nbits + ecc_get_nbits, + run_selftests, + ecc_generate_ext, + compute_keygrip, + _gcry_ecc_get_param, + _gcry_ecc_get_curve, + _gcry_ecc_get_param_sexp }; gcry_pk_spec_t _gcry_pubkey_spec_ecdh = @@ -2026,12 +2032,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdh = ecc_decrypt_raw, NULL, NULL, - ecc_get_nbits - }; - - -pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = - { + ecc_get_nbits, run_selftests, ecc_generate_ext, compute_keygrip, diff --git a/cipher/elgamal.c b/cipher/elgamal.c index d105cb4..44990aa 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -849,12 +849,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_elg = elg_decrypt, elg_sign, elg_verify, - elg_get_nbits - }; - -pk_extra_spec_t _gcry_pubkey_extraspec_elg = - { + elg_get_nbits, NULL, - elg_generate_ext, - NULL + elg_generate_ext }; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 8fa7ebf..5be6b85 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -44,44 +44,31 @@ static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, struct pk_encoding_ctx *ctx); -/* A dummy extraspec so that we do not need to tests the extraspec - field from the module specification against NULL and instead - directly test the respective fields of extraspecs. */ -static pk_extra_spec_t dummy_extra_spec; - - /* This is the list of the default public-key ciphers included in libgcrypt. FIPS_ALLOWED indicated whether the algorithm is used in FIPS mode. */ static struct pubkey_table_entry { gcry_pk_spec_t *pubkey; - pk_extra_spec_t *extraspec; unsigned int algorithm; int fips_allowed; } pubkey_table[] = { #if USE_RSA - { &_gcry_pubkey_spec_rsa, - &_gcry_pubkey_extraspec_rsa, GCRY_PK_RSA, 1}, + { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA, 1}, #endif #if USE_ELGAMAL - { &_gcry_pubkey_spec_elg, - &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG }, - { &_gcry_pubkey_spec_elg, - &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG_E }, + { &_gcry_pubkey_spec_elg, GCRY_PK_ELG }, + { &_gcry_pubkey_spec_elg, GCRY_PK_ELG_E }, #endif #if USE_DSA - { &_gcry_pubkey_spec_dsa, - &_gcry_pubkey_extraspec_dsa, GCRY_PK_DSA, 1 }, + { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA, 1 }, #endif #if USE_ECC - { &_gcry_pubkey_spec_ecdsa, - &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 }, - { &_gcry_pubkey_spec_ecdh, - &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDH, 0 }, + { &_gcry_pubkey_spec_ecdsa, GCRY_PK_ECDSA, 0 }, + { &_gcry_pubkey_spec_ecdh, GCRY_PK_ECDH, 0 }, #endif - { NULL, 0 }, + { NULL, 0 } }; /* List of registered ciphers. */ @@ -228,7 +215,7 @@ pk_register_default (void) err = _gcry_module_add (&pubkeys_registered, pubkey_table[i].algorithm, (void *) pubkey_table[i].pubkey, - (void *) pubkey_table[i].extraspec, + NULL, NULL); } @@ -268,7 +255,6 @@ gcry_pk_lookup_name (const char *name) and a pointer representhing this module is stored in MODULE. */ gcry_error_t _gcry_pk_register (gcry_pk_spec_t *pubkey, - pk_extra_spec_t *extraspec, unsigned int *algorithm_id, gcry_module_t *module) { @@ -282,7 +268,7 @@ _gcry_pk_register (gcry_pk_spec_t *pubkey, ath_mutex_lock (&pubkeys_registered_lock); err = _gcry_module_add (&pubkeys_registered, 0, (void *) pubkey, - (void *)(extraspec? extraspec : &dummy_extra_spec), + NULL, &mod); ath_mutex_unlock (&pubkeys_registered_lock); @@ -566,12 +552,11 @@ pubkey_generate (int algorithm, pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); if (pubkey) { - pk_extra_spec_t *extraspec = pubkey->extraspec; - - if (extraspec && extraspec->ext_generate) + if (((gcry_pk_spec_t *) pubkey->spec)->ext_generate) { + /* Use the extended generate function. */ - ec = extraspec->ext_generate + ec = ((gcry_pk_spec_t *) pubkey->spec)->ext_generate (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo); } else @@ -1877,7 +1862,7 @@ sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, of its intimate knowledge about the ECC parameters from ecc.c. */ static gcry_err_code_t sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, - gcry_mpi_t *elements, pk_extra_spec_t *extraspec, + gcry_mpi_t *elements, gcry_pk_spec_t *spec, int want_private) { @@ -1927,7 +1912,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, list = gcry_sexp_find_token (key_sexp, "curve", 5); if (list) { - if (extraspec->get_param) + if (spec->get_param) { char *curve; gcry_mpi_t params[6]; @@ -1943,7 +1928,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, err = GPG_ERR_INV_OBJ; goto leave; } - err = extraspec->get_param (curve, params); + err = spec->get_param (curve, params); gcry_free (curve); if (err) goto leave; @@ -2038,7 +2023,6 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, gcry_mpi_t *array; gcry_module_t module; gcry_pk_spec_t *pubkey; - pk_extra_spec_t *extraspec; int is_ecc; /* Check that the first element is valid. If we are looking for a @@ -2097,7 +2081,6 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, else { pubkey = (gcry_pk_spec_t *) module->spec; - extraspec = module->extraspec; } if (override_elems) @@ -2112,7 +2095,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, int use, if (!err) { if (is_ecc) - err = sexp_elements_extract_ecc (list, elems, array, extraspec, + err = sexp_elements_extract_ecc (list, elems, array, pubkey, want_private); else err = sexp_elements_extract (list, elems, array, pubkey->name, 0); @@ -3926,7 +3909,6 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) gcry_sexp_t list = NULL, l2 = NULL; gcry_pk_spec_t *pubkey = NULL; gcry_module_t module = NULL; - pk_extra_spec_t *extraspec; const char *s; char *name = NULL; int idx; @@ -3964,7 +3946,6 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) goto fail; /* Unknown algorithm. */ pubkey = (gcry_pk_spec_t *) module->spec; - extraspec = module->extraspec; elems = pubkey->elements_grip; if (!elems) @@ -3973,10 +3954,10 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) if (gcry_md_open (&md, GCRY_MD_SHA1, 0)) goto fail; - if (extraspec && extraspec->comp_keygrip) + if (pubkey->comp_keygrip) { /* Module specific method to compute a keygrip. */ - if (extraspec->comp_keygrip (md, list)) + if (pubkey->comp_keygrip (md, list)) goto fail; } else @@ -4031,10 +4012,10 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) gcry_sexp_t list = NULL; gcry_sexp_t l2; gcry_module_t module = NULL; - pk_extra_spec_t *extraspec; char *name = NULL; const char *result = NULL; int want_private = 1; + gcry_pk_spec_t *spec; if (r_nbits) *r_nbits = 0; @@ -4078,11 +4059,11 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) goto leave; } - extraspec = module->extraspec; - if (!extraspec || !extraspec->get_curve) + spec = module->spec; + if (!spec || !spec->get_curve) goto leave; - result = extraspec->get_curve (pkey, iterator, r_nbits); + result = spec->get_curve (pkey, iterator, r_nbits); leave: if (pkey) @@ -4107,8 +4088,8 @@ gcry_sexp_t gcry_pk_get_param (int algo, const char *name) { gcry_module_t module = NULL; - pk_extra_spec_t *extraspec; gcry_sexp_t result = NULL; + gcry_pk_spec_t *spec; if (algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH) return NULL; @@ -4120,9 +4101,9 @@ gcry_pk_get_param (int algo, const char *name) ath_mutex_unlock (&pubkeys_registered_lock); if (module) { - extraspec = module->extraspec; - if (extraspec && extraspec->get_curve_param) - result = extraspec->get_curve_param (name); + spec = module->spec; + if (spec && spec->get_curve_param) + result = spec->get_curve_param (name); ath_mutex_lock (&pubkeys_registered_lock); _gcry_module_release (module); @@ -4320,18 +4301,19 @@ gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { gcry_module_t module = NULL; - pk_extra_spec_t *extraspec = NULL; gcry_err_code_t ec = 0; + gcry_pk_spec_t *spec = NULL; REGISTER_DEFAULT_PUBKEYS; ath_mutex_lock (&pubkeys_registered_lock); module = _gcry_module_lookup_id (pubkeys_registered, algo); if (module && !(module->flags & FLAG_MODULE_DISABLED)) - extraspec = module->extraspec; + spec = module->spec; + ath_mutex_unlock (&pubkeys_registered_lock); - if (extraspec && extraspec->selftest) - ec = extraspec->selftest (algo, extended, report); + if (spec && spec->selftest) + ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_PUBKEY_ALGO; diff --git a/cipher/rsa.c b/cipher/rsa.c index e7c880d..f4d3ca1 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -1392,9 +1392,6 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa = rsa_sign, rsa_verify, rsa_get_nbits, - }; -pk_extra_spec_t _gcry_pubkey_extraspec_rsa = - { run_selftests, rsa_generate_ext, compute_keygrip diff --git a/src/cipher-proto.h b/src/cipher-proto.h index e9f4bab..eec3d35 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -23,6 +23,8 @@ #ifndef G10_CIPHER_PROTO_H #define G10_CIPHER_PROTO_H + + /* Definition of a function used to report selftest failures. DOMAIN is a string describing the function block: "cipher", "digest", "pubkey or "random", @@ -38,24 +40,76 @@ typedef void (*selftest_report_func_t)(const char *domain, typedef gpg_err_code_t (*selftest_func_t) (int algo, int extended, selftest_report_func_t report); + +/* + * + * Public key related definitions. + * + */ + +/* Type for the pk_generate function. */ +typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo, + unsigned int nbits, + unsigned long use_e, + gcry_mpi_t *skey, + gcry_mpi_t **retfactors); +/* Type for the extended generate function. */ +typedef gcry_err_code_t (*pk_ext_generate_t) (int algo, + unsigned int nbits, + unsigned long evalue, + gcry_sexp_t genparms, + gcry_mpi_t *skey, + gcry_mpi_t **retfactors, + gcry_sexp_t *extrainfo); + +/* Type for the pk_check_secret_key function. */ +typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, + gcry_mpi_t *skey); + +/* Type for the pk_encrypt function. */ +typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, + gcry_mpi_t *resarr, + gcry_mpi_t data, + gcry_mpi_t *pkey, + int flags); + +/* Type for the pk_decrypt function. */ +typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, + gcry_mpi_t *result, + gcry_mpi_t *data, + gcry_mpi_t *skey, + int flags); + +/* Type for the pk_sign function. */ +typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo, + gcry_mpi_t *resarr, + gcry_mpi_t data, + gcry_mpi_t *skey, + int flags, + int hashalgo); + +/* Type for the pk_verify function. */ +typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo, + gcry_mpi_t hash, + gcry_mpi_t *data, + gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), + void *opaquev, + int flags, + int hashalgo); + +/* Type for the pk_get_nbits function. */ +typedef unsigned (*gcry_pk_get_nbits_t) (int algo, + gcry_mpi_t *pkey); -/* An extended type of the generate function. */ -typedef gcry_err_code_t (*pk_ext_generate_t) - (int algo, - unsigned int nbits, - unsigned long evalue, - gcry_sexp_t genparms, - gcry_mpi_t *skey, - gcry_mpi_t **retfactors, - gcry_sexp_t *extrainfo); /* The type used to compute the keygrip. */ -typedef gpg_err_code_t (*pk_comp_keygrip_t) - (gcry_md_hd_t md, gcry_sexp_t keyparm); +typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md, + gcry_sexp_t keyparm); /* The type used to query ECC curve parameters. */ -typedef gcry_err_code_t (*pk_get_param_t) - (const char *name, gcry_mpi_t *pkey); +typedef gcry_err_code_t (*pk_get_param_t) (const char *name, + gcry_mpi_t *pkey); /* The type used to query an ECC curve name. */ typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator, @@ -64,6 +118,35 @@ typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator, /* The type used to query ECC curve parameters by name. */ typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); + +/* Module specification structure for public key algoritms. */ +typedef struct gcry_pk_spec +{ + const char *name; + const char **aliases; + const char *elements_pkey; + const char *elements_skey; + const char *elements_enc; + const char *elements_sig; + const char *elements_grip; + int use; + gcry_pk_generate_t generate; + gcry_pk_check_secret_key_t check_secret_key; + gcry_pk_encrypt_t encrypt; + gcry_pk_decrypt_t decrypt; + gcry_pk_sign_t sign; + gcry_pk_verify_t verify; + gcry_pk_get_nbits_t get_nbits; + selftest_func_t selftest; + pk_ext_generate_t ext_generate; + pk_comp_keygrip_t comp_keygrip; + pk_get_param_t get_param; + pk_get_curve_t get_curve; + pk_get_curve_param_t get_curve_param; +} gcry_pk_spec_t; + + + /* The type used to convey additional information to a cipher. */ typedef gpg_err_code_t (*cipher_set_extra_info_t) (void *c, int what, const void *buffer, size_t buflen); @@ -87,16 +170,6 @@ typedef struct md_extra_spec selftest_func_t selftest; } md_extra_spec_t; -typedef struct pk_extra_spec -{ - selftest_func_t selftest; - pk_ext_generate_t ext_generate; - pk_comp_keygrip_t comp_keygrip; - pk_get_param_t get_param; - pk_get_curve_t get_curve; - pk_get_curve_param_t get_curve_param; -} pk_extra_spec_t; - /* The private register functions. */ @@ -109,7 +182,6 @@ gcry_error_t _gcry_md_register (gcry_md_spec_t *cipher, unsigned int *algorithm_id, gcry_module_t *module); gcry_error_t _gcry_pk_register (gcry_pk_spec_t *cipher, - pk_extra_spec_t *extraspec, unsigned int *algorithm_id, gcry_module_t *module); diff --git a/src/cipher.h b/src/cipher.h index dffd081..7f10aee 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -241,10 +241,5 @@ extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; -extern pk_extra_spec_t _gcry_pubkey_extraspec_rsa; -extern pk_extra_spec_t _gcry_pubkey_extraspec_dsa; -extern pk_extra_spec_t _gcry_pubkey_extraspec_elg; -extern pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa; - #endif /*G10_CIPHER_H*/ diff --git a/src/gcrypt-module.h b/src/gcrypt-module.h index 75ca8ab..9fcb8ab 100644 --- a/src/gcrypt-module.h +++ b/src/gcrypt-module.h @@ -98,73 +98,6 @@ typedef struct gcry_cipher_spec /* ********************** */ -/* Type for the pk_generate function. */ -typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo, - unsigned int nbits, - unsigned long use_e, - gcry_mpi_t *skey, - gcry_mpi_t **retfactors); - -/* Type for the pk_check_secret_key function. */ -typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, - gcry_mpi_t *skey); - -/* Type for the pk_encrypt function. */ -typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, - gcry_mpi_t *resarr, - gcry_mpi_t data, - gcry_mpi_t *pkey, - int flags); - -/* Type for the pk_decrypt function. */ -typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, - gcry_mpi_t *result, - gcry_mpi_t *data, - gcry_mpi_t *skey, - int flags); - -/* Type for the pk_sign function. */ -typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo, - gcry_mpi_t *resarr, - gcry_mpi_t data, - gcry_mpi_t *skey, - int flags, - int hashalgo); - -/* Type for the pk_verify function. */ -typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo, - gcry_mpi_t hash, - gcry_mpi_t *data, - gcry_mpi_t *pkey, - int (*cmp) (void *, gcry_mpi_t), - void *opaquev, - int flags, - int hashalgo); - -/* Type for the pk_get_nbits function. */ -typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey); - -/* Module specification structure for message digests. */ -typedef struct gcry_pk_spec -{ - const char *name; - const char **aliases; - const char *elements_pkey; - const char *elements_skey; - const char *elements_enc; - const char *elements_sig; - const char *elements_grip; - int use; - gcry_pk_generate_t generate; - gcry_pk_check_secret_key_t check_secret_key; - gcry_pk_encrypt_t encrypt; - gcry_pk_decrypt_t decrypt; - gcry_pk_sign_t sign; - gcry_pk_verify_t verify; - gcry_pk_get_nbits_t get_nbits; -} gcry_pk_spec_t; - - /* ********************** */ /* Type for the md_init function. */ ----------------------------------------------------------------------- Summary of changes: NEWS | 1 + cipher/dsa.c | 8 +- cipher/ecc.c | 21 +- cipher/elgamal.c | 23 +- cipher/pubkey.c | 1054 ++++++++++++++------------------------------------- cipher/rsa.c | 6 +- doc/gcrypt.texi | 6 +- src/cipher-proto.h | 128 +++++-- src/cipher.h | 6 +- src/gcrypt-module.h | 67 ---- 10 files changed, 428 insertions(+), 892 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Sep 20 18:15:03 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 20 Sep 2013 18:15:03 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-256-g722bfc1 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 722bfc1e5f2268453db62f38cc46b5ec6ef3adee (commit) via 64cd7ab93da7c95cc8aa320c61c6e29f9e2399c4 (commit) from 6576f0a7684292cb5691bfcabad0acca4c06c014 (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 722bfc1e5f2268453db62f38cc46b5ec6ef3adee Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 pk: Move s-exp creation for gcry_pk_decrypt to the modules. * cipher/pubkey.c (sexp_to_enc): Remove RET_MODERN arg and merge it into FLAGS. (gcry_pk_decrypt): Move result s-exp building into the modules. * src/cipher-proto.h (gcry_pk_decrypt_t): Add some args. * cipher/ecc.c (ecc_decrypt_raw): Change to return an s-exp. * cipher/elgamal.c (elg_decrypt): Ditto. * cipher/rsa.c (rsa_decrypt): Ditto. (rsa_blind, rsa_unblind): Merge into rsa_decrypt. This saves several extra MPI allocations. -- The extra args added to gcry_pk_decrypt_t are a temporary solution unti we move the input s-exp parsing also into the modules. Signed-off-by: Werner Koch diff --git a/cipher/ecc.c b/cipher/ecc.c index 9a9c21b..cf054f8 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1661,20 +1661,24 @@ ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k, * see ecc_encrypt_raw for details. */ static gcry_err_code_t -ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, - gcry_mpi_t *skey, int flags) +ecc_decrypt_raw (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags, + enum pk_encoding encoding, int hash_algo, + unsigned char *label, size_t labellen) { + gpg_err_code_t rc; ECC_secret_key sk; mpi_point_struct R; /* Result that we return. */ mpi_point_struct kG; mpi_ec_t ctx; gcry_mpi_t r; - int err; (void)algo; (void)flags; - - *result = NULL; + (void)encoding; + (void)hash_algo; + (void)label; + (void)labellen; if (!data || !data[0] || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] @@ -1682,11 +1686,11 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, return GPG_ERR_BAD_MPI; point_init (&kG); - err = _gcry_ecc_os2ec (&kG, data[0]); - if (err) + rc = _gcry_ecc_os2ec (&kG, data[0]); + if (rc) { point_free (&kG); - return err; + return rc; } sk.E.model = MPI_EC_WEIERSTRASS; @@ -1694,22 +1698,22 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, sk.E.a = skey[1]; sk.E.b = skey[2]; point_init (&sk.E.G); - err = _gcry_ecc_os2ec (&sk.E.G, skey[3]); - if (err) + rc = _gcry_ecc_os2ec (&sk.E.G, skey[3]); + if (rc) { point_free (&kG); point_free (&sk.E.G); - return err; + return rc; } sk.E.n = skey[4]; point_init (&sk.Q); - err = _gcry_ecc_os2ec (&sk.Q, skey[5]); - if (err) + rc = _gcry_ecc_os2ec (&sk.Q, skey[5]); + if (rc) { point_free (&kG); point_free (&sk.E.G); point_free (&sk.Q); - return err; + return rc; } sk.d = skey[6]; @@ -1733,6 +1737,10 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, log_fatal ("ecdh: Failed to get affine coordinates\n"); r = _gcry_ecc_ec2os (x, y, sk.E.p); + if (!r) + rc = gpg_err_code_from_syserror (); + else + rc = 0; mpi_free (x); mpi_free (y); } @@ -1743,14 +1751,10 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, point_free (&sk.E.G); point_free (&sk.Q); - if (!r) - return GPG_ERR_ENOMEM; - - /* Success. */ - - *result = r; - - return 0; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %m)", r)); + mpi_free (r); + return rc; } diff --git a/cipher/elgamal.c b/cipher/elgamal.c index c2a953b..ecbac75 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -30,6 +30,8 @@ #include "g10lib.h" #include "mpi.h" #include "cipher.h" +#include "pubkey-internal.h" + typedef struct { @@ -777,28 +779,73 @@ elg_encrypt (int algo, gcry_sexp_t *r_result, static gcry_err_code_t -elg_decrypt (int algo, gcry_mpi_t *result, - gcry_mpi_t *data, gcry_mpi_t *skey, int flags) +elg_decrypt (int algo, gcry_sexp_t *r_plain, + gcry_mpi_t *data, gcry_mpi_t *skey, int flags, + enum pk_encoding encoding, int hash_algo, + unsigned char *label, size_t labellen) { - gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_err_code_t rc; ELG_secret_key sk; + gcry_mpi_t plain; (void)algo; - (void)flags; if ((! data[0]) || (! data[1]) || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) - err = GPG_ERR_BAD_MPI; + rc = GPG_ERR_BAD_MPI; else { + unsigned char *unpad = NULL; + size_t unpadlen = 0; + unsigned int nbits; + sk.p = skey[0]; sk.g = skey[1]; sk.y = skey[2]; sk.x = skey[3]; - *result = mpi_alloc_secure (mpi_get_nlimbs (sk.p)); - decrypt (*result, data[0], data[1], &sk); + + nbits = gcry_mpi_get_nbits (sk.p); + + plain = mpi_snew (nbits); + decrypt (plain, data[0], data[1], &sk); + + /* Reverse the encoding and build the s-expression. */ + switch (encoding) + { + case PUBKEY_ENC_PKCS1: + rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + case PUBKEY_ENC_OAEP: + rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen, + nbits, hash_algo, plain, label, labellen); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + default: + /* Raw format. For backward compatibility we need to assume a + signed mpi by using the sexp format string "%m". */ + rc = gcry_err_code + (gcry_sexp_build (r_plain, NULL, + (flags & PUBKEY_FLAG_LEGACYRESULT) + ? "%m" : "(value %m)", + plain)); + break; + } + + gcry_free (unpad); + mpi_free (plain); } - return err; + return rc; } diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 7085b25..99b9ba8 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -714,7 +714,7 @@ get_hash_algo (const char *s, size_t n) */ static gcry_err_code_t sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, - int *ret_modern, int *flags, struct pk_encoding_ctx *ctx) + int *flags, struct pk_encoding_ctx *ctx) { gcry_err_code_t err = 0; gcry_sexp_t list = NULL; @@ -726,8 +726,6 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, const char *elems; gcry_mpi_t *array = NULL; - *ret_modern = 0; - /* Check that the first element is valid. */ list = gcry_sexp_find_token (sexp, "enc-val" , 0); if (!list) @@ -757,7 +755,6 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, const char *s; int i; - *ret_modern = 1; for (i = gcry_sexp_length (l2) - 1; i > 0; i--) { s = gcry_sexp_nth_data (l2, i, &n); @@ -863,6 +860,8 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, list = l2; l2 = NULL; } + else + parsed_flags |= PUBKEY_FLAG_LEGACYRESULT; spec = spec_from_name (name); if (!spec) @@ -1533,11 +1532,8 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) gcry_err_code_t rc; gcry_mpi_t *skey = NULL; gcry_mpi_t *data = NULL; - gcry_mpi_t plain = NULL; - unsigned char *unpad = NULL; - size_t unpadlen = 0; int i; - int modern, flags; + int flags; struct pk_encoding_ctx ctx; gcry_pk_spec_t *spec = NULL; gcry_pk_spec_t *spec_enc = NULL; @@ -1551,7 +1547,7 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) goto leave; init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, gcry_pk_get_nbits (s_skey)); - rc = sexp_to_enc (s_data, &data, &spec_enc, &modern, &flags, &ctx); + rc = sexp_to_enc (s_data, &data, &spec_enc, &flags, &ctx); if (rc) goto leave; @@ -1571,59 +1567,25 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) } if (spec->decrypt) - rc = spec->decrypt (spec->algo, &plain, data, skey, flags); + rc = spec->decrypt (spec->algo, r_plain, data, skey, flags, + ctx.encoding, ctx.hash_algo, + ctx.label, ctx.labellen); else rc = GPG_ERR_NOT_IMPLEMENTED; if (rc) goto leave; - if (DBG_CIPHER && !fips_mode ()) - log_mpidump (" plain", plain); - - /* Do un-padding if necessary. */ - switch (ctx.encoding) - { - case PUBKEY_ENC_PKCS1: - rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, - gcry_pk_get_nbits (s_skey), - plain); - mpi_free (plain); - plain = NULL; - if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); - break; - - case PUBKEY_ENC_OAEP: - rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen, - gcry_pk_get_nbits (s_skey), ctx.hash_algo, - plain, ctx.label, ctx.labellen); - mpi_free (plain); - plain = NULL; - if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); - break; + /* if (DBG_CIPHER && !fips_mode ()) */ + /* log_mpidump (" plain", plain); */ - default: - /* Raw format. For backward compatibility we need to assume a - signed mpi by using the sexp format string "%m". */ - rc = gcry_err_code (gcry_sexp_build - (r_plain, NULL, modern? "(value %m)" : "%m", plain)); - break; - } leave: - gcry_free (unpad); - if (skey) { release_mpi_array (skey); gcry_free (skey); } - mpi_free (plain); - if (data) { release_mpi_array (data); diff --git a/cipher/rsa.c b/cipher/rsa.c index 5754e43..7105271 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -32,6 +32,7 @@ #include "g10lib.h" #include "mpi.h" #include "cipher.h" +#include "pubkey-internal.h" typedef struct @@ -737,47 +738,6 @@ secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey ) -/* Perform RSA blinding. */ -static gcry_mpi_t -rsa_blind (gcry_mpi_t x, gcry_mpi_t r, gcry_mpi_t e, gcry_mpi_t n) -{ - /* A helper. */ - gcry_mpi_t a; - - /* Result. */ - gcry_mpi_t y; - - a = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - - /* Now we calculate: y = (x * r^e) mod n, where r is the random - number, e is the public exponent, x is the non-blinded data and n - is the RSA modulus. */ - gcry_mpi_powm (a, r, e, n); - gcry_mpi_mulm (y, a, x, n); - - gcry_mpi_release (a); - - return y; -} - -/* Undo RSA blinding. */ -static gcry_mpi_t -rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n) -{ - gcry_mpi_t y; - - y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - - /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded - decrypted data, ri is the modular multiplicative inverse of r and - n is the RSA modulus. */ - - gcry_mpi_mulm (y, ri, x, n); - - return y; -} - /********************************************* ************** interface ****************** *********************************************/ @@ -926,15 +886,18 @@ rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, static gcry_err_code_t -rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, - gcry_mpi_t *skey, int flags) +rsa_decrypt (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags, + enum pk_encoding encoding, int hash_algo, + unsigned char *label, size_t labellen) + { + gpg_err_code_t rc; RSA_secret_key sk; - gcry_mpi_t r = MPI_NULL; /* Random number needed for blinding. */ - gcry_mpi_t ri = MPI_NULL; /* Modular multiplicative inverse of - r. */ - gcry_mpi_t x = MPI_NULL; /* Data to decrypt. */ - gcry_mpi_t y; /* Result. */ + gcry_mpi_t plain; /* Decrypted data. */ + unsigned char *unpad = NULL; + size_t unpadlen = 0; + unsigned int nbits; (void)algo; @@ -946,24 +909,29 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, sk.q = skey[4]; /* Optional. */ sk.u = skey[5]; /* Optional. */ - y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + nbits = gcry_mpi_get_nbits (sk.n); + + plain = gcry_mpi_snew (nbits); /* We use blinding by default to mitigate timing attacks which can be practically mounted over the network as shown by Brumley and Boney in 2003. */ if (! (flags & PUBKEY_FLAG_NO_BLINDING)) { - /* Initialize blinding. */ + gcry_mpi_t r; /* Random number needed for blinding. */ + gcry_mpi_t ri; /* Modular multiplicative inverse of r. */ + gcry_mpi_t ciph; /* Blinded data to decrypt. */ /* First, we need a random number r between 0 and n - 1, which is relatively prime to n (i.e. it is neither p nor q). The random number needs to be only unpredictable, thus we employ the gcry_create_nonce function by using GCRY_WEAK_RANDOM with gcry_mpi_randomize. */ - r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); - ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + r = gcry_mpi_snew (nbits); + ri = gcry_mpi_snew (nbits); + ciph = gcry_mpi_snew (nbits); - gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), GCRY_WEAK_RANDOM); + gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM); gcry_mpi_mod (r, r, sk.n); /* Calculate inverse of r. It practically impossible that the @@ -971,39 +939,64 @@ rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, allocated resources. */ if (!gcry_mpi_invm (ri, r, sk.n)) return GPG_ERR_INTERNAL; - } - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - x = rsa_blind (data[0], r, sk.e, sk.n); - else - x = data[0]; - - /* Do the encryption. */ - secret (y, x, &sk); + /* Do blinding. We calculate: y = (x * r^e) mod n, where r is + the random number, e is the public exponent, x is the + non-blinded data and n is the RSA modulus. */ + gcry_mpi_powm (ciph, r, sk.e, sk.n); + gcry_mpi_mulm (ciph, ciph, data[0], sk.n); - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - { - /* Undo blinding. */ - gcry_mpi_t a = gcry_mpi_copy (y); + /* Perform decryption. */ + secret (plain, ciph, &sk); - gcry_mpi_release (y); - y = rsa_unblind (a, ri, sk.n); + /* Undo blinding. Here we calculate: y = (x * r^-1) mod n, + where x is the blinded decrypted data, ri is the modular + multiplicative inverse of r and n is the RSA modulus. */ + gcry_mpi_mulm (plain, plain, ri, sk.n); - gcry_mpi_release (a); + gcry_mpi_release (ciph); + gcry_mpi_release (r); + gcry_mpi_release (ri); } + else + secret (plain, data[0], &sk); - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + /* Reverse the encoding and build the s-expression. */ + switch (encoding) { - /* Deallocate resources needed for blinding. */ - gcry_mpi_release (x); - gcry_mpi_release (r); - gcry_mpi_release (ri); + case PUBKEY_ENC_PKCS1: + rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + case PUBKEY_ENC_OAEP: + rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen, + nbits, hash_algo, plain, label, labellen); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + default: + /* Raw format. For backward compatibility we need to assume a + signed mpi by using the sexp format string "%m". */ + rc = gcry_err_code + (gcry_sexp_build (r_plain, NULL, + (flags & PUBKEY_FLAG_LEGACYRESULT)? "%m":"(value %m)", + plain)); + break; } - /* Copy out result. */ - *result = y; + gcry_free (unpad); + mpi_free (plain); - return GPG_ERR_NO_ERROR; + return rc; } diff --git a/src/cipher-proto.h b/src/cipher-proto.h index 1285fe8..212857b 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -67,10 +67,14 @@ typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, /* Type for the pk_decrypt function. */ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, - gcry_mpi_t *result, + gcry_sexp_t *r_result, gcry_mpi_t *data, gcry_mpi_t *skey, - int flags); + int flags, + enum pk_encoding encoding, + int hash_algo, + unsigned char *label, + size_t labellen); /* Type for the pk_sign function. */ typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo, diff --git a/src/cipher.h b/src/cipher.h index 9fe30a6..e3a2fe0 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -30,6 +30,7 @@ #define PUBKEY_FLAG_RFC6979 (1 << 1) #define PUBKEY_FLAG_EDDSA (1 << 2) #define PUBKEY_FLAG_FIXEDLEN (1 << 3) +#define PUBKEY_FLAG_LEGACYRESULT (1 << 4) enum pk_operation { diff --git a/tests/basic.c b/tests/basic.c index 14ceea4..e9709d5 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -3654,7 +3654,18 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) } rc = gcry_pk_decrypt (&plain, ciph, skey); if (gcry_err_code (rc) != datas[dataidx].decrypt_expected_rc) - fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (rc)); + { + if (verbose) + { + show_sexp (" data:\n", data); + show_sexp (" ciph:\n", ciph); + show_sexp (" key:\n", skey); + } + fail ("gcry_pk_decrypt failed: expected %d (%s), got %d (%s)\n", + datas[dataidx].decrypt_expected_rc, + gpg_strerror (datas[dataidx].decrypt_expected_rc), + rc, gpg_strerror (rc)); + } if (!rc && datas[dataidx].unpadded) { commit 64cd7ab93da7c95cc8aa320c61c6e29f9e2399c4 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 pk: Remove unused function. * cipher/pubkey.c (_gcry_pk_aliased_algo_name): Remove diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 736d4b9..7085b25 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -153,28 +153,6 @@ gcry_pk_algo_name (int algo) } -/* A special version of gcry_pk_algo name to return the first aliased - name of the algorithm. This is required to adhere to the spki - specs where the algorithm names are lowercase. */ -const char * -_gcry_pk_aliased_algo_name (int algo) -{ - gcry_pk_spec_t *spec; - const char *name; - - spec = spec_from_algo (algo); - if (spec) - { - name = spec->aliases? *spec->aliases : NULL; - if (!name || !*name) - name = spec->name; - } - else - name = NULL; - return name; -} - - /**************** * A USE of 0 means: don't care. */ diff --git a/src/cipher.h b/src/cipher.h index dde24ce..9fe30a6 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -177,7 +177,6 @@ void _gcry_register_primegen_progress (gcry_handler_progress_t cb, void *cb_data); /*-- pubkey.c --*/ -const char * _gcry_pk_aliased_algo_name (int algorithm); /* Declarations for the cipher specifications. */ extern gcry_cipher_spec_t _gcry_cipher_spec_blowfish; ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 48 +++++++++-------- cipher/elgamal.c | 63 ++++++++++++++++++++--- cipher/pubkey.c | 80 ++++------------------------- cipher/rsa.c | 145 +++++++++++++++++++++++++--------------------------- src/cipher-proto.h | 8 ++- src/cipher.h | 2 +- tests/basic.c | 13 ++++- 7 files changed, 179 insertions(+), 180 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Sep 20 19:01:41 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 20 Sep 2013 19:01:41 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-257-g3e5cfa2 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 3e5cfa20acfeccb9df2c3fae2730344b40b36104 (commit) from 722bfc1e5f2268453db62f38cc46b5ec6ef3adee (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 3e5cfa20acfeccb9df2c3fae2730344b40b36104 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 sexp: Change internal versions to always use gpg_err_code_t. * src/sexp.c (gcry_sexp_new, gcry_sexp_create, gcry_sexp_build) (gcry_sexp_build_array, gcry_sexp_canon_len): Change error return type from gpg_error_t to gpg_err_code_t. Remove all calls to gpg_error. * src/visibility.c (gcry_sexp_new, gcry_sexp_create, gcry_sexp_sscan) (gcry_sexp_build, gcry_sexp_build_array, gcry_sexp_canon_len): Map error codes via gpg_error. * cipher/dsa.c, cipher/ecc.c, cipher/elgamal.c, cipher/rsa.c: Remove use gpg_err_code wrappers. -- We should do such a change for all other use of internal functions. It just does not make sense to use gpg_error in the internal interface because the error source is always Libgcrypt. Signed-off-by: Werner Koch diff --git a/cipher/dsa.c b/cipher/dsa.c index ceff947..394800d 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -817,10 +817,9 @@ dsa_generate (int algo, unsigned int nbits, unsigned long evalue, { /* Format the seed-values unless domain parameters are used for which a H_VALUE of NULL is an indication. */ - rc = gpg_err_code (gcry_sexp_build - (&seedinfo, NULL, - "(seed-values(counter %d)(seed %b)(h %m))", - counter, (int)seedlen, seed, h_value)); + rc = gcry_sexp_build (&seedinfo, NULL, + "(seed-values(counter %d)(seed %b)(h %m))", + counter, (int)seedlen, seed, h_value); gcry_free (seed); gcry_mpi_release (h_value); } @@ -876,8 +875,7 @@ dsa_generate (int algo, unsigned int nbits, unsigned long evalue, arg_list[i++] = factors + j; arg_list[i] = NULL; - rc = gpg_err_code (gcry_sexp_build_array - (&misc_info, NULL, format, arg_list)); + rc = gcry_sexp_build_array (&misc_info, NULL, format, arg_list); } } @@ -886,17 +884,16 @@ dsa_generate (int algo, unsigned int nbits, unsigned long evalue, } if (!rc) - rc = gcry_err_code (gcry_sexp_build - (r_skey, NULL, - "(key-data" - " (public-key" - " (dsa(p%m)(q%m)(g%m)(y%m)))" - " (private-key" - " (dsa(p%m)(q%m)(g%m)(y%m)(x%m)))" - " %S)", - sk.p, sk.q, sk.g, sk.y, - sk.p, sk.q, sk.g, sk.y, sk.x, - misc_info)); + rc = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (dsa(p%m)(q%m)(g%m)(y%m)))" + " (private-key" + " (dsa(p%m)(q%m)(g%m)(y%m)(x%m)))" + " %S)", + sk.p, sk.q, sk.g, sk.y, + sk.p, sk.q, sk.g, sk.y, sk.x, + misc_info); gcry_mpi_release (sk.p); @@ -976,9 +973,7 @@ dsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey, s = mpi_alloc (mpi_get_nlimbs (sk.p)); rc = sign (r, s, data, &sk, flags, hashalgo); if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(sig-val(dsa(r%M)(s%M)))", - r, s)); + rc = gcry_sexp_build (r_result, NULL, "(sig-val(dsa(r%M)(s%M)))", r, s); mpi_free (r); mpi_free (s); } diff --git a/cipher/ecc.c b/cipher/ecc.c index cf054f8..2161b64 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1271,18 +1271,17 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, goto leave; } - rc = gcry_err_code (gcry_sexp_build - (r_skey, NULL, - "(key-data" - " (public-key" - " (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" - " (private-key" - " (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" - " )", - curve_info, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, - curve_info, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret)); + rc = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" + " (private-key" + " (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" + " )", + curve_info, + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, + curve_info, + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret); if (rc) goto leave; @@ -1434,17 +1433,15 @@ ecc_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey, { rc = sign_eddsa (data, &sk, r, s, hashalgo, skey[5]); if (!rc) - rc = gcry_err_code (gcry_sexp_build - (r_result, NULL, - "(sig-val(eddsa(r%M)(s%M)))", r, s)); + rc = gcry_sexp_build (r_result, NULL, + "(sig-val(eddsa(r%M)(s%M)))", r, s); } else { rc = sign_ecdsa (data, &sk, r, s, flags, hashalgo); if (!rc) - rc = gcry_err_code (gcry_sexp_build - (r_result, NULL, - "(sig-val(ecdsa(r%M)(s%M)))", r, s)); + rc = gcry_sexp_build (r_result, NULL, + "(sig-val(ecdsa(r%M)(s%M)))", r, s); } gcry_mpi_release (sk.d); sk.d = NULL; @@ -1644,9 +1641,7 @@ ecc_encrypt_raw (int algo, gcry_sexp_t *r_result, gcry_mpi_t k, point_free (&pk.E.G); point_free (&pk.Q); - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(enc-val(ecdh(s%m)(e%m)))", - s, e)); + rc = gcry_sexp_build (r_result, NULL, "(enc-val(ecdh(s%m)(e%m)))", s, e); mpi_free (s); mpi_free (e); @@ -1752,7 +1747,7 @@ ecc_decrypt_raw (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data, point_free (&sk.Q); if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %m)", r)); + rc = gcry_sexp_build (r_plain, NULL, "(value %m)", r); mpi_free (r); return rc; } @@ -1924,20 +1919,18 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec) if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY)) { /* Let's return a private key. */ - rc = gpg_err_code - (gcry_sexp_build - (r_sexp, NULL, - "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))", - ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d)); + rc = gcry_sexp_build + (r_sexp, NULL, + "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))", + ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d); } else if (ec->Q) { /* Let's return a public key. */ - rc = gpg_err_code - (gcry_sexp_build - (r_sexp, NULL, - "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))", - ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q)); + rc = gcry_sexp_build + (r_sexp, NULL, + "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))", + ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q); } else rc = GPG_ERR_BAD_CRYPT_CTX; diff --git a/cipher/elgamal.c b/cipher/elgamal.c index ecbac75..c63059d 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -692,17 +692,16 @@ elg_generate (int algo, unsigned int nbits, unsigned long evalue, goto leave; } - rc = gcry_err_code (gcry_sexp_build - (r_skey, NULL, - "(key-data" - " (public-key" - " (elg(p%m)(g%m)(y%m)))" - " (private-key" + rc = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (elg(p%m)(g%m)(y%m)))" + " (private-key" " (elg(p%m)(g%m)(y%m)(x%m)))" - " %S)", - sk.p, sk.g, sk.y, - sk.p, sk.g, sk.y, sk.x, - misc_info)); + " %S)", + sk.p, sk.g, sk.y, + sk.p, sk.g, sk.y, sk.x, + misc_info); leave: mpi_free (sk.p); @@ -768,9 +767,7 @@ elg_encrypt (int algo, gcry_sexp_t *r_result, a = mpi_alloc (mpi_get_nlimbs (pk.p)); b = mpi_alloc (mpi_get_nlimbs (pk.p)); do_encrypt (a, b, data, &pk); - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(enc-val(elg(a%m)(b%m)))", - a, b)); + rc = gcry_sexp_build (r_result, NULL, "(enc-val(elg(a%m)(b%m)))", a, b); mpi_free (a); mpi_free (b); } @@ -817,8 +814,8 @@ elg_decrypt (int algo, gcry_sexp_t *r_plain, mpi_free (plain); plain = NULL; if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); + rc = gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad); break; case PUBKEY_ENC_OAEP: @@ -827,18 +824,17 @@ elg_decrypt (int algo, gcry_sexp_t *r_plain, mpi_free (plain); plain = NULL; if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); + rc = gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad); break; default: /* Raw format. For backward compatibility we need to assume a signed mpi by using the sexp format string "%m". */ - rc = gcry_err_code - (gcry_sexp_build (r_plain, NULL, - (flags & PUBKEY_FLAG_LEGACYRESULT) - ? "%m" : "(value %m)", - plain)); + rc = gcry_sexp_build (r_plain, NULL, + (flags & PUBKEY_FLAG_LEGACYRESULT) + ? "%m" : "(value %m)", + plain); break; } @@ -876,9 +872,7 @@ elg_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey, r = mpi_alloc (mpi_get_nlimbs (sk.p)); s = mpi_alloc (mpi_get_nlimbs (sk.p)); sign (r, s, data, &sk); - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(sig-val(elg(r%M)(s%M)))", - r, s)); + rc = gcry_sexp_build (r_result, NULL, "(sig-val(elg(r%M)(s%M)))", r, s); mpi_free (r); mpi_free (s); } diff --git a/cipher/rsa.c b/cipher/rsa.c index 7105271..53b9d89 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -794,17 +794,16 @@ rsa_generate (int algo, unsigned int nbits, unsigned long evalue, if (!ec) { - ec = gcry_err_code (gcry_sexp_build - (r_skey, NULL, - "(key-data" - " (public-key" - " (rsa(n%m)(e%m)))" - " (private-key" - " (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))" - " %S)", - sk.n, sk.e, - sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, - swap_info)); + ec = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (rsa(n%m)(e%m)))" + " (private-key" + " (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))" + " %S)", + sk.n, sk.e, + sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, + swap_info); } mpi_free (sk.n); @@ -869,16 +868,13 @@ rsa_encrypt (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen); if (!rc) { - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(enc-val(rsa(a%b)))", - (int)emlen, em)); + rc = gcry_sexp_build (r_result, NULL, + "(enc-val(rsa(a%b)))", (int)emlen, em); gcry_free (em); } } else - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(enc-val(rsa(a%m)))", - result)); + rc = gcry_sexp_build (r_result, NULL, "(enc-val(rsa(a%m)))", result); mpi_free (result); return rc; @@ -969,8 +965,8 @@ rsa_decrypt (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data, mpi_free (plain); plain = NULL; if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); + rc = gcry_sexp_build (r_plain, NULL, + "(value %b)", (int)unpadlen, unpad); break; case PUBKEY_ENC_OAEP: @@ -979,17 +975,16 @@ rsa_decrypt (int algo, gcry_sexp_t *r_plain, gcry_mpi_t *data, mpi_free (plain); plain = NULL; if (!rc) - rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", - (int)unpadlen, unpad)); + rc = gcry_sexp_build (r_plain, NULL, + "(value %b)", (int)unpadlen, unpad); break; default: /* Raw format. For backward compatibility we need to assume a signed mpi by using the sexp format string "%m". */ - rc = gcry_err_code - (gcry_sexp_build (r_plain, NULL, - (flags & PUBKEY_FLAG_LEGACYRESULT)? "%m":"(value %m)", - plain)); + rc = gcry_sexp_build (r_plain, NULL, + (flags & PUBKEY_FLAG_LEGACYRESULT) + ? "%m":"(value %m)", plain); break; } @@ -1033,16 +1028,13 @@ rsa_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey, rc = _gcry_mpi_to_octet_string (&em, NULL, result, emlen); if (!rc) { - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(sig-val(rsa(s%b)))", - (int)emlen, em)); + rc = gcry_sexp_build (r_result, NULL, + "(sig-val(rsa(s%b)))", (int)emlen, em); gcry_free (em); } } else - rc = gcry_err_code (gcry_sexp_build (r_result, NULL, - "(sig-val(rsa(s%M)))", - result)); + rc = gcry_sexp_build (r_result, NULL, "(sig-val(rsa(s%M)))", result); mpi_free (result); return rc; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index 212857b..5b152b5 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -24,6 +24,8 @@ #define G10_CIPHER_PROTO_H +enum pk_encoding; + /* Definition of a function used to report selftest failures. DOMAIN is a string describing the function block: diff --git a/src/g10lib.h b/src/g10lib.h index 57176e9..73ba683 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -405,8 +405,8 @@ gcry_err_code_t _gcry_mpi_init (void); /*-- sexp.c --*/ -gcry_error_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, - const char *format, va_list arg_ptr); +gcry_err_code_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, va_list arg_ptr); gcry_mpi_t _gcry_sexp_nth_opaque_mpi (gcry_sexp_t list, int number); char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number); diff --git a/src/sexp.c b/src/sexp.c index 882ee52..54d0c4a 100644 --- a/src/sexp.c +++ b/src/sexp.c @@ -54,12 +54,12 @@ struct gcry_sexp #define TOKEN_SPECIALS "-./_:*+=" -static gcry_error_t +static gcry_err_code_t vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length, int argflag, void **arg_list, va_list arg_ptr); -static gcry_error_t +static gcry_err_code_t sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length, int argflag, void **arg_list, ...); @@ -210,18 +210,18 @@ normalize ( gcry_sexp_t list ) This function returns 0 and and the pointer to the new object in RETSEXP or an error code in which case RETSEXP is set to NULL. */ -gcry_error_t +gcry_err_code_t gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, int autodetect, void (*freefnc)(void*) ) { - gcry_error_t errcode; + gcry_err_code_t errcode; gcry_sexp_t se; if (!retsexp) - return gcry_error (GPG_ERR_INV_ARG); + return GPG_ERR_INV_ARG; *retsexp = NULL; if (autodetect < 0 || autodetect > 1 || !buffer) - return gcry_error (GPG_ERR_INV_ARG); + return GPG_ERR_INV_ARG; if (!length && !autodetect) { /* What a brave caller to assume that there is really a canonical @@ -249,11 +249,11 @@ gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, GCRYSEXP object and use the BUFFER directly. */ freefnc (buffer); } - return gcry_error (GPG_ERR_NO_ERROR); + return 0; } /* Same as gcry_sexp_create but don't transfer ownership */ -gcry_error_t +gcry_err_code_t gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, int autodetect) { @@ -1047,7 +1047,7 @@ unquote_string (const char *string, size_t length, unsigned char *buf) * common operation gcry_sexp_cdr_mpi() will always return a secure MPI * regardless whether it is needed or not. */ -static gcry_error_t +static gpg_err_code_t vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length, int argflag, void **arg_list, va_list arg_ptr) @@ -1643,18 +1643,18 @@ vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, else *retsexp = normalize (c.sexp); - return gcry_error (err); + return err; #undef MAKE_SPACE #undef STORE_LEN } -static gcry_error_t +static gpg_err_code_t sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length, int argflag, void **arg_list, ...) { - gcry_error_t rc; + gcry_err_code_t rc; va_list arg_ptr; va_start (arg_ptr, arg_list); @@ -1666,10 +1666,10 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, } -gcry_error_t +gpg_err_code_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) { - gcry_error_t rc; + gcry_err_code_t rc; va_list arg_ptr; va_start (arg_ptr, format); @@ -1681,7 +1681,7 @@ gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) } -gcry_error_t +gcry_err_code_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, const char *format, va_list arg_ptr) { @@ -1692,7 +1692,7 @@ _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, /* Like gcry_sexp_build, but uses an array instead of variable function arguments. */ -gcry_error_t +gcry_err_code_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, const char *format, void **arg_list) { @@ -1700,7 +1700,7 @@ gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, } -gcry_error_t +gcry_err_code_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length) { @@ -1987,13 +1987,13 @@ gcry_sexp_sprint (const gcry_sexp_t list, int mode, NULL. */ size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length, - size_t *erroff, gcry_error_t *errcode) + size_t *erroff, gcry_err_code_t *errcode) { const unsigned char *p; const unsigned char *disphint = NULL; unsigned int datalen = 0; size_t dummy_erroff; - gcry_error_t dummy_errcode; + gcry_err_code_t dummy_errcode; size_t count = 0; int level = 0; @@ -2002,13 +2002,13 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (!errcode) errcode = &dummy_errcode; - *errcode = gcry_error (GPG_ERR_NO_ERROR); + *errcode = GPG_ERR_NO_ERROR; *erroff = 0; if (!buffer) return 0; if (*buffer != '(') { - *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL); + *errcode = GPG_ERR_SEXP_NOT_CANONICAL; return 0; } @@ -2017,7 +2017,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (length && count >= length) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); + *errcode = GPG_ERR_SEXP_STRING_TOO_LONG; return 0; } @@ -2028,7 +2028,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (length && (count+datalen) >= length) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); + *errcode = GPG_ERR_SEXP_STRING_TOO_LONG; return 0; } count += datalen; @@ -2040,7 +2040,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, else { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC); + *errcode = GPG_ERR_SEXP_INV_LEN_SPEC; return 0; } } @@ -2049,7 +2049,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (disphint) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + *errcode = GPG_ERR_SEXP_UNMATCHED_DH; return 0; } level++; @@ -2059,13 +2059,13 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (!level) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN); + *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN; return 0; } if (disphint) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + *errcode = GPG_ERR_SEXP_UNMATCHED_DH; return 0; } if (!--level) @@ -2076,7 +2076,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (disphint) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH); + *errcode = GPG_ERR_SEXP_NESTED_DH; return 0; } disphint = p; @@ -2086,7 +2086,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if ( !disphint ) { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + *errcode = GPG_ERR_SEXP_UNMATCHED_DH; return 0; } disphint = NULL; @@ -2096,7 +2096,7 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, if (*p == '0') { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX); + *errcode = GPG_ERR_SEXP_ZERO_PREFIX; return 0; } datalen = atoi_1 (p); @@ -2104,13 +2104,13 @@ gcry_sexp_canon_len (const unsigned char *buffer, size_t length, else if (*p == '&' || *p == '\\') { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC); + *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC; return 0; } else { *erroff = count; - *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER); + *errcode = GPG_ERR_SEXP_BAD_CHARACTER; return 0; } } diff --git a/src/visibility.c b/src/visibility.c index 3c8041a..cfb159f 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -86,7 +86,7 @@ gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, int autodetect) { - return _gcry_sexp_new (retsexp, buffer, length, autodetect); + return gpg_error (_gcry_sexp_new (retsexp, buffer, length, autodetect)); } gcry_error_t @@ -94,35 +94,35 @@ gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, int autodetect, void (*freefnc) (void *)) { - return _gcry_sexp_create (retsexp, buffer, length, - autodetect, freefnc); + return gpg_error (_gcry_sexp_create (retsexp, buffer, length, + autodetect, freefnc)); } gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, const char *buffer, size_t length) { - return _gcry_sexp_sscan (retsexp, erroff, buffer, length); + return gpg_error (_gcry_sexp_sscan (retsexp, erroff, buffer, length)); } gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) { - gcry_error_t err; + gcry_err_code_t rc; va_list arg_ptr; va_start (arg_ptr, format); - err = _gcry_sexp_vbuild (retsexp, erroff, format, arg_ptr); + rc = _gcry_sexp_vbuild (retsexp, erroff, format, arg_ptr); va_end (arg_ptr); - return err; + return gpg_error (rc); } gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, const char *format, void **arg_list) { - return _gcry_sexp_build_array (retsexp, erroff, format, arg_list); + return gpg_error (_gcry_sexp_build_array (retsexp, erroff, format, arg_list)); } void @@ -135,7 +135,13 @@ size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length, size_t *erroff, gcry_error_t *errcode) { - return _gcry_sexp_canon_len (buffer, length, erroff, errcode); + size_t n; + gpg_err_code_t rc; + + n = _gcry_sexp_canon_len (buffer, length, erroff, &rc); + if (errcode) + *errcode = gpg_error (rc); + return n; } size_t ----------------------------------------------------------------------- Summary of changes: cipher/dsa.c | 35 ++++++++++++---------------- cipher/ecc.c | 57 ++++++++++++++++++++-------------------------- cipher/elgamal.c | 44 +++++++++++++++-------------------- cipher/rsa.c | 54 ++++++++++++++++++------------------------- src/cipher-proto.h | 2 + src/g10lib.h | 4 +- src/sexp.c | 64 ++++++++++++++++++++++++++-------------------------- src/visibility.c | 24 ++++++++++++------- 8 files changed, 133 insertions(+), 151 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 21 13:32:59 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 21 Sep 2013 13:32:59 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-259-g902ea60 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 902ea6052c11108bd19333c31b03e084bed1fb86 (commit) via cce7449efe471b076c5a97929ac8907162011394 (commit) from 3e5cfa20acfeccb9df2c3fae2730344b40b36104 (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 902ea6052c11108bd19333c31b03e084bed1fb86 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Make STRIBOG use the new _gcry_md_block_write helper * cipher/stribog.c (STRIBOG_STRUCT): Add 'bctx' and remove 'buf' and 'count'. (stribog_init_512): Initialize 'bctx'. (transform64): New function. (stribog_write): Remove. (stribog_final): Use _gcry_md_block_write and bctx. (_gcry_digest_spec_stribog_256, _gcry_digest_spec_stribog_512): Use _gcry_md_block_write. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/stribog.c b/cipher/stribog.c index ec7ffe9..234a17e 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -32,6 +32,7 @@ typedef struct { + gcry_md_block_ctx_t bctx; union { u64 h[8]; @@ -39,8 +40,6 @@ typedef struct }; u64 N[8]; u64 Sigma[8]; - byte buf[64]; - int count; } STRIBOG_CONTEXT; static const byte Pi[256] = @@ -1276,11 +1275,19 @@ static void g (u64 *h, u64 *m, u64 *N) static void +transform64 (void *context, const unsigned char *inbuf_arg); + + +static void stribog_init_512 (void *context) { STRIBOG_CONTEXT *hd = context; memset (hd, 0, sizeof (*hd)); + + hd->bctx.blocksize = 64; + hd->bctx.bwrite = transform64; + hd->bctx.stack_burn = 768; } static void @@ -1340,35 +1347,11 @@ transform (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count) } static void -stribog_write (void *context, const void *inbuf_arg, size_t inlen) +transform64 (void *context, const unsigned char *inbuf_arg) { STRIBOG_CONTEXT *hd = context; - const unsigned char *inbuf = inbuf_arg; - if (hd->count == 64) - { - transform (hd, hd->buf, hd->count * 8); - hd->count = 0; - _gcry_burn_stack (768); - } - if (!inbuf) - return; - if (hd->count) - { - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; - stribog_write (context, NULL, 0); - if (!inlen) - return; - } - while (inlen >= 64) - { - transform (hd, inbuf, 64 * 8); - inlen -= 64; - inbuf += 64; - } - _gcry_burn_stack (768); - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; + + transform (hd, inbuf_arg, 64 * 8); } /* @@ -1383,14 +1366,14 @@ stribog_final (void *context) u64 Z[8] = {}; int i; - stribog_write (context, NULL, 0); /* flush */ ; + _gcry_md_block_write (context, NULL, 0); /* flush */ ; /* PAD. It does not count towards message length */ - i = hd->count; + i = hd->bctx.count; /* After flush we have at least one byte free) */ - hd->buf[i++] = 1; + hd->bctx.buf[i++] = 1; while (i < 64) - hd->buf[i++] = 0; - transform (hd, hd->buf, hd->count * 8); + hd->bctx.buf[i++] = 0; + transform (hd, hd->bctx.buf, hd->bctx.count * 8); g (hd->h, hd->N, Z); g (hd->h, hd->Sigma, Z); @@ -1431,13 +1414,13 @@ stribog_read_256 (void *context) gcry_md_spec_t _gcry_digest_spec_stribog_256 = { "STRIBOG256", NULL, 0, NULL, 32, - stribog_init_256, stribog_write, stribog_final, stribog_read_256, + stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256, sizeof (STRIBOG_CONTEXT) }; gcry_md_spec_t _gcry_digest_spec_stribog_512 = { "STRIBOG512", NULL, 0, NULL, 64, - stribog_init_512, stribog_write, stribog_final, stribog_read_512, + stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512, sizeof (STRIBOG_CONTEXT) }; commit cce7449efe471b076c5a97929ac8907162011394 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Make SHA-512 use the new _gcry_md_block_write helper * cipher/hash-common.c (_gcry_md_block_write): Check that hd->buf is large enough. * cipher/hash-common.h (MD_BLOCK_MAX_BLOCKSIZE, MD_NBLOCKS_TYPE): New macros. (gcry_md_block_ctx_t): Use above macros for 'nblocks' and 'buf'. * cipher/sha512.c (SHA512_STATE): New struct. (SHA512_CONTEXT): Add 'bctx' and 'state'. (sha512_init, sha384_init): Initialize 'bctx'. (__transform, _gcry_sha512_transform_armv7_neon): Use SHA512_STATE for 'hd'. (transform): For now, do not return burn stack. (sha512_write): Remove. (sha512_final): Use _gcry_md_block_write and bctx. (_gcry_digest_spec_sha512, _gcry_digest_spec_sha384): Use _gcry_md_block_write. -- Patch changes 'nblocks' counter to 64-bits when SHA-512 is enabled. This does not cause problems with other algorithms; they are already casting 'nblocks' to u32 variable in their finalization functions. Also move 'buf' member to head of 'gcry_md_block_ctx_t' to ensure proper alignment; this is because some algorithms cast buffer pointer to (u64*) in final endian conversion. Signed-off-by: Jussi Kivilinna diff --git a/cipher/hash-common.c b/cipher/hash-common.c index a823a66..1a6e8e9 100644 --- a/cipher/hash-common.c +++ b/cipher/hash-common.c @@ -102,7 +102,10 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) const unsigned char *inbuf = inbuf_arg; gcry_md_block_ctx_t *hd = context; - if ( hd->buf == NULL || hd->bwrite == NULL) + if (sizeof(hd->buf) < hd->blocksize) + BUG(); + + if (hd->buf == NULL || hd->bwrite == NULL) return; if (hd->count == hd->blocksize) /* Flush the buffer. */ diff --git a/cipher/hash-common.h b/cipher/hash-common.h index 1d1d4ec..4dd5441 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -20,6 +20,8 @@ #ifndef GCRY_HASH_COMMON_H #define GCRY_HASH_COMMON_H +#include "types.h" + const char * _gcry_hash_selftest_check_one /**/ (int algo, @@ -29,11 +31,20 @@ const char * _gcry_hash_selftest_check_one /* Type for the md_write helper function. */ typedef void (*_gcry_md_block_write_t) (void *c, const unsigned char *buf); +#if defined(HAVE_U64_TYPEDEF) && defined(USE_SHA512) +/* SHA-512 needs u64 and larger buffer. */ +# define MD_BLOCK_MAX_BLOCKSIZE 128 +# define MD_NBLOCKS_TYPE u64 +#else +# define MD_BLOCK_MAX_BLOCKSIZE 64 +# define MD_NBLOCKS_TYPE u32 +#endif + typedef struct gcry_md_block_ctx { - u32 nblocks; - int count; - byte buf[64]; + byte buf[MD_BLOCK_MAX_BLOCKSIZE]; + MD_NBLOCKS_TYPE nblocks; + int count; size_t blocksize; _gcry_md_block_write_t bwrite; size_t stack_burn; diff --git a/cipher/sha512.c b/cipher/sha512.c index fee3e71..ed63ae6 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -67,18 +67,25 @@ typedef struct { u64 h0, h1, h2, h3, h4, h5, h6, h7; - u64 nblocks; - byte buf[128]; - int count; +} SHA512_STATE; + +typedef struct +{ + gcry_md_block_ctx_t bctx; + SHA512_STATE state; #ifdef USE_ARM_NEON_ASM int use_neon; #endif } SHA512_CONTEXT; static void +transform (void *context, const unsigned char *data); + +static void sha512_init (void *context) { - SHA512_CONTEXT *hd = context; + SHA512_CONTEXT *ctx = context; + SHA512_STATE *hd = &ctx->state; hd->h0 = U64_C(0x6a09e667f3bcc908); hd->h1 = U64_C(0xbb67ae8584caa73b); @@ -89,17 +96,22 @@ sha512_init (void *context) hd->h6 = U64_C(0x1f83d9abfb41bd6b); hd->h7 = U64_C(0x5be0cd19137e2179); - hd->nblocks = 0; - hd->count = 0; + ctx->bctx.nblocks = 0; + ctx->bctx.count = 0; + ctx->bctx.blocksize = 128; + ctx->bctx.bwrite = transform; + ctx->bctx.stack_burn = 256; + #ifdef USE_ARM_NEON_ASM - hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; + ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; #endif } static void sha384_init (void *context) { - SHA512_CONTEXT *hd = context; + SHA512_CONTEXT *ctx = context; + SHA512_STATE *hd = &ctx->state; hd->h0 = U64_C(0xcbbb9d5dc1059ed8); hd->h1 = U64_C(0x629a292a367cd507); @@ -110,10 +122,14 @@ sha384_init (void *context) hd->h6 = U64_C(0xdb0c2e0d64f98fa7); hd->h7 = U64_C(0x47b5481dbefa4fa4); - hd->nblocks = 0; - hd->count = 0; + ctx->bctx.nblocks = 0; + ctx->bctx.count = 0; + ctx->bctx.blocksize = 128; + ctx->bctx.bwrite = transform; + ctx->bctx.stack_burn = 256; + #ifdef USE_ARM_NEON_ASM - hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; + ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; #endif } @@ -196,7 +212,7 @@ static const u64 k[] = * Transform the message W which consists of 16 64-bit-words */ static void -__transform (SHA512_CONTEXT *hd, const unsigned char *data) +__transform (SHA512_STATE *hd, const unsigned char *data) { u64 a, b, c, d, e, f, g, h; u64 w[16]; @@ -477,71 +493,33 @@ __transform (SHA512_CONTEXT *hd, const unsigned char *data) #ifdef USE_ARM_NEON_ASM -void _gcry_sha512_transform_armv7_neon (SHA512_CONTEXT *hd, +void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd, const unsigned char *data, const u64 k[]); #endif -static unsigned int -transform (SHA512_CONTEXT *hd, const unsigned char *data) +static void +transform (void *context, const unsigned char *data) { + SHA512_CONTEXT *ctx = context; + #ifdef USE_ARM_NEON_ASM if (hd->use_neon) { - _gcry_sha512_transform_armv7_neon(hd, data, k); + _gcry_sha512_transform_armv7_neon(&ctx->state, data, k); + /* TODO: return burn stack to md_block_write */ /* return stack burn depth */ - return (sizeof(void *) * 3); + return /*(sizeof(void *) * 3)*/; } #endif - __transform (hd, data); + __transform (&ctx->state, data); + /* TODO: return burn stack to md_block_write */ /* return stack burn depth */ - return 256; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -sha512_write (void *context, const void *inbuf_arg, size_t inlen) -{ - const unsigned char *inbuf = inbuf_arg; - SHA512_CONTEXT *hd = context; - unsigned int stack_burn_depth = 0; - - if (hd->count == 128) - { /* flush the buffer */ - stack_burn_depth = transform (hd, hd->buf); - _gcry_burn_stack (stack_burn_depth); - hd->count = 0; - hd->nblocks++; - } - if (!inbuf) - return; - if (hd->count) - { - for (; inlen && hd->count < 128; inlen--) - hd->buf[hd->count++] = *inbuf++; - sha512_write (context, NULL, 0); - if (!inlen) - return; - } - - while (inlen >= 128) - { - stack_burn_depth = transform (hd, inbuf); - hd->count = 0; - hd->nblocks++; - inlen -= 128; - inbuf += 128; - } - _gcry_burn_stack (stack_burn_depth); - for (; inlen && hd->count < 128; inlen--) - hd->buf[hd->count++] = *inbuf++; + return /*256*/; } @@ -561,15 +539,15 @@ sha512_final (void *context) u64 t, msb, lsb; byte *p; - sha512_write (context, NULL, 0); /* flush */ ; + _gcry_md_block_write (context, NULL, 0); /* flush */ ; - t = hd->nblocks; + t = hd->bctx.nblocks; /* multiply by 128 to make a byte count */ lsb = t << 7; msb = t >> 57; /* add the count */ t = lsb; - if ((lsb += hd->count) < t) + if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; @@ -577,49 +555,50 @@ sha512_final (void *context) msb <<= 3; msb |= t >> 61; - if (hd->count < 112) + if (hd->bctx.count < 112) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while (hd->count < 112) - hd->buf[hd->count++] = 0; /* pad */ + hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ + while (hd->bctx.count < 112) + hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while (hd->count < 128) - hd->buf[hd->count++] = 0; - sha512_write (context, NULL, 0); /* flush */ ; - memset (hd->buf, 0, 112); /* fill next block with zeroes */ + hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ + while (hd->bctx.count < 128) + hd->bctx.buf[hd->bctx.count++] = 0; + _gcry_md_block_write (context, NULL, 0); /* flush */ ; + memset (hd->bctx.buf, 0, 112); /* fill next block with zeroes */ } /* append the 128 bit count */ - hd->buf[112] = msb >> 56; - hd->buf[113] = msb >> 48; - hd->buf[114] = msb >> 40; - hd->buf[115] = msb >> 32; - hd->buf[116] = msb >> 24; - hd->buf[117] = msb >> 16; - hd->buf[118] = msb >> 8; - hd->buf[119] = msb; - - hd->buf[120] = lsb >> 56; - hd->buf[121] = lsb >> 48; - hd->buf[122] = lsb >> 40; - hd->buf[123] = lsb >> 32; - hd->buf[124] = lsb >> 24; - hd->buf[125] = lsb >> 16; - hd->buf[126] = lsb >> 8; - hd->buf[127] = lsb; - stack_burn_depth = transform (hd, hd->buf); + hd->bctx.buf[112] = msb >> 56; + hd->bctx.buf[113] = msb >> 48; + hd->bctx.buf[114] = msb >> 40; + hd->bctx.buf[115] = msb >> 32; + hd->bctx.buf[116] = msb >> 24; + hd->bctx.buf[117] = msb >> 16; + hd->bctx.buf[118] = msb >> 8; + hd->bctx.buf[119] = msb; + + hd->bctx.buf[120] = lsb >> 56; + hd->bctx.buf[121] = lsb >> 48; + hd->bctx.buf[122] = lsb >> 40; + hd->bctx.buf[123] = lsb >> 32; + hd->bctx.buf[124] = lsb >> 24; + hd->bctx.buf[125] = lsb >> 16; + hd->bctx.buf[126] = lsb >> 8; + hd->bctx.buf[127] = lsb; + transform (hd, hd->bctx.buf); + stack_burn_depth = hd->bctx.stack_burn; _gcry_burn_stack (stack_burn_depth); - p = hd->buf; + p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN -#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0) +#define X(a) do { *(u64*)p = hd->state.h##a ; p += 8; } while (0) #else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \ - *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \ - *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0) +#define X(a) do { *p++ = hd->state.h##a >> 56; *p++ = hd->state.h##a >> 48; \ + *p++ = hd->state.h##a >> 40; *p++ = hd->state.h##a >> 32; \ + *p++ = hd->state.h##a >> 24; *p++ = hd->state.h##a >> 16; \ + *p++ = hd->state.h##a >> 8; *p++ = hd->state.h##a; } while(0) #endif X (0); X (1); @@ -638,7 +617,7 @@ static byte * sha512_read (void *context) { SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context; - return hd->buf; + return hd->bctx.buf; } @@ -797,7 +776,7 @@ static gcry_md_oid_spec_t oid_spec_sha512[] = gcry_md_spec_t _gcry_digest_spec_sha512 = { "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, - sha512_init, sha512_write, sha512_final, sha512_read, + sha512_init, _gcry_md_block_write, sha512_final, sha512_read, sizeof (SHA512_CONTEXT), }; md_extra_spec_t _gcry_digest_extraspec_sha512 = @@ -825,7 +804,7 @@ static gcry_md_oid_spec_t oid_spec_sha384[] = gcry_md_spec_t _gcry_digest_spec_sha384 = { "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, - sha384_init, sha512_write, sha512_final, sha512_read, + sha384_init, _gcry_md_block_write, sha512_final, sha512_read, sizeof (SHA512_CONTEXT), }; md_extra_spec_t _gcry_digest_extraspec_sha384 = ----------------------------------------------------------------------- Summary of changes: cipher/hash-common.c | 5 +- cipher/hash-common.h | 17 ++++- cipher/sha512.c | 179 ++++++++++++++++++++++---------------------------- cipher/stribog.c | 55 +++++---------- 4 files changed, 116 insertions(+), 140 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 21 13:38:46 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 21 Sep 2013 13:38:46 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-261-g7409de7 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 7409de7bc28ff8847c9d71d8c3e35e1968d59d60 (commit) via 592c2ab3deeeccbb6d3b078ed7bf0e6627c8e1fb (commit) from 902ea6052c11108bd19333c31b03e084bed1fb86 (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 7409de7bc28ff8847c9d71d8c3e35e1968d59d60 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 gostr3411_94: set better burn stack depth estimate * cipher/gost28147.c (_gcry_gost_enc_one): Account function stack to burn stack depth. * cipher/gostr3411-94.c (max): New macro. (do_hash_step, transform): Return stack burn depth. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/gost28147.c b/cipher/gost28147.c index 862e7d6..c669148 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -168,7 +168,7 @@ unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key, byte *out, byte *in) { gost_setkey (c, key, 32); - return gost_encrypt_block (c, out, in); + return gost_encrypt_block (c, out, in) + 5 * sizeof(void *); } static unsigned int diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c index bfd52bd..368fc01 100644 --- a/cipher/gostr3411-94.c +++ b/cipher/gostr3411-94.c @@ -30,6 +30,8 @@ #include "gost.h" +#define max(a, b) (((a) > (b)) ? (a) : (b)) + typedef struct { gcry_md_block_ctx_t bctx; GOST28147_context hd; @@ -148,11 +150,12 @@ do_add (unsigned char *s, unsigned char *a) } } -static void +static unsigned int do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m) { unsigned char u[32], v[32], s[32]; unsigned char k[32]; + unsigned int burn; int i; memcpy (u, h, 32); @@ -161,7 +164,7 @@ do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m) for (i = 0; i < 4; i++) { do_p (k, u, v); - _gcry_gost_enc_one (hd, k, s + i*8, h + i*8); + burn = _gcry_gost_enc_one (hd, k, s + i*8, h + i*8); do_a (u); if (i == 1) @@ -198,6 +201,12 @@ do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m) memcpy (h, s+20, 12); memcpy (h+12, s, 20); + + return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ + + 4 * 32 + 2 * sizeof(int) /* stack */ + + max(burn /* _gcry_gost_enc_one */, + sizeof(void*) * 2 /* do_a2 call */ + + 16 + sizeof(int) /* do_a2 stack */ ); } @@ -206,13 +215,13 @@ transform (void *ctx, const unsigned char *data) { GOSTR3411_CONTEXT *hd = ctx; byte m[32]; + unsigned int burn; memcpy (m, data, 32); - do_hash_step (&hd->hd, hd->h, m); + burn = do_hash_step (&hd->hd, hd->h, m); do_add (hd->sigma, m); -/* FIXME: Fix this arbitrary value for the stack_burn size. -wk */ - return /* stack_burn */ 200; + return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*); } /* commit 592c2ab3deeeccbb6d3b078ed7bf0e6627c8e1fb Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Use hash transform function return type for passing burn stack depth * cipher/gostr4311-94.c (transform): Return stack burn depth. * cipher/hash-common.c (_gcry_md_block_write): Use stack burn depth returned by 'hd->bwrite'. * cipher/hash-common.h (_gcry_md_block_write_t): Change return type to 'unsigned int'. (gry_md_block_ctx_t): Remove 'stack_burn'. * cipher/md4.c (transform): Return stack burn depth. (md4_final): Use stack burn depth from transform. * cipher/md5.c (transform): Return stack burn depth. (md5_final): Use stack burn depth from transform. * cipher/rmd160.c (transform): Return stack burn depth. (rmd160_final): Use stack burn depth from transform. * cipher/sha1.c (transform): Return stack burn depth. (sha1_final): Use stack burn depth from transform. * cipher/sha256.c (transform): Return stack burn depth. (sha256_final): Use stack burn depth from transform. * cipher/sha512.c (__transform, transform): Return stack burn depth. (sha512_final): Use stack burn depth from transform. * cipher/stribog.c (transform64): Return stack burn depth. * cipher/tiger.c (transform): Return stack burn depth. (tiger_final): Use stack burn depth from transform. -- Transform function might want different depth of stack burn depending on detected CPU features (like in SHA-512 on ARM with NEON). So return stack burn depth from transform functions as a request or a hint to calling function. Signed-off-by: Jussi Kivilinna diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c index 93bf597..bfd52bd 100644 --- a/cipher/gostr3411-94.c +++ b/cipher/gostr3411-94.c @@ -38,7 +38,7 @@ typedef struct { u32 len; } GOSTR3411_CONTEXT; -static void +static unsigned int transform (void *c, const unsigned char *data); static void @@ -53,8 +53,6 @@ gost3411_init (void *context) hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 32; - /* FIXME: Fix this arbitrary value for the stack_burn size. -wk */ - hd->bctx.stack_burn = 200; hd->bctx.bwrite = transform; } @@ -203,7 +201,7 @@ do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m) } -static void +static unsigned int transform (void *ctx, const unsigned char *data) { GOSTR3411_CONTEXT *hd = ctx; @@ -212,6 +210,9 @@ transform (void *ctx, const unsigned char *data) memcpy (m, data, 32); do_hash_step (&hd->hd, hd->h, m); do_add (hd->sigma, m); + +/* FIXME: Fix this arbitrary value for the stack_burn size. -wk */ + return /* stack_burn */ 200; } /* diff --git a/cipher/hash-common.c b/cipher/hash-common.c index 1a6e8e9..e318e7e 100644 --- a/cipher/hash-common.c +++ b/cipher/hash-common.c @@ -101,6 +101,7 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) { const unsigned char *inbuf = inbuf_arg; gcry_md_block_ctx_t *hd = context; + unsigned int stack_burn = 0; if (sizeof(hd->buf) < hd->blocksize) BUG(); @@ -110,8 +111,9 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) if (hd->count == hd->blocksize) /* Flush the buffer. */ { - hd->bwrite (hd, hd->buf); - _gcry_burn_stack (hd->stack_burn); + stack_burn = hd->bwrite (hd, hd->buf); + _gcry_burn_stack (stack_burn); + stack_burn = 0; hd->count = 0; hd->nblocks++; } @@ -129,13 +131,13 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) while (inlen >= hd->blocksize) { - hd->bwrite (hd, inbuf); + stack_burn = hd->bwrite (hd, inbuf); hd->count = 0; hd->nblocks++; inlen -= hd->blocksize; inbuf += hd->blocksize; } - _gcry_burn_stack (hd->stack_burn); + _gcry_burn_stack (stack_burn); for (; inlen && hd->count < hd->blocksize; inlen--) hd->buf[hd->count++] = *inbuf++; } diff --git a/cipher/hash-common.h b/cipher/hash-common.h index 4dd5441..3caf0a7 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -29,7 +29,8 @@ const char * _gcry_hash_selftest_check_one const void *expect, size_t expectlen); /* Type for the md_write helper function. */ -typedef void (*_gcry_md_block_write_t) (void *c, const unsigned char *buf); +typedef unsigned int (*_gcry_md_block_write_t) (void *c, + const unsigned char *buf); #if defined(HAVE_U64_TYPEDEF) && defined(USE_SHA512) /* SHA-512 needs u64 and larger buffer. */ @@ -47,7 +48,6 @@ typedef struct gcry_md_block_ctx int count; size_t blocksize; _gcry_md_block_write_t bwrite; - size_t stack_burn; } gcry_md_block_ctx_t; diff --git a/cipher/md4.c b/cipher/md4.c index 9e75fbc..2de530c 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -64,7 +64,7 @@ typedef struct { u32 A,B,C,D; /* chaining variables */ } MD4_CONTEXT; -static void +static unsigned int transform ( void *c, const unsigned char *data ); static void @@ -80,7 +80,6 @@ md4_init( void *context ) ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; - ctx->bctx.stack_burn = 80+6*sizeof(void*); ctx->bctx.bwrite = transform; } @@ -92,7 +91,7 @@ md4_init( void *context ) /**************** * transform 64 bytes */ -static void +static unsigned int transform ( void *c, const unsigned char *data ) { MD4_CONTEXT *ctx = c; @@ -188,6 +187,8 @@ transform ( void *c, const unsigned char *data ) ctx->B += B; ctx->C += C; ctx->D += D; + + return /*burn_stack*/ 80+6*sizeof(void*); } @@ -204,6 +205,7 @@ md4_final( void *context ) MD4_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; + unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; @@ -244,8 +246,8 @@ md4_final( void *context ) hd->bctx.buf[61] = msb >> 8; hd->bctx.buf[62] = msb >> 16; hd->bctx.buf[63] = msb >> 24; - transform( hd, hd->bctx.buf ); - _gcry_burn_stack (80+6*sizeof(void*)); + burn = transform( hd, hd->bctx.buf ); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN diff --git a/cipher/md5.c b/cipher/md5.c index 9857f2c..88745a8 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -48,7 +48,7 @@ typedef struct { u32 A,B,C,D; /* chaining variables */ } MD5_CONTEXT; -static void +static unsigned int transform ( void *ctx, const unsigned char *data ); static void @@ -64,7 +64,6 @@ md5_init( void *context ) ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; - ctx->bctx.stack_burn = 80+6*sizeof(void*); ctx->bctx.bwrite = transform; } @@ -82,7 +81,7 @@ md5_init( void *context ) /**************** * transform n*64 bytes */ -static void +static unsigned int transform ( void *c, const unsigned char *data ) { MD5_CONTEXT *ctx = c; @@ -213,6 +212,8 @@ transform ( void *c, const unsigned char *data ) ctx->B += B; ctx->C += C; ctx->D += D; + + return /*burn_stack*/ 80+6*sizeof(void*); } @@ -229,6 +230,7 @@ md5_final( void *context) MD5_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; + unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; @@ -269,8 +271,8 @@ md5_final( void *context) hd->bctx.buf[61] = msb >> 8; hd->bctx.buf[62] = msb >> 16; hd->bctx.buf[63] = msb >> 24; - transform( hd, hd->bctx.buf ); - _gcry_burn_stack (80+6*sizeof(void*)); + burn = transform( hd, hd->bctx.buf ); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 5bb32a6..7f143df 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -139,7 +139,7 @@ * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ -static void +static unsigned int transform ( void *ctx, const unsigned char *data ); void @@ -152,10 +152,10 @@ _gcry_rmd160_init (void *context) hd->h2 = 0x98BADCFE; hd->h3 = 0x10325476; hd->h4 = 0xC3D2E1F0; + hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; - hd->bctx.stack_burn = 108+5*sizeof(void*); hd->bctx.bwrite = transform; } @@ -164,7 +164,7 @@ _gcry_rmd160_init (void *context) /**************** * Transform the message X which consists of 16 32-bit-words */ -static void +static unsigned int transform ( void *ctx, const unsigned char *data ) { RMD160_CONTEXT *hd = ctx; @@ -400,6 +400,8 @@ transform ( void *ctx, const unsigned char *data ) hd->h3 = hd->h4 + b + aa; hd->h4 = hd->h0 + c + bb; hd->h0 = t; + + return /*burn_stack*/ 108+5*sizeof(void*); } @@ -434,6 +436,7 @@ rmd160_final( void *context ) RMD160_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; + unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; @@ -474,8 +477,8 @@ rmd160_final( void *context ) hd->bctx.buf[61] = msb >> 8; hd->bctx.buf[62] = msb >> 16; hd->bctx.buf[63] = msb >> 24; - transform( hd, hd->bctx.buf ); - _gcry_burn_stack (108+5*sizeof(void*)); + burn = transform( hd, hd->bctx.buf ); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN diff --git a/cipher/sha1.c b/cipher/sha1.c index 9e4e9c6..382bce8 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -57,10 +57,10 @@ typedef struct u32 h0,h1,h2,h3,h4; } SHA1_CONTEXT; - -static void +static unsigned int transform (void *c, const unsigned char *data); + static void sha1_init (void *context) { @@ -71,10 +71,10 @@ sha1_init (void *context) hd->h2 = 0x98badcfe; hd->h3 = 0x10325476; hd->h4 = 0xc3d2e1f0; + hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; - hd->bctx.stack_burn = 88+4*sizeof(void*); hd->bctx.bwrite = transform; } @@ -104,7 +104,7 @@ sha1_init (void *context) /* * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA. */ -static void +static unsigned int transform (void *ctx, const unsigned char *data) { SHA1_CONTEXT *hd = ctx; @@ -224,6 +224,8 @@ transform (void *ctx, const unsigned char *data) hd->h2 += c; hd->h3 += d; hd->h4 += e; + + return /* burn_stack */ 88+4*sizeof(void*); } @@ -238,9 +240,9 @@ static void sha1_final(void *context) { SHA1_CONTEXT *hd = context; - u32 t, msb, lsb; unsigned char *p; + unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; @@ -281,8 +283,8 @@ sha1_final(void *context) hd->bctx.buf[61] = lsb >> 16; hd->bctx.buf[62] = lsb >> 8; hd->bctx.buf[63] = lsb ; - transform( hd, hd->bctx.buf ); - _gcry_burn_stack (88+4*sizeof(void*)); + burn = transform( hd, hd->bctx.buf ); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN diff --git a/cipher/sha256.c b/cipher/sha256.c index 1785699..cf23f2f 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -50,9 +50,10 @@ typedef struct { u32 h0,h1,h2,h3,h4,h5,h6,h7; } SHA256_CONTEXT; -static void +static unsigned int transform (void *c, const unsigned char *data); + static void sha256_init (void *context) { @@ -70,7 +71,6 @@ sha256_init (void *context) hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; - hd->bctx.stack_burn = 74*4+32; hd->bctx.bwrite = transform; } @@ -92,7 +92,6 @@ sha224_init (void *context) hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; - hd->bctx.stack_burn = 74*4+32; hd->bctx.bwrite = transform; } @@ -145,7 +144,7 @@ Sum1 (u32 x) } -static void +static unsigned int transform (void *ctx, const unsigned char *data) { SHA256_CONTEXT *hd = ctx; @@ -261,6 +260,8 @@ transform (void *ctx, const unsigned char *data) hd->h5 += f; hd->h6 += g; hd->h7 += h; + + return /*burn_stack*/ 74*4+32; } #undef S0 #undef S1 @@ -278,6 +279,7 @@ sha256_final(void *context) SHA256_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; + unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; @@ -318,8 +320,8 @@ sha256_final(void *context) hd->bctx.buf[61] = lsb >> 16; hd->bctx.buf[62] = lsb >> 8; hd->bctx.buf[63] = lsb; - transform (hd, hd->bctx.buf); - _gcry_burn_stack (74*4+32); + burn = transform (hd, hd->bctx.buf); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN diff --git a/cipher/sha512.c b/cipher/sha512.c index ed63ae6..26cbe14 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -63,7 +63,6 @@ # endif #endif - typedef struct { u64 h0, h1, h2, h3, h4, h5, h6, h7; @@ -78,7 +77,7 @@ typedef struct #endif } SHA512_CONTEXT; -static void +static unsigned int transform (void *context, const unsigned char *data); static void @@ -100,7 +99,6 @@ sha512_init (void *context) ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; - ctx->bctx.stack_burn = 256; #ifdef USE_ARM_NEON_ASM ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; @@ -126,7 +124,6 @@ sha384_init (void *context) ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; - ctx->bctx.stack_burn = 256; #ifdef USE_ARM_NEON_ASM ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; @@ -211,7 +208,7 @@ static const u64 k[] = /**************** * Transform the message W which consists of 16 64-bit-words */ -static void +static unsigned int __transform (SHA512_STATE *hd, const unsigned char *data) { u64 a, b, c, d, e, f, g, h; @@ -489,6 +486,9 @@ __transform (SHA512_STATE *hd, const unsigned char *data) hd->h5 += f; hd->h6 += g; hd->h7 += h; + + return /* burn_stack */ (8 + 16) * sizeof(u64) + sizeof(u32) + + 3 * sizeof(void*); } @@ -499,7 +499,7 @@ void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd, #endif -static void +static unsigned int transform (void *context, const unsigned char *data) { SHA512_CONTEXT *ctx = context; @@ -509,17 +509,13 @@ transform (void *context, const unsigned char *data) { _gcry_sha512_transform_armv7_neon(&ctx->state, data, k); - /* TODO: return burn stack to md_block_write */ - /* return stack burn depth */ - return /*(sizeof(void *) * 3)*/; + /* _gcry_sha512_transform_armv7_neon does not store sensitive data + * to stack. */ + return /* no burn_stack */ 0; } #endif - __transform (&ctx->state, data); - - /* TODO: return burn stack to md_block_write */ - /* return stack burn depth */ - return /*256*/; + return __transform (&ctx->state, data) + 3 * sizeof(void*); } @@ -587,8 +583,7 @@ sha512_final (void *context) hd->bctx.buf[125] = lsb >> 16; hd->bctx.buf[126] = lsb >> 8; hd->bctx.buf[127] = lsb; - transform (hd, hd->bctx.buf); - stack_burn_depth = hd->bctx.stack_burn; + stack_burn_depth = transform (hd, hd->bctx.buf); _gcry_burn_stack (stack_burn_depth); p = hd->bctx.buf; diff --git a/cipher/stribog.c b/cipher/stribog.c index 234a17e..1f79882 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -1274,7 +1274,7 @@ static void g (u64 *h, u64 *m, u64 *N) } -static void +static unsigned int transform64 (void *context, const unsigned char *inbuf_arg); @@ -1287,7 +1287,6 @@ stribog_init_512 (void *context) hd->bctx.blocksize = 64; hd->bctx.bwrite = transform64; - hd->bctx.stack_burn = 768; } static void @@ -1346,12 +1345,14 @@ transform (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count) hd->Sigma[i] += M[i]; } -static void +static unsigned int transform64 (void *context, const unsigned char *inbuf_arg) { STRIBOG_CONTEXT *hd = context; transform (hd, inbuf_arg, 64 * 8); + + return /* burn_stack */ 768; } /* diff --git a/cipher/tiger.c b/cipher/tiger.c index 49d3919..8f5959b 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -587,7 +587,7 @@ static u64 sbox4[256] = { U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */ }; -static void +static unsigned int transform ( void *ctx, const unsigned char *data ); static void @@ -598,10 +598,10 @@ do_init (void *context, int variant) hd->a = 0x0123456789abcdefLL; hd->b = 0xfedcba9876543210LL; hd->c = 0xf096a5b4c3b2e187LL; + hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; - hd->bctx.stack_burn = 21*8+11*sizeof(void*); hd->bctx.bwrite = transform; hd->variant = variant; } @@ -691,7 +691,7 @@ key_schedule( u64 *x ) /**************** * Transform the message DATA which consists of 512 bytes (8 words) */ -static void +static unsigned int transform ( void *ctx, const unsigned char *data ) { TIGER_CONTEXT *hd = ctx; @@ -735,6 +735,8 @@ transform ( void *ctx, const unsigned char *data ) hd->a = a; hd->b = b; hd->c = c; + + return /*burn_stack*/ 21*8+11*sizeof(void*); } @@ -747,6 +749,7 @@ tiger_final( void *context ) TIGER_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; + unsigned int burn; byte pad = hd->variant == 2? 0x80 : 0x01; _gcry_md_block_write(hd, NULL, 0); /* flush */; @@ -788,8 +791,8 @@ tiger_final( void *context ) hd->bctx.buf[61] = msb >> 8; hd->bctx.buf[62] = msb >> 16; hd->bctx.buf[63] = msb >> 24; - transform( hd, hd->bctx.buf ); - _gcry_burn_stack (21*8+11*sizeof(void*)); + burn = transform( hd, hd->bctx.buf ); + _gcry_burn_stack (burn); p = hd->bctx.buf; #ifdef WORDS_BIGENDIAN ----------------------------------------------------------------------- Summary of changes: cipher/gost28147.c | 2 +- cipher/gostr3411-94.c | 24 +++++++++++++++++------- cipher/hash-common.c | 10 ++++++---- cipher/hash-common.h | 4 ++-- cipher/md4.c | 12 +++++++----- cipher/md5.c | 12 +++++++----- cipher/rmd160.c | 13 ++++++++----- cipher/sha1.c | 16 +++++++++------- cipher/sha256.c | 14 ++++++++------ cipher/sha512.c | 27 +++++++++++---------------- cipher/stribog.c | 7 ++++--- cipher/tiger.c | 13 ++++++++----- 12 files changed, 88 insertions(+), 66 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 21 15:05:06 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 21 Sep 2013 15:05:06 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-262-g9337e03 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 9337e03824a5bdd3bbbcb8382cabefe6d6c32e1e (commit) from 7409de7bc28ff8847c9d71d8c3e35e1968d59d60 (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 9337e03824a5bdd3bbbcb8382cabefe6d6c32e1e Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Optimize and cleanup 32-bit and 64-bit endianess transforms * cipher/bithelp.h (bswap32, bswap64, le_bswap32, be_bswap32) (le_bswap64, be_bswap64): New. * cipher/bufhelp.h (buf_get_be32, buf_get_le32, buf_put_le32) (buf_put_be32, buf_get_be64, buf_get_le64, buf_put_be64) (buf_put_le64): New. * cipher/blowfish.c (do_encrypt_block, do_decrypt_block): Use new endian conversion helpers. (do_bf_setkey): Turn endian specific code to generic. * cipher/camellia.c (GETU32, PUTU32): Use new endian conversion helpers. * cipher/cast5.c (rol): Remove, use rol from bithelp. (F1, F2, F3): Fix to use rol from bithelp. (do_encrypt_block, do_decrypt_block, do_cast_setkey): Use new endian conversion helpers. * cipher/des.c (READ_64BIT_DATA, WRITE_64BIT_DATA): Ditto. * cipher/md4.c (transform, md4_final): Ditto. * cipher/md5.c (transform, md5_final): Ditto. * cipher/rmd160.c (transform, rmd160_final): Ditto. * cipher/salsa20.c (LE_SWAP32, LE_READ_UINT32): Ditto. * cipher/scrypt.c (READ_UINT64, LE_READ_UINT64, LE_SWAP32): Ditto. * cipher/seed.c (GETU32, PUTU32): Ditto. * cipher/serpent.c (byte_swap_32): Remove. (serpent_key_prepare, serpent_encrypt_internal) (serpent_decrypt_internal): Use new endian conversion helpers. * cipher/sha1.c (transform, sha1_final): Ditto. * cipher/sha256.c (transform, sha256_final): Ditto. * cipher/sha512.c (__transform, sha512_final): Ditto. * cipher/stribog.c (transform, stribog_final): Ditto. * cipher/tiger.c (transform, tiger_final): Ditto. * cipher/twofish.c (INPACK, OUTUNPACK): Ditto. * cipher/whirlpool.c (buffer_to_block, block_to_buffer): Ditto. * configure.ac (gcry_cv_have_builtin_bswap32): Check for compiler provided __builtin_bswap32. (gcry_cv_have_builtin_bswap64): Check for compiler provided __builtin_bswap64. -- Patch add helper functions that provide conversions to/from integers and buffers of different endianess. Benefits are code cleanup and optimization for architectures that have byte-swaping instructions and/or can do fast unaligned memory accesses. Signed-off-by: Jussi Kivilinna diff --git a/cipher/bithelp.h b/cipher/bithelp.h index 785701e..734dcbb 100644 --- a/cipher/bithelp.h +++ b/cipher/bithelp.h @@ -20,6 +20,8 @@ #ifndef G10_BITHELP_H #define G10_BITHELP_H +#include "types.h" + /**************** * Rotate the 32 bit unsigned integer X by N bits left/right @@ -52,5 +54,43 @@ ror(u32 x, int n) #define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) #endif +/* Byte swap for 32-bit and 64-bit integers. If available, use compiler + provided helpers. */ +#ifdef HAVE_BUILTIN_BSWAP32 +# define bswap32 __builtin_bswap32 +#else +static inline u32 bswap32(u32 x) +{ + return ((rol(x, 8) & 0x00ff00ffL) | (ror(x, 8) & 0xff00ff00L)); +} +#endif + +#ifdef HAVE_U64_TYPEDEF +# ifdef HAVE_BUILTIN_BSWAP64 +# define bswap64 __builtin_bswap64 +# else +static inline u64 bswap64(u64 x) +{ + return ((u64)bswap32(x) << 32) | (bswap32(x >> 32)); +} +# endif +#endif + +/* Endian dependent byte swap operations. */ +#ifdef WORDS_BIGENDIAN +# define le_bswap32(x) bswap32(x) +# define be_bswap32(x) ((u32)(x)) +# ifdef HAVE_U64_TYPEDEF +# define le_bswap64(x) bswap64(x) +# define be_bswap64(x) ((u64)(x)) +# endif +#else +# define le_bswap32(x) ((u32)(x)) +# define be_bswap32(x) bswap32(x) +# ifdef HAVE_U64_TYPEDEF +# define le_bswap64(x) ((u64)(x)) +# define be_bswap64(x) bswap64(x) +# endif +#endif #endif /*G10_BITHELP_H*/ diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 80e1ec7..61042ed 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -544,17 +544,11 @@ do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf ) { u32 d1, d2; - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + d1 = buf_get_be32(inbuf); + d2 = buf_get_be32(inbuf + 4); do_encrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; + buf_put_be32(outbuf, d1); + buf_put_be32(outbuf + 4, d2); } static unsigned int @@ -571,17 +565,11 @@ do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf) { u32 d1, d2; - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + d1 = buf_get_be32(inbuf); + d2 = buf_get_be32(inbuf + 4); decrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; + buf_put_be32(outbuf, d1); + buf_put_be32(outbuf + 4, d2); } static unsigned int @@ -903,17 +891,10 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { -#ifdef WORDS_BIGENDIAN - ((byte*)&data)[0] = key[j]; - ((byte*)&data)[1] = key[(j+1)%keylen]; - ((byte*)&data)[2] = key[(j+2)%keylen]; - ((byte*)&data)[3] = key[(j+3)%keylen]; -#else - ((byte*)&data)[3] = key[j]; - ((byte*)&data)[2] = key[(j+1)%keylen]; - ((byte*)&data)[1] = key[(j+2)%keylen]; - ((byte*)&data)[0] = key[(j+3)%keylen]; -#endif + data = ((u32)key[j] << 24) | + ((u32)key[(j+1)%keylen] << 16) | + ((u32)key[(j+2)%keylen] << 8) | + ((u32)key[(j+3)%keylen]); c->p[i] ^= data; j = (j+4) % keylen; } diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index d829cf1..c637dac 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -20,6 +20,8 @@ #ifndef G10_BUFHELP_H #define G10_BUFHELP_H +#include + #ifdef HAVE_STDINT_H # include /* uintptr_t */ #elif defined(HAVE_INTTYPES_H) @@ -28,6 +30,8 @@ /* In this case, uintptr_t is provided by config.h. */ #endif +#include "bithelp.h" + #if defined(__i386__) || defined(__x86_64__) || \ (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) @@ -179,4 +183,143 @@ do_bytes: } } + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \ + ((u32)in[2] << 8) | (u32)in[3]; +} + +static inline u32 buf_get_le32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \ + ((u32)in[1] << 8) | (u32)in[0]; +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + byte *out = _buf; + out[0] = val >> 24; + out[1] = val >> 16; + out[2] = val >> 8; + out[3] = val; +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + byte *out = _buf; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + +#ifdef HAVE_U64_TYPEDEF +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \ + ((u64)in[2] << 40) | ((u64)in[3] << 32) | \ + ((u64)in[4] << 24) | ((u64)in[5] << 16) | \ + ((u64)in[6] << 8) | (u64)in[7]; +} + +static inline u64 buf_get_le64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \ + ((u64)in[5] << 40) | ((u64)in[4] << 32) | \ + ((u64)in[3] << 24) | ((u64)in[2] << 16) | \ + ((u64)in[1] << 8) | (u64)in[0]; +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + byte *out = _buf; + out[0] = val >> 56; + out[1] = val >> 48; + out[2] = val >> 40; + out[3] = val >> 32; + out[4] = val >> 24; + out[5] = val >> 16; + out[6] = val >> 8; + out[7] = val; +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + byte *out = _buf; + out[7] = val >> 56; + out[6] = val >> 48; + out[5] = val >> 40; + out[4] = val >> 32; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} +#endif /*HAVE_U64_TYPEDEF*/ + +#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + return be_bswap32(*(const u32 *)_buf); +} + +static inline u32 buf_get_le32(const void *_buf) +{ + return le_bswap32(*(const u32 *)_buf); +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + u32 *out = _buf; + *out = be_bswap32(val); +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + u32 *out = _buf; + *out = le_bswap32(val); +} + +#ifdef HAVE_U64_TYPEDEF +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + return be_bswap64(*(const u64 *)_buf); +} + +static inline u64 buf_get_le64(const void *_buf) +{ + return le_bswap64(*(const u64 *)_buf); +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + u64 *out = _buf; + *out = be_bswap64(val); +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + u64 *out = _buf; + *out = le_bswap64(val); +} +#endif /*HAVE_U64_TYPEDEF*/ + +#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + #endif /*G10_BITHELP_H*/ diff --git a/cipher/camellia.c b/cipher/camellia.c index 038d911..03510a3 100644 --- a/cipher/camellia.c +++ b/cipher/camellia.c @@ -25,6 +25,7 @@ #include #include +#include "bufhelp.h" #include "camellia.h" /* u32 must be 32bit word */ @@ -59,17 +60,8 @@ typedef unsigned char u8; #else /* not MS-VC */ -# define GETU32(pt) \ - (((u32)(pt)[0] << 24) \ - ^ ((u32)(pt)[1] << 16) \ - ^ ((u32)(pt)[2] << 8) \ - ^ ((u32)(pt)[3])) - -# define PUTU32(ct, st) { \ - (ct)[0] = (u8)((st) >> 24); \ - (ct)[1] = (u8)((st) >> 16); \ - (ct)[2] = (u8)((st) >> 8); \ - (ct)[3] = (u8)(st); } +# define GETU32(pt) buf_get_be32(pt) +# define PUTU32(ct, st) buf_put_be32(ct, st) #endif diff --git a/cipher/cast5.c b/cipher/cast5.c index 0cd5953..ae6b509 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -42,6 +42,7 @@ #include "g10lib.h" #include "types.h" #include "cipher.h" +#include "bithelp.h" #include "bufhelp.h" #include "cipher-selftest.h" @@ -448,25 +449,11 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf) #else /*USE_ARMV6_ASM*/ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol(int n, u32 x) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n) - :"cc"); - return x; -} -#else -#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - -#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ +#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol(I,(r))), \ (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) -#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ +#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol(I,(r))), \ (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) -#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ +#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol(I,(r))), \ (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) static void @@ -483,8 +470,8 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) */ - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = buf_get_be32(inbuf + 0); + r = buf_get_be32(inbuf + 4); /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: * Li = Ri-1; @@ -513,14 +500,8 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and * concatenate to form the ciphertext.) */ - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + buf_put_be32(outbuf + 0, r); + buf_put_be32(outbuf + 4, l); } static unsigned int @@ -543,8 +524,8 @@ do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) Km = c->Km; Kr = c->Kr; - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = buf_get_be32(inbuf + 0); + r = buf_get_be32(inbuf + 4); t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); @@ -563,14 +544,8 @@ do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + buf_put_be32(outbuf + 0, r); + buf_put_be32(outbuf + 4, l); } static unsigned int @@ -949,10 +924,10 @@ do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) if( keylen != 16 ) return GPG_ERR_INV_KEYLEN; - x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; - x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; - x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; - x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; + x[0] = buf_get_be32(key + 0); + x[1] = buf_get_be32(key + 4); + x[2] = buf_get_be32(key + 8); + x[3] = buf_get_be32(key + 12); key_schedule( x, z, k ); for(i=0; i < 16; i++ ) diff --git a/cipher/des.c b/cipher/des.c index 7db9e5d..f1550d1 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -118,6 +118,7 @@ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" +#include "bufhelp.h" #if defined(__GNUC__) && defined(__GNU_LIBRARY__) #define working_memcmp memcmp @@ -455,14 +456,12 @@ static unsigned char weak_keys_chksum[20] = { * Macros to convert 8 bytes from/to 32bit words. */ #define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + left = buf_get_be32(data + 0); \ + right = buf_get_be32(data + 4); #define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; + buf_put_be32(data + 0, left); \ + buf_put_be32(data + 4, right); /* * Handy macros for encryption and decryption of data diff --git a/cipher/md4.c b/cipher/md4.c index 2de530c..e2d096c 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -56,6 +56,7 @@ #include "cipher.h" #include "bithelp.h" +#include "bufhelp.h" #include "hash-common.h" @@ -100,23 +101,10 @@ transform ( void *c, const unsigned char *data ) register u32 B = ctx->B; register u32 C = ctx->C; register u32 D = ctx->D; + int i; -#ifdef WORDS_BIGENDIAN - { - int i; - byte *p2; - const byte *p1; - for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - memcpy (in, data, 64); -#endif + for ( i = 0; i < 16; i++ ) + in[i] = buf_get_le32(data + i * 4); /* Round 1. */ #define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s); @@ -238,24 +226,13 @@ md4_final( void *context ) memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32((*hd).a) ; p += 4; } while(0) X(A); X(B); X(C); diff --git a/cipher/md5.c b/cipher/md5.c index 88745a8..db0f315 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -40,6 +40,7 @@ #include "cipher.h" #include "bithelp.h" +#include "bufhelp.h" #include "hash-common.h" @@ -91,24 +92,10 @@ transform ( void *c, const unsigned char *data ) register u32 C = ctx->C; register u32 D = ctx->D; u32 *cwp = correct_words; + int i; -#ifdef WORDS_BIGENDIAN - { - int i; - byte *p2; - const byte *p1; - for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - memcpy( correct_words, data, 64 ); -#endif - + for ( i = 0; i < 16; i++ ) + correct_words[i] = buf_get_le32(data + i * 4); #define OP(a, b, c, d, s, T) \ do \ @@ -263,24 +250,13 @@ md5_final( void *context) memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32((*hd).a) ; p += 4; } while(0) X(A); X(B); X(C); diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 7f143df..d156e61 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -28,6 +28,7 @@ #include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ #include "bithelp.h" +#include "bufhelp.h" /********************************* * RIPEMD-160 is not patented, see (as of 25.10.97) @@ -170,32 +171,11 @@ transform ( void *ctx, const unsigned char *data ) RMD160_CONTEXT *hd = ctx; register u32 a,b,c,d,e; u32 aa,bb,cc,dd,ee,t; -#ifdef WORDS_BIGENDIAN u32 x[16]; - { - int i; - byte *p2; - const byte *p1; - for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - /* This version is better because it is always aligned; - * The performance penalty on a 586-100 is about 6% which - * is acceptable - because the data is more local it might - * also be possible that this is faster on some machines. - * This function (when compiled with -02 on gcc 2.7.2) - * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; - * [measured with a 4MB data and "gpgm --print-md rmd160"] */ - u32 x[16]; - memcpy( x, data, 64 ); -#endif + int i; + for ( i = 0; i < 16; i++ ) + x[i] = buf_get_le32(data + i * 4); #define K0 0x00000000 #define K1 0x5A827999 @@ -469,24 +449,13 @@ rmd160_final( void *context ) memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ - *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32(hd->h##a) ; p += 4; } while(0) X(0); X(1); X(2); diff --git a/cipher/salsa20.c b/cipher/salsa20.c index 37f2989..88f5372 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -75,19 +75,9 @@ typedef struct #define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31)))) -#ifdef WORDS_BIGENDIAN -# define LE_SWAP32(v) \ - ( (ROTL32( 8, v) & 0x00FF00FFul) \ - |(ROTL32(24, v) & 0xFF00FF00ul)) -#else -# define LE_SWAP32(v) (v) -#endif +#define LE_SWAP32(v) le_bswap32(v) -#define LE_READ_UINT32(p) \ - ( (((u32)(p)[3]) << 24) \ - | (((u32)(p)[2]) << 16) \ - | (((u32)(p)[1]) << 8) \ - | ((u32)(p)[0])) +#define LE_READ_UINT32(p) buf_get_le32(p) static void salsa20_setiv (void *context, const byte *iv, unsigned int ivlen); diff --git a/cipher/scrypt.c b/cipher/scrypt.c index 9e29288..6f6a7f1 100644 --- a/cipher/scrypt.c +++ b/cipher/scrypt.c @@ -58,38 +58,14 @@ /* Reads a 64-bit integer, in network, big-endian, byte order */ -#define READ_UINT64(p) \ -( (((u64) (p)[0]) << 56) \ - | (((u64) (p)[1]) << 48) \ - | (((u64) (p)[2]) << 40) \ - | (((u64) (p)[3]) << 32) \ - | (((u64) (p)[4]) << 24) \ - | (((u64) (p)[5]) << 16) \ - | (((u64) (p)[6]) << 8) \ - | ((u64) (p)[7])) - +#define READ_UINT64(p) buf_get_be64(p) /* And the other, little-endian, byteorder */ -#define LE_READ_UINT64(p) \ -( (((u64) (p)[7]) << 56) \ - | (((u64) (p)[6]) << 48) \ - | (((u64) (p)[5]) << 40) \ - | (((u64) (p)[4]) << 32) \ - | (((u64) (p)[3]) << 24) \ - | (((u64) (p)[2]) << 16) \ - | (((u64) (p)[1]) << 8) \ - | ((u64) (p)[0])) - - - -#ifdef WORDS_BIGENDIAN -#define LE_SWAP32(v) \ - ((ROTL32(8, v) & 0x00FF00FFUL) | \ - (ROTL32(24, v) & 0xFF00FF00UL)) -#else -#define LE_SWAP32(v) (v) -#endif +#define LE_READ_UINT64(p) buf_get_le64(p) + +#define LE_SWAP32(v) le_bswap32(v) + #define QROUND(x0, x1, x2, x3) do { \ x1 ^= ROTL32(7, x0 + x3); \ diff --git a/cipher/seed.c b/cipher/seed.c index 1600c55..474ccba 100644 --- a/cipher/seed.c +++ b/cipher/seed.c @@ -29,15 +29,12 @@ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" +#include "bufhelp.h" #define NUMKC 16 -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ - ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { (ct)[0] = (byte)((st) >> 24); \ - (ct)[1] = (byte)((st) >> 16); \ - (ct)[2] = (byte)((st) >> 8); \ - (ct)[3] = (byte)(st); } +#define GETU32(pt) buf_get_be32(pt) +#define PUTU32(ct, st) buf_put_be32(ct, st) union wordbuf { diff --git a/cipher/serpent.c b/cipher/serpent.c index 72895ed..4720b9c 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -119,11 +119,6 @@ extern void _gcry_serpent_avx2_cfb_dec(serpent_context_t *ctx, static const char *serpent_test (void); -#define byte_swap_32(x) \ - (0 \ - | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ - | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - /* * These are the S-Boxes of Serpent from following research paper. * @@ -548,14 +543,10 @@ serpent_key_prepare (const byte *key, unsigned int key_length, int i; /* Copy key. */ - memcpy (key_prepared, key, key_length); key_length /= 4; -#ifdef WORDS_BIGENDIAN for (i = 0; i < key_length; i++) - key_prepared[i] = byte_swap_32 (key_prepared[i]); -#else - i = key_length; -#endif + key_prepared[i] = buf_get_le32 (key + i * 4); + if (i < 8) { /* Key must be padded according to the Serpent @@ -683,13 +674,10 @@ serpent_encrypt_internal (serpent_context_t *context, serpent_block_t b, b_next; int round = 0; - memcpy (b, input, sizeof (b)); -#ifdef WORDS_BIGENDIAN - b[0] = byte_swap_32 (b[0]); - b[1] = byte_swap_32 (b[1]); - b[2] = byte_swap_32 (b[2]); - b[3] = byte_swap_32 (b[3]); -#endif + b[0] = buf_get_le32 (input + 0); + b[1] = buf_get_le32 (input + 4); + b[2] = buf_get_le32 (input + 8); + b[3] = buf_get_le32 (input + 12); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); @@ -725,13 +713,10 @@ serpent_encrypt_internal (serpent_context_t *context, ROUND_LAST (7, context->keys, b, b_next); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif - memcpy (output, b_next, sizeof (b_next)); + buf_put_le32 (output + 0, b_next[0]); + buf_put_le32 (output + 4, b_next[1]); + buf_put_le32 (output + 8, b_next[2]); + buf_put_le32 (output + 12, b_next[3]); } static void @@ -741,13 +726,10 @@ serpent_decrypt_internal (serpent_context_t *context, serpent_block_t b, b_next; int round = ROUNDS; - memcpy (b_next, input, sizeof (b)); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif + b_next[0] = buf_get_le32 (input + 0); + b_next[1] = buf_get_le32 (input + 4); + b_next[2] = buf_get_le32 (input + 8); + b_next[3] = buf_get_le32 (input + 12); ROUND_FIRST_INVERSE (7, context->keys, b_next, b); @@ -783,13 +765,10 @@ serpent_decrypt_internal (serpent_context_t *context, ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif - memcpy (output, b_next, sizeof (b_next)); + buf_put_le32 (output + 0, b_next[0]); + buf_put_le32 (output + 4, b_next[1]); + buf_put_le32 (output + 8, b_next[2]); + buf_put_le32 (output + 12, b_next[3]); } static unsigned int diff --git a/cipher/sha1.c b/cipher/sha1.c index 382bce8..aef9f05 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -38,6 +38,7 @@ #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" @@ -108,27 +109,13 @@ static unsigned int transform (void *ctx, const unsigned char *data) { SHA1_CONTEXT *hd = ctx; + const u32 *idata = (const void *)data; register u32 a, b, c, d, e; /* Local copies of the chaining variables. */ register u32 tm; /* Helper. */ u32 x[16]; /* The array we work on. */ -#ifdef WORDS_BIGENDIAN - memcpy (x, data, 64); - data += 64; -#else - { - int i; - unsigned char *p; - - for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 ) - { - p[3] = *data++; - p[2] = *data++; - p[1] = *data++; - p[0] = *data++; - } - } -#endif +#define I(i) (x[i] = buf_get_be32(idata + i)) + /* Get the values of the chaining variables. */ a = hd->h0; b = hd->h1; @@ -137,22 +124,22 @@ transform (void *ctx, const unsigned char *data) e = hd->h4; /* Transform. */ - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); + R( a, b, c, d, e, F1, K1, I( 0) ); + R( e, a, b, c, d, F1, K1, I( 1) ); + R( d, e, a, b, c, F1, K1, I( 2) ); + R( c, d, e, a, b, F1, K1, I( 3) ); + R( b, c, d, e, a, F1, K1, I( 4) ); + R( a, b, c, d, e, F1, K1, I( 5) ); + R( e, a, b, c, d, F1, K1, I( 6) ); + R( d, e, a, b, c, F1, K1, I( 7) ); + R( c, d, e, a, b, F1, K1, I( 8) ); + R( b, c, d, e, a, F1, K1, I( 9) ); + R( a, b, c, d, e, F1, K1, I(10) ); + R( e, a, b, c, d, F1, K1, I(11) ); + R( d, e, a, b, c, F1, K1, I(12) ); + R( c, d, e, a, b, F1, K1, I(13) ); + R( b, c, d, e, a, F1, K1, I(14) ); + R( a, b, c, d, e, F1, K1, I(15) ); R( e, a, b, c, d, F1, K1, M(16) ); R( d, e, a, b, c, F1, K1, M(17) ); R( c, d, e, a, b, F1, K1, M(18) ); @@ -275,24 +262,13 @@ sha1_final(void *context) memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = msb >> 24; - hd->bctx.buf[57] = msb >> 16; - hd->bctx.buf[58] = msb >> 8; - hd->bctx.buf[59] = msb ; - hd->bctx.buf[60] = lsb >> 24; - hd->bctx.buf[61] = lsb >> 16; - hd->bctx.buf[62] = lsb >> 8; - hd->bctx.buf[63] = lsb ; + buf_put_be32(hd->bctx.buf + 56, msb); + buf_put_be32(hd->bctx.buf + 60, lsb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) -#endif +#define X(a) do { *(u32*)p = be_bswap32(hd->h##a) ; p += 4; } while(0) X(0); X(1); X(2); diff --git a/cipher/sha256.c b/cipher/sha256.c index cf23f2f..ad08cc7 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -42,6 +42,7 @@ #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" @@ -168,7 +169,6 @@ transform (void *ctx, const unsigned char *data) }; u32 a,b,c,d,e,f,g,h,t1,t2; - u32 x[16]; u32 w[64]; int i; @@ -181,24 +181,8 @@ transform (void *ctx, const unsigned char *data) g = hd->h6; h = hd->h7; -#ifdef WORDS_BIGENDIAN - memcpy (x, data, 64); -#else - { - byte *p2; - - for (i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) - { - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif - for (i=0; i < 16; i++) - w[i] = x[i]; + w[i] = buf_get_be32(data + i * 4); for (; i < 64; i++) w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16]; @@ -312,24 +296,13 @@ sha256_final(void *context) memset (hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = msb >> 24; - hd->bctx.buf[57] = msb >> 16; - hd->bctx.buf[58] = msb >> 8; - hd->bctx.buf[59] = msb; - hd->bctx.buf[60] = lsb >> 24; - hd->bctx.buf[61] = lsb >> 16; - hd->bctx.buf[62] = lsb >> 8; - hd->bctx.buf[63] = lsb; + buf_put_be32(hd->bctx.buf + 56, msb); + buf_put_be32(hd->bctx.buf + 60, lsb); burn = transform (hd, hd->bctx.buf); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) -#endif +#define X(a) do { *(u32*)p = be_bswap32(hd->h##a); p += 4; } while(0) X(0); X(1); X(2); diff --git a/cipher/sha512.c b/cipher/sha512.c index 26cbe14..505a1e4 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -50,6 +50,7 @@ #include #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" @@ -225,26 +226,8 @@ __transform (SHA512_STATE *hd, const unsigned char *data) g = hd->h6; h = hd->h7; -#ifdef WORDS_BIGENDIAN - memcpy (w, data, 128); -#else - { - int i; - byte *p2; - - for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8) - { - p2[7] = *data++; - p2[6] = *data++; - p2[5] = *data++; - p2[4] = *data++; - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif + for ( t = 0; t < 16; t++ ) + w[t] = buf_get_be64(data + t * 8); #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) @@ -566,35 +549,13 @@ sha512_final (void *context) memset (hd->bctx.buf, 0, 112); /* fill next block with zeroes */ } /* append the 128 bit count */ - hd->bctx.buf[112] = msb >> 56; - hd->bctx.buf[113] = msb >> 48; - hd->bctx.buf[114] = msb >> 40; - hd->bctx.buf[115] = msb >> 32; - hd->bctx.buf[116] = msb >> 24; - hd->bctx.buf[117] = msb >> 16; - hd->bctx.buf[118] = msb >> 8; - hd->bctx.buf[119] = msb; - - hd->bctx.buf[120] = lsb >> 56; - hd->bctx.buf[121] = lsb >> 48; - hd->bctx.buf[122] = lsb >> 40; - hd->bctx.buf[123] = lsb >> 32; - hd->bctx.buf[124] = lsb >> 24; - hd->bctx.buf[125] = lsb >> 16; - hd->bctx.buf[126] = lsb >> 8; - hd->bctx.buf[127] = lsb; + buf_put_be64(hd->bctx.buf + 112, msb); + buf_put_be64(hd->bctx.buf + 120, lsb); stack_burn_depth = transform (hd, hd->bctx.buf); _gcry_burn_stack (stack_burn_depth); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u64*)p = hd->state.h##a ; p += 8; } while (0) -#else /* little endian */ -#define X(a) do { *p++ = hd->state.h##a >> 56; *p++ = hd->state.h##a >> 48; \ - *p++ = hd->state.h##a >> 40; *p++ = hd->state.h##a >> 32; \ - *p++ = hd->state.h##a >> 24; *p++ = hd->state.h##a >> 16; \ - *p++ = hd->state.h##a >> 8; *p++ = hd->state.h##a; } while(0) -#endif +#define X(a) do { *(u64*)p = be_bswap64(hd->state.h##a) ; p += 8; } while (0) X (0); X (1); X (2); diff --git a/cipher/stribog.c b/cipher/stribog.c index 1f79882..61aa222 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -27,6 +27,7 @@ #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" @@ -1304,25 +1305,8 @@ transform (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count) u64 l; int i; -#ifndef WORDS_BIGENDIAN - memcpy (M, data, 64); -#else - { - byte *p2; - - for (i = 0, p2 = (byte *) M; i < 8; i++, p2 += 8) - { - p2[7] = *data++; - p2[6] = *data++; - p2[5] = *data++; - p2[4] = *data++; - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif + for (i = 0; i < 8; i++) + M[i] = buf_get_le64(data + i * 8); g (hd->h, M, hd->N); l = hd->N[0]; @@ -1379,19 +1363,8 @@ stribog_final (void *context) g (hd->h, hd->N, Z); g (hd->h, hd->Sigma, Z); -#ifdef WORDS_BIGENDIAN for (i = 0; i < 8; i++) - { - u64 T = hd->h[i]; - T = ((T & U64_C(0x00ff00ff00ff00ff)) << 8) | - ((T & U64_C(0xff00ff00ff00ff00)) >> 8); - T = ((T & U64_C(0x0000ffff0000ffff)) << 16) | - ((T & U64_C(0xffff0000ffff0000)) >> 16); - T = ((T & U64_C(0x00000000ffffffff)) << 32) | - ((T & U64_C(0xffffffff00000000)) >> 32); - hd->h[i] = T; - } -#endif + hd->h[i] = le_bswap64(hd->h[i]); _gcry_burn_stack (768); } diff --git a/cipher/tiger.c b/cipher/tiger.c index 8f5959b..df16098 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -28,6 +28,8 @@ #include "g10lib.h" #include "cipher.h" #include "hash-common.h" +#include "bithelp.h" +#include "bufhelp.h" /* We really need a 64 bit type for this code. */ #ifdef HAVE_U64_TYPEDEF @@ -697,24 +699,10 @@ transform ( void *ctx, const unsigned char *data ) TIGER_CONTEXT *hd = ctx; u64 a,b,c,aa,bb,cc; u64 x[8]; -#ifdef WORDS_BIGENDIAN -#define MKWORD(d,n) \ - ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ - | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ - | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ - | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) - x[0] = MKWORD(data, 0); - x[1] = MKWORD(data, 1); - x[2] = MKWORD(data, 2); - x[3] = MKWORD(data, 3); - x[4] = MKWORD(data, 4); - x[5] = MKWORD(data, 5); - x[6] = MKWORD(data, 6); - x[7] = MKWORD(data, 7); -#undef MKWORD -#else - memcpy( &x[0], data, 64 ); -#endif + int i; + + for ( i = 0; i < 8; i++ ) + x[i] = buf_get_le64(data + i * 8); /* save */ a = aa = hd->a; @@ -783,30 +771,14 @@ tiger_final( void *context ) memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u64*)p = hd->a ; p += 8; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \ - *p++ = hd->a >> 40; *p++ = hd->a >> 32; \ - *p++ = hd->a >> 24; *p++ = hd->a >> 16; \ - *p++ = hd->a >> 8; *p++ = hd->a; } while(0) -#endif -#define Y(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; \ - *p++ = hd->a >> 32; *p++ = hd->a >> 40; \ - *p++ = hd->a >> 48; *p++ = hd->a >> 56; } while(0) +#define X(a) do { *(u64*)p = be_bswap64(hd->a); p += 8; } while(0) +#define Y(a) do { *(u64*)p = le_bswap64(hd->a); p += 8; } while(0) if (hd->variant == 0) { X(a); diff --git a/cipher/twofish.c b/cipher/twofish.c index 70cdb47..17b3aa3 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -798,13 +798,12 @@ extern void _gcry_twofish_amd64_cfb_dec(const TWOFISH_context *c, byte *out, * whitening subkey number m. */ #define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + x = buf_get_le32(in + (n) * 4); \ + x ^= ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + buf_put_le32(out + (n) * 4, x) #endif /*!USE_AMD64_ASM*/ diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 2c3beb7..954640a 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -37,7 +37,7 @@ #include "g10lib.h" #include "cipher.h" -#include "bithelp.h" +#include "bufhelp.h" /* Size of a whirlpool block (in bytes). */ #define BLOCK_SIZE 64 @@ -65,30 +65,13 @@ typedef struct { counter. */ #define buffer_to_block(buffer, block, i) \ for (i = 0; i < 8; i++) \ - (block)[i] = ((u64) (0 \ - | (((u64) (buffer)[i * 8 + 0]) << 56) \ - | (((u64) (buffer)[i * 8 + 1]) << 48) \ - | (((u64) (buffer)[i * 8 + 2]) << 40) \ - | (((u64) (buffer)[i * 8 + 3]) << 32) \ - | (((u64) (buffer)[i * 8 + 4]) << 24) \ - | (((u64) (buffer)[i * 8 + 5]) << 16) \ - | (((u64) (buffer)[i * 8 + 6]) << 8) \ - | (((u64) (buffer)[i * 8 + 7]) << 0))); + (block)[i] = buf_get_be64((buffer) + i * 8); /* Convert the block BLOCK into a buffer BUFFER, using I as counter. */ #define block_to_buffer(buffer, block, i) \ for (i = 0; i < 8; i++) \ - { \ - (buffer)[i * 8 + 0] = (block[i] >> 56) & 0xFF; \ - (buffer)[i * 8 + 1] = (block[i] >> 48) & 0xFF; \ - (buffer)[i * 8 + 2] = (block[i] >> 40) & 0xFF; \ - (buffer)[i * 8 + 3] = (block[i] >> 32) & 0xFF; \ - (buffer)[i * 8 + 4] = (block[i] >> 24) & 0xFF; \ - (buffer)[i * 8 + 5] = (block[i] >> 16) & 0xFF; \ - (buffer)[i * 8 + 6] = (block[i] >> 8) & 0xFF; \ - (buffer)[i * 8 + 7] = (block[i] >> 0) & 0xFF; \ - } + buf_put_be64((buffer) + i * 8, (block)[i]); /* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ #define block_copy(block_dst, block_src, i) \ diff --git a/configure.ac b/configure.ac index 91bbf4b..2c92028 100644 --- a/configure.ac +++ b/configure.ac @@ -774,6 +774,36 @@ AC_SUBST(FALLBACK_SOCKLEN_T) # +# Check for __builtin_bswap32 intrinsic. +# +AC_CACHE_CHECK(for __builtin_bswap32, + [gcry_cv_have_builtin_bswap32], + [gcry_cv_have_builtin_bswap32=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[int foo(int x) { return __builtin_bswap32(x); }]])], + [gcry_cv_have_builtin_bswap32=yes])]) +if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then + AC_DEFINE(HAVE_BUILTIN_BSWAP32,1, + [Defined if compiler has '__builtin_bswap32' intrinsic]) +fi + + +# +# Check for __builtin_bswap64 intrinsic. +# +AC_CACHE_CHECK(for __builtin_bswap64, + [gcry_cv_have_builtin_bswap64], + [gcry_cv_have_builtin_bswap64=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[int foo(int x) { return __builtin_bswap64(x); }]])], + [gcry_cv_have_builtin_bswap64=yes])]) +if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then + AC_DEFINE(HAVE_BUILTIN_BSWAP64,1, + [Defined if compiler has '__builtin_bswap64' intrinsic]) +fi + + +# # Check for VLA support (variable length arrays). # AC_CACHE_CHECK(whether the variable length arrays are supported, ----------------------------------------------------------------------- Summary of changes: cipher/bithelp.h | 40 +++++++++++++++ cipher/blowfish.c | 43 ++++----------- cipher/bufhelp.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cipher/camellia.c | 14 +---- cipher/cast5.c | 57 ++++++--------------- cipher/des.c | 11 ++-- cipher/md4.c | 37 +++----------- cipher/md5.c | 38 +++----------- cipher/rmd160.c | 45 +++-------------- cipher/salsa20.c | 14 +---- cipher/scrypt.c | 30 +---------- cipher/seed.c | 9 +-- cipher/serpent.c | 57 +++++++-------------- cipher/sha1.c | 70 ++++++++----------------- cipher/sha256.c | 37 ++------------ cipher/sha512.c | 51 ++---------------- cipher/stribog.c | 35 ++----------- cipher/tiger.c | 48 ++++-------------- cipher/twofish.c | 7 +-- cipher/whirlpool.c | 23 +------- configure.ac | 30 +++++++++++ 21 files changed, 350 insertions(+), 489 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sat Sep 21 15:10:18 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 21 Sep 2013 15:10:18 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-264-g925d4fb 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 925d4fb3e8f2df3c5566ec6b5df7620a3d3504e5 (commit) via cfea5c28a3822e1e7e401e5107ebe07ba7fdcf37 (commit) from 9337e03824a5bdd3bbbcb8382cabefe6d6c32e1e (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 925d4fb3e8f2df3c5566ec6b5df7620a3d3504e5 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 bufhelp: enable fast unaligned memory accesses on powerpc * cipher/bufhelp.h [__powerpc__] (BUFHELP_FAST_UNALIGNED_ACCESS): Set macro enabled. [__powerpc64__] (BUFHELP_FAST_UNALIGNED_ACCESS): Ditto. -- PowerPC can handle unaligned memory accesses fast, so enable fast buffer handling in bufhelp.h. Signed-off-by: Jussi Kivilinna diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index c637dac..21fac07 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -34,6 +34,7 @@ #if defined(__i386__) || defined(__x86_64__) || \ + defined(__powerpc__) || defined(__powerpc64__) || \ (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) /* These architectures are able of unaligned memory accesses and can handle those fast. commit cfea5c28a3822e1e7e401e5107ebe07ba7fdcf37 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Remove i386 inline assembly version of rotation functions * cipher/bithelp.h (rol, ror): Remove i386 version, change macros to inline functions. * src/hmac256.c (ror): Ditto. -- (Current) compilers can optimize '(x << c) | (x >> (32-c))' to rotation instruction. So remove i386 specific assembly for manually doing this. Furthermore, compiler can generate faster code in case where 'c' is constant and can use rotate with immediate value rather than rotate with %cl register. Signed-off-by: Jussi Kivilinna diff --git a/cipher/bithelp.h b/cipher/bithelp.h index 734dcbb..601ecac 100644 --- a/cipher/bithelp.h +++ b/cipher/bithelp.h @@ -26,33 +26,15 @@ /**************** * Rotate the 32 bit unsigned integer X by N bits left/right */ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol( u32 x, int n) +static inline u32 rol( u32 x, int n) { - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n) - :"cc"); - return x; + return ( (x << n) | (x >> (32-n)) ); } -#else -#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -ror(u32 x, int n) +static inline u32 ror(u32 x, int n) { - __asm__("rorl %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n) - :"cc"); - return x; + return ( (x >> n) | (x << (32-n)) ); } -#else -#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) -#endif /* Byte swap for 32-bit and 64-bit integers. If available, use compiler provided helpers. */ diff --git a/src/hmac256.c b/src/hmac256.c index 2fda47b..94a26da 100644 --- a/src/hmac256.c +++ b/src/hmac256.c @@ -98,19 +98,10 @@ struct hmac256_context /* Rotate a 32 bit word. */ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -ror(u32 x, int n) +static inline u32 ror(u32 x, int n) { - __asm__("rorl %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n) - :"cc"); - return x; + return ( ((x) >> (n)) | ((x) << (32-(n))) ); } -#else -#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) -#endif #define my_wipememory2(_ptr,_set,_len) do { \ volatile char *_vptr=(volatile char *)(_ptr); \ ----------------------------------------------------------------------- Summary of changes: cipher/bithelp.h | 26 ++++---------------------- cipher/bufhelp.h | 1 + src/hmac256.c | 13 ++----------- 3 files changed, 7 insertions(+), 33 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 23 09:25:21 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 23 Sep 2013 09:25:21 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-265-g4552437 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 4552437bb3c5ff96a889fd31e4bc504b2a12fac7 (commit) from 925d4fb3e8f2df3c5566ec6b5df7620a3d3504e5 (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 4552437bb3c5ff96a889fd31e4bc504b2a12fac7 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ec: Use mpi_mulm instead of mpi_powm. * mpi/ec.c (ec_pow2): New. (ec_powm): Remove call to mpi_abs. (dup_point_weierstrass, dup_point_twistededwards) (add_points_weierstrass, add_points_twistededwards) (_gcry_mpi_ec_curve_point): Use ec_pow2. Signed-off-by: Werner Koch diff --git a/mpi/ec.c b/mpi/ec.c index 730f766..e52facd 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -367,9 +367,22 @@ ec_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e, mpi_ec_t ctx) { mpi_powm (w, b, e, ctx->p); - _gcry_mpi_abs (w); + /* _gcry_mpi_abs (w); */ } + +/* Shortcut for + ec_powm (B, B, mpi_const (MPI_C_TWO), ctx); + for easier optimization. */ +static void +ec_pow2 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx) +{ + /* Using mpi_mul is slightly faster (at least on amd64). */ + /* mpi_powm (w, b, mpi_const (MPI_C_TWO), ctx->p); */ + mpi_mulm (w, b, b, ctx->p); +} + + static void ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx) { @@ -803,7 +816,7 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) /* L1 = 3(X - Z^2)(X + Z^2) */ /* T1: used for Z^2. */ /* T2: used for the right term. */ - ec_powm (t1, point->z, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (t1, point->z, ctx); ec_subm (l1, point->x, t1, ctx); ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx); ec_addm (t2, point->x, t1, ctx); @@ -813,7 +826,7 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) { /* L1 = 3X^2 + aZ^4 */ /* T1: used for aZ^4. */ - ec_powm (l1, point->x, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (l1, point->x, ctx); ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx); ec_powm (t1, point->z, mpi_const (MPI_C_FOUR), ctx); ec_mulm (t1, t1, ctx->a, ctx); @@ -825,19 +838,19 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) /* L2 = 4XY^2 */ /* T2: used for Y2; required later. */ - ec_powm (t2, point->y, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (t2, point->y, ctx); ec_mulm (l2, t2, point->x, ctx); ec_mulm (l2, l2, mpi_const (MPI_C_FOUR), ctx); /* X3 = L1^2 - 2L2 */ /* T1: used for L2^2. */ - ec_powm (x3, l1, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (x3, l1, ctx); ec_mulm (t1, l2, mpi_const (MPI_C_TWO), ctx); ec_subm (x3, x3, t1, ctx); /* L3 = 8Y^4 */ /* T2: taken from above. */ - ec_powm (t2, t2, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (t2, t2, ctx); ec_mulm (l3, t2, mpi_const (MPI_C_EIGHT), ctx); /* Y3 = L1(L2 - X3) - L3 */ @@ -892,12 +905,12 @@ dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) /* B = (X_1 + Y_1)^2 */ ec_addm (B, X1, Y1, ctx); - ec_powm (B, B, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (B, B, ctx); /* C = X_1^2 */ /* D = Y_1^2 */ - ec_powm (C, X1, mpi_const (MPI_C_TWO), ctx); - ec_powm (D, Y1, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (C, X1, ctx); + ec_pow2 (D, Y1, ctx); /* E = aC */ ec_mulm (E, ctx->a, C, ctx); @@ -906,7 +919,7 @@ dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) ec_addm (F, E, D, ctx); /* H = Z_1^2 */ - ec_powm (H, Z1, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (H, Z1, ctx); /* J = F - 2H */ ec_mulm (J, H, mpi_const (MPI_C_TWO), ctx); @@ -1016,14 +1029,14 @@ add_points_weierstrass (mpi_point_t result, mpi_set (l1, x1); else { - ec_powm (l1, z2, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (l1, z2, ctx); ec_mulm (l1, l1, x1, ctx); } if (z1_is_one) mpi_set (l2, x2); else { - ec_powm (l2, z1, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (l2, z1, ctx); ec_mulm (l2, l2, x2, ctx); } /* l3 = l1 - l2 */ @@ -1062,8 +1075,8 @@ add_points_weierstrass (mpi_point_t result, ec_mulm (z3, z1, z2, ctx); ec_mulm (z3, z3, l3, ctx); /* x3 = l6^2 - l7 l3^2 */ - ec_powm (t1, l6, mpi_const (MPI_C_TWO), ctx); - ec_powm (t2, l3, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (t1, l6, ctx); + ec_pow2 (t2, l3, ctx); ec_mulm (t2, t2, l7, ctx); ec_subm (x3, t1, t2, ctx); /* l9 = l7 l3^2 - 2 x3 */ @@ -1146,7 +1159,7 @@ add_points_twistededwards (mpi_point_t result, ec_mulm (A, Z1, Z2, ctx); /* B = A^2 */ - ec_powm (B, A, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (B, A, ctx); /* C = X1 ? X2 */ ec_mulm (C, X1, X2, ctx); @@ -1369,8 +1382,8 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) case MPI_EC_TWISTEDEDWARDS: { /* a ? x^2 + y^2 - 1 - b ? x^2 ? y^2 == 0 */ - ec_powm (x, x, mpi_const (MPI_C_TWO), ctx); - ec_powm (y, y, mpi_const (MPI_C_TWO), ctx); + ec_pow2 (x, x, ctx); + ec_pow2 (y, y, ctx); ec_mulm (w, ctx->a, x, ctx); ec_addm (w, w, y, ctx); ec_subm (w, w, mpi_const (MPI_C_ONE), ctx); diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c index 98abc56..5f7ad3f 100644 --- a/mpi/mpi-add.c +++ b/mpi/mpi-add.c @@ -224,12 +224,12 @@ void gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) { gcry_mpi_add(w, u, v); - _gcry_mpi_fdiv_r( w, w, m ); + _gcry_mpi_mod (w, w, m); } void gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) { gcry_mpi_sub(w, u, v); - _gcry_mpi_fdiv_r( w, w, m ); + _gcry_mpi_mod (w, w, m); } diff --git a/mpi/mpi-mul.c b/mpi/mpi-mul.c index 9aefd21..ec6aea0 100644 --- a/mpi/mpi-mul.c +++ b/mpi/mpi-mul.c @@ -205,8 +205,8 @@ gcry_mpi_mul( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) void -gcry_mpi_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) { - gcry_mpi_mul(w, u, v); - _gcry_mpi_fdiv_r( w, w, m ); + gcry_mpi_mul (w, u, v); + _gcry_mpi_mod (w, w, m); } ----------------------------------------------------------------------- Summary of changes: mpi/ec.c | 47 ++++++++++++++++++++++++++++++----------------- mpi/mpi-add.c | 4 ++-- mpi/mpi-mul.c | 6 +++--- 3 files changed, 35 insertions(+), 22 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 23 22:56:56 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 23 Sep 2013 22:56:56 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-266-gd5f9146 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 d5f91466695c5736f441c9bf1998436184a4bf61 (commit) from 4552437bb3c5ff96a889fd31e4bc504b2a12fac7 (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 d5f91466695c5736f441c9bf1998436184a4bf61 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 pk: Add algo id GCRY_PK_ECC and deprecate ECDSA and ECDH. * src/gcrypt.h.in (GCRY_PK_ECC): New. * cipher/pubkey.c (map_algo): New. (spec_from_algo, gcry_pk_get_param, _gcry_pk_selftest): Use it. * cipher/ecc.c (selftests_ecdsa): Report using GCRY_PK_ECC. (run_selftests): Simplify. (ecdh_names, ecdsa_names): Merge into a new ecc_names. (_gcry_pubkey_spec_ecdh, _gcry_pubkey_spec_ecdsa): Merge into new _gcry_pubkey_spec_ecc. -- The algo ids are actually a relict from Libgcrypt's former life as GnuPG's crypto code. They don't make much sense anymore and are often not needed. This patch requires some changes to the GnuPG 2.1 code (which has still not been released). For example the secret key transfer between gpg and gpg-agent (gpg --export and gpg --import). Fortunately this will also require to add usage flags to the secret key storage of gpg-agent which is is something we should have done a long time ago. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 678805d..1e84cbe 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,9 @@ Noteworthy changes in version 1.6.0 (unreleased) * Added support for negative numbers to gcry_mpi_print, gcry_mpi_aprint and gcry_mpi_scan. + * The algorithm ids GCRY_PK_ECDSA and GCRY_PK_ECDH are now + deprecated. Use GCRY_PK_ECC instead. + * Interface changes relative to the 1.5.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_ac_* REMOVED. @@ -103,6 +106,7 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRY_MD_STRIBOG256 NEW. GCRY_MD_STRIBOG512 NEW. GCRYCTL_DISABLE_ALGO CHANGED: Not anymore thread-safe. + GCRY_PK_ECC NEW. Noteworthy changes in version 1.5.0 (2011-06-29) diff --git a/cipher/ecc.c b/cipher/ecc.c index 2161b64..d31b4be 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1965,7 +1965,7 @@ selftests_ecdsa (selftest_report_func_t report) failed: if (report) - report ("pubkey", GCRY_PK_ECDSA, what, errtxt); + report ("pubkey", GCRY_PK_ECC, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } @@ -1974,72 +1974,38 @@ selftests_ecdsa (selftest_report_func_t report) static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { - gpg_err_code_t ec; - (void)extended; - switch (algo) - { - case GCRY_PK_ECDSA: - ec = selftests_ecdsa (report); - break; - default: - ec = GPG_ERR_PUBKEY_ALGO; - break; + if (algo != GCRY_PK_ECC) + return GPG_ERR_PUBKEY_ALGO; - } - return ec; + return selftests_ecdsa (report); } -static const char *ecdsa_names[] = +static const char *ecc_names[] = { - "ecdsa", - "eddsa", "ecc", - NULL, - }; -static const char *ecdh_names[] = - { + "ecdsa", "ecdh", - "ecc", - NULL, - }; - -gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = - { - GCRY_PK_ECDSA, { 0, 0 }, - GCRY_PK_USAGE_SIGN, - "ECDSA", ecdsa_names, - "pabgnq", "pabgnqd", "", "rs", "pabgnq", - ecc_generate, - ecc_check_secret_key, - NULL, + "eddsa", NULL, - ecc_sign, - ecc_verify, - ecc_get_nbits, - run_selftests, - compute_keygrip, - _gcry_ecc_get_param, - _gcry_ecc_get_curve, - _gcry_ecc_get_param_sexp }; -gcry_pk_spec_t _gcry_pubkey_spec_ecdh = +gcry_pk_spec_t _gcry_pubkey_spec_ecc = { - GCRY_PK_ECDH, { 0, 0 }, - GCRY_PK_USAGE_ENCR, - "ECDH", ecdh_names, - "pabgnq", "pabgnqd", "se", "", "pabgnq", + GCRY_PK_ECC, { 0, 0 }, + (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), + "ECC", ecc_names, + "pabgnq", "pabgnqd", "sw", "rs", "pabgnq", ecc_generate, ecc_check_secret_key, ecc_encrypt_raw, ecc_decrypt_raw, - NULL, - NULL, + ecc_sign, + ecc_verify, ecc_get_nbits, run_selftests, compute_keygrip, diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 99b9ba8..4738c29 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -38,8 +38,7 @@ static gcry_pk_spec_t *pubkey_list[] = { #if USE_ECC - &_gcry_pubkey_spec_ecdsa, - &_gcry_pubkey_spec_ecdh, + &_gcry_pubkey_spec_ecc, #endif #if USE_RSA &_gcry_pubkey_spec_rsa, @@ -55,6 +54,21 @@ static gcry_pk_spec_t *pubkey_list[] = }; +static int +map_algo (int algo) +{ + switch (algo) + { + case GCRY_PK_ECDSA: + 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 * @@ -63,6 +77,8 @@ spec_from_algo (int algo) int idx; gcry_pk_spec_t *spec; + algo = map_algo (algo); + for (idx = 0; (spec = pubkey_list[idx]); idx++) if (algo == spec->algo) return spec; @@ -2156,7 +2172,9 @@ gcry_pk_get_param (int algo, const char *name) gcry_sexp_t result = NULL; gcry_pk_spec_t *spec = NULL; - if (algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH) + algo = map_algo (algo); + + if (algo != GCRY_PK_ECC) return NULL; spec = spec_from_name ("ecc"); @@ -2334,13 +2352,17 @@ gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec; - gcry_pk_spec_t *spec = spec_from_algo (algo); + gcry_pk_spec_t *spec; + algo = map_algo (algo); + spec = spec_from_algo (algo); if (spec && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_PUBKEY_ALGO; + /* Fixme: We need to change the report fucntion to allow passing + of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */ if (report) report ("pubkey", algo, "module", spec && !spec->flags.disabled? diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 4c1485c..5d1be8d 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2124,9 +2124,10 @@ The point representing the public key @math{Q = dG}. The private key @math{d} @end table -All point values are encoded in standard format; Libgcrypt does -currently only support uncompressed points, thus the first byte needs to -be @code{0x04}. +All point values are encoded in standard format; Libgcrypt does in +general only support uncompressed points, thus the first byte needs to +be @code{0x04}. However ``EdDSA'' describes its own compression +scheme which is used by default. The public key is similar with "private-key" replaced by "public-key" and no @var{d-mpi}. @@ -2200,6 +2201,10 @@ for signing. Use RSA-OAEP padding for encryption. @item pss Use RSA-PSS padding for signing. + at item eddsa +Use the EdDSA scheme instead of ECDSA. + at item rfc6979 +For DSA and ECDSA use a deterministic scheme for the k parameter. @item no-blinding Do not use a technique called `blinding', which is used by default in order to prevent leaking of secret information. Blinding is only @@ -2680,11 +2685,11 @@ are allowed. When specifying Q all values of N in the range 512 to 15680 are valid as long as they are multiples of 8. @item transient-key -This is only meaningful for RSA, DSA, ECDSA, and ECDH keys. This is a flag +This is only meaningful for RSA, DSA, and ECC keys. This is a flag with no value. If given the key is created using a faster and a -somewhat less secure random number generator. This flag may be used for -keys which are only used for a short time or per-message and do not require full -cryptographic strength. +somewhat less secure random number generator. This flag may be used +for keys which are only used for a short time or per-message and do +not require full cryptographic strength. @item domain This is only meaningful for DLP algorithms. If specified keys are diff --git a/src/cipher.h b/src/cipher.h index e3a2fe0..ea7a141 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -240,8 +240,7 @@ extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; extern gcry_pk_spec_t _gcry_pubkey_spec_elg; extern gcry_pk_spec_t _gcry_pubkey_spec_elg_e; extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; -extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; -extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecc; #endif /*G10_CIPHER_H*/ diff --git a/src/fips.c b/src/fips.c index e45baba..11b2caa 100644 --- a/src/fips.c +++ b/src/fips.c @@ -546,7 +546,7 @@ run_pubkey_selftests (int extended) { GCRY_PK_RSA, GCRY_PK_DSA, - /* GCRY_PK_ECDSA is not enabled in fips mode. */ + /* GCRY_PK_ECC is not enabled in fips mode. */ 0 }; int idx; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 3634c24..62c9721 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -978,9 +978,10 @@ enum gcry_pk_algos GCRY_PK_RSA_S = 3, /* (deprecated) */ GCRY_PK_ELG_E = 16, GCRY_PK_DSA = 17, + GCRY_PK_ECC = 18, /* Generic ECC. */ GCRY_PK_ELG = 20, - GCRY_PK_ECDSA = 301, - GCRY_PK_ECDH = 302 + GCRY_PK_ECDSA = 301, /* (deprecated: use 18). */ + GCRY_PK_ECDH = 302 /* (deprecated: use 18). */ }; /* Flags describing usage capabilities of a PK algorithm. */ ----------------------------------------------------------------------- Summary of changes: NEWS | 4 +++ cipher/ecc.c | 62 ++++++++++++------------------------------------------ cipher/pubkey.c | 30 +++++++++++++++++++++++--- doc/gcrypt.texi | 19 ++++++++++------ src/cipher.h | 3 +- src/fips.c | 2 +- src/gcrypt.h.in | 5 ++- 7 files changed, 61 insertions(+), 64 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Tue Sep 24 15:16:14 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 24 Sep 2013 15:16:14 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-267-gdf013c9 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 df013c9820709421ef9550158ac5df0060d73379 (commit) from d5f91466695c5736f441c9bf1998436184a4bf61 (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 df013c9820709421ef9550158ac5df0060d73379 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ecc: Allow the use of an uncompressed public key. * cipher/ecc.c (eddsa_encodepoint): Factor most code out to ... (eddsa_encode_x_y): new fucntion. (eddsa_decodepoint): Allow use of an uncompressed public key. * tests/t-ed25519.c (N_TESTS): Adjust. * tests/t-ed25519.inp: Add test 1025. diff --git a/cipher/ecc.c b/cipher/ecc.c index d31b4be..82d5bba 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -606,24 +606,17 @@ eddsa_encodempi (gcry_mpi_t mpi, unsigned int minlen, } -/* Encode POINT using the EdDSA scheme. X and Y are scratch variables - supplied by the caller and CTX is the usual context. MINLEN is the - required length in bytes for the result. On success 0 is returned - an a malloced buffer with the encoded point is stored at R_BUFFER; - the length of this buffer is stored at R_BUFLEN. */ +/* Encode (X,Y) using the EdDSA scheme. MINLEN is the required length + in bytes for the result. On success 0 is returned and a malloced + buffer with the encoded point is stored at R_BUFFER; the length of + this buffer is stored at R_BUFLEN. */ static gpg_err_code_t -eddsa_encodepoint (mpi_point_t point, unsigned int minlen, mpi_ec_t ctx, - gcry_mpi_t x, gcry_mpi_t y, - unsigned char **r_buffer, unsigned int *r_buflen) +eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int minlen, + unsigned char **r_buffer, unsigned int *r_buflen) { unsigned char *rawmpi; unsigned int rawmpilen; - if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) - { - log_error ("eddsa_encodepoint: Failed to get affine coordinates\n"); - return GPG_ERR_INTERNAL; - } rawmpi = _gcry_mpi_get_buffer (y, minlen, &rawmpilen, NULL); if (!rawmpi) return gpg_err_code_from_syserror (); @@ -635,12 +628,30 @@ eddsa_encodepoint (mpi_point_t point, unsigned int minlen, mpi_ec_t ctx, return 0; } +/* Encode POINT using the EdDSA scheme. X and Y are scratch variables + supplied by the caller and CTX is the usual context. MINLEN is the + required length in bytes for the result. On success 0 is returned + and a malloced buffer with the encoded point is stored at R_BUFFER; + the length of this buffer is stored at R_BUFLEN. */ +static gpg_err_code_t +eddsa_encodepoint (mpi_point_t point, unsigned int minlen, mpi_ec_t ctx, + gcry_mpi_t x, gcry_mpi_t y, + unsigned char **r_buffer, unsigned int *r_buflen) +{ + if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) + { + log_error ("eddsa_encodepoint: Failed to get affine coordinates\n"); + return GPG_ERR_INTERNAL; + } + return eddsa_encode_x_y (x, y, minlen, r_buffer, r_buflen); +} + /* Decode the EdDSA style encoded PK and set it into RESULT. LEN is the expected length in bytes of the encoded key and CTX the usual curve context. If R_ENCPK is not NULL, the encoded PK is stored at - that address; this is a new copy to be release by the caller. In - contrast to the supplied PK, this is not an MPI and thus guarnteed + that address; this is a new copy to be released by the caller. In + contrast to the supplied PK, this is not an MPI and thus guarnateed to be properly padded. R_ENCPKLEN received the length of that encoded key. */ static gpg_err_code_t @@ -648,6 +659,7 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, mpi_point_t result, unsigned char **r_encpk, unsigned int *r_encpklen) { + gpg_err_code_t rc; unsigned char *rawmpi; unsigned int rawmpilen; gcry_mpi_t yy, t, x, p1, p2, p3; @@ -655,12 +667,50 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, if (mpi_is_opaque (pk)) { - const void *buf; + const unsigned char *buf; buf = gcry_mpi_get_opaque (pk, &rawmpilen); if (!buf) return GPG_ERR_INV_OBJ; rawmpilen = (rawmpilen + 7)/8; + + /* First check whether the public key has been given in standard + uncompressed format. No need to recover x in this case. + Detection is easy: The size of the buffer will be odd and the + first byte be 0x04. */ + if (rawmpilen > 1 && buf[0] == 0x04 && (rawmpilen%2)) + { + gcry_mpi_t y; + + rc = gcry_mpi_scan (&x, GCRYMPI_FMT_STD, + buf+1, (rawmpilen-1)/2, NULL); + if (rc) + return rc; + rc = gcry_mpi_scan (&y, GCRYMPI_FMT_STD, + buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2, NULL); + if (rc) + { + mpi_free (x); + return rc; + } + + if (r_encpk) + { + rc = eddsa_encode_x_y (x, y, len, r_encpk, r_encpklen); + if (rc) + { + mpi_free (x); + mpi_free (y); + return rc; + } + } + mpi_snatch (result->x, x); + mpi_snatch (result->y, y); + mpi_set_ui (result->z, 1); + return 0; + } + + /* EdDSA compressed point. */ rawmpi = gcry_malloc (rawmpilen? rawmpilen:1); if (!rawmpi) return gpg_err_code_from_syserror (); @@ -669,6 +719,9 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, } else { + /* Note: Without using an opaque MPI it is not reliable possible + to find out whether the public key has been given in + uncompressed format. Thus we expect EdDSA format here. */ rawmpi = _gcry_mpi_get_buffer (pk, len, &rawmpilen, NULL); if (!rawmpi) return gpg_err_code_from_syserror (); diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c index f816fda..0a6ae14 100644 --- a/tests/t-ed25519.c +++ b/tests/t-ed25519.c @@ -32,7 +32,7 @@ #include "stopwatch.h" #define PGM "t-ed25519" -#define N_TESTS 1024 +#define N_TESTS 1025 #define my_isascii(c) (!((c) & 0x80)) #define digitp(p) (*(p) >= '0' && *(p) <= '9') @@ -460,7 +460,9 @@ check_ed25519 (void) xfree (sig); if (ntests != N_TESTS) - fail ("did %d tests but expected %s", ntests, N_TESTS); + fail ("did %d tests but expected %d", ntests, N_TESTS); + else if ((ntests % 256)) + show_note ("%d tests done\n", ntests); fclose (fp); xfree (fname); diff --git a/tests/t-ed25519.inp b/tests/t-ed25519.inp index 5da0d6e..61387c4 100644 --- a/tests/t-ed25519.inp +++ b/tests/t-ed25519.inp @@ -2,13 +2,14 @@ # This has been taken from # http://ed25519.cr.yp.to/python/sign.input # which distributed them as public domain. -# For our use converted using this schript: +# For our use converted using this script: # awk -F: 'BEGIN {n=1} { print "TST: " n; n++; \ # print "SK: " substr($1,0,64); print "PK: " $2;\ # print "MSG: " $3; print "SIG: " substr($4,0,128); print ""}' # # The PK appended to the SK and the MSG appended to the SIG have been -# stripped. +# stripped. A few additional tests have been added to the 1024 +# original tests. TST: 1 SK: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60 @@ -6153,3 +6154,11 @@ SK: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5 PK: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e MSG: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0 SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03 + +# Now an additional test with the data from test 1 but using an +# uncompressed public key. +TST: 1025 +SK: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60 +PK: 0455d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7 +MSG: +SIG: e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 85 +++++++++++++++++++++++++++++++++++++++++--------- tests/t-ed25519.c | 6 ++- tests/t-ed25519.inp | 13 ++++++- 3 files changed, 84 insertions(+), 20 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 25 09:35:44 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 25 Sep 2013 09:35:44 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-268-g1f5f445 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 1f5f4452e5bca105ec2197a4facbf9778e7dc31e (commit) from df013c9820709421ef9550158ac5df0060d73379 (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 1f5f4452e5bca105ec2197a4facbf9778e7dc31e Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ecc: Fix highly unlikely endless loop in sign_ecdsa. * cipher/ecc.c (sign_ecdsa): Turn while-do into do-while loops. -- Reported-by: Dmitry Eremin-Solenikov Signed-off-by: Werner Koch diff --git a/cipher/ecc.c b/cipher/ecc.c index 82d5bba..0b89ec2 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -408,21 +408,16 @@ sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, x = mpi_alloc (0); point_init (&I); - mpi_set_ui (s, 0); - mpi_set_ui (r, 0); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); - while (!mpi_cmp_ui (s, 0)) /* s == 0 */ + /* Two loops to avoid R or S are zero. This is more of a joke than + a real demand because the probability of them being zero is less + than any hardware failure. Some specs however require it. */ + do { - while (!mpi_cmp_ui (r, 0)) /* r == 0 */ + do { - /* Note, that we are guaranteed to enter this loop at least - once because r has been intialized to 0. We can't use a - do_while because we want to keep the value of R even if S - has to be recomputed. */ - mpi_free (k); k = NULL; if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo) @@ -458,11 +453,14 @@ sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s, } mpi_mod (r, x, skey->E.n); /* r = x mod n */ } + while (!mpi_cmp_ui (r, 0)); + mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n */ mpi_addm (sum, hash, dr, skey->E.n); /* sum = hash + (d*r) mod n */ mpi_invm (k_1, k, skey->E.n); /* k_1 = k^(-1) mod n */ mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } + while (!mpi_cmp_ui (s, 0)); if (DBG_CIPHER) { ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 18 ++++++++---------- 1 files changed, 8 insertions(+), 10 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Sep 25 18:48:22 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 25 Sep 2013 18:48:22 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-273-g1c6660d 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 1c6660debdbf1e4c3e80074c846a3e3097f214bb (commit) via 9b7c49971588edf6acfc74bfb797eb79d19cb350 (commit) via d6683d2a6065986a9198d2d2eaa02c005b68cea4 (commit) via 9a4447ccd1b90bcd701941e80a7f484a1825fcea (commit) via 64a7d347847d606eb5f4c156e24ba060271b8f6b (commit) from 1f5f4452e5bca105ec2197a4facbf9778e7dc31e (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 1c6660debdbf1e4c3e80074c846a3e3097f214bb Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 mpi: Change not yet used _gcry_mpi_set_opaque_copy. * mpi/mpiutil.c (_gcry_mpi_set_opaque_copy): Change prototype. (_gcry_mpi_get_opaque_copy): Take care of gcry_malloc failure. diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 3855dc4..c9e6b31 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -283,13 +283,15 @@ gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits ) gcry_mpi_t -_gcry_mpi_set_opaque_copy (gcry_mpi_t a, void *p, unsigned int nbits) +_gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits) { void *d; unsigned int n; n = (nbits+7)/8; d = gcry_is_secure (p)? gcry_malloc_secure (n) : gcry_malloc (n); + if (!d) + return NULL; memcpy (d, p, n); return gcry_mpi_set_opaque (a, d, nbits); } @@ -318,7 +320,8 @@ _gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits) return NULL; n = (*nbits+7)/8; d = gcry_is_secure (s)? gcry_malloc_secure (n) : gcry_malloc (n); - memcpy (d, s, n); + if (d) + memcpy (d, s, n); return d; } diff --git a/src/mpi.h b/src/mpi.h index 279c485..780d5eb 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -135,7 +135,7 @@ void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); gcry_mpi_t _gcry_mpi_new (unsigned int nbits); gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a, - void *p, unsigned int nbits); + const void *p, unsigned int nbits); void *_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits); int _gcry_mpi_is_neg (gcry_mpi_t a); void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u); commit 9b7c49971588edf6acfc74bfb797eb79d19cb350 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 sexp: Improve printing of data with a leading zero. * src/sexp.c (suitable_encoding): Detect leading zero byte. diff --git a/src/sexp.c b/src/sexp.c index 54d0c4a..6a2a9be 100644 --- a/src/sexp.c +++ b/src/sexp.c @@ -1725,6 +1725,8 @@ suitable_encoding (const unsigned char *buffer, size_t length) if (*buffer & 0x80) return 0; /* If the MSB is set we assume that buffer represents a negative number. */ + if (!*buffer) + return 0; /* Starting with a zero is pretty much a binary string. */ for (s=buffer; length; s++, length--) { commit d6683d2a6065986a9198d2d2eaa02c005b68cea4 Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ecc: Allow the name "q at eddsa" to get/set the public key. * cipher/ecc-curves.c (_gcry_ecc_get_mpi): Support "q at eddsa". (_gcry_ecc_set_mpi): Support "q". * cipher/ecc.c (eddsa_encodepoint): Rename to ... (_gcry_ecc_eddsa_encodepoint): this and make global. Remove arg MINLEN and take from context. (eddsa_decodepoint): Rename to (_gcry_ecc_eddsa_decodepoint): this and make global. Remove arg LEN and take from context. (sign_eddsa, verify_eddsa): Take B from context. (ecc_sign, ecc_verify): Add hack to set DIALECT. (_gcry_pk_ecc_get_sexp): Use _gcry_ecc_compute_public. Handle EdDSA. * src/ec-context.h (mpi_ec_ctx_s): Add field NBITS. * mpi/ec.c (ec_p_init): Init NBITS. * tests/t-mpi-point.c (test_curve): Add Ed25519. (sample_ed25519_q): New. (context_param): Check new sample key. (hex2buffer, hex2mpiopa): New. (cmp_mpihex): Take care of opaque MPIs. Signed-off-by: Werner Koch diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h index 031994a..cdb1362 100644 --- a/cipher/ecc-common.h +++ b/cipher/ecc-common.h @@ -84,5 +84,15 @@ gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value); mpi_point_t _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec); +/*-- ecc.c --*/ +gpg_err_code_t _gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ctx, + gcry_mpi_t x, gcry_mpi_t y, + unsigned char **r_buffer, + unsigned int *r_buflen); +gpg_err_code_t _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, + mpi_point_t result, + unsigned char **r_encpk, + unsigned int *r_encpklen); + #endif /*GCRY_ECC_COMMON_H*/ diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index e6a993f..7447340 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -812,6 +812,9 @@ _gcry_ecc_get_param_sexp (const char *name) gcry_mpi_t _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy) { + if (!*name) + return NULL; + if (!strcmp (name, "p") && ec->p) return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); if (!strcmp (name, "a") && ec->a) @@ -833,17 +836,35 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy) if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); - /* If a point has been requested, return it in standard encoding. */ + /* If the base point has been requested, return it in standard + encoding. */ if (!strcmp (name, "g") && ec->G) return _gcry_mpi_ec_ec2os (ec->G, ec); - if (!strcmp (name, "q")) + + /* If the public key has been requested, return it by default in + standard uncompressed encoding or if requested in other + encodings. */ + if (*name == 'q' && (!name[1] || name[1] == '@')) { /* If only the private key is given, compute the public key. */ if (!ec->Q) ec->Q = _gcry_ecc_compute_public (NULL, ec); - if (ec->Q) + if (!ec->Q) + return NULL; + + if (name[1] != '@') return _gcry_mpi_ec_ec2os (ec->Q, ec); + + if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_TWISTEDEDWARDS) + { + unsigned char *encpk; + unsigned int encpklen; + + if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, + &encpk, &encpklen)) + return gcry_mpi_set_opaque (NULL, encpk, encpklen*8); + } } return NULL; @@ -874,7 +895,11 @@ _gcry_ecc_get_point (const char *name, mpi_ec_t ec) gpg_err_code_t _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec) { - if (!strcmp (name, "p")) + gpg_err_code_t rc = 0; + + if (!*name) + ; + else if (!strcmp (name, "p")) { mpi_free (ec->p); ec->p = mpi_copy (newvalue); @@ -896,15 +921,40 @@ _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec) mpi_free (ec->n); ec->n = mpi_copy (newvalue); } + else if (*name == 'q' && (!name[1] || name[1] == '@')) + { + if (newvalue) + { + if (!ec->Q) + ec->Q = gcry_mpi_point_new (0); + if (ec->dialect == ECC_DIALECT_ED25519) + rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL); + else + rc = _gcry_ecc_os2ec (ec->Q, newvalue); + } + if (rc || !newvalue) + { + gcry_mpi_point_release (ec->Q); + ec->Q = NULL; + } + /* Note: We assume that Q matches d and thus do not reset d. */ + } else if (!strcmp (name, "d")) { mpi_free (ec->d); ec->d = mpi_copy (newvalue); + if (ec->d) + { + /* We need to reset the public key because it may not + anymore match. */ + gcry_mpi_point_release (ec->Q); + ec->Q = NULL; + } } else - return GPG_ERR_UNKNOWN_NAME; + rc = GPG_ERR_UNKNOWN_NAME; - return 0; + return rc; } diff --git a/cipher/ecc.c b/cipher/ecc.c index 0b89ec2..abd501f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -626,36 +626,47 @@ eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int minlen, return 0; } -/* Encode POINT using the EdDSA scheme. X and Y are scratch variables - supplied by the caller and CTX is the usual context. MINLEN is the - required length in bytes for the result. On success 0 is returned - and a malloced buffer with the encoded point is stored at R_BUFFER; - the length of this buffer is stored at R_BUFLEN. */ -static gpg_err_code_t -eddsa_encodepoint (mpi_point_t point, unsigned int minlen, mpi_ec_t ctx, - gcry_mpi_t x, gcry_mpi_t y, - unsigned char **r_buffer, unsigned int *r_buflen) +/* Encode POINT using the EdDSA scheme. X and Y are either scratch + variables supplied by the caller or NULL. CTX is the usual + context. On success 0 is returned and a malloced buffer with the + encoded point is stored at R_BUFFER; the length of this buffer is + stored at R_BUFLEN. */ +gpg_err_code_t +_gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ec, + gcry_mpi_t x_in, gcry_mpi_t y_in, + unsigned char **r_buffer, unsigned int *r_buflen) { - if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) + gpg_err_code_t rc; + gcry_mpi_t x, y; + + x = x_in? x_in : mpi_new (0); + y = y_in? y_in : mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, point, ec)) { log_error ("eddsa_encodepoint: Failed to get affine coordinates\n"); - return GPG_ERR_INTERNAL; + rc = GPG_ERR_INTERNAL; } - return eddsa_encode_x_y (x, y, minlen, r_buffer, r_buflen); + else + rc = eddsa_encode_x_y (x, y, ec->nbits/8, r_buffer, r_buflen); + + if (!x_in) + mpi_free (x); + if (!y_in) + mpi_free (y); + return rc; } -/* Decode the EdDSA style encoded PK and set it into RESULT. LEN is - the expected length in bytes of the encoded key and CTX the usual - curve context. If R_ENCPK is not NULL, the encoded PK is stored at - that address; this is a new copy to be released by the caller. In - contrast to the supplied PK, this is not an MPI and thus guarnateed - to be properly padded. R_ENCPKLEN received the length of that - encoded key. */ -static gpg_err_code_t -eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, - mpi_point_t result, - unsigned char **r_encpk, unsigned int *r_encpklen) +/* Decode the EdDSA style encoded PK and set it into RESULT. CTX is + the usual curve context. If R_ENCPK is not NULL, the encoded PK is + stored at that address; this is a new copy to be released by the + caller. In contrast to the supplied PK, this is not an MPI and + thus guarnateed to be properly padded. R_ENCPKLEN received the + length of that encoded key. */ +gpg_err_code_t +_gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result, + unsigned char **r_encpk, unsigned int *r_encpklen) { gpg_err_code_t rc; unsigned char *rawmpi; @@ -694,7 +705,7 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, if (r_encpk) { - rc = eddsa_encode_x_y (x, y, len, r_encpk, r_encpklen); + rc = eddsa_encode_x_y (x, y, ctx->nbits/8, r_encpk, r_encpklen); if (rc) { mpi_free (x); @@ -720,7 +731,7 @@ eddsa_decodepoint (gcry_mpi_t pk, unsigned int len, mpi_ec_t ctx, /* Note: Without using an opaque MPI it is not reliable possible to find out whether the public key has been given in uncompressed format. Thus we expect EdDSA format here. */ - rawmpi = _gcry_mpi_get_buffer (pk, len, &rawmpilen, NULL); + rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL); if (!rawmpi) return gpg_err_code_from_syserror (); } @@ -896,7 +907,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, { int rc; mpi_ec_t ctx = NULL; - int b = 256/8; /* The only size we currently support. */ + int b; unsigned int tmp; unsigned char hash_d[64]; /* Fixme: malloc in secure memory */ unsigned char digest[64]; @@ -927,6 +938,10 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, r = mpi_new (0); ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); + b = ctx->nbits/8; + if (b != 256/8) + return GPG_ERR_INTERNAL; /* We only support 256 bit. */ + /* Hash the secret key. We clear DIGEST so we can use it to left pad the key with zeroes for hashing. */ @@ -959,7 +974,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, parameter. */ if (pk) { - rc = eddsa_decodepoint (pk, b, ctx, &Q, &encpk, &encpklen); + rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen); if (rc) goto leave; if (DBG_CIPHER) @@ -973,7 +988,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, else { _gcry_mpi_ec_mul_point (&Q, a, &skey->E.G, ctx); - rc = eddsa_encodepoint (&Q, b, ctx, x, y, &encpk, &encpklen); + rc = _gcry_ecc_eddsa_encodepoint (&Q, ctx, x, y, &encpk, &encpklen); if (rc) goto leave; if (DBG_CIPHER) @@ -1003,7 +1018,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, log_printpnt (" r", &I, ctx); /* Convert R into affine coordinates and apply encoding. */ - rc = eddsa_encodepoint (&I, b, ctx, x, y, &rawmpi, &rawmpilen); + rc = _gcry_ecc_eddsa_encodepoint (&I, ctx, x, y, &rawmpi, &rawmpilen); if (rc) goto leave; if (DBG_CIPHER) @@ -1067,7 +1082,7 @@ verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey, { int rc; mpi_ec_t ctx = NULL; - int b = 256/8; /* The only size we currently support. */ + int b; unsigned int tmp; mpi_point_struct Q; /* Public key. */ unsigned char *encpk = NULL; /* Encoded public key. */ @@ -1094,9 +1109,12 @@ verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey, ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, pkey->E.p, pkey->E.a, pkey->E.b); + b = ctx->nbits/8; + if (b != 256/8) + return GPG_ERR_INTERNAL; /* We only support 256 bit. */ /* Decode and check the public key. */ - rc = eddsa_decodepoint (pk, b, ctx, &Q, &encpk, &encpklen); + rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen); if (rc) goto leave; if (!_gcry_mpi_ec_curve_point (&Q, ctx)) @@ -1170,7 +1188,7 @@ verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey, _gcry_mpi_ec_mul_point (&Ib, h, &Q, ctx); _gcry_mpi_neg (Ib.x, Ib.x); _gcry_mpi_ec_add_points (&Ia, &Ia, &Ib, ctx); - rc = eddsa_encodepoint (&Ia, b, ctx, s, h, &tbuf, &tlen); + rc = _gcry_ecc_eddsa_encodepoint (&Ia, ctx, s, h, &tbuf, &tlen); if (rc) goto leave; if (tlen != rlen || memcmp (tbuf, rbuf, tlen)) @@ -1301,7 +1319,7 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, unsigned char *encpk; unsigned int encpklen; - rc = eddsa_encodepoint (&sk.Q, 256/8, ctx, x, y, &encpk, &encpklen); + rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, x, y, &encpk, &encpklen); if (rc) return rc; public = mpi_new (0); @@ -1443,9 +1461,15 @@ ecc_sign (int algo, gcry_sexp_t *r_result, gcry_mpi_t data, gcry_mpi_t *skey, || !skey[6] ) return GPG_ERR_BAD_MPI; + /* FIXME: The setting of model and dialect are crude hacks. We will + fix that by moving the s-expression parsing from pubkey.c to + here. */ sk.E.model = ((flags & PUBKEY_FLAG_EDDSA) ? MPI_EC_TWISTEDEDWARDS : MPI_EC_WEIERSTRASS); + sk.E.dialect = ((flags & PUBKEY_FLAG_EDDSA) + ? ECC_DIALECT_ED25519 + : ECC_DIALECT_STANDARD); sk.E.p = skey[0]; sk.E.a = skey[1]; sk.E.b = skey[2]; @@ -1525,9 +1549,15 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, || !pkey[3] || !pkey[4] || !pkey[5] ) return GPG_ERR_BAD_MPI; + /* FIXME: The setting of model and dialect are crude hacks. We will + fix that by moving the s-expression parsing from pubkey.c to + here. */ pk.E.model = ((flags & PUBKEY_FLAG_EDDSA) ? MPI_EC_TWISTEDEDWARDS : MPI_EC_WEIERSTRASS); + pk.E.dialect = ((flags & PUBKEY_FLAG_EDDSA) + ? ECC_DIALECT_ED25519 + : ECC_DIALECT_STANDARD); pk.E.p = pkey[0]; pk.E.a = pkey[1]; pk.E.b = pkey[2]; @@ -1922,7 +1952,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) Low-level API helper functions. */ -/* This is the wroker function for gcry_pubkey_get_sexp for ECC +/* This is the worker function for gcry_pubkey_get_sexp for ECC algorithms. Note that the caller has already stored NULL at R_SEXP. */ gpg_err_code_t @@ -1940,10 +1970,7 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec) /* Compute the public point if it is missing. */ if (!ec->Q && ec->d) - { - ec->Q = gcry_mpi_point_new (0); - _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); - } + ec->Q = _gcry_ecc_compute_public (NULL, ec); /* Encode G and Q. */ mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec); @@ -1957,7 +1984,23 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec) rc = GPG_ERR_BAD_CRYPT_CTX; goto leave; } - mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec); + + if (ec->dialect == ECC_DIALECT_ED25519) + { + unsigned char *encpk; + unsigned int encpklen; + + rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, + &encpk, &encpklen); + if (rc) + goto leave; + mpi_Q = gcry_mpi_set_opaque (NULL, encpk, encpklen*8); + encpk = NULL; + } + else + { + mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec); + } if (!mpi_Q) { rc = GPG_ERR_BROKEN_PUBKEY; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 5d1be8d..0590a26 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -4182,10 +4182,16 @@ modified, it is suggested to pass @code{1} to @var{copy}, so that the function guarantees that a modifiable copy of the MPI is returned. If @code{0} is used for @var{copy}, this function may return a constant flagged MPI. In any case @code{gcry_mpi_release} needs to be called -to release the result. For valid names @ref{ecc_keyparam}. If a -point parameter is requested it is returned as an uncompressed encoded -point. If the public key @code{q} is requested but only the private -key @code{d} is available, @code{q} will be recomputed on the fly. +to release the result. For valid names @ref{ecc_keyparam}. If the +public key @code{q} is requested but only the private key @code{d} is +available, @code{q} will be recomputed on the fly. If a point +parameter is requested it is returned as an uncompressed +encoded point unless these special names are used: + at table @var + at item q@@eddsa +Return an EdDSA style compressed point. This is only supported for +Twisted Edwards curves. + at end table @end deftypefun @deftypefun gcry_mpi_point_t gcry_mpi_ec_get_point ( @ diff --git a/mpi/ec.c b/mpi/ec.c index 883d8f6..c6d0fc8 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -436,6 +436,10 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, ctx->model = model; ctx->dialect = dialect; + if (dialect == ECC_DIALECT_ED25519) + ctx->nbits = 256; + else + ctx->nbits = mpi_get_nbits (p); ctx->p = mpi_copy (p); ctx->a = mpi_copy (a); if (b && model == MPI_EC_TWISTEDEDWARDS) diff --git a/src/ec-context.h b/src/ec-context.h index fdfbc0a..8dce7a7 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -27,6 +27,8 @@ struct mpi_ec_ctx_s enum ecc_dialects dialect; /* The ECC dialect used with the curve. */ + unsigned int nbits; /* Number of bits. */ + /* Domain parameters. Note that they may not all be set and if set the MPIs may be flaged as constant. */ gcry_mpi_t p; /* Prime specifying the field GF(p). */ diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 62c9721..5f49edc 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -726,7 +726,7 @@ void gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); currently useless as no flags are allowed. */ void gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); -/* Return true when the FLAG is set for A. */ +/* Return true if the FLAG is set for A. */ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); /* Private function - do not use. */ diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index 6683189..0641779 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -36,6 +36,14 @@ static int debug; static int error_count; +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) #define xmalloc(a) gcry_xmalloc ((a)) #define xcalloc(a,b) gcry_xcalloc ((a),(b)) #define xfree(a) gcry_free ((a)) @@ -113,6 +121,15 @@ static struct "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6" "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, + { + "Ed25519", + "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", + "-0x01", + "-0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4", + "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED", + "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A", + "0x6666666666666666666666666666666666666666666666666666666666666658" + }, { NULL, NULL, NULL, NULL, NULL } }; @@ -127,6 +144,20 @@ static const char sample_p256_q_y[] = "00E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E"; +/* A sample public key for Ed25519. */ +static const char sample_ed25519_q[] = + "04" + "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce" + "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7"; +static const char sample_ed25519_q_x[] = + "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce"; +static const char sample_ed25519_q_y[] = + "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7"; +static const char sample_ed25519_q_eddsa[] = + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; +static const char sample_ed25519_d[] = + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"; + static void show (const char *format, ...) @@ -241,7 +272,49 @@ hex2mpi (const char *string) err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL); if (err) - die ("hex2mpi '%s' failed: %s\n", gpg_strerror (err)); + die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err)); + return val; +} + + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +hex2buffer (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + return NULL; /* Invalid hex digits. */ + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + + +static gcry_mpi_t +hex2mpiopa (const char *string) +{ + char *buffer; + size_t buflen; + gcry_mpi_t val; + + buffer = hex2buffer (string, &buflen); + if (!buffer) + die ("hex2mpiopa '%s' failed: parser error\n", string); + val = gcry_mpi_set_opaque (NULL, buffer, buflen*8); + if (!buffer) + die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string); return val; } @@ -253,7 +326,10 @@ cmp_mpihex (gcry_mpi_t a, const char *b) gcry_mpi_t bval; int res; - bval = hex2mpi (b); + if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) + bval = hex2mpiopa (b); + else + bval = hex2mpi (b); res = gcry_mpi_cmp (a, bval); gcry_mpi_release (bval); return res; @@ -459,7 +535,7 @@ context_param (void) gpg_error_t err; int idx; gcry_ctx_t ctx = NULL; - gcry_mpi_t q; + gcry_mpi_t q, d; gcry_sexp_t keyparam; wherestr = "context_param"; @@ -492,13 +568,11 @@ context_param (void) continue; } - gcry_ctx_release (ctx); - - show ("checking sample public key\n"); + show ("checking sample public key (nistp256)\n"); q = hex2mpi (sample_p256_q); err = gcry_sexp_build (&keyparam, NULL, - "(public-key(ecdsa(curve %s)(q %m)))", + "(public-key(ecc(curve %s)(q %m)))", "NIST P-256", q); if (err) die ("gcry_sexp_build failed: %s\n", gpg_strerror (err)); @@ -511,18 +585,112 @@ context_param (void) /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */ /* gpg_strerror (err)); */ + gcry_ctx_release (ctx); err = gcry_mpi_ec_new (&ctx, keyparam, NULL); if (err) - fail ("gcry_mpi_ec_new failed for sample public key: %s\n", + fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n", gpg_strerror (err)); else { gcry_sexp_t sexp; - get_and_cmp_mpi ("q", sample_p256_q, "NIST P-256", ctx); - get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "NIST P-256", + get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx); + get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256", ctx); + /* Delete Q. */ + err = gcry_mpi_ec_set_mpi ("q", NULL, ctx); + if (err) + fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err)); + if (gcry_mpi_ec_get_mpi ("q", ctx, 0)) + fail ("clearing Q for nistp256 did not work\n"); + + /* Set Q again. */ + q = hex2mpi (sample_p256_q); + err = gcry_mpi_ec_set_mpi ("q", q, ctx); + if (err) + fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err)); + get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx); + + /* Get as s-expression. */ + err = gcry_pubkey_get_sexp (&sexp, 0, ctx); + if (err) + fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err)); + else if (debug) + print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp); + gcry_sexp_release (sexp); + + err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx); + if (err) + fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", + gpg_strerror (err)); + else if (debug) + print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp); + gcry_sexp_release (sexp); + + err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx); + if (gpg_err_code (err) != GPG_ERR_NO_SECKEY) + fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n", + gpg_strerror (err)); + gcry_sexp_release (sexp); + } + + show ("checking sample public key (Ed25519)\n"); + q = hex2mpi (sample_ed25519_q); + gcry_sexp_release (keyparam); + err = gcry_sexp_build (&keyparam, NULL, + "(public-key(ecc(curve %s)(q %m)))", + "Ed25519", q); + if (err) + die ("gcry_sexp_build failed: %s\n", gpg_strerror (err)); + gcry_mpi_release (q); + + /* We can't call gcry_pk_testkey because it is only implemented for + private keys. */ + /* err = gcry_pk_testkey (keyparam); */ + /* if (err) */ + /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */ + /* gpg_strerror (err)); */ + + gcry_ctx_release (ctx); + err = gcry_mpi_ec_new (&ctx, keyparam, NULL); + if (err) + fail ("gcry_mpi_ec_new failed for sample public key: %s\n", + gpg_strerror (err)); + else + { + gcry_sexp_t sexp; + + get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx); + get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y, + "Ed25519", ctx); + get_and_cmp_mpi ("q at eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx); + + /* Delete Q by setting d and the clearing d. The clearing is + required so that we can check whether Q has been cleared and + because further tests only expect a public key. */ + d = hex2mpi (sample_ed25519_d); + err = gcry_mpi_ec_set_mpi ("d", d, ctx); + if (err) + fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err)); + gcry_mpi_release (d); + err = gcry_mpi_ec_set_mpi ("d", NULL, ctx); + if (err) + fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err)); + if (gcry_mpi_ec_get_mpi ("q", ctx, 0)) + fail ("setting d for Ed25519 did not reset Q\n"); + + /* Set Q again. We need to use an opaque MPI here because + sample_ed25519_q is in uncompressed format which can only be + auto-detected if passed opaque. */ + q = hex2mpiopa (sample_ed25519_q); + err = gcry_mpi_ec_set_mpi ("q", q, ctx); + if (err) + fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err)); + gcry_mpi_release (q); + get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx); + + /* Get as s-expression. */ err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (err) fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err)); @@ -544,9 +712,9 @@ context_param (void) gpg_strerror (err)); gcry_sexp_release (sexp); - gcry_ctx_release (ctx); } + gcry_ctx_release (ctx); gcry_sexp_release (keyparam); } @@ -730,7 +898,7 @@ basic_ec_math_simplified (void) print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp); gcry_sexp_release (sexp); - /* Does get_sexp return the public key if after d has been deleted? */ + /* Does get_sexp return the public key after d has been deleted? */ err = gcry_mpi_ec_set_mpi ("d", NULL, ctx); if (err) die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n"); commit 9a4447ccd1b90bcd701941e80a7f484a1825fcea Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 mpicalc: Add statement to compute the number of bits. * src/mpicalc.c (do_nbits): New. (main): Add statement 'b'. Signed-off-by: Werner Koch diff --git a/src/mpicalc.c b/src/mpicalc.c index 762d7c8..dd85227 100644 --- a/src/mpicalc.c +++ b/src/mpicalc.c @@ -238,6 +238,20 @@ do_rshift (void) } +static void +do_nbits (void) +{ + unsigned int n; + + if (stackidx < 1) + { + fputs ("stack underflow\n", stderr); + return; + } + n = mpi_get_nbits (stack[stackidx - 1]); + mpi_set_ui (stack[stackidx - 1], n); +} + static int my_getc (void) @@ -279,6 +293,7 @@ print_help (void) "i remove item [0] := [1] {-1}\n" "d dup item [-1] := [0] {+1}\n" "r reverse [0] := [1], [1] := [0] {0}\n" + "b # of bits [0] := nbits([0]) {0}\n" "c clear stack\n" "p print top item\n" "f print the stack\n" @@ -381,7 +396,7 @@ main (int argc, char **argv) do_add (); } break; - case '-': + case '-': if ((c = my_getc ()) == '-') do_dec (); else if (isdigit (c) || (c >= 'A' && c <= 'F')) @@ -454,6 +469,9 @@ main (int argc, char **argv) stack[stackidx-2] = tmp; } break; + case 'b': + do_nbits (); + break; case 'c': for (i = 0; i < stackidx; i++) { commit 64a7d347847d606eb5f4c156e24ba060271b8f6b Author: Werner Koch Date: Sat Sep 7 10:06:46 2013 +0200 ecc: Refactor low-level access functions. * mpi/ec.c (point_copy): Move to cipher/ecc-curves.c. (ec_get_reset): Rename to _gcry_mpi_ec_get_reset and make global. (_gcry_mpi_ec_get_mpi): Factor most code out to _gcry_ecc_get_mpi. (_gcry_mpi_ec_get_point): Factor most code out to _gcry_ecc_get_point. (_gcry_mpi_ec_set_mpi): Factor most code out to _gcry_ecc_set_mpi. (_gcry_mpi_ec_set_point): Factor most code out to _gcry_ecc_set_point. * cipher/ecc-curves.c (_gcry_ecc_get_mpi): New. (_gcry_ecc_get_point, _gcry_ecc_set_mpi, _gcry_ecc_set_point): New. * cipher/ecc-misc.c (_gcry_ecc_compute_public): New. Signed-off-by: Werner Koch diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h index e806059..031994a 100644 --- a/cipher/ecc-common.h +++ b/cipher/ecc-common.h @@ -82,5 +82,7 @@ const char *_gcry_ecc_dialect2str (enum ecc_dialects dialect); gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p); gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value); +mpi_point_t _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec); + #endif /*GCRY_ECC_COMMON_H*/ diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 49c0959..e6a993f 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -270,6 +270,23 @@ static const ecc_domain_parms_t domain_parms[] = +/* Return a copy of POINT. */ +static gcry_mpi_point_t +point_copy (gcry_mpi_point_t point) +{ + gcry_mpi_point_t newpoint; + + if (point) + { + newpoint = gcry_mpi_point_new (0); + point_set (newpoint, point); + } + else + newpoint = NULL; + return newpoint; +} + + /* Helper to scan a hex string. */ static gcry_mpi_t scanval (const char *string) @@ -787,3 +804,126 @@ _gcry_ecc_get_param_sexp (const char *name) return result; } + + +/* Return an MPI (or opaque MPI) described by NAME and the context EC. + If COPY is true a copy is returned, if not a const MPI may be + returned. In any case mpi_free must be used. */ +gcry_mpi_t +_gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy) +{ + if (!strcmp (name, "p") && ec->p) + return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); + if (!strcmp (name, "a") && ec->a) + return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a); + if (!strcmp (name, "b") && ec->b) + return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b); + if (!strcmp (name, "n") && ec->n) + return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n); + if (!strcmp (name, "d") && ec->d) + return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d); + + /* Return a requested point coordinate. */ + if (!strcmp (name, "g.x") && ec->G && ec->G->x) + return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x); + if (!strcmp (name, "g.y") && ec->G && ec->G->y) + return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y); + if (!strcmp (name, "q.x") && ec->Q && ec->Q->x) + return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x); + if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) + return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); + + /* If a point has been requested, return it in standard encoding. */ + if (!strcmp (name, "g") && ec->G) + return _gcry_mpi_ec_ec2os (ec->G, ec); + if (!strcmp (name, "q")) + { + /* If only the private key is given, compute the public key. */ + if (!ec->Q) + ec->Q = _gcry_ecc_compute_public (NULL, ec); + + if (ec->Q) + return _gcry_mpi_ec_ec2os (ec->Q, ec); + } + + return NULL; +} + + +/* Return a point described by NAME and the context EC. */ +gcry_mpi_point_t +_gcry_ecc_get_point (const char *name, mpi_ec_t ec) +{ + if (!strcmp (name, "g") && ec->G) + return point_copy (ec->G); + if (!strcmp (name, "q")) + { + /* If only the private key is given, compute the public key. */ + if (!ec->Q) + ec->Q = _gcry_ecc_compute_public (NULL, ec); + + if (ec->Q) + return point_copy (ec->Q); + } + + return NULL; +} + + +/* Store the MPI NEWVALUE into the context EC under NAME. */ +gpg_err_code_t +_gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec) +{ + if (!strcmp (name, "p")) + { + mpi_free (ec->p); + ec->p = mpi_copy (newvalue); + _gcry_mpi_ec_get_reset (ec); + } + else if (!strcmp (name, "a")) + { + mpi_free (ec->a); + ec->a = mpi_copy (newvalue); + _gcry_mpi_ec_get_reset (ec); + } + else if (!strcmp (name, "b")) + { + mpi_free (ec->b); + ec->b = mpi_copy (newvalue); + } + else if (!strcmp (name, "n")) + { + mpi_free (ec->n); + ec->n = mpi_copy (newvalue); + } + else if (!strcmp (name, "d")) + { + mpi_free (ec->d); + ec->d = mpi_copy (newvalue); + } + else + return GPG_ERR_UNKNOWN_NAME; + + return 0; +} + + +/* Store the point NEWVALUE into the context EC under NAME. */ +gpg_err_code_t +_gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec) +{ + if (!strcmp (name, "g")) + { + gcry_mpi_point_release (ec->G); + ec->G = point_copy (newvalue); + } + else if (!strcmp (name, "q")) + { + gcry_mpi_point_release (ec->Q); + ec->Q = point_copy (newvalue); + } + else + return GPG_ERR_UNKNOWN_NAME; + + return 0; +} diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index f8db81a..1dc0480 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -232,3 +232,24 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) return 0; } + + +/* Compute the public key from the the context EC. Obviously a + requirement is that the secret key is available in EC. On success + Q is returned; on error NULL. If Q is NULL a newly allocated pint + is returned. */ +mpi_point_t +_gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec) +{ + if (!ec->d || !ec->G || !ec->p || !ec->a) + return NULL; + if (ec->model == MPI_EC_TWISTEDEDWARDS && !ec->b) + return NULL; + + if (!Q) + Q = gcry_mpi_point_new (0); + if (!Q) + return NULL; + _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); + return Q; +} diff --git a/mpi/ec.c b/mpi/ec.c index e52facd..883d8f6 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -132,23 +132,6 @@ point_set (mpi_point_t d, mpi_point_t s) } -/* Return a copy of POINT. */ -static gcry_mpi_point_t -point_copy (gcry_mpi_point_t point) -{ - gcry_mpi_point_t newpoint; - - if (point) - { - newpoint = gcry_mpi_point_new (0); - point_set (newpoint, point); - } - else - newpoint = NULL; - return newpoint; -} - - /* Set the projective coordinates from POINT into X, Y, and Z. If a coordinate is not required, X, Y, or Z may be passed as NULL. */ void @@ -396,8 +379,8 @@ ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx) /* Force recomputation of all helper variables. */ -static void -ec_get_reset (mpi_ec_t ec) +void +_gcry_mpi_ec_get_reset (mpi_ec_t ec) { ec->t.valid.a_is_pminus3 = 0; ec->t.valid.two_inv_p = 0; @@ -458,7 +441,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, if (b && model == MPI_EC_TWISTEDEDWARDS) ctx->b = mpi_copy (b); - ec_get_reset (ctx); + _gcry_mpi_ec_get_reset (ctx); /* Allocate scratch variables. */ for (i=0; i< DIM(ctx->t.scratch); i++) @@ -590,44 +573,7 @@ _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - if (!strcmp (name, "p") && ec->p) - return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); - if (!strcmp (name, "a") && ec->a) - return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a); - if (!strcmp (name, "b") && ec->b) - return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b); - if (!strcmp (name, "n") && ec->n) - return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n); - if (!strcmp (name, "d") && ec->d) - return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d); - - /* Return a requested point coordinate. */ - if (!strcmp (name, "g.x") && ec->G && ec->G->x) - return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x); - if (!strcmp (name, "g.y") && ec->G && ec->G->y) - return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y); - if (!strcmp (name, "q.x") && ec->Q && ec->Q->x) - return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x); - if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) - return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); - - /* If a point has been requested, return it in standard encoding. */ - if (!strcmp (name, "g") && ec->G) - return _gcry_mpi_ec_ec2os (ec->G, ec); - if (!strcmp (name, "q")) - { - /* If only the private key is given, compute the public key. */ - if (!ec->Q && ec->d && ec->G && ec->p && ec->a) - { - ec->Q = gcry_mpi_point_new (0); - _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); - } - - if (ec->Q) - return _gcry_mpi_ec_ec2os (ec->Q, ec); - } - - return NULL; + return _gcry_ecc_get_mpi (name, ec, copy); } @@ -638,22 +584,7 @@ _gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy) (void)copy; /* Not used. */ - if (!strcmp (name, "g") && ec->G) - return point_copy (ec->G); - if (!strcmp (name, "q")) - { - /* If only the private key is given, compute the public key. */ - if (!ec->Q && ec->d && ec->G && ec->p && ec->a) - { - ec->Q = gcry_mpi_point_new (0); - _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); - } - - if (ec->Q) - return point_copy (ec->Q); - } - - return NULL; + return _gcry_ecc_get_point (name, ec); } @@ -663,37 +594,7 @@ _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue, { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - if (!strcmp (name, "p")) - { - mpi_free (ec->p); - ec->p = mpi_copy (newvalue); - ec_get_reset (ec); - } - else if (!strcmp (name, "a")) - { - mpi_free (ec->a); - ec->a = mpi_copy (newvalue); - ec_get_reset (ec); - } - else if (!strcmp (name, "b")) - { - mpi_free (ec->b); - ec->b = mpi_copy (newvalue); - } - else if (!strcmp (name, "n")) - { - mpi_free (ec->n); - ec->n = mpi_copy (newvalue); - } - else if (!strcmp (name, "d")) - { - mpi_free (ec->d); - ec->d = mpi_copy (newvalue); - } - else - return GPG_ERR_UNKNOWN_NAME; - - return 0; + return _gcry_ecc_set_mpi (name, newvalue, ec); } @@ -703,20 +604,7 @@ _gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue, { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - if (!strcmp (name, "g")) - { - gcry_mpi_point_release (ec->G); - ec->G = point_copy (newvalue); - } - else if (!strcmp (name, "q")) - { - gcry_mpi_point_release (ec->Q); - ec->Q = point_copy (newvalue); - } - else - return GPG_ERR_UNKNOWN_NAME; - - return 0; + return _gcry_ecc_set_point (name, newvalue, ec); } diff --git a/src/ec-context.h b/src/ec-context.h index f2ad19b..fdfbc0a 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -62,5 +62,20 @@ struct mpi_ec_ctx_s }; +/*-- mpi/ec.c --*/ +void _gcry_mpi_ec_get_reset (mpi_ec_t ec); + + +/*-- cipher/ecc-curves.c --*/ +gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, + gcry_sexp_t keyparam, const char *curvename); + +gcry_mpi_t _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy); +gcry_mpi_point_t _gcry_ecc_get_point (const char *name, mpi_ec_t ec); +gpg_err_code_t _gcry_ecc_set_mpi (const char *name, + gcry_mpi_t newvalue, mpi_ec_t ec); +gpg_err_code_t _gcry_ecc_set_point (const char *name, + gcry_mpi_point_t newvalue, mpi_ec_t ec); + #endif /*GCRY_EC_CONTEXT_H*/ diff --git a/src/mpi.h b/src/mpi.h index 3466951..279c485 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -333,8 +333,6 @@ int _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx); gcry_mpi_t _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx); -gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, - gcry_sexp_t keyparam, const char *curvename); gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy); gcry_mpi_point_t _gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy); ----------------------------------------------------------------------- Summary of changes: cipher/ecc-common.h | 12 +++ cipher/ecc-curves.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ cipher/ecc-misc.c | 21 ++++++ cipher/ecc.c | 121 ++++++++++++++++++++++---------- doc/gcrypt.texi | 14 +++- mpi/ec.c | 130 +++------------------------------- mpi/mpiutil.c | 7 ++- src/ec-context.h | 17 +++++ src/gcrypt.h.in | 2 +- src/mpi.h | 4 +- src/mpicalc.c | 20 +++++- src/sexp.c | 2 + tests/t-mpi-point.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++--- 13 files changed, 551 insertions(+), 181 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Thu Sep 26 11:48:20 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Thu, 26 Sep 2013 11:48:20 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-274-gdb60d82 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 db60d828137c4f3682ca4ca2a54fe3d96d3db5f9 (commit) from 1c6660debdbf1e4c3e80074c846a3e3097f214bb (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 db60d828137c4f3682ca4ca2a54fe3d96d3db5f9 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Make libgcrypt build with Clang on i386 * cipher/longlong.h [__i386__] (add_ssaaaa, sub_ddmmss) (umul_ppmm, udiv_qrnnd): Do not cast asm output to USItype. -- Clang defines __GNUC__ even when it's not GCC compatible. As result Clang enables GCC-only assembly code in mpi/longlong.h and fails to build. However, since changes to make libgcrypt build with Clang are smallish, and changes do not cause problems with GCC, patch just does them. Signed-off-by: Jussi Kivilinna diff --git a/mpi/longlong.h b/mpi/longlong.h index 773d1c7..4e315df 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -468,8 +468,8 @@ extern USItype __udiv_qrnnd (); #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl %5,%1\n" \ "adcl %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -478,8 +478,8 @@ extern USItype __udiv_qrnnd (); #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1\n" \ "sbbl %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -487,15 +487,15 @@ extern USItype __udiv_qrnnd (); __CLOBBER_CC) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ - : "=a" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ + : "=a" ((w0)), \ + "=d" ((w1)) \ : "%0" ((USItype)(u)), \ "rm" ((USItype)(v)) \ __CLOBBER_CC) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divl %4" \ - : "=a" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ + : "=a" ((q)), \ + "=d" ((r)) \ : "0" ((USItype)(n0)), \ "1" ((USItype)(n1)), \ "rm" ((USItype)(d)) \ ----------------------------------------------------------------------- Summary of changes: mpi/longlong.h | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 30 10:51:08 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 30 Sep 2013 10:51:08 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-275-gd2076f2 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 d2076f27bb7c5d505abf25fc622d21794c4a5df3 (commit) from db60d828137c4f3682ca4ca2a54fe3d96d3db5f9 (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 d2076f27bb7c5d505abf25fc622d21794c4a5df3 Author: Werner Koch Date: Mon Sep 30 10:18:25 2013 +0200 Add logging functions to the API. * src/gcrypt.h.in (_GCRY_GCC_ATTR_PRINTF): New. (gcry_log_debug, gcry_log_debughex, gcry_log_debugmpi): New. (gcry_log_debugpnt, gcry_log_debugsxp): New. * src/visibility.c (gcry_log_debug): New. (gcry_log_debughex, gcry_log_debugmpi, gcry_log_debugpnt): New. (gcry_log_debugsxp): New. * src/libgcrypt.def, src/libgcrypt.vers: Add new functions. * src/misc.c (_gcry_logv): Make public. (_gcry_log_printsxp): New. * src/g10lib.h (log_printsxp): New macro. -- For debugging applications it is often required to dump certain data structures. Libgcrypt uses several internal functions for this. To avoid re-implementing everything in the caller, we now provide access to some of those functions. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 1e84cbe..c232a99 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,10 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRY_MD_STRIBOG512 NEW. GCRYCTL_DISABLE_ALGO CHANGED: Not anymore thread-safe. GCRY_PK_ECC NEW. + gcry_log_debug NEW. + gcry_log_debughex NEW. + gcry_log_debugmpi NEW. + gcry_log_debugpnt NEW. Noteworthy changes in version 1.5.0 (2011-06-29) diff --git a/src/g10lib.h b/src/g10lib.h index 73ba683..ff7f4b3 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -115,6 +115,8 @@ void _gcry_divide_by_zero (void) JNLIB_GCC_A_NR; const char *_gcry_gettext (const char *key) GCC_ATTR_FORMAT_ARG(1); void _gcry_fatal_error(int rc, const char *text ) JNLIB_GCC_A_NR; +void _gcry_logv (int level, + const char *fmt, va_list arg_ptr) JNLIB_GCC_A_PRINTF(2,0); void _gcry_log( int level, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3); void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); @@ -126,6 +128,7 @@ void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printhex (const char *text, const void *buffer, size_t length); void _gcry_log_printmpi (const char *text, gcry_mpi_t mpi); +void _gcry_log_printsxp (const char *text, gcry_sexp_t sexp); void _gcry_set_log_verbosity( int level ); int _gcry_log_verbosity( int level ); @@ -153,6 +156,7 @@ int _gcry_log_verbosity( int level ); #define log_printf _gcry_log_printf #define log_printhex _gcry_log_printhex #define log_printmpi _gcry_log_printmpi +#define log_printsxp _gcry_log_printsxp /* Compatibility macro. */ #define log_mpidump _gcry_log_printmpi diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 5f49edc..8fca52e 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -100,6 +100,8 @@ extern "C" { #define _GCRY_GCC_ATTR_MALLOC __attribute__ ((__malloc__)) #endif +#define _GCRY_GCC_ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a))) + #endif /*__GNUC__*/ #ifndef _GCRY_GCC_ATTR_DEPRECATED @@ -111,6 +113,9 @@ extern "C" { #ifndef _GCRY_GCC_ATTR_MALLOC #define _GCRY_GCC_ATTR_MALLOC #endif +#ifndef _GCRY_GCC_ATTR_PRINTF +#define _GCRY_GCC_ATTR_PRINTF +#endif /* Make up an attribute to mark functions and types as deprecated but allow internal use by Libgcrypt. */ @@ -1405,6 +1410,15 @@ gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags); /* Release the context object CTX. */ void gcry_ctx_release (gcry_ctx_t ctx); +/* Log data using Libgcrypt's own log interface. */ +void gcry_log_debug (const char *fmt, ...) _GCRY_GCC_ATTR_PRINTF(1,2); +void gcry_log_debughex (const char *text, const void *buffer, size_t length); +void gcry_log_debugmpi (const char *text, gcry_mpi_t mpi); +void gcry_log_debugpnt (const char *text, + gcry_mpi_point_t point, gcry_ctx_t ctx); +void gcry_log_debugsxp (const char *text, gcry_sexp_t sexp); + + /* Log levels used by the internal logging facility. */ enum gcry_log_levels { diff --git a/src/libgcrypt.def b/src/libgcrypt.def index 9fa4245..7efb3b9 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -247,5 +247,11 @@ EXPORTS gcry_md_hash_buffers @219 + gcry_log_debug @220 + gcry_log_debughex @221 + gcry_log_debugmpi @222 + gcry_log_debugpnt @223 + gcry_log_debugsxp @224 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 904ab41..b1669fd 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -101,6 +101,9 @@ GCRYPT_1.6 { gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul; gcry_mpi_ec_curve_point; + gcry_log_debug; + gcry_log_debughex; gcry_log_debugmpi; gcry_log_debugpnt; gcry_log_debugsxp; + _gcry_mpi_get_const; gcry_ctx_release; diff --git a/src/misc.c b/src/misc.c index a19e1e4..d9b85cb 100644 --- a/src/misc.c +++ b/src/misc.c @@ -115,7 +115,7 @@ _gcry_log_verbosity( int level ) * This is our log function which prints all log messages to stderr or * using the function defined with gcry_set_log_handler(). */ -static void +void _gcry_logv( int level, const char *fmt, va_list arg_ptr ) { if (log_handler) @@ -361,6 +361,55 @@ _gcry_log_printmpi (const char *text, gcry_mpi_t mpi) } } +/* Print SEXP in human readabale format. With TEXT of NULL print just the raw + dump without any wrappping, with TEXT an empty string, print a + trailing linefeed, otherwise print the full debug output. */ +void +_gcry_log_printsxp (const char *text, gcry_sexp_t sexp) +{ + int with_lf = 0; + + if (text && *text) + { + if ((with_lf = strchr (text, '\n'))) + log_debug ("%s", text); + else + log_debug ("%s: ", text); + } + if (sexp) + { + int any = 0; + char *buf, *p, *pend; + size_t size; + + size = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); + p = buf = gcry_xmalloc (size); + gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buf, size); + + do + { + if (any && !with_lf) + log_debug ("%*s ", (int)strlen(text), ""); + else + any = 1; + pend = strchr (p, '\n'); + size = pend? (pend - p) : strlen (p); + if (with_lf) + log_debug ("%.*s\n", (int)size, p); + else + log_printf ("%.*s\n", (int)size, p); + if (pend) + p = pend + 1; + else + p += size; + } + while (*p); + gcry_free (buf); + } + if (text) + log_printf ("\n"); +} + void _gcry_burn_stack (unsigned int bytes) diff --git a/src/visibility.c b/src/visibility.c index cfb159f..6e3c755 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1209,6 +1209,42 @@ gcry_ctx_release (gcry_ctx_t ctx) } void +gcry_log_debug (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv (GCRY_LOG_DEBUG, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gcry_log_debughex (const char *text, const void *buffer, size_t length) +{ + _gcry_log_printhex (text, buffer, length); +} + +void +gcry_log_debugmpi (const char *text, gcry_mpi_t mpi) +{ + _gcry_log_printmpi (text, mpi); +} + +void +gcry_log_debugpnt (const char *text, mpi_point_t point, gcry_ctx_t ctx) +{ + mpi_ec_t ec = ctx? _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC) : NULL; + + _gcry_mpi_point_log (text, point, ec); +} + +void +gcry_log_debugsxp (const char *text, gcry_sexp_t sexp) +{ + _gcry_log_printsxp (text, sexp); +} + +void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data) { _gcry_set_progress_handler (cb, cb_data); diff --git a/src/visibility.h b/src/visibility.h index 5e3556c..7e7793b 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -604,6 +604,12 @@ MARK_VISIBLE (gcry_mpi_test_bit) MARK_VISIBLE (gcry_ctx_release) +MARK_VISIBLEX(gcry_log_debug) +MARK_VISIBLEX(gcry_log_debughex) +MARK_VISIBLEX(gcry_log_debugmpi) +MARK_VISIBLEX(gcry_log_debugpnt) +MARK_VISIBLEX(gcry_log_debugsxp) + /* Functions used to implement macros. */ MARK_VISIBLEX(_gcry_mpi_get_const) ----------------------------------------------------------------------- Summary of changes: NEWS | 4 ++++ src/g10lib.h | 4 ++++ src/gcrypt.h.in | 14 ++++++++++++++ src/libgcrypt.def | 6 ++++++ src/libgcrypt.vers | 3 +++ src/misc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/visibility.c | 36 ++++++++++++++++++++++++++++++++++++ src/visibility.h | 6 ++++++ 8 files changed, 123 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 30 20:11:16 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Mon, 30 Sep 2013 20:11:16 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-278-g68cefd0 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 68cefd0f1d60ac33b58031df9b1d165cb1bf0f14 (commit) via a96d622e1a36d40d1504b7ada567e90ec9957443 (commit) via 10d7351411f19bb2c03d2e24ca5a38dabe45023b (commit) from d2076f27bb7c5d505abf25fc622d21794c4a5df3 (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 68cefd0f1d60ac33b58031df9b1d165cb1bf0f14 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 Make Whirlpool use the _gcry_md_block_write helper * cipher/whirlpool.c (whirlpool_context_t): Add 'bctx', remove 'buffer', 'count' and 'nblocks'. (whirlpool_init): Initialize 'bctx'. (whirlpool_transform): Adjust context argument type and burn stack depth. (whirlpool_add): Remove. (whirlpool_write): Use _gcry_md_block_write. (whirlpool_final, whirlpool_read): Adjust for 'bctx' usage. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/hash-common.h b/cipher/hash-common.h index 3caf0a7..ce91da5 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -32,8 +32,8 @@ const char * _gcry_hash_selftest_check_one typedef unsigned int (*_gcry_md_block_write_t) (void *c, const unsigned char *buf); -#if defined(HAVE_U64_TYPEDEF) && defined(USE_SHA512) -/* SHA-512 needs u64 and larger buffer. */ +#if defined(HAVE_U64_TYPEDEF) && (defined(USE_SHA512) || defined(USE_WHIRLPOOL)) +/* SHA-512 needs u64 and larger buffer. Whirlpool needs u64. */ # define MD_BLOCK_MAX_BLOCKSIZE 128 # define MD_NBLOCKS_TYPE u64 #else diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 6b5f1a9..fa632f9 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -38,6 +38,7 @@ #include "cipher.h" #include "bufhelp.h" +#include "hash-common.h" /* Size of a whirlpool block (in bytes). */ #define BLOCK_SIZE 64 @@ -51,10 +52,8 @@ typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; typedef struct { + gcry_md_block_ctx_t bctx; whirlpool_block_t hash_state; - unsigned char buffer[BLOCK_SIZE]; - size_t count; - u64 nblocks; } whirlpool_context_t; @@ -1161,12 +1160,20 @@ static const u64 C7[256] = +static unsigned int +whirlpool_transform (void *ctx, const unsigned char *data); + + + static void whirlpool_init (void *ctx) { whirlpool_context_t *context = ctx; memset (context, 0, sizeof (*context)); + + context->bctx.blocksize = BLOCK_SIZE; + context->bctx.bwrite = whirlpool_transform; } @@ -1174,8 +1181,9 @@ whirlpool_init (void *ctx) * Transform block. */ static unsigned int -whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) +whirlpool_transform (void *ctx, const unsigned char *data) { + whirlpool_context_t *context = ctx; whirlpool_block_t data_block; whirlpool_block_t key; whirlpool_block_t state; @@ -1269,67 +1277,18 @@ whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) block_xor (context->hash_state, state, i); return /*burn_stack*/ 4 * sizeof(whirlpool_block_t) + 2 * sizeof(int) + - 3 * sizeof(void*); -} - -static void -whirlpool_add (whirlpool_context_t *context, - const void *buffer_arg, size_t buffer_n) -{ - const unsigned char *buffer = buffer_arg; - unsigned int burn = 0; - - if (context->count == BLOCK_SIZE) - { - /* Flush the buffer. */ - burn = whirlpool_transform (context, context->buffer); - _gcry_burn_stack (burn); - burn = 0; - context->count = 0; - context->nblocks++; - } - if (! buffer) - return; /* Nothing to add. */ - - if (context->count) - { - while (buffer_n && (context->count < BLOCK_SIZE)) - { - context->buffer[context->count++] = *buffer++; - buffer_n--; - } - whirlpool_add (context, NULL, 0); - /* Can return early now that bit counter calculation is done in final. */ - if (!buffer_n) - return; - } - - while (buffer_n >= BLOCK_SIZE) - { - burn = whirlpool_transform (context, buffer); - context->count = 0; - context->nblocks++; - buffer_n -= BLOCK_SIZE; - buffer += BLOCK_SIZE; - } - while (buffer_n && (context->count < BLOCK_SIZE)) - { - context->buffer[context->count++] = *buffer++; - buffer_n--; - } - - _gcry_burn_stack (burn); + 4 * sizeof(void*); } static void whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) { whirlpool_context_t *context = ctx; - u64 old_nblocks = context->nblocks; + u64 old_nblocks = context->bctx.nblocks; - whirlpool_add (context, buffer, buffer_n); + _gcry_md_block_write (context, buffer, buffer_n); - gcry_assert (old_nblocks <= context->nblocks); + gcry_assert (old_nblocks <= context->bctx.nblocks); } static void @@ -1340,13 +1299,13 @@ whirlpool_final (void *ctx) u64 t, lsb, msb; unsigned char *length; - t = context->nblocks; + t = context->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 58; /* add the count */ t = lsb; - if ((lsb += context->count) < t) + if ((lsb += context->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; @@ -1358,28 +1317,28 @@ whirlpool_final (void *ctx) whirlpool_write (context, NULL, 0); /* Pad. */ - context->buffer[context->count++] = 0x80; + context->bctx.buf[context->bctx.count++] = 0x80; - if (context->count > 32) + if (context->bctx.count > 32) { /* An extra block is necessary. */ - while (context->count < 64) - context->buffer[context->count++] = 0; + while (context->bctx.count < 64) + context->bctx.buf[context->bctx.count++] = 0; whirlpool_write (context, NULL, 0); } - while (context->count < 32) - context->buffer[context->count++] = 0; + while (context->bctx.count < 32) + context->bctx.buf[context->bctx.count++] = 0; /* Add length of message. */ - length = context->buffer + context->count; + length = context->bctx.buf + context->bctx.count; buf_put_be64(&length[0 * 8], 0); buf_put_be64(&length[1 * 8], 0); buf_put_be64(&length[2 * 8], msb); buf_put_be64(&length[3 * 8], lsb); - context->count += 32; + context->bctx.count += 32; whirlpool_write (context, NULL, 0); - block_to_buffer (context->buffer, context->hash_state, i); + block_to_buffer (context->bctx.buf, context->hash_state, i); } static byte * @@ -1387,7 +1346,7 @@ whirlpool_read (void *ctx) { whirlpool_context_t *context = ctx; - return context->buffer; + return context->bctx.buf; } gcry_md_spec_t _gcry_digest_spec_whirlpool = commit a96d622e1a36d40d1504b7ada567e90ec9957443 Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 whirlpool: add stack burning after transform * cipher/whirlpool.c (whirlpool_transform): Return burn stack depth. (whirlpool_add): Do burn_stack. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 1ee8916..6b5f1a9 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1173,7 +1173,7 @@ whirlpool_init (void *ctx) /* * Transform block. */ -static void +static unsigned int whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) { whirlpool_block_t data_block; @@ -1267,6 +1267,9 @@ whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) block_xor (context->hash_state, data_block, i); block_xor (context->hash_state, state, i); + + return /*burn_stack*/ 4 * sizeof(whirlpool_block_t) + 2 * sizeof(int) + + 3 * sizeof(void*); } static void @@ -1274,12 +1277,14 @@ whirlpool_add (whirlpool_context_t *context, const void *buffer_arg, size_t buffer_n) { const unsigned char *buffer = buffer_arg; + unsigned int burn = 0; if (context->count == BLOCK_SIZE) { /* Flush the buffer. */ - whirlpool_transform (context, context->buffer); - /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ + burn = whirlpool_transform (context, context->buffer); + _gcry_burn_stack (burn); + burn = 0; context->count = 0; context->nblocks++; } @@ -1298,11 +1303,10 @@ whirlpool_add (whirlpool_context_t *context, if (!buffer_n) return; } - /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ while (buffer_n >= BLOCK_SIZE) { - whirlpool_transform (context, buffer); + burn = whirlpool_transform (context, buffer); context->count = 0; context->nblocks++; buffer_n -= BLOCK_SIZE; @@ -1313,6 +1317,8 @@ whirlpool_add (whirlpool_context_t *context, context->buffer[context->count++] = *buffer++; buffer_n--; } + + _gcry_burn_stack (burn); } static void commit 10d7351411f19bb2c03d2e24ca5a38dabe45023b Author: Jussi Kivilinna Date: Sat Sep 21 13:54:38 2013 +0300 whirlpool: do bitcount calculation in finalization part * cipher/whirlpool.c (whirlpool_context_t): Remove 'length', add 'nblocks'. (whirlpool_add): Update 'nblocks' instead of 'length', and add early return at one spot. (whirlpool_write): Check for 'nblocks' overflow. (whirlpool_final): Convert 'nblocks' to bit-counter, and use whirlpool_write instead of whirlpool_add. -- Currently Whirlpool uses large 256 bit counter that is increased in the 'write' function. However, we could to bit counter calculation as is done in all the rest hash algorithms; use 64-bit block counter that is converted to bit counter in finalization function. This change does limit amount of bytes Whirlpool can process before overflowing bit counter. With 256-bit counter, overflow happens after ~1.3e67 gigabytes. With 64-bit block counter, overflow happens just after ~1.1e12 gigabytes. Patch keeps the old behaviour of halting if counter overflows. Main benefit for this patch is that after this change, we can use the _gcry_md_block_write helper for Whirlpool too. Signed-off-by: Jussi Kivilinna diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 954640a..1ee8916 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -54,7 +54,7 @@ typedef struct { whirlpool_block_t hash_state; unsigned char buffer[BLOCK_SIZE]; size_t count; - unsigned char length[32]; + u64 nblocks; } whirlpool_context_t; @@ -1274,11 +1274,6 @@ whirlpool_add (whirlpool_context_t *context, const void *buffer_arg, size_t buffer_n) { const unsigned char *buffer = buffer_arg; - u64 buffer_size; - unsigned int carry; - unsigned int i; - - buffer_size = buffer_n; if (context->count == BLOCK_SIZE) { @@ -1286,6 +1281,7 @@ whirlpool_add (whirlpool_context_t *context, whirlpool_transform (context, context->buffer); /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ context->count = 0; + context->nblocks++; } if (! buffer) return; /* Nothing to add. */ @@ -1298,6 +1294,9 @@ whirlpool_add (whirlpool_context_t *context, buffer_n--; } whirlpool_add (context, NULL, 0); + /* Can return early now that bit counter calculation is done in final. */ + if (!buffer_n) + return; } /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ @@ -1305,6 +1304,7 @@ whirlpool_add (whirlpool_context_t *context, { whirlpool_transform (context, buffer); context->count = 0; + context->nblocks++; buffer_n -= BLOCK_SIZE; buffer += BLOCK_SIZE; } @@ -1313,29 +1313,17 @@ whirlpool_add (whirlpool_context_t *context, context->buffer[context->count++] = *buffer++; buffer_n--; } - - /* Update bit counter. */ - carry = 0; - buffer_size <<= 3; - for (i = 1; i <= 32; i++) - { - if (! (buffer_size || carry)) - break; - - carry += context->length[32 - i] + (buffer_size & 0xFF); - context->length[32 - i] = carry; - buffer_size >>= 8; - carry >>= 8; - } - gcry_assert (! (buffer_size || carry)); } static void whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) { whirlpool_context_t *context = ctx; + u64 old_nblocks = context->nblocks; whirlpool_add (context, buffer, buffer_n); + + gcry_assert (old_nblocks <= context->nblocks); } static void @@ -1343,9 +1331,25 @@ whirlpool_final (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; + u64 t, lsb, msb; + unsigned char *length; + + t = context->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 58; + /* add the count */ + t = lsb; + if ((lsb += context->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 61; /* Flush. */ - whirlpool_add (context, NULL, 0); + whirlpool_write (context, NULL, 0); /* Pad. */ context->buffer[context->count++] = 0x80; @@ -1355,15 +1359,19 @@ whirlpool_final (void *ctx) /* An extra block is necessary. */ while (context->count < 64) context->buffer[context->count++] = 0; - whirlpool_add (context, NULL, 0); + whirlpool_write (context, NULL, 0); } while (context->count < 32) context->buffer[context->count++] = 0; /* Add length of message. */ - memcpy (context->buffer + context->count, context->length, 32); + length = context->buffer + context->count; + buf_put_be64(&length[0 * 8], 0); + buf_put_be64(&length[1 * 8], 0); + buf_put_be64(&length[2 * 8], msb); + buf_put_be64(&length[3 * 8], lsb); context->count += 32; - whirlpool_add (context, NULL, 0); + whirlpool_write (context, NULL, 0); block_to_buffer (context->buffer, context->hash_state, i); } ----------------------------------------------------------------------- Summary of changes: cipher/hash-common.h | 4 +- cipher/whirlpool.c | 131 ++++++++++++++++++++------------------------------ 2 files changed, 54 insertions(+), 81 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 30 21:23:11 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 30 Sep 2013 21:23:11 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-281-ga2618c8 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 a2618c822e666d4121cba29bee3fd50bf70c9743 (commit) via c325adb8f5092b80a626bd3bb5e49cf7f3a29fc8 (commit) via d69a13d3d1c14ad6a6aa7cd349d6d2dfb152d422 (commit) from 68cefd0f1d60ac33b58031df9b1d165cb1bf0f14 (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 a2618c822e666d4121cba29bee3fd50bf70c9743 Author: Werner Koch Date: Mon Sep 30 20:32:20 2013 +0200 ecc: Prepare for future Ed25519 optimization. * mpi/ec-ed25519.c: New but empty file. * mpi/ec-internal.h: New. * mpi/ec.c: Include ec-internal.h. (ec_mod): New. (ec_addm): Use ec_mod. (ec_mulm): Remove commented code. Use ec_mod. (ec_subm): Call simple sub. (ec_pow2): Use ec_mulm. (ec_mul2): New. (dup_point_weierstrass): Use ec_mul2. (dup_point_twistededwards): Add special case for a == -1. Use ec_mul2. (add_points_weierstrass): Use ec_mul2. (add_points_twistededwards): Add special case for a == -1. (_gcry_mpi_ec_curve_point): Ditto. (ec_p_init): Add hack to test Barrett functions. * src/ec-context.h (mpi_ec_ctx_s): Add P_BARRETT. * mpi/mpi-mod.c (_gcry_mpi_mod_barrett): Fix sign problem. Signed-off-by: Werner Koch diff --git a/mpi/Makefile.am b/mpi/Makefile.am index e900539..c41b1ea 100644 --- a/mpi/Makefile.am +++ b/mpi/Makefile.am @@ -174,4 +174,4 @@ libmpi_la_SOURCES = longlong.h \ mpih-div.c \ mpih-mul.c \ mpiutil.c \ - ec.c + ec.c ec-internal.h ec-ed25519.c diff --git a/mpi/ec-ed25519.c b/mpi/ec-ed25519.c new file mode 100644 index 0000000..acfe2a6 --- /dev/null +++ b/mpi/ec-ed25519.c @@ -0,0 +1,37 @@ +/* ec-ed25519.c - Ed25519 optimized elliptic curve functions + * Copyright (C) 2013 g10 Code GmbH + * + * 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 . + */ + +#include +#include +#include +#include + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" +#include "context.h" +#include "ec-context.h" + + +void +_gcry_mpi_ec_ed25519_mod (gcry_mpi_t a) +{ + (void)a; + +} diff --git a/mpi/ec-internal.h b/mpi/ec-internal.h new file mode 100644 index 0000000..759335a --- /dev/null +++ b/mpi/ec-internal.h @@ -0,0 +1,25 @@ +/* ec-internal.h - Internal declarations of ec*.c + * Copyright (C) 2013 g10 Code GmbH + * + * 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 . + */ + +#ifndef GCRY_EC_INTERNAL_H +#define GCRY_EC_INTERNAL_H + +void _gcry_mpi_ec_ed25519_mod (gcry_mpi_t a); + +#endif /*GCRY_EC_INTERNAL_H*/ diff --git a/mpi/ec.c b/mpi/ec.c index de681a1..889df8e 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -28,6 +28,7 @@ #include "g10lib.h" #include "context.h" #include "ec-context.h" +#include "ec-internal.h" #define point_init(a) _gcry_mpi_point_init ((a)) @@ -224,131 +225,46 @@ gcry_mpi_point_snatch_set (mpi_point_t point, } +/* W = W mod P. */ +static void +ec_mod (gcry_mpi_t w, mpi_ec_t ec) +{ + if (0 && ec->dialect == ECC_DIALECT_ED25519) + _gcry_mpi_ec_ed25519_mod (w); + else if (ec->t.p_barrett) + _gcry_mpi_mod_barrett (w, w, ec->t.p_barrett); + else + _gcry_mpi_mod (w, w, ec->p); +} + static void ec_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) { - mpi_addm (w, u, v, ctx->p); + gcry_mpi_add (w, u, v); + ec_mod (w, ctx); } static void -ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) +ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ec) { - mpi_subm (w, u, v, ctx->p); + (void)ec; + gcry_mpi_sub (w, u, v); + /*ec_mod (w, ec);*/ } static void ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) { -#if 0 - /* NOTE: This code works only for limb sizes of 32 bit. */ - mpi_limb_t *wp, *sp; + mpi_mul (w, u, v); + ec_mod (w, ctx); +} - if (ctx->nist_nbits == 192) - { - mpi_mul (w, u, v); - mpi_resize (w, 12); - wp = w->d; - - sp = ctx->s[0]->d; - sp[0*2+0] = wp[0*2+0]; - sp[0*2+1] = wp[0*2+1]; - sp[1*2+0] = wp[1*2+0]; - sp[1*2+1] = wp[1*2+1]; - sp[2*2+0] = wp[2*2+0]; - sp[2*2+1] = wp[2*2+1]; - - sp = ctx->s[1]->d; - sp[0*2+0] = wp[3*2+0]; - sp[0*2+1] = wp[3*2+1]; - sp[1*2+0] = wp[3*2+0]; - sp[1*2+1] = wp[3*2+1]; - sp[2*2+0] = 0; - sp[2*2+1] = 0; - - sp = ctx->s[2]->d; - sp[0*2+0] = 0; - sp[0*2+1] = 0; - sp[1*2+0] = wp[4*2+0]; - sp[1*2+1] = wp[4*2+1]; - sp[2*2+0] = wp[4*2+0]; - sp[2*2+1] = wp[4*2+1]; - - sp = ctx->s[3]->d; - sp[0*2+0] = wp[5*2+0]; - sp[0*2+1] = wp[5*2+1]; - sp[1*2+0] = wp[5*2+0]; - sp[1*2+1] = wp[5*2+1]; - sp[2*2+0] = wp[5*2+0]; - sp[2*2+1] = wp[5*2+1]; - - ctx->s[0]->nlimbs = 6; - ctx->s[1]->nlimbs = 6; - ctx->s[2]->nlimbs = 6; - ctx->s[3]->nlimbs = 6; - - mpi_add (ctx->c, ctx->s[0], ctx->s[1]); - mpi_add (ctx->c, ctx->c, ctx->s[2]); - mpi_add (ctx->c, ctx->c, ctx->s[3]); - - while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) - mpi_sub ( ctx->c, ctx->c, ctx->p ); - mpi_set (w, ctx->c); - } - else if (ctx->nist_nbits == 384) - { - int i; - mpi_mul (w, u, v); - mpi_resize (w, 24); - wp = w->d; - -#define NEXT(a) do { ctx->s[(a)]->nlimbs = 12; \ - sp = ctx->s[(a)]->d; \ - i = 0; } while (0) -#define X(a) do { sp[i++] = wp[(a)];} while (0) -#define X0(a) do { sp[i++] = 0; } while (0) - NEXT(0); - X(0);X(1);X(2);X(3);X(4);X(5);X(6);X(7);X(8);X(9);X(10);X(11); - NEXT(1); - X0();X0();X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0(); - NEXT(2); - X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22);X(23); - NEXT(3); - X(21);X(22);X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20); - NEXT(4); - X0();X(23);X0();X(20);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19); - NEXT(5); - X0();X0();X0();X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0(); - NEXT(6); - X(20);X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0();X0(); - NEXT(7); - X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22); - NEXT(8); - X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0();X0();X0();X0(); - NEXT(9); - X0();X0();X0();X(23);X(23);X0();X0();X0();X0();X0();X0();X0(); -#undef X0 -#undef X -#undef NEXT - mpi_add (ctx->c, ctx->s[0], ctx->s[1]); - mpi_add (ctx->c, ctx->c, ctx->s[1]); - mpi_add (ctx->c, ctx->c, ctx->s[2]); - mpi_add (ctx->c, ctx->c, ctx->s[3]); - mpi_add (ctx->c, ctx->c, ctx->s[4]); - mpi_add (ctx->c, ctx->c, ctx->s[5]); - mpi_add (ctx->c, ctx->c, ctx->s[6]); - mpi_sub (ctx->c, ctx->c, ctx->s[7]); - mpi_sub (ctx->c, ctx->c, ctx->s[8]); - mpi_sub (ctx->c, ctx->c, ctx->s[9]); - - while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) - mpi_sub ( ctx->c, ctx->c, ctx->p ); - while ( ctx->c->sign ) - mpi_add ( ctx->c, ctx->c, ctx->p ); - mpi_set (w, ctx->c); - } - else -#endif /*0*/ - mpi_mulm (w, u, v, ctx->p); +/* W = 2 * U mod P. */ +static void +ec_mul2 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx) +{ + mpi_lshift (w, u, 1); + ec_mod (w, ctx); } static void @@ -368,7 +284,7 @@ ec_pow2 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx) { /* Using mpi_mul is slightly faster (at least on amd64). */ /* mpi_powm (w, b, mpi_const (MPI_C_TWO), ctx->p); */ - mpi_mulm (w, b, b, ctx->p); + ec_mulm (w, b, b, ctx); } @@ -437,6 +353,15 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { int i; + static int use_barrett; + + if (!use_barrett) + { + if (getenv ("GCRYPT_BARRETT")) + use_barrett = 1; + else + use_barrett = -1; + } /* Fixme: Do we want to check some constraints? e.g. a < p */ @@ -451,6 +376,8 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, if (b && model == MPI_EC_TWISTEDEDWARDS) ctx->b = mpi_copy (b); + ctx->t.p_barrett = use_barrett > 0? _gcry_mpi_barrett_init (ctx->p, 0):NULL; + _gcry_mpi_ec_get_reset (ctx); /* Allocate scratch variables. */ @@ -483,6 +410,8 @@ ec_deinit (void *opaque) mpi_ec_t ctx = opaque; int i; + _gcry_mpi_barrett_free (ctx->t.p_barrett); + /* Domain parameter. */ mpi_free (ctx->p); mpi_free (ctx->a); @@ -732,7 +661,7 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) } /* Z3 = 2YZ */ ec_mulm (z3, point->y, point->z, ctx); - ec_mulm (z3, z3, mpi_const (MPI_C_TWO), ctx); + ec_mul2 (z3, z3, ctx); /* L2 = 4XY^2 */ /* T2: used for Y2; required later. */ @@ -743,7 +672,7 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) /* X3 = L1^2 - 2L2 */ /* T1: used for L2^2. */ ec_pow2 (x3, l1, ctx); - ec_mulm (t1, l2, mpi_const (MPI_C_TWO), ctx); + ec_mul2 (t1, l2, ctx); ec_subm (x3, x3, t1, ctx); /* L3 = 8Y^4 */ @@ -811,7 +740,13 @@ dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) ec_pow2 (D, Y1, ctx); /* E = aC */ - ec_mulm (E, ctx->a, C, ctx); + if (ctx->dialect == ECC_DIALECT_ED25519) + { + mpi_set (E, C); + _gcry_mpi_neg (E, E); + } + else + ec_mulm (E, ctx->a, C, ctx); /* F = E + D */ ec_addm (F, E, D, ctx); @@ -820,7 +755,7 @@ dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx) ec_pow2 (H, Z1, ctx); /* J = F - 2H */ - ec_mulm (J, H, mpi_const (MPI_C_TWO), ctx); + ec_mul2 (J, H, ctx); ec_subm (J, F, J, ctx); /* X_3 = (B - C - D) ? J */ @@ -978,7 +913,7 @@ add_points_weierstrass (mpi_point_t result, ec_mulm (t2, t2, l7, ctx); ec_subm (x3, t1, t2, ctx); /* l9 = l7 l3^2 - 2 x3 */ - ec_mulm (t1, x3, mpi_const (MPI_C_TWO), ctx); + ec_mul2 (t1, x3, ctx); ec_subm (l9, t2, t1, ctx); /* y3 = (l9 l6 - l8 l3^3)/2 */ ec_mulm (l9, l9, l6, ctx); @@ -1085,8 +1020,19 @@ add_points_twistededwards (mpi_point_t result, ec_mulm (X3, X3, A, ctx); /* Y_3 = A ? G ? (D - aC) */ - ec_mulm (Y3, ctx->a, C, ctx); - ec_subm (Y3, D, Y3, ctx); + if (ctx->dialect == ECC_DIALECT_ED25519) + { + /* Using ec_addm (Y3, D, C, ctx) is possible but a litte bit + slower because a subm does currently skip the mod step. */ + mpi_set (Y3, C); + _gcry_mpi_neg (Y3, Y3); + ec_subm (Y3, D, Y3, ctx); + } + else + { + ec_mulm (Y3, ctx->a, C, ctx); + ec_subm (Y3, D, Y3, ctx); + } ec_mulm (Y3, Y3, G, ctx); ec_mulm (Y3, Y3, A, ctx); @@ -1282,7 +1228,13 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) /* a ? x^2 + y^2 - 1 - b ? x^2 ? y^2 == 0 */ ec_pow2 (x, x, ctx); ec_pow2 (y, y, ctx); - ec_mulm (w, ctx->a, x, ctx); + if (ctx->dialect == ECC_DIALECT_ED25519) + { + mpi_set (w, x); + _gcry_mpi_neg (w, w); + } + else + ec_mulm (w, ctx->a, x, ctx); ec_addm (w, w, y, ctx); ec_subm (w, w, mpi_const (MPI_C_ONE), ctx); ec_mulm (x, x, y, ctx); diff --git a/mpi/mpi-mod.c b/mpi/mpi-mod.c index 795826e..3d6248b 100644 --- a/mpi/mpi-mod.c +++ b/mpi/mpi-mod.c @@ -111,7 +111,7 @@ _gcry_mpi_barrett_free (mpi_barrett_t ctx) _gcry_mpi_barrett_init must have been called to do the precalculations. CTX is the context created by this precalculation and also conveys M. If the Barret reduction could no be done a - starightforward reduction method is used. + straightforward reduction method is used. We assume that these conditions are met: Input: x =(x_2k-1 ...x_0)_b @@ -126,6 +126,7 @@ _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) gcry_mpi_t y = ctx->y; gcry_mpi_t r1 = ctx->r1; gcry_mpi_t r2 = ctx->r2; + int sign; mpi_normalize (x); if (mpi_get_nlimbs (x) > 2*k ) @@ -134,6 +135,9 @@ _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) return; } + sign = x->sign; + x->sign = 0; + /* 1. q1 = floor( x / b^k-1) * q2 = q1 * y * q3 = floor( q2 / b^k+1 ) @@ -172,6 +176,7 @@ _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) while ( mpi_cmp( r, m ) >= 0 ) mpi_sub ( r, r, m ); + x->sign = sign; } diff --git a/src/ec-context.h b/src/ec-context.h index 8dce7a7..ba6bdfc 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -53,6 +53,8 @@ struct mpi_ec_ctx_s gcry_mpi_t two_inv_p; + mpi_barrett_t p_barrett; + /* Scratch variables. */ gcry_mpi_t scratch[11]; diff --git a/src/misc.c b/src/misc.c index d577b24..912039a 100644 --- a/src/misc.c +++ b/src/misc.c @@ -396,7 +396,8 @@ _gcry_log_printsxp (const char *text, gcry_sexp_t sexp) { int any = 0; int n_closing; - char *buf, *p, *pend; + char *buf, *pend; + const char *p; size_t size; size = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); commit c325adb8f5092b80a626bd3bb5e49cf7f3a29fc8 Author: Werner Koch Date: Mon Sep 30 20:17:05 2013 +0200 ecc: Fix recomputing of Q for Ed25519. * cipher/ecc-misc.c (reverse_buffer): New. (_gcry_ecc_compute_public): Add ED255519 specific code. * cipher/ecc.c (sign_eddsa): Allocate DIGEST in secure memory. Get rid of HASH_D. * tests/t-mpi-point.c (context_param): Test recomputing of Q for Ed25519. Signed-off-by: Werner Koch diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 1dc0480..d89971f 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -234,22 +234,96 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) } +static void +reverse_buffer (unsigned char *buffer, unsigned int length) +{ + unsigned int tmp, i; + + for (i=0; i < length/2; i++) + { + tmp = buffer[i]; + buffer[i] = buffer[length-1-i]; + buffer[length-1-i] = tmp; + } +} + + /* Compute the public key from the the context EC. Obviously a requirement is that the secret key is available in EC. On success - Q is returned; on error NULL. If Q is NULL a newly allocated pint + Q is returned; on error NULL. If Q is NULL a newly allocated point is returned. */ mpi_point_t _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec) { + int rc; + if (!ec->d || !ec->G || !ec->p || !ec->a) return NULL; if (ec->model == MPI_EC_TWISTEDEDWARDS && !ec->b) return NULL; - if (!Q) - Q = gcry_mpi_point_new (0); - if (!Q) - return NULL; - _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); + switch (ec->dialect) + { + case ECC_DIALECT_ED25519: + { + gcry_mpi_t a; + unsigned char *rawmpi = NULL; + unsigned int rawmpilen; + unsigned char *digest; + gcry_buffer_t hvec[2]; + int b = (ec->nbits+7)/8; + + gcry_assert (b >= 32); + digest = gcry_calloc_secure (2, b); + if (!digest) + return NULL; + memset (hvec, 0, sizeof hvec); + + rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL); + if (!rawmpi) + return NULL; + memset (digest, 0, b); + hvec[0].data = digest; + hvec[0].off = 0; + hvec[0].len = b > rawmpilen? b - rawmpilen : 0; + hvec[1].data = rawmpi; + hvec[1].off = 0; + hvec[1].len = rawmpilen; + /* FIXME: Put and take the hash algo from the context. */ + rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, digest, hvec, 2); + gcry_free (rawmpi); + if (rc) + { + gcry_free (digest); + return NULL; + } + + /* Compute the A value. */ + reverse_buffer (digest, 32); /* Only the first half of the hash. */ + digest[0] = (digest[0] & 0x7f) | 0x40; + digest[31] &= 0xf8; + a = mpi_snew (0); + _gcry_mpi_set_buffer (a, digest, 32, 0); + gcry_free (digest); + + /* And finally the public key. */ + if (!Q) + Q = gcry_mpi_point_new (0); + if (Q) + _gcry_mpi_ec_mul_point (Q, a, ec->G, ec); + mpi_free (a); + } + break; + + default: + { + if (!Q) + Q = gcry_mpi_point_new (0); + if (Q) + _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); + } + break; + } + return Q; } diff --git a/cipher/ecc.c b/cipher/ecc.c index abd501f..a7fb90f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -909,8 +909,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, mpi_ec_t ctx = NULL; int b; unsigned int tmp; - unsigned char hash_d[64]; /* Fixme: malloc in secure memory */ - unsigned char digest[64]; + unsigned char *digest; gcry_buffer_t hvec[3]; const void *mbuf; size_t mlen; @@ -938,37 +937,41 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, r = mpi_new (0); ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, skey->E.p, skey->E.a, skey->E.b); - b = ctx->nbits/8; + b = (ctx->nbits+7)/8; if (b != 256/8) return GPG_ERR_INTERNAL; /* We only support 256 bit. */ + digest = gcry_calloc_secure (2, b); + if (!digest) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } - /* Hash the secret key. We clear DIGEST so we can use it to left - pad the key with zeroes for hashing. */ + /* Hash the secret key. We clear DIGEST so we can use it as input + to left pad the key with zeroes for hashing. */ rawmpi = _gcry_mpi_get_buffer (skey->d, 0, &rawmpilen, NULL); if (!rawmpi) { rc = gpg_err_code_from_syserror (); goto leave; } - memset (digest, 0, b); hvec[0].data = digest; hvec[0].off = 0; hvec[0].len = b > rawmpilen? b - rawmpilen : 0; hvec[1].data = rawmpi; hvec[1].off = 0; hvec[1].len = rawmpilen; - rc = _gcry_md_hash_buffers (hashalgo, 0, hash_d, hvec, 2); + rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2); gcry_free (rawmpi); rawmpi = NULL; if (rc) goto leave; - /* Compute the A value (this modifies hash_d). */ - reverse_buffer (hash_d, 32); /* Only the first half of the hash. */ - hash_d[0] = (hash_d[0] & 0x7f) | 0x40; - hash_d[31] &= 0xf8; - _gcry_mpi_set_buffer (a, hash_d, 32, 0); - /* log_printmpi (" a", a); */ + /* Compute the A value (this modifies DIGEST). */ + reverse_buffer (digest, 32); /* Only the first half of the hash. */ + digest[0] = (digest[0] & 0x7f) | 0x40; + digest[31] &= 0xf8; + _gcry_mpi_set_buffer (a, digest, 32, 0); /* Compute the public key if it has not been supplied as optional parameter. */ @@ -1001,7 +1004,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, if (DBG_CIPHER) log_printhex (" m", mbuf, mlen); - hvec[0].data = hash_d; + hvec[0].data = digest; hvec[0].off = 32; hvec[0].len = 32; hvec[1].data = (char*)mbuf; @@ -1063,6 +1066,7 @@ sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (r); + gcry_free (digest); _gcry_mpi_ec_free (ctx); point_free (&I); point_free (&Q); diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index 0641779..5a0b311 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -666,9 +666,17 @@ context_param (void) "Ed25519", ctx); get_and_cmp_mpi ("q at eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx); - /* Delete Q by setting d and the clearing d. The clearing is + /* Set d tosee whether Q is correctly re-computed. */ + d = hex2mpi (sample_ed25519_d); + err = gcry_mpi_ec_set_mpi ("d", d, ctx); + if (err) + fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err)); + gcry_mpi_release (d); + get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx); + + /* Delete Q by setting d and then clearing d. The clearing is required so that we can check whether Q has been cleared and - because further tests only expect a public key. */ + because further tests only expect a public key. */ d = hex2mpi (sample_ed25519_d); err = gcry_mpi_ec_set_mpi ("d", d, ctx); if (err) commit d69a13d3d1c14ad6a6aa7cd349d6d2dfb152d422 Author: Werner Koch Date: Mon Sep 30 13:20:06 2013 +0200 log: Try to print s-expressions in a more compact format. * src/misc.c (count_closing_parens): New. (_gcry_log_printsxp): Use new function. * mpi/ec.c (_gcry_mpi_point_log): Take care of a NULL point. Signed-off-by: Werner Koch diff --git a/mpi/ec.c b/mpi/ec.c index c6d0fc8..de681a1 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -42,6 +42,12 @@ _gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx) gcry_mpi_t x, y; char buf[100]; + if (!point) + { + snprintf (buf, sizeof buf - 1, "%s.*", name); + log_mpidump (buf, NULL); + return; + } snprintf (buf, sizeof buf - 1, "%s.X", name); if (ctx) diff --git a/src/misc.c b/src/misc.c index d9b85cb..d577b24 100644 --- a/src/misc.c +++ b/src/misc.c @@ -361,6 +361,22 @@ _gcry_log_printmpi (const char *text, gcry_mpi_t mpi) } } + +static int +count_closing_parens (const char *p) +{ + int count = 0; + + for (; *p; p++) + if (*p == ')') + count++; + else if (!strchr ("\n \t", *p)) + return 0; + + return count; +} + + /* Print SEXP in human readabale format. With TEXT of NULL print just the raw dump without any wrappping, with TEXT an empty string, print a trailing linefeed, otherwise print the full debug output. */ @@ -371,7 +387,7 @@ _gcry_log_printsxp (const char *text, gcry_sexp_t sexp) if (text && *text) { - if ((with_lf = strchr (text, '\n'))) + if ((with_lf = !!strchr (text, '\n'))) log_debug ("%s", text); else log_debug ("%s: ", text); @@ -379,6 +395,7 @@ _gcry_log_printsxp (const char *text, gcry_sexp_t sexp) if (sexp) { int any = 0; + int n_closing; char *buf, *p, *pend; size_t size; @@ -395,18 +412,26 @@ _gcry_log_printsxp (const char *text, gcry_sexp_t sexp) pend = strchr (p, '\n'); size = pend? (pend - p) : strlen (p); if (with_lf) - log_debug ("%.*s\n", (int)size, p); + log_debug ("%.*s", (int)size, p); else - log_printf ("%.*s\n", (int)size, p); + log_printf ("%.*s", (int)size, p); if (pend) p = pend + 1; else p += size; + n_closing = count_closing_parens (p); + if (n_closing) + { + while (n_closing--) + log_printf (")"); + p = ""; + } + log_printf ("\n"); } while (*p); gcry_free (buf); } - if (text) + else if (text) log_printf ("\n"); } ----------------------------------------------------------------------- Summary of changes: cipher/ecc-misc.c | 86 +++++++++++++- cipher/ecc.c | 32 +++--- mpi/Makefile.am | 2 +- cipher/gost.h => mpi/ec-ed25519.c | 30 +++-- src/hwf-common.h => mpi/ec-internal.h | 16 +-- mpi/ec.c | 200 +++++++++++++-------------------- mpi/mpi-mod.c | 7 +- src/ec-context.h | 2 + src/misc.c | 36 +++++- tests/t-mpi-point.c | 12 ++- 10 files changed, 251 insertions(+), 172 deletions(-) copy cipher/gost.h => mpi/ec-ed25519.c (63%) copy src/hwf-common.h => mpi/ec-internal.h (67%) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Sep 30 21:46:34 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 30 Sep 2013 21:46:34 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-282-g1d85452 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 1d85452412b65e7976bc94969fc513ff6b880ed8 (commit) from a2618c822e666d4121cba29bee3fd50bf70c9743 (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 1d85452412b65e7976bc94969fc513ff6b880ed8 Author: Werner Koch Date: Mon Sep 30 21:14:11 2013 +0200 ecc: Use faster b parameter for Ed25519. * cipher/ecc-curves.c (domain_parms): Replace b. * tests/t-mpi-point.c (test_curve): Ditto. -- This change has been suggested by NIIBE Yutaka: Here, 0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4 is: (121666^-1 mod q)*121665. (121666^-1) * 121665 mod q is: 0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A While it works for both, I think that shorter is better. Signed-off-by: Werner Koch diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 7447340..15888a8 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -103,7 +103,7 @@ static const ecc_domain_parms_t domain_parms[] = MPI_EC_TWISTEDEDWARDS, ECC_DIALECT_ED25519, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", "-0x01", - "-0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4", + "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A", "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED", "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A", "0x6666666666666666666666666666666666666666666666666666666666666658" diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index 5a0b311..a345cbc 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -125,7 +125,7 @@ static struct "Ed25519", "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", "-0x01", - "-0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4", + "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A", "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED", "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A", "0x6666666666666666666666666666666666666666666666666666666666666658" ----------------------------------------------------------------------- Summary of changes: cipher/ecc-curves.c | 2 +- tests/t-mpi-point.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org