Signed-off-by: Tianjia Zhang tianjia.zhang@linux.alibaba.com --- Makefile.in | 1 + gcm-sm4-meta.c | 60 ++++++++++++++++++++++++++++ gcm-sm4.c | 81 ++++++++++++++++++++++++++++++++++++++ gcm.h | 25 +++++++++++- nettle-meta-aeads.c | 1 + nettle-meta.h | 1 + testsuite/gcm-test.c | 18 +++++++++ testsuite/meta-aead-test.c | 1 + 8 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 gcm-sm4-meta.c create mode 100644 gcm-sm4.c
diff --git a/Makefile.in b/Makefile.in index 62511df4..a4c45201 100644 --- a/Makefile.in +++ b/Makefile.in @@ -112,6 +112,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \ gcm-aes256.c gcm-aes256-meta.c \ gcm-camellia128.c gcm-camellia128-meta.c \ gcm-camellia256.c gcm-camellia256-meta.c \ + gcm-sm4.c gcm-sm4-meta.c \ cmac.c cmac64.c cmac-aes128.c cmac-aes256.c cmac-des3.c \ cmac-aes128-meta.c cmac-aes256-meta.c cmac-des3-meta.c \ gost28147.c gosthash94.c gosthash94-meta.c \ diff --git a/gcm-sm4-meta.c b/gcm-sm4-meta.c new file mode 100644 index 00000000..dc7bd1ae --- /dev/null +++ b/gcm-sm4-meta.c @@ -0,0 +1,60 @@ +/* gcm-sm4-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 <assert.h> + +#include "nettle-meta.h" + +#include "gcm.h" + +static nettle_set_key_func gcm_sm4_set_nonce_wrapper; +static void +gcm_sm4_set_nonce_wrapper (void *ctx, const uint8_t *nonce) +{ + gcm_sm4_set_iv (ctx, GCM_IV_SIZE, nonce); +} + +const struct nettle_aead nettle_gcm_sm4 = + { "gcm_sm4", sizeof(struct gcm_sm4_ctx), + GCM_BLOCK_SIZE, SM4_KEY_SIZE, + GCM_IV_SIZE, GCM_DIGEST_SIZE, + (nettle_set_key_func *) gcm_sm4_set_key, + (nettle_set_key_func *) gcm_sm4_set_key, + gcm_sm4_set_nonce_wrapper, + (nettle_hash_update_func *) gcm_sm4_update, + (nettle_crypt_func *) gcm_sm4_encrypt, + (nettle_crypt_func *) gcm_sm4_decrypt, + (nettle_hash_digest_func *) gcm_sm4_digest, + }; diff --git a/gcm-sm4.c b/gcm-sm4.c new file mode 100644 index 00000000..70c1c6cf --- /dev/null +++ b/gcm-sm4.c @@ -0,0 +1,81 @@ +/* gcm-sm4.c + + Galois counter mode using SM4 as the underlying cipher. + + 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 "gcm.h" + +void +gcm_sm4_set_key(struct gcm_sm4_ctx *ctx, const uint8_t *key) +{ + GCM_SET_KEY(ctx, sm4_set_key, sm4_encrypt, key); +} + +void +gcm_sm4_set_iv (struct gcm_sm4_ctx *ctx, + size_t length, const uint8_t *iv) +{ + GCM_SET_IV (ctx, length, iv); +} + +void +gcm_sm4_update (struct gcm_sm4_ctx *ctx, + size_t length, const uint8_t *data) +{ + GCM_UPDATE (ctx, length, data); +} + +void +gcm_sm4_encrypt(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *dst, const uint8_t *src) +{ + GCM_ENCRYPT(ctx, sm4_encrypt, length, dst, src); +} + +void +gcm_sm4_decrypt(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *dst, const uint8_t *src) +{ + GCM_DECRYPT(ctx, sm4_encrypt, length, dst, src); +} + +void +gcm_sm4_digest(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *digest) +{ + GCM_DIGEST(ctx, sm4_encrypt, length, digest); +} diff --git a/gcm.h b/gcm.h index 96578530..2a35de3c 100644 --- a/gcm.h +++ b/gcm.h @@ -40,6 +40,7 @@
#include "aes.h" #include "camellia.h" +#include "sm4.h"
#ifdef __cplusplus extern "C" { @@ -95,6 +96,13 @@ extern "C" { #define gcm_camellia256_decrypt nettle_gcm_camellia256_decrypt #define gcm_camellia256_digest nettle_gcm_camellia256_digest
+#define gcm_sm4_set_key nettle_gcm_sm4_set_key +#define gcm_sm4_set_iv nettle_gcm_sm4_set_iv +#define gcm_sm4_update nettle_gcm_sm4_update +#define gcm_sm4_encrypt nettle_gcm_sm4_encrypt +#define gcm_sm4_decrypt nettle_gcm_sm4_decrypt +#define gcm_sm4_digest nettle_gcm_sm4_digest + #define GCM_BLOCK_SIZE 16 #define GCM_IV_SIZE (GCM_BLOCK_SIZE - 4) #define GCM_DIGEST_SIZE 16 @@ -322,7 +330,22 @@ void gcm_camellia256_decrypt(struct gcm_camellia256_ctx *ctx, void gcm_camellia256_digest(struct gcm_camellia256_ctx *ctx, size_t length, uint8_t *digest);
- + +struct gcm_sm4_ctx GCM_CTX(struct sm4_ctx); + +void gcm_sm4_set_key(struct gcm_sm4_ctx *ctx, const uint8_t *key); +void gcm_sm4_set_iv (struct gcm_sm4_ctx *ctx, + size_t length, const uint8_t *iv); +void gcm_sm4_update (struct gcm_sm4_ctx *ctx, + size_t length, const uint8_t *data); +void gcm_sm4_encrypt(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *dst, const uint8_t *src); +void gcm_sm4_decrypt(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *dst, const uint8_t *src); +void gcm_sm4_digest(struct gcm_sm4_ctx *ctx, + size_t length, uint8_t *digest); + + #ifdef __cplusplus } #endif diff --git a/nettle-meta-aeads.c b/nettle-meta-aeads.c index c99cc465..78f38a3c 100644 --- a/nettle-meta-aeads.c +++ b/nettle-meta-aeads.c @@ -43,6 +43,7 @@ const struct nettle_aead * const _nettle_aeads[] = { &nettle_gcm_aes256, &nettle_gcm_camellia128, &nettle_gcm_camellia256, + &nettle_gcm_sm4, &nettle_eax_aes128, &nettle_chacha_poly1305, NULL diff --git a/nettle-meta.h b/nettle-meta.h index 3d0440e8..19dc96c5 100644 --- a/nettle-meta.h +++ b/nettle-meta.h @@ -200,6 +200,7 @@ extern const struct nettle_aead nettle_gcm_aes192; extern const struct nettle_aead nettle_gcm_aes256; extern const struct nettle_aead nettle_gcm_camellia128; extern const struct nettle_aead nettle_gcm_camellia256; +extern const struct nettle_aead nettle_gcm_sm4; extern const struct nettle_aead nettle_eax_aes128; extern const struct nettle_aead nettle_chacha_poly1305;
diff --git a/testsuite/gcm-test.c b/testsuite/gcm-test.c index df1fc94a..d9af0e0a 100644 --- a/testsuite/gcm-test.c +++ b/testsuite/gcm-test.c @@ -540,6 +540,24 @@ test_main(void) "16aedbf5a0de6a57 a637b39b"), /* iv */ SHEX("5791883f822013f8bd136fc36fb9946b")); /* tag */
+ /* + * GCM-SM4 Test Vectors from + * https://datatracker.ietf.org/doc/html/rfc8998 + */ + test_aead(&nettle_gcm_sm4, NULL, + SHEX("0123456789ABCDEFFEDCBA9876543210"), + SHEX("FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2"), + SHEX("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" + "CCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDD" + "EEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFF" + "EEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAA"), + SHEX("17F399F08C67D5EE19D0DC9969C4BB7D" + "5FD46FD3756489069157B282BB200735" + "D82710CA5C22F0CCFA7CBF93D496AC15" + "A56834CBCF98C397B4024A2691233B8D"), + SHEX("00001234567800000000ABCD"), + SHEX("83DE3541E4C2B58177E065A9BF7B62EC")); + /* Test gcm_hash, with varying message size, keys and iv all zero. Not compared to any other implementation. */ test_gcm_hash (SDATA("a"), diff --git a/testsuite/meta-aead-test.c b/testsuite/meta-aead-test.c index 1fcede40..ceeca227 100644 --- a/testsuite/meta-aead-test.c +++ b/testsuite/meta-aead-test.c @@ -8,6 +8,7 @@ const char* aeads[] = { "gcm_aes256", "gcm_camellia128", "gcm_camellia256", + "gcm_sm4", "eax_aes128", "chacha_poly1305", };