summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianjia Zhang <tianjia.zhang@linux.alibaba.com>2022-02-21 16:37:15 +0800
committerNiels Möller <nisse@lysator.liu.se>2022-08-18 11:33:54 +0200
commit9e8966cc113874d7cfa096187c8ebe70770ad232 (patch)
treead67c75281a81a0cfd35e0b00d0831ebfbd663dc
parentf29c11cddb9deb5278660f9aa0e8da255d9502c9 (diff)
downloadnettle-9e8966cc113874d7cfa096187c8ebe70770ad232.tar.gz
gcm: Add SM4 as the GCM underlying cipher
Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
-rw-r--r--Makefile.in1
-rw-r--r--gcm-sm4-meta.c60
-rw-r--r--gcm-sm4.c81
-rw-r--r--gcm.h25
-rw-r--r--nettle-meta-aeads.c1
-rw-r--r--nettle-meta.h1
-rw-r--r--testsuite/gcm-test.c18
-rw-r--r--testsuite/meta-aead-test.c1
8 files changed, 187 insertions, 1 deletions
diff --git a/Makefile.in b/Makefile.in
index 6f957aef..4d60aef3 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..090460d3
--- /dev/null
+++ b/gcm-sm4-meta.c
@@ -0,0 +1,60 @@
+/* gcm-sm4-meta.c
+
+ Copyright (C) 2022 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..19d91ae9
--- /dev/null
+++ b/gcm-sm4.c
@@ -0,0 +1,81 @@
+/* gcm-sm4.c
+
+ Galois counter mode using SM4 as the underlying cipher.
+
+ Copyright (C) 2022 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_encrypt_key, sm4_crypt, 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_crypt, 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_crypt, length, dst, src);
+}
+
+void
+gcm_sm4_digest(struct gcm_sm4_ctx *ctx,
+ size_t length, uint8_t *digest)
+{
+ GCM_DIGEST(ctx, sm4_crypt, length, digest);
+}
diff --git a/gcm.h b/gcm.h
index 96578530..39af5ab0 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 8955e9b8..d70cdd1e 100644
--- a/testsuite/gcm-test.c
+++ b/testsuite/gcm-test.c
@@ -577,6 +577,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",
};