From 8d10627e9371aadaf00771bcb29a73420b891cd4 Mon Sep 17 00:00:00 2001 From: Jia Zhang Date: Sat, 28 Oct 2017 23:58:20 -0400 Subject: [PATCH 1/2] sm3: add the support for compiling with libgcrypt * lib/gc-gnulib.c: Support sm3 in internal functions. * lib/gc-libgcrypt.c: Support sm3 with libgcrypt. * lib/gc.h: Declear SM3-related stuffs. * m4/gc-sm3.m4: m4 file for gc-sm3 module. * modules/crypto/gc-sm3: Define gc-sm3 module. * modules/crypto/gc-sm3-tests: Define gc-sm3 test module. * tests/test-gc-sm3.c: Implement SM3 test case with libgcrypt. * MODULES.html.sh: List gc-sm3 module. --- MODULES.html.sh | 1 + lib/gc-gnulib.c | 44 +++++++++++++++ lib/gc-libgcrypt.c | 46 ++++++++++++++++ lib/gc.h | 5 +- m4/gc-sm3.m4 | 10 ++++ modules/crypto/gc-sm3 | 24 +++++++++ modules/crypto/gc-sm3-tests | 11 ++++ tests/test-gc-sm3.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 m4/gc-sm3.m4 create mode 100644 modules/crypto/gc-sm3 create mode 100644 modules/crypto/gc-sm3-tests create mode 100644 tests/test-gc-sm3.c diff --git a/MODULES.html.sh b/MODULES.html.sh index 7729772ec..2cf7594a1 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 61d5d980a..f888cf597 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 f0c8d8229..49ba0e13c 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 a47cc8d0e..e65ba49a3 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 000000000..3d0eb4710 --- /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 000000000..de52e0454 --- /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 000000000..21488df1c --- /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@ $(LIBGCRYPT_LIBS) diff --git a/tests/test-gc-sm3.c b/tests/test-gc-sm3.c new file mode 100644 index 000000000..3e412c851 --- /dev/null +++ b/tests/test-gc-sm3.c @@ -0,0 +1,129 @@ +/* + * 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 +#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; +} -- 2.14.1