Add XMSS CL

This commit is contained in:
Zhi Guan
2026-06-24 10:56:50 +08:00
parent e7c0a28f9b
commit 03c8276501
9 changed files with 1418 additions and 3 deletions

View File

@@ -113,6 +113,7 @@ option(ENABLE_SM3_SSE "Enable SM3 SSE assembly implementation" ${GMSSL_DEFAULT_E
option(ENABLE_SM4_CTR_AESNI_AVX "Enable SM4 CTR AESNI+AVX assembly implementation" OFF) option(ENABLE_SM4_CTR_AESNI_AVX "Enable SM4 CTR AESNI+AVX assembly implementation" OFF)
option(ENABLE_SM4_CL "Enable SM4 OpenCL" OFF) option(ENABLE_SM4_CL "Enable SM4 OpenCL" OFF)
option(ENABLE_LMS_CL "Enable LMS OpenCL" OFF) option(ENABLE_LMS_CL "Enable LMS OpenCL" OFF)
option(ENABLE_XMSS_CL "Enable XMSS OpenCL" OFF)
option(ENABLE_INTEL_RDRAND "Enable Intel RDRAND instructions" OFF) option(ENABLE_INTEL_RDRAND "Enable Intel RDRAND instructions" OFF)
@@ -562,6 +563,19 @@ if (ENABLE_XMSS)
list(APPEND tests xmss) list(APPEND tests xmss)
endif() endif()
if (ENABLE_XMSS_CL)
if (NOT ENABLE_XMSS)
message(FATAL_ERROR "ENABLE_XMSS_CL requires ENABLE_XMSS")
endif()
message(STATUS "ENABLE_XMSS_CL is ON")
add_definitions(-DENABLE_XMSS_CL)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
add_definitions(-DMACOS) # to include <OpenCL/OpenCL.h>
endif()
list(APPEND src src/xmss_cl.c)
list(APPEND tests xmss_cl)
endif()
if (ENABLE_SPHINCS) if (ENABLE_SPHINCS)
message(STATUS "ENABLE_SPHINCS is ON") message(STATUS "ENABLE_SPHINCS is ON")
@@ -784,7 +798,7 @@ else()
endif() endif()
endif() endif()
if (ENABLE_SM4_CL OR ENABLE_LMS_CL) if (ENABLE_SM4_CL OR ENABLE_LMS_CL OR ENABLE_XMSS_CL)
if (APPLE) if (APPLE)
target_link_libraries(gmssl "-framework OpenCL") target_link_libraries(gmssl "-framework OpenCL")
else() else()
@@ -967,7 +981,7 @@ endif()
# #
set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_NAME "GmSSL")
set(CPACK_PACKAGE_VENDOR "GmSSL develop team") set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1164") set(CPACK_PACKAGE_VERSION "3.3.0-dev.1165")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
set(CPACK_NSIS_MODIFY_PATH ON) set(CPACK_NSIS_MODIFY_PATH ON)
include(CPack) include(CPack)

View File

@@ -18,7 +18,7 @@ extern "C" {
#define GMSSL_VERSION_NUM 30300 #define GMSSL_VERSION_NUM 30300
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1164" #define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1165"
int gmssl_version_num(void); int gmssl_version_num(void);
const char *gmssl_version_str(void); const char *gmssl_version_str(void);

64
include/gmssl/xmss_cl.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_XMSS_CL_H
#define GMSSL_XMSS_CL_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <gmssl/xmss.h>
#ifdef MACOS
#include <OpenCL/OpenCL.h>
#else
#include <CL/cl.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
cl_context context;
cl_command_queue queue;
cl_program program;
cl_kernel leafs_kernel;
cl_kernel internal_nodes_kernel;
size_t local_work_size;
} XMSS_CL_CTX;
int xmss_cl_init(XMSS_CL_CTX *ctx);
void xmss_cl_cleanup(XMSS_CL_CTX *ctx);
int xmss_cl_build_tree(XMSS_CL_CTX *ctx,
const xmss_sm3_digest_t secret, const xmss_sm3_digest_t seed,
const xmss_adrs_t adrs, size_t height, xmss_sm3_digest_t *tree);
int xmss_cl_key_generate_ex(XMSS_CL_CTX *ctx, XMSS_KEY *key, uint32_t xmss_type,
const xmss_sm3_digest_t seed, const xmss_sm3_digest_t secret,
const xmss_sm3_digest_t sk_prf);
int xmss_cl_key_generate(XMSS_CL_CTX *ctx, XMSS_KEY *key, uint32_t xmss_type);
int xmss_cl_private_key_from_bytes(XMSS_CL_CTX *ctx, XMSS_KEY *key,
const uint8_t **in, size_t *inlen);
int xmssmt_cl_key_generate_ex(XMSS_CL_CTX *ctx, XMSSMT_KEY *key, uint32_t xmssmt_type,
const xmss_sm3_digest_t seed, const xmss_sm3_digest_t secret,
const xmss_sm3_digest_t sk_prf);
int xmssmt_cl_key_generate(XMSS_CL_CTX *ctx, XMSSMT_KEY *key, uint32_t xmssmt_type);
int xmssmt_cl_key_update(XMSS_CL_CTX *ctx, XMSSMT_KEY *key);
int xmssmt_cl_sign_init(XMSS_CL_CTX *ctx, XMSSMT_SIGN_CTX *sign_ctx, XMSSMT_KEY *key);
#ifdef __cplusplus
}
#endif
#endif

1059
src/xmss_cl.c Normal file

File diff suppressed because it is too large Load Diff

151
tests/xmss_cltest.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/xmss_cl.h>
#include <gmssl/error.h>
static int test_xmss_cl_build_tree(XMSS_CL_CTX *cl_ctx)
{
xmss_sm3_digest_t seed;
xmss_sm3_digest_t secret;
xmss_adrs_t adrs;
xmss_sm3_digest_t *cpu_tree = NULL;
xmss_sm3_digest_t *cl_tree = NULL;
size_t height = 4;
size_t tree_nodes = xmss_num_tree_nodes(height);
size_t i;
int ret = -1;
for (i = 0; i < sizeof(seed); i++) {
seed[i] = (uint8_t)i;
secret[i] = (uint8_t)(0x80 + i);
}
xmss_adrs_set_layer_address(adrs, 0);
xmss_adrs_set_tree_address(adrs, 0);
if (!(cpu_tree = malloc(sizeof(xmss_sm3_digest_t) * tree_nodes))
|| !(cl_tree = malloc(sizeof(xmss_sm3_digest_t) * tree_nodes))) {
error_print();
goto end;
}
xmss_build_tree(secret, seed, adrs, height, cpu_tree);
if (xmss_cl_build_tree(cl_ctx, secret, seed, adrs, height, cl_tree) != 1) {
error_print();
goto end;
}
if (memcmp(cpu_tree, cl_tree, sizeof(xmss_sm3_digest_t) * tree_nodes) != 0) {
error_print();
goto end;
}
ret = 1;
end:
free(cpu_tree);
free(cl_tree);
return ret;
}
static int test_xmss_cl_sign_verify(XMSS_CL_CTX *cl_ctx)
{
XMSS_KEY key;
XMSS_SIGN_CTX sign_ctx;
XMSS_SIGN_CTX verify_ctx;
uint8_t msg[] = "abc";
uint8_t sig[XMSS_SIGNATURE_MAX_SIZE];
size_t siglen = 0;
int ret = -1;
memset(&key, 0, sizeof(key));
memset(&sign_ctx, 0, sizeof(sign_ctx));
memset(&verify_ctx, 0, sizeof(verify_ctx));
if (xmss_cl_key_generate(cl_ctx, &key, XMSS_SM3_10_256) != 1) {
error_print();
goto end;
}
if (xmss_sign_init(&sign_ctx, &key) != 1
|| xmss_sign_update(&sign_ctx, msg, sizeof(msg)) != 1
|| xmss_sign_finish(&sign_ctx, sig, &siglen) != 1) {
error_print();
goto end;
}
if (xmss_verify_init(&verify_ctx, &key, sig, siglen) != 1
|| xmss_verify_update(&verify_ctx, msg, sizeof(msg)) != 1
|| xmss_verify_finish(&verify_ctx) != 1) {
error_print();
goto end;
}
ret = 1;
end:
xmss_key_cleanup(&key);
return ret;
}
static int test_xmssmt_cl_sign_verify(XMSS_CL_CTX *cl_ctx)
{
XMSSMT_KEY key;
XMSSMT_SIGN_CTX sign_ctx;
XMSSMT_SIGN_CTX verify_ctx;
uint8_t msg[] = "abc";
uint8_t sig[XMSSMT_SIGNATURE_MAX_SIZE];
size_t siglen = 0;
int ret = -1;
memset(&key, 0, sizeof(key));
memset(&sign_ctx, 0, sizeof(sign_ctx));
memset(&verify_ctx, 0, sizeof(verify_ctx));
if (xmssmt_cl_key_generate(cl_ctx, &key, XMSSMT_SM3_20_4_256) != 1) {
error_print();
goto end;
}
if (xmssmt_cl_sign_init(cl_ctx, &sign_ctx, &key) != 1
|| xmssmt_sign_update(&sign_ctx, msg, sizeof(msg)) != 1
|| xmssmt_sign_finish(&sign_ctx, sig, &siglen) != 1) {
error_print();
goto end;
}
if (xmssmt_verify_init(&verify_ctx, &key, sig, siglen) != 1
|| xmssmt_verify_update(&verify_ctx, msg, sizeof(msg)) != 1
|| xmssmt_verify_finish(&verify_ctx) != 1) {
error_print();
goto end;
}
ret = 1;
end:
xmssmt_key_cleanup(&key);
return ret;
}
int main(void)
{
XMSS_CL_CTX cl_ctx;
int ret = 1;
memset(&cl_ctx, 0, sizeof(cl_ctx));
if (xmss_cl_init(&cl_ctx) != 1) {
error_print();
return 1;
}
if (test_xmss_cl_build_tree(&cl_ctx) != 1) goto end;
if (test_xmss_cl_sign_verify(&cl_ctx) != 1) goto end;
if (test_xmssmt_cl_sign_verify(&cl_ctx) != 1) goto end;
ret = 0;
end:
xmss_cl_cleanup(&cl_ctx);
return ret;
}

View File

@@ -15,6 +15,9 @@
#include <gmssl/mem.h> #include <gmssl/mem.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/xmss.h> #include <gmssl/xmss.h>
#ifdef ENABLE_XMSS_CL
#include <gmssl/xmss_cl.h>
#endif
static const char *usage = "-xmss_type type -out file [-pubout file] [-verbose]\n"; static const char *usage = "-xmss_type type -out file [-pubout file] [-verbose]\n";
@@ -48,8 +51,15 @@ int xmsskeygen_main(int argc, char **argv)
uint8_t pubout[XMSS_PUBLIC_KEY_SIZE]; uint8_t pubout[XMSS_PUBLIC_KEY_SIZE];
uint8_t *ppubout; uint8_t *ppubout;
size_t puboutlen ; size_t puboutlen ;
#ifdef ENABLE_XMSS_CL
XMSS_CL_CTX cl_ctx;
int cl_inited = 0;
#endif
memset(&key, 0, sizeof(key)); memset(&key, 0, sizeof(key));
#ifdef ENABLE_XMSS_CL
memset(&cl_ctx, 0, sizeof(cl_ctx));
#endif
argc--; argc--;
argv++; argv++;
@@ -109,10 +119,22 @@ bad:
goto end; goto end;
} }
#ifdef ENABLE_XMSS_CL
if (xmss_cl_init(&cl_ctx) != 1) {
error_print();
goto end;
}
cl_inited = 1;
if (xmss_cl_key_generate(&cl_ctx, &key, xmss_type_val) != 1) {
error_print();
goto end;
}
#else
if (xmss_key_generate(&key, xmss_type_val) != 1) { if (xmss_key_generate(&key, xmss_type_val) != 1) {
error_print(); error_print();
return -1; return -1;
} }
#endif
if (verbose) { if (verbose) {
xmss_public_key_print(stderr, 0, 0, "xmss_public_key", &key); xmss_public_key_print(stderr, 0, 0, "xmss_public_key", &key);
} }
@@ -154,6 +176,9 @@ bad:
ret = 0; ret = 0;
end: end:
#ifdef ENABLE_XMSS_CL
if (cl_inited) xmss_cl_cleanup(&cl_ctx);
#endif
xmss_key_cleanup(&key); xmss_key_cleanup(&key);
if (out) { if (out) {
gmssl_secure_clear(out, outlen); gmssl_secure_clear(out, outlen);

View File

@@ -15,6 +15,9 @@
#include <gmssl/mem.h> #include <gmssl/mem.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/xmss.h> #include <gmssl/xmss.h>
#ifdef ENABLE_XMSS_CL
#include <gmssl/xmss_cl.h>
#endif
static const char *usage = "-xmssmt_type type -out file [-pubout file] [-verbose]\n"; static const char *usage = "-xmssmt_type type -out file [-pubout file] [-verbose]\n";
@@ -52,8 +55,15 @@ int xmssmtkeygen_main(int argc, char **argv)
uint8_t *pout; uint8_t *pout;
uint8_t *ppubout = pubout; uint8_t *ppubout = pubout;
size_t outlen = 0, puboutlen = 0; size_t outlen = 0, puboutlen = 0;
#ifdef ENABLE_XMSS_CL
XMSS_CL_CTX cl_ctx;
int cl_inited = 0;
#endif
memset(&key, 0, sizeof(key)); memset(&key, 0, sizeof(key));
#ifdef ENABLE_XMSS_CL
memset(&cl_ctx, 0, sizeof(cl_ctx));
#endif
argc--; argc--;
argv++; argv++;
@@ -113,10 +123,22 @@ bad:
goto end; goto end;
} }
#ifdef ENABLE_XMSS_CL
if (xmss_cl_init(&cl_ctx) != 1) {
error_print();
goto end;
}
cl_inited = 1;
if (xmssmt_cl_key_generate(&cl_ctx, &key, xmssmt_type_val) != 1) {
error_print();
goto end;
}
#else
if (xmssmt_key_generate(&key, xmssmt_type_val) != 1) { if (xmssmt_key_generate(&key, xmssmt_type_val) != 1) {
error_print(); error_print();
return -1; return -1;
} }
#endif
if (verbose) { if (verbose) {
xmssmt_public_key_print(stderr, 0, 0, "xmssmt_public_key", &key); xmssmt_public_key_print(stderr, 0, 0, "xmssmt_public_key", &key);
} }
@@ -151,6 +173,9 @@ bad:
ret = 0; ret = 0;
end: end:
#ifdef ENABLE_XMSS_CL
if (cl_inited) xmss_cl_cleanup(&cl_ctx);
#endif
xmssmt_key_cleanup(&key); xmssmt_key_cleanup(&key);
if (out) { if (out) {
gmssl_secure_clear(out, outlen); gmssl_secure_clear(out, outlen);

View File

@@ -15,6 +15,9 @@
#include <gmssl/mem.h> #include <gmssl/mem.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/xmss.h> #include <gmssl/xmss.h>
#ifdef ENABLE_XMSS_CL
#include <gmssl/xmss_cl.h>
#endif
static const char *usage = "-key file [-in file] [-out file] [-verbose]\n"; static const char *usage = "-key file [-in file] [-out file] [-verbose]\n";
@@ -69,8 +72,15 @@ int xmssmtsign_main(int argc, char **argv)
XMSSMT_SIGN_CTX ctx; XMSSMT_SIGN_CTX ctx;
uint8_t sig[XMSSMT_SIGNATURE_MAX_SIZE]; uint8_t sig[XMSSMT_SIGNATURE_MAX_SIZE];
size_t siglen; size_t siglen;
#ifdef ENABLE_XMSS_CL
XMSS_CL_CTX cl_ctx;
int cl_inited = 0;
#endif
memset(&key, 0, sizeof(key)); memset(&key, 0, sizeof(key));
#ifdef ENABLE_XMSS_CL
memset(&cl_ctx, 0, sizeof(cl_ctx));
#endif
argc--; argc--;
argv++; argv++;
@@ -126,6 +136,14 @@ bad:
goto end; goto end;
} }
#ifdef ENABLE_XMSS_CL
if (xmss_cl_init(&cl_ctx) != 1) {
error_print();
goto end;
}
cl_inited = 1;
#endif
if (xmssmt_private_key_from_file(&key, keyfp) != 1) { if (xmssmt_private_key_from_file(&key, keyfp) != 1) {
fprintf(stderr, "%s: read private key failure\n", prog); fprintf(stderr, "%s: read private key failure\n", prog);
goto end; goto end;
@@ -140,10 +158,17 @@ bad:
goto end; goto end;
} }
#ifdef ENABLE_XMSS_CL
if (xmssmt_cl_sign_init(&cl_ctx, &ctx, &key) != 1) {
error_print();
goto end;
}
#else
if (xmssmt_sign_init(&ctx, &key) != 1) { if (xmssmt_sign_init(&ctx, &key) != 1) {
error_print(); error_print();
goto end; goto end;
} }
#endif
while (1) { while (1) {
uint8_t buf[1024]; uint8_t buf[1024];
@@ -171,6 +196,9 @@ bad:
ret = 0; ret = 0;
end: end:
#ifdef ENABLE_XMSS_CL
if (cl_inited) xmss_cl_cleanup(&cl_ctx);
#endif
xmssmt_key_cleanup(&key); xmssmt_key_cleanup(&key);
gmssl_secure_clear(&ctx, sizeof(ctx)); gmssl_secure_clear(&ctx, sizeof(ctx));
if (keyfp) fclose(keyfp); if (keyfp) fclose(keyfp);

View File

@@ -16,6 +16,9 @@
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/endian.h> #include <gmssl/endian.h>
#include <gmssl/xmss.h> #include <gmssl/xmss.h>
#ifdef ENABLE_XMSS_CL
#include <gmssl/xmss_cl.h>
#endif
static const char *usage = "-key file [-in file] [-out file] [-verbose]\n"; static const char *usage = "-key file [-in file] [-out file] [-verbose]\n";
@@ -68,8 +71,17 @@ int xmsssign_main(int argc, char **argv)
XMSS_SIGN_CTX ctx; XMSS_SIGN_CTX ctx;
uint8_t sig[XMSS_SIGNATURE_MAX_SIZE]; uint8_t sig[XMSS_SIGNATURE_MAX_SIZE];
size_t siglen; size_t siglen;
#ifdef ENABLE_XMSS_CL
XMSS_CL_CTX cl_ctx;
uint8_t *keybuf = NULL;
size_t keylen = 0;
int cl_inited = 0;
#endif
memset(&key, 0, sizeof(key)); memset(&key, 0, sizeof(key));
#ifdef ENABLE_XMSS_CL
memset(&cl_ctx, 0, sizeof(cl_ctx));
#endif
argc--; argc--;
argv++; argv++;
@@ -125,10 +137,40 @@ bad:
goto end; goto end;
} }
#ifdef ENABLE_XMSS_CL
if (xmss_cl_init(&cl_ctx) != 1) {
error_print();
goto end;
}
cl_inited = 1;
if (fseek(keyfp, 0, SEEK_END) != 0
|| (keylen = (size_t)ftell(keyfp)) == (size_t)-1
|| fseek(keyfp, 0, SEEK_SET) != 0) {
error_print();
goto end;
}
if (!(keybuf = malloc(keylen))) {
error_print();
goto end;
}
if (fread(keybuf, 1, keylen, keyfp) != keylen) {
fprintf(stderr, "%s: read private key failure\n", prog);
goto end;
}
{
const uint8_t *cp = keybuf;
size_t len = keylen;
if (xmss_cl_private_key_from_bytes(&cl_ctx, &key, &cp, &len) != 1 || len) {
fprintf(stderr, "%s: read private key failure\n", prog);
goto end;
}
}
#else
if (xmss_private_key_from_file(&key, keyfp) != 1) { if (xmss_private_key_from_file(&key, keyfp) != 1) {
fprintf(stderr, "%s: read private key failure\n", prog); fprintf(stderr, "%s: read private key failure\n", prog);
goto end; goto end;
} }
#endif
if (verbose) { if (verbose) {
xmss_public_key_print(stderr, 0, 0, "lms_public_key", &key); xmss_public_key_print(stderr, 0, 0, "lms_public_key", &key);
@@ -170,6 +212,13 @@ bad:
ret = 0; ret = 0;
end: end:
#ifdef ENABLE_XMSS_CL
if (cl_inited) xmss_cl_cleanup(&cl_ctx);
if (keybuf) {
gmssl_secure_clear(keybuf, keylen);
free(keybuf);
}
#endif
xmss_key_cleanup(&key); xmss_key_cleanup(&key);
gmssl_secure_clear(&ctx, sizeof(ctx)); gmssl_secure_clear(&ctx, sizeof(ctx));
if (keyfp) fclose(keyfp); if (keyfp) fclose(keyfp);