Add OSCCA SM3 secure hash generic hash algorithm, described in OSCCA GM/T 0004-2012 SM3.
Tianjia Zhang (4): Add OSCCA SM3 hash algorithm testsuite: add test for SM3 hash function hmac: add support for SM3 hash function nettle-benchmark: bench SM3 hashes
Makefile.in | 7 +- examples/nettle-benchmark.c | 2 +- hmac-sm3-meta.c | 47 +++++++ hmac-sm3.c | 59 +++++++++ hmac.h | 19 +++ nettle-meta-hashes.c | 1 + nettle-meta-macs.c | 1 + nettle-meta.h | 2 + sm3-meta.c | 41 ++++++ sm3.c | 250 ++++++++++++++++++++++++++++++++++++ sm3.h | 81 ++++++++++++ testsuite/.gitignore | 1 + testsuite/Makefile.in | 2 +- testsuite/hmac-test.c | 6 + testsuite/meta-hash-test.c | 3 +- testsuite/meta-mac-test.c | 1 + testsuite/sm3-test.c | 20 +++ 17 files changed, 537 insertions(+), 6 deletions(-) create mode 100644 hmac-sm3-meta.c create mode 100644 hmac-sm3.c create mode 100644 sm3-meta.c create mode 100644 sm3.c create mode 100644 sm3.h create mode 100644 testsuite/sm3-test.c
Add OSCCA SM3 secure hash (OSCCA GM/T 0004-2012 SM3) generic hash transformation.
Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com --- Makefile.in | 3 +- nettle-meta-hashes.c | 1 + nettle-meta.h | 1 + sm3-meta.c | 41 ++++++ sm3.c | 250 +++++++++++++++++++++++++++++++++++++ sm3.h | 81 ++++++++++++ testsuite/meta-hash-test.c | 3 +- 7 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 sm3-meta.c create mode 100644 sm3.c create mode 100644 sm3.h
diff --git a/Makefile.in b/Makefile.in index e6fc25b8..77f474c3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -145,6 +145,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \ sha3-224.c sha3-224-meta.c sha3-256.c sha3-256-meta.c \ sha3-384.c sha3-384-meta.c sha3-512.c sha3-512-meta.c \ shake256.c \ + sm3.c sm3-meta.c \ serpent-set-key.c serpent-encrypt.c serpent-decrypt.c \ serpent-meta.c \ streebog.c streebog-meta.c \ @@ -233,7 +234,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \ pbkdf2.h \ pgp.h pkcs1.h pss.h pss-mgf1.h realloc.h ripemd160.h rsa.h \ salsa20.h sexp.h \ - serpent.h sha.h sha1.h sha2.h sha3.h streebog.h twofish.h \ + serpent.h sha.h sha1.h sha2.h sha3.h sm3.h streebog.h twofish.h \ umac.h yarrow.h xts.h poly1305.h nist-keywrap.h
INSTALL_HEADERS = $(HEADERS) version.h @IF_MINI_GMP@ mini-gmp.h diff --git a/nettle-meta-hashes.c b/nettle-meta-hashes.c index 8e96dd41..4d421182 100644 --- a/nettle-meta-hashes.c +++ b/nettle-meta-hashes.c @@ -55,6 +55,7 @@ const struct nettle_hash * const _nettle_hashes[] = { &nettle_sha3_512, &nettle_streebog256, &nettle_streebog512, + &nettle_sm3, NULL };
diff --git a/nettle-meta.h b/nettle-meta.h index 6a62b653..664321d8 100644 --- a/nettle-meta.h +++ b/nettle-meta.h @@ -145,6 +145,7 @@ extern const struct nettle_hash nettle_sha3_384; extern const struct nettle_hash nettle_sha3_512; extern const struct nettle_hash nettle_streebog256; extern const struct nettle_hash nettle_streebog512; +extern const struct nettle_hash nettle_sm3;
struct nettle_mac { diff --git a/sm3-meta.c b/sm3-meta.c new file mode 100644 index 00000000..7aae7ce4 --- /dev/null +++ b/sm3-meta.c @@ -0,0 +1,41 @@ +/* sm3-meta.c + + Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "nettle-meta.h" + +#include "sm3.h" + +const struct nettle_hash nettle_sm3 += _NETTLE_HASH(sm3, SM3); diff --git a/sm3.c b/sm3.c new file mode 100644 index 00000000..955939fa --- /dev/null +++ b/sm3.c @@ -0,0 +1,250 @@ +/* sm3.c + + The SM3 hash function. + + Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <string.h> + +#include "sm3.h" + +#include "macros.h" +#include "nettle-write.h" + +static const uint32_t K[64] = +{ + 0x79cc4519UL, 0xf3988a32UL, 0xe7311465UL, 0xce6228cbUL, + 0x9cc45197UL, 0x3988a32fUL, 0x7311465eUL, 0xe6228cbcUL, + 0xcc451979UL, 0x988a32f3UL, 0x311465e7UL, 0x6228cbceUL, + 0xc451979cUL, 0x88a32f39UL, 0x11465e73UL, 0x228cbce6UL, + 0x9d8a7a87UL, 0x3b14f50fUL, 0x7629ea1eUL, 0xec53d43cUL, + 0xd8a7a879UL, 0xb14f50f3UL, 0x629ea1e7UL, 0xc53d43ceUL, + 0x8a7a879dUL, 0x14f50f3bUL, 0x29ea1e76UL, 0x53d43cecUL, + 0xa7a879d8UL, 0x4f50f3b1UL, 0x9ea1e762UL, 0x3d43cec5UL, + 0x7a879d8aUL, 0xf50f3b14UL, 0xea1e7629UL, 0xd43cec53UL, + 0xa879d8a7UL, 0x50f3b14fUL, 0xa1e7629eUL, 0x43cec53dUL, + 0x879d8a7aUL, 0x0f3b14f5UL, 0x1e7629eaUL, 0x3cec53d4UL, + 0x79d8a7a8UL, 0xf3b14f50UL, 0xe7629ea1UL, 0xcec53d43UL, + 0x9d8a7a87UL, 0x3b14f50fUL, 0x7629ea1eUL, 0xec53d43cUL, + 0xd8a7a879UL, 0xb14f50f3UL, 0x629ea1e7UL, 0xc53d43ceUL, + 0x8a7a879dUL, 0x14f50f3bUL, 0x29ea1e76UL, 0x53d43cecUL, + 0xa7a879d8UL, 0x4f50f3b1UL, 0x9ea1e762UL, 0x3d43cec5UL +}; + +/* + Transform the message X which consists of 16 32-bit-words. See + GM/T 004-2012 for details. */ +#define R(i, a, b, c, d, e, f, g, h, t, w1, w2) \ + do { \ + ss1 = ROTL32(7, (ROTL32(12, (a)) + (e) + (t))); \ + ss2 = ss1 ^ ROTL32(12, (a)); \ + d += FF ## i(a, b, c) + ss2 + ((w1) ^ (w2)); \ + h += GG ## i(e, f, g) + ss1 + (w1); \ + b = ROTL32(9, (b)); \ + f = ROTL32(19, (f)); \ + h = P0((h)); \ + } while (0) + +#define R1(a,b,c,d,e,f,g,h,t,w1,w2) R(1,a,b,c,d,e,f,g,h,t,w1,w2) +#define R2(a,b,c,d,e,f,g,h,t,w1,w2) R(2,a,b,c,d,e,f,g,h,t,w1,w2) + +#define FF1(x, y, z) (x ^ y ^ z) +#define FF2(x, y, z) ((x & y) | (x & z) | (y & z)) + +#define GG1(x, y, z) (x ^ y ^ z) +#define GG2(x, y, z) ((x & y) | ( ~x & z)) + +/* Message expansion */ +#define P0(x) ((x) ^ ROTL32(9, (x)) ^ ROTL32(17, (x))) +#define P1(x) ((x) ^ ROTL32(15, (x)) ^ ROTL32(23, (x))) +#define I(i) (w[i] = READ_UINT32(input + i * 4)) +#define W1(i) (w[i & 0x0f]) +#define W2(i) (w[i & 0x0f] = \ + P1(w[i & 0x0f] ^ w[(i-9) & 0x0f] ^ ROTL32(15, w[(i-3) & 0x0f])) \ + ^ ROTL32(7, w[(i-13) & 0x0f]) \ + ^ w[(i-6) & 0x0f]) + + +static void +sm3_compress(uint32_t *state, const uint8_t *input) +{ + uint32_t a, b, c, d, e, f, g, h, ss1, ss2; + uint32_t w[16]; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4)); + R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5)); + R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6)); + R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7)); + R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8)); + R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9)); + R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10)); + R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11)); + R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12)); + R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13)); + R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14)); + R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15)); + R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16)); + R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17)); + R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18)); + R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19)); + + R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20)); + R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21)); + R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22)); + R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23)); + R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24)); + R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25)); + R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26)); + R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27)); + R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28)); + R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29)); + R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30)); + R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31)); + R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32)); + R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33)); + R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34)); + R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35)); + + R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36)); + R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37)); + R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38)); + R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39)); + R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40)); + R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41)); + R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42)); + R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43)); + R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44)); + R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45)); + R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46)); + R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47)); + R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48)); + R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49)); + R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50)); + R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51)); + + R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52)); + R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53)); + R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54)); + R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55)); + R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56)); + R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57)); + R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58)); + R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59)); + R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60)); + R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61)); + R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62)); + R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63)); + R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64)); + R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65)); + R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66)); + R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67)); + + state[0] ^= a; + state[1] ^= b; + state[2] ^= c; + state[3] ^= d; + state[4] ^= e; + state[5] ^= f; + state[6] ^= g; + state[7] ^= h; +} + +void +sm3_init(struct sm3_ctx *ctx) +{ + static const uint32_t H0[_SM3_DIGEST_LENGTH] = + { + 0x7380166fUL, 0x4914b2b9UL, 0x172442d7UL, 0xda8a0600UL, + 0xa96f30bcUL, 0x163138aaUL, 0xe38dee4dUL, 0xb0fb0e4eUL + }; + + memcpy(ctx->state, H0, sizeof(H0)); + + /* Initialize bit count */ + ctx->count = 0; + + /* Initialize buffer */ + ctx->index = 0; +} + +#define COMPRESS(ctx, data) (sm3_compress((ctx)->state, (data))) + +void +sm3_update(struct sm3_ctx *ctx, + size_t length, const uint8_t *data) +{ + MD_UPDATE(ctx, length, data, COMPRESS, ctx->count++); +} + +static void +sm3_write_digest(struct sm3_ctx *ctx, + size_t length, + uint8_t *digest) +{ + uint64_t bit_count; + + assert(length <= SM3_DIGEST_SIZE); + + MD_PAD(ctx, 8, COMPRESS); + + /* There are 512 = 2^9 bits in one block */ + bit_count = (ctx->count << 9) | (ctx->index << 3); + + /* This is slightly inefficient, as the numbers are converted to + big-endian format, and will be converted back by the compression + function. It's probably not worth the effort to fix this. */ + WRITE_UINT64(ctx->block + (SM3_BLOCK_SIZE - 8), bit_count); + COMPRESS(ctx, ctx->block); + + _nettle_write_be32(length, digest, ctx->state); +} + +void +sm3_digest(struct sm3_ctx *ctx, + size_t length, + uint8_t *digest) +{ + sm3_write_digest(ctx, length, digest); + sm3_init(ctx); +} diff --git a/sm3.h b/sm3.h new file mode 100644 index 00000000..f825b9fc --- /dev/null +++ b/sm3.h @@ -0,0 +1,81 @@ +/* sm3.h + + The SM3 hash function. + + Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#ifndef NETTLE_SM3_H_INCLUDED +#define NETTLE_SM3_H_INCLUDED + +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name mangling */ +#define sm3_init nettle_sm3_init +#define sm3_update nettle_sm3_update +#define sm3_digest nettle_sm3_digest + +#define SM3_DIGEST_SIZE 32 +#define SM3_BLOCK_SIZE 64 +/* For backwards compatibility */ +#define SM3_DATA_SIZE SM3_BLOCK_SIZE + +/* Digest is kept internally as 8 32-bit words. */ +#define _SM3_DIGEST_LENGTH 8 + +struct sm3_ctx +{ + uint32_t state[_SM3_DIGEST_LENGTH]; + uint64_t count; /* Block count */ + unsigned index; /* Into buffer */ + uint8_t block[SM3_BLOCK_SIZE]; /* Block buffer */ +}; + +void +sm3_init(struct sm3_ctx *ctx); + +void +sm3_update(struct sm3_ctx *ctx, + size_t length, + const uint8_t *data); + +void +sm3_digest(struct sm3_ctx *ctx, + size_t length, + uint8_t *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_SM3_H_INCLUDED */ diff --git a/testsuite/meta-hash-test.c b/testsuite/meta-hash-test.c index eb9f3698..3aed43fc 100644 --- a/testsuite/meta-hash-test.c +++ b/testsuite/meta-hash-test.c @@ -21,7 +21,8 @@ const char* hashes[] = { "sha3_384", "sha3_512", "streebog256", - "streebog512" + "streebog512", + "sm3", };
void
Add a testuite for SM3 hash function. Test vectors are based on: https://datatracker.ietf.org/doc/html/draft-shen-sm3-hash-01
Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com --- testsuite/.gitignore | 1 + testsuite/Makefile.in | 2 +- testsuite/sm3-test.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 testsuite/sm3-test.c
diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 9d8a7681..ca41472e 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -97,6 +97,7 @@ /sha512-224-test /sha512-256-test /sha512-test +/sm3-test /streebog-test /twofish-test /umac-test diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 2b554261..6734d3e6 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -24,7 +24,7 @@ TS_NETTLE_SOURCES = aes-test.c aes-keywrap-test.c arcfour-test.c arctwo-test.c \ sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \ sha3-permute-test.c sha3-224-test.c sha3-256-test.c \ sha3-384-test.c sha3-512-test.c \ - shake256-test.c streebog-test.c \ + shake256-test.c streebog-test.c sm3-test.c \ serpent-test.c twofish-test.c version-test.c \ knuth-lfib-test.c \ cbc-test.c cfb-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \ diff --git a/testsuite/sm3-test.c b/testsuite/sm3-test.c new file mode 100644 index 00000000..d3684afd --- /dev/null +++ b/testsuite/sm3-test.c @@ -0,0 +1,20 @@ +#include "testutils.h" +#include "sm3.h" + +void +test_main(void) +{ + /* test vectors from: + * https://datatracker.ietf.org/doc/html/draft-shen-sm3-hash-01 + */ + test_hash(&nettle_sm3, + SDATA("abc"), + SHEX("66c7f0f462eeedd9 d1f2d46bdc10e4e2" + "4167c4875cf2f7a2 297da02b8f4ba8e0")); + + test_hash(&nettle_sm3, + SDATA("abcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcd"), + SHEX("debe9ff92275b8a1 38604889c18e5a4d" + "6fdb70e5387e5765 293dcba39c0c5732")); +}
Add support for calculating HMAC using SM3 hash functions.
Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com --- Makefile.in | 4 +-- hmac-sm3-meta.c | 47 +++++++++++++++++++++++++++++++ hmac-sm3.c | 59 +++++++++++++++++++++++++++++++++++++++ hmac.h | 19 +++++++++++++ nettle-meta-macs.c | 1 + nettle-meta.h | 1 + testsuite/hmac-test.c | 6 ++++ testsuite/meta-mac-test.c | 1 + 8 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 hmac-sm3-meta.c create mode 100644 hmac-sm3.c
diff --git a/Makefile.in b/Makefile.in index 77f474c3..0590c370 100644 --- a/Makefile.in +++ b/Makefile.in @@ -117,10 +117,10 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \ gost28147.c gosthash94.c gosthash94-meta.c \ hmac.c hmac-gosthash94.c hmac-md5.c hmac-ripemd160.c \ hmac-sha1.c hmac-sha224.c hmac-sha256.c hmac-sha384.c \ - hmac-sha512.c hmac-streebog.c \ + hmac-sha512.c hmac-streebog.c hmac-sm3.c \ hmac-md5-meta.c hmac-ripemd160-meta.c hmac-sha1-meta.c \ hmac-sha224-meta.c hmac-sha256-meta.c hmac-sha384-meta.c \ - hmac-sha512-meta.c hmac-streebog-meta.c \ + hmac-sha512-meta.c hmac-streebog-meta.c hmac-sm3-meta.c \ knuth-lfib.c hkdf.c \ md2.c md2-meta.c md4.c md4-meta.c \ md5.c md5-compress.c md5-compat.c md5-meta.c \ diff --git a/hmac-sm3-meta.c b/hmac-sm3-meta.c new file mode 100644 index 00000000..d3d7f3d2 --- /dev/null +++ b/hmac-sm3-meta.c @@ -0,0 +1,47 @@ +/* hmac-sm3-meta.c + + Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "nettle-meta.h" + +#include "hmac.h" + +static void +hmac_sm3_set_key_wrapper (void *ctx, const uint8_t *key) +{ + hmac_sm3_set_key (ctx, SM3_DIGEST_SIZE, key); +} + +const struct nettle_mac nettle_hmac_sm3 += _NETTLE_HMAC(hmac_sm3, SM3); diff --git a/hmac-sm3.c b/hmac-sm3.c new file mode 100644 index 00000000..decb4a2d --- /dev/null +++ b/hmac-sm3.c @@ -0,0 +1,59 @@ +/* hmac-sm3.c + + HMAC-SM3 message authentication code. + + Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "hmac.h" + +void +hmac_sm3_set_key(struct hmac_sm3_ctx *ctx, + size_t key_length, const uint8_t *key) +{ + HMAC_SET_KEY(ctx, &nettle_sm3, key_length, key); +} + +void +hmac_sm3_update(struct hmac_sm3_ctx *ctx, + size_t length, const uint8_t *data) +{ + sm3_update(&ctx->state, length, data); +} + +void +hmac_sm3_digest(struct hmac_sm3_ctx *ctx, + size_t length, uint8_t *digest) +{ + HMAC_DIGEST(ctx, &nettle_sm3, length, digest); +} diff --git a/hmac.h b/hmac.h index 72c8fd57..453a67af 100644 --- a/hmac.h +++ b/hmac.h @@ -42,6 +42,7 @@ #include "sha1.h" #include "sha2.h" #include "streebog.h" +#include "sm3.h"
#ifdef __cplusplus extern "C" { @@ -81,6 +82,9 @@ extern "C" { #define hmac_streebog512_set_key nettle_hmac_streebog512_set_key #define hmac_streebog512_update nettle_hmac_streebog512_update #define hmac_streebog512_digest nettle_hmac_streebog512_digest +#define hmac_sm3_set_key nettle_hmac_sm3_set_key +#define hmac_sm3_update nettle_hmac_sm3_update +#define hmac_sm3_digest nettle_hmac_sm3_digest
void hmac_set_key(void *outer, void *inner, void *state, @@ -273,6 +277,21 @@ void hmac_streebog256_digest(struct hmac_streebog256_ctx *ctx, size_t length, uint8_t *digest);
+/* hmac-sm3 */ +struct hmac_sm3_ctx HMAC_CTX(struct sm3_ctx); + +void +hmac_sm3_set_key(struct hmac_sm3_ctx *ctx, + size_t key_length, const uint8_t *key); + +void +hmac_sm3_update(struct hmac_sm3_ctx *ctx, + size_t length, const uint8_t *data); + +void +hmac_sm3_digest(struct hmac_sm3_ctx *ctx, + size_t length, uint8_t *digest); + #ifdef __cplusplus } #endif diff --git a/nettle-meta-macs.c b/nettle-meta-macs.c index 5e8f8713..40aa6dcd 100644 --- a/nettle-meta-macs.c +++ b/nettle-meta-macs.c @@ -50,6 +50,7 @@ const struct nettle_mac * const _nettle_macs[] = { &nettle_hmac_sha512, &nettle_hmac_streebog256, &nettle_hmac_streebog512, + &nettle_hmac_sm3, NULL };
diff --git a/nettle-meta.h b/nettle-meta.h index 664321d8..d684947e 100644 --- a/nettle-meta.h +++ b/nettle-meta.h @@ -291,6 +291,7 @@ extern const struct nettle_mac nettle_hmac_sha384; extern const struct nettle_mac nettle_hmac_sha512; extern const struct nettle_mac nettle_hmac_streebog256; extern const struct nettle_mac nettle_hmac_streebog512; +extern const struct nettle_mac nettle_hmac_sm3;
#ifdef __cplusplus } diff --git a/testsuite/hmac-test.c b/testsuite/hmac-test.c index 348f7920..0d1fb44c 100644 --- a/testsuite/hmac-test.c +++ b/testsuite/hmac-test.c @@ -883,4 +883,10 @@ test_main(void) SHEX("0126bdb87800af214341456563780100"), SHEX("a1aa5f7de402d7b3d323f2991c8d4534" "013137010a83754fd0af6d7cd4922ed9")); + + HMAC_TEST(sm3, + SDATA("monkey monkey monkey monkey"), + SDATA("abc"), + SHEX("7a9388e2ca5343b5d76e7c2c3d84f239" + "f306c0b60d5e0dc4d2771e42860a6a2b")); } diff --git a/testsuite/meta-mac-test.c b/testsuite/meta-mac-test.c index adbd4326..0ff82810 100644 --- a/testsuite/meta-mac-test.c +++ b/testsuite/meta-mac-test.c @@ -14,6 +14,7 @@ const char* macs[] = { "hmac_sha512", "hmac_streebog256", "hmac_streebog512", + "hmac_sm3", };
void
Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com --- examples/nettle-benchmark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c index 50a5815a..ba5dd284 100644 --- a/examples/nettle-benchmark.c +++ b/examples/nettle-benchmark.c @@ -909,7 +909,7 @@ main(int argc, char **argv) &nettle_sha3_384, &nettle_sha3_512, &nettle_ripemd160, &nettle_gosthash94, &nettle_gosthash94cp, &nettle_streebog256, - &nettle_streebog512, + &nettle_streebog512, &nettle_sm3, NULL };
Tianjia Zhang tianjia.zhang@linux.alibaba.com writes:
Add OSCCA SM3 secure hash generic hash algorithm, described in OSCCA GM/T 0004-2012 SM3.
Thanks, I've had a first quick look, and it looks nice. I don't know much about this hash function, though. A few questions:
* Is there some reasonably authoritative English reference for the algorithm? I checked wikipedia, and it only links to an old internet draft, https://tools.ietf.org/id/draft-oscca-cfrg-sm3-02.html
* The name "sm3" is a bit short, would it make sense to add some family-prefix, maybe "oscca_sm3"?
* Do you have some examples of protocols or applications that specify the use of sm3?
* The implementation, it's written from scratch, or is it based on some reference implementation?
Regards, /Niels
Hi Niels,
SM2/3/4 is a series of algorithms, which are all standards formulated by the China Cryptography Administration. They are widely used in China. At present, they are all ISO international standards. We will also consider supporting SM2 and SM4 algorithms in the future.
On 11/26/21 12:04 AM, Niels Möller wrote:
Tianjia Zhang tianjia.zhang@linux.alibaba.com writes:
Add OSCCA SM3 secure hash generic hash algorithm, described in OSCCA GM/T 0004-2012 SM3.
Thanks, I've had a first quick look, and it looks nice. I don't know much about this hash function, though. A few questions >
- Is there some reasonably authoritative English reference for the algorithm? I checked wikipedia, and it only links to an old internet draft, https://tools.ietf.org/id/draft-oscca-cfrg-sm3-02.html
You can refer to the ISO specification here: https://www.iso.org/standard/67116.html Or PDF version: https://github.com/alipay/tls13-sm-spec/blob/master/sm-en-pdfs/sm3/GBT.32905...
- The name "sm3" is a bit short, would it make sense to add some family-prefix, maybe "oscca_sm3"?
I do not recommend adding algorithm family prefixes. The algorithm names are already standardized, and the current mainstream implementations also use SM3 names, such as libgcrypt, openssl, linux kernel, coreutils, etc.
- Do you have some examples of protocols or applications that specify the use of sm3?
The SM2/3/4 algorithm can now be used in TLS 1.3 and other scenarios. It is also mandatory to use this type of algorithm in some areas in China. You can refer to: https://datatracker.ietf.org/doc/html/rfc8998 https://datatracker.ietf.org/doc/draft-chen-sm2-sm3-algorithms/
- The implementation, it's written from scratch, or is it based on some reference implementation?
The specification does not define the reference implementation of the algorithm. This series of patches mainly refers to the SM3 implementation in libgcrypt and gnulib.
Regards, /Niels
I hope your question has been answered, thanks again.
Best regards, Tianjia
Tianjia Zhang tianjia.zhang@linux.alibaba.com writes:
You can refer to the ISO specification here: https://www.iso.org/standard/67116.html Or PDF version: https://github.com/alipay/tls13-sm-spec/blob/master/sm-en-pdfs/sm3/GBT.32905...
I see that RFC 8998 refers to http://www.gmbz.org.cn/upload/2018-07-24/1532401392982079739.pdf, which looks like the same pdf file. I find it a bit odd that the document carries no information on author or organization.
The specification does not define the reference implementation of the algorithm. This series of patches mainly refers to the SM3 implementation in libgcrypt and gnulib.
It looks like the gcrypt implementation is licensed under LGPLv2.1 or later (see https://github.com/gpg/libgcrypt/blob/master/cipher/sm3.c), so should be fine to copy into nettle (in contrast to gnulib code, which appears to be GPLv3, and would need explicit permission from copyright holder before relicensing). But if it is a derived work of libgcrypt, in the sense of copyright law, the copyright header needs to acknowledge that, ie,
Copyright (C) 2017 Jia Zhang Copyright (C) 2021 Tianjia Zhang tianjia.zhang@linux.alibaba.com
Or did you write both versions, with Jia being an alternate form of your name?
Regards, /Niels
Hi Niels,
On 11/28/21 6:03 PM, Niels Möller wrote:
Tianjia Zhang tianjia.zhang@linux.alibaba.com writes:
You can refer to the ISO specification here: https://www.iso.org/standard/67116.html Or PDF version: https://github.com/alipay/tls13-sm-spec/blob/master/sm-en-pdfs/sm3/GBT.32905...
I see that RFC 8998 refers to http://www.gmbz.org.cn/upload/2018-07-24/1532401392982079739.pdf, which looks like the same pdf file. I find it a bit odd that the document carries no information on author or organization.
There is no author in the document, but the website www.gmbz.org.cn that publishes this standard is China’s Cryptography Standardization Technical Committee.
Thank you very much for your reminder, Jia Zhang is not himself, but another colleague of our team, I will add copyright information in the next version
The specification does not define the reference implementation of the algorithm. This series of patches mainly refers to the SM3 implementation in libgcrypt and gnulib.
It looks like the gcrypt implementation is licensed under LGPLv2.1 or later (see https://github.com/gpg/libgcrypt/blob/master/cipher/sm3.c), so should be fine to copy into nettle (in contrast to gnulib code, which appears to be GPLv3, and would need explicit permission from copyright holder before relicensing). But if it is a derived work of libgcrypt, in the sense of copyright law, the copyright header needs to acknowledge that, ie,
Copyright (C) 2017 Jia Zhang Copyright (C) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Or did you write both versions, with Jia being an alternate form of your name?
Thanks for pointing it out, Jia Zhang is another colleague of our team, I will add copyright information in the next version.
Best regards, Tianjia
nettle-bugs@lists.lysator.liu.se