From: Jia Zhang Date: Sun, 29 Oct 2017 03:58:20 +0000 (-0400) Subject: New module: crypto/gc-sm3 X-Git-Tag: v1.0~5854 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=e128f7fb2f0be16d96e5cc274bdd61bcb68313eb;p=gnulib.git New module: crypto/gc-sm3 * lib/gc.h: Declare SM3-related stuffs. * lib/gc-gnulib.c: Support sm3 in internal functions. * lib/gc-libgcrypt.c: Support sm3 with libgcrypt. * m4/gc-sm3.m4: m4 file for gc-sm3 module. * modules/crypto/gc-sm3: Define gc-sm3 module. * tests/test-gc-sm3.c: Implement SM3 test case with libgcrypt. * modules/crypto/gc-sm3-tests: Define gc-sm3 test module. * MODULES.html.sh: List gc-sm3 module. --- diff --git a/ChangeLog b/ChangeLog index 9d88925f09..7523b34d3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2017-10-29 Jia Zhang + + New module: crypto/gc-sm3 + * lib/gc.h: Declare SM3-related stuffs. + * lib/gc-gnulib.c: Support sm3 in internal functions. + * lib/gc-libgcrypt.c: Support sm3 with libgcrypt. + * m4/gc-sm3.m4: m4 file for gc-sm3 module. + * modules/crypto/gc-sm3: Define gc-sm3 module. + * tests/test-gc-sm3.c: Implement SM3 test case with libgcrypt. + * modules/crypto/gc-sm3-tests: Define gc-sm3 test module. + * MODULES.html.sh: List gc-sm3 module. + 2017-10-29 Bruno Haible random, random_r: Mention different prototypes on Haiku. diff --git a/MODULES.html.sh b/MODULES.html.sh index 7729772ecb..2cf7594a16 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1988,6 +1988,7 @@ func_all_modules () func_module crypto/gc-random func_module crypto/gc-rijndael func_module crypto/gc-sha1 + func_module crypto/gc-sm3 func_end_table element="Compiler warning management" diff --git a/lib/gc-gnulib.c b/lib/gc-gnulib.c index 61d5d980a6..f888cf5970 100644 --- a/lib/gc-gnulib.c +++ b/lib/gc-gnulib.c @@ -48,6 +48,9 @@ #ifdef GNULIB_GC_SHA1 # include "sha1.h" #endif +#ifdef GNULIB_GC_SM3 +# include "sm3.h" +#endif #if defined(GNULIB_GC_HMAC_MD5) || defined(GNULIB_GC_HMAC_SHA1) || defined(GNULIB_GC_HMAC_SHA256) || defined(GNULIB_GC_HMAC_SHA512) # include "hmac.h" #endif @@ -618,6 +621,9 @@ typedef struct _gc_hash_ctx #ifdef GNULIB_GC_SHA1 struct sha1_ctx sha1Context; #endif +#ifdef GNULIB_GC_SM3 + struct sm3_ctx sm3Context; +#endif } _gc_hash_ctx; Gc_rc @@ -662,6 +668,12 @@ gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle) break; #endif +#ifdef GNULIB_GC_SM3 + case GC_SM3: + sm3_init_ctx (&ctx->sm3Context); + break; +#endif + default: rc = GC_INVALID_HASH; break; @@ -717,6 +729,10 @@ gc_hash_digest_length (Gc_hash hash) len = GC_SHA1_DIGEST_SIZE; break; + case GC_SM3: + len = GC_SM3_DIGEST_SIZE; + break; + default: return 0; } @@ -755,6 +771,12 @@ gc_hash_write (gc_hash_handle handle, size_t len, const char *data) break; #endif +#ifdef GNULIB_GC_SM3 + case GC_SM3: + sm3_process_bytes (data, len, &ctx->sm3Context); + break; +#endif + default: break; } @@ -796,6 +818,13 @@ gc_hash_read (gc_hash_handle handle) break; #endif +#ifdef GNULIB_GC_SM3 + case GC_SM3: + sm3_finish_ctx (&ctx->sm3Context, ctx->hash); + ret = ctx->hash; + break; +#endif + default: return NULL; } @@ -840,6 +869,12 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) break; #endif +#ifdef GNULIB_GC_SM3 + case GC_SM3: + sm3_buffer (in, inlen, resbuf); + break; +#endif + default: return GC_INVALID_HASH; } @@ -883,6 +918,15 @@ gc_sha1 (const void *in, size_t inlen, void *resbuf) } #endif +#ifdef GNULIB_GC_SM3 +Gc_rc +gc_sm3 (const void *in, size_t inlen, void *resbuf) +{ + sm3_buffer (in, inlen, resbuf); + return GC_OK; +} +#endif + #ifdef GNULIB_GC_HMAC_MD5 Gc_rc gc_hmac_md5 (const void *key, size_t keylen, diff --git a/lib/gc-libgcrypt.c b/lib/gc-libgcrypt.c index f0c8d82293..49ba0e13cb 100644 --- a/lib/gc-libgcrypt.c +++ b/lib/gc-libgcrypt.c @@ -304,6 +304,10 @@ gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle) gcryalg = GCRY_MD_RMD160; break; + case GC_SM3: + gcryalg = GCRY_MD_SM3; + break; + default: rc = GC_INVALID_HASH; } @@ -403,6 +407,10 @@ gc_hash_digest_length (Gc_hash hash) len = GC_SHA224_DIGEST_SIZE; break; + case GC_SM3: + len = GC_SM3_DIGEST_SIZE; + break; + default: return 0; } @@ -530,6 +538,12 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) break; #endif +#ifdef GNULIB_GC_SM3 + case GC_SM3: + gcryalg = GCRY_MD_SM3; + break; +#endif + default: return GC_INVALID_HASH; } @@ -646,6 +660,38 @@ gc_sha1 (const void *in, size_t inlen, void *resbuf) } #endif +#ifdef GNULIB_GC_SM3 +Gc_rc +gc_sm3 (const void *in, size_t inlen, void *resbuf) +{ + size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_SM3); + gcry_md_hd_t hd; + gpg_error_t err; + unsigned char *p; + + assert (outlen == GC_SM3_DIGEST_SIZE); + + err = gcry_md_open (&hd, GCRY_MD_SM3, 0); + if (err != GPG_ERR_NO_ERROR) + return GC_INVALID_HASH; + + gcry_md_write (hd, in, inlen); + + p = gcry_md_read (hd, GCRY_MD_SM3); + if (p == NULL) + { + gcry_md_close (hd); + return GC_INVALID_HASH; + } + + memcpy (resbuf, p, outlen); + + gcry_md_close (hd); + + return GC_OK; +} +#endif + #ifdef GNULIB_GC_HMAC_MD5 Gc_rc gc_hmac_md5 (const void *key, size_t keylen, diff --git a/lib/gc.h b/lib/gc.h index a47cc8d0e3..e65ba49a34 100644 --- a/lib/gc.h +++ b/lib/gc.h @@ -47,7 +47,8 @@ enum Gc_hash GC_SHA256, GC_SHA384, GC_SHA512, - GC_SHA224 + GC_SHA224, + GC_SM3 }; typedef enum Gc_hash Gc_hash; @@ -69,6 +70,7 @@ typedef void *gc_hash_handle; #define GC_SHA384_DIGEST_SIZE 48 #define GC_SHA512_DIGEST_SIZE 64 #define GC_SHA224_DIGEST_SIZE 24 +#define GC_SM3_DIGEST_SIZE 32 /* Cipher types. */ enum Gc_cipher @@ -156,6 +158,7 @@ extern Gc_rc gc_md2 (const void *in, size_t inlen, void *resbuf); extern Gc_rc gc_md4 (const void *in, size_t inlen, void *resbuf); extern Gc_rc gc_md5 (const void *in, size_t inlen, void *resbuf); extern Gc_rc gc_sha1 (const void *in, size_t inlen, void *resbuf); +extern Gc_rc gc_sm3 (const void *in, size_t inlen, void *resbuf); extern Gc_rc gc_hmac_md5 (const void *key, size_t keylen, const void *in, size_t inlen, char *resbuf); extern Gc_rc gc_hmac_sha1 (const void *key, size_t keylen, diff --git a/m4/gc-sm3.m4 b/m4/gc-sm3.m4 new file mode 100644 index 0000000000..3d0eb4710e --- /dev/null +++ b/m4/gc-sm3.m4 @@ -0,0 +1,10 @@ +# gc-sm3.m4 serial 1 +dnl Copyright (C) 2017 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_GC_SM3], +[ + AC_REQUIRE([gl_GC]) +]) diff --git a/modules/crypto/gc-sm3 b/modules/crypto/gc-sm3 new file mode 100644 index 0000000000..de52e04547 --- /dev/null +++ b/modules/crypto/gc-sm3 @@ -0,0 +1,24 @@ +Description: +Generic crypto wrappers for SM3 functions. + +Files: +m4/gc-sm3.m4 + +Depends-on: +crypto/gc +crypto/sm3 [test "$ac_cv_libgcrypt" != yes] + +configure.ac: +gl_GC_SM3 +gl_MODULE_INDICATOR([gc-sm3]) + +Makefile.am: + +Include: +"gc.h" + +License: +LGPLv2+ + +Maintainer: +Jia Zhang diff --git a/modules/crypto/gc-sm3-tests b/modules/crypto/gc-sm3-tests new file mode 100644 index 0000000000..006f41f374 --- /dev/null +++ b/modules/crypto/gc-sm3-tests @@ -0,0 +1,11 @@ +Files: +tests/test-gc-sm3.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-gc-sm3 +check_PROGRAMS += test-gc-sm3 +test_gc_sm3_LDADD = $(LDADD) @LIB_CRYPTO@ diff --git a/tests/test-gc-sm3.c b/tests/test-gc-sm3.c new file mode 100644 index 0000000000..608725d0b2 --- /dev/null +++ b/tests/test-gc-sm3.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2017 Free Software Foundation, Inc. + * Written by Jia Zhang + * + * This program 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . */ + +#include + +#include +#include +#include "gc.h" + +int +main (int argc, char *argv[]) +{ + Gc_rc rc; + gc_hash_handle h; + + rc = gc_init (); + if (rc != GC_OK) + { + printf ("gc_init() failed\n"); + return 1; + } + + /* Test vector from GM/T 004-2012. */ + + { + const char *in = "abc"; + size_t inlen = strlen (in); + const char *expect = "\x66\xc7\xf0\xf4\x62\xee\xed\xd9\xd1" + "\xf2\xd4\x6b\xdc\x10\xe4\xe2\x41\x67\xc4\x87\x5c" + "\xf2\xf7\xa2\x29\x7d\xa0\x2b\x8f\x4b\xa8\xe0"; + char out[32]; + const char *p; + + if (gc_sm3 (in, inlen, out) != 0) + { + printf ("gc_sm3 call failed\n"); + return 1; + } + + if (memcmp (out, expect, 32) != 0) + { + size_t i; + printf ("sm3 mismatch. expected:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) expect[i] & 0xFF); + printf ("\ncomputed:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) out[i] & 0xFF); + printf ("\n"); + return 1; + } + + rc = gc_hash_buffer (GC_SM3, "abc", 3, out); + if (rc != GC_OK) + { + printf ("gc_hash_buffer(sm3) call failed: %u\n", rc); + return 1; + } + + if (memcmp (out, expect, 32) != 0) + { + size_t i; + printf ("sm3' mismatch. expected:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) expect[i] & 0xFF); + printf ("\ncomputed:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) out[i] & 0xFF); + printf ("\n"); + return 1; + } + + if (gc_hash_digest_length (GC_SM3) != 32) + { + printf ("gc_hash_digest_length (GC_SM3) failed\n"); + return 1; + } + + if ((rc = gc_hash_open (GC_SM3, 0, &h)) != GC_OK) + { + printf ("gc_hash_open(GC_SM3) failed (%u)\n", rc); + return 1; + } + + gc_hash_write (h, inlen, in); + + p = gc_hash_read (h); + + if (!p) + { + printf ("gc_hash_read failed\n"); + return 1; + } + + if (memcmp (p, expect, 32) != 0) + { + size_t i; + printf ("sm3 mismatch. expected:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) expect[i] & 0xFF); + printf ("\ncomputed:\n"); + for (i = 0; i < 32; i++) + printf ("%02x ", (unsigned int) p[i] & 0xFF); + printf ("\n"); + return 1; + } + + gc_hash_close (h); + } + + gc_done (); + + return 0; +}