From 43396395d6a76a57018526d7afb4293fe3703433 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Thu, 28 Dec 2023 10:19:53 +0800 Subject: [PATCH] Add `sm3_xmss` command --- src/sm3_xmss.c | 25 ++++++- tools/gmssl.c | 4 ++ tools/sm3xmss_keygen.c | 159 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 tools/sm3xmss_keygen.c diff --git a/src/sm3_xmss.c b/src/sm3_xmss.c index 11bbe660..1a461f93 100644 --- a/src/sm3_xmss.c +++ b/src/sm3_xmss.c @@ -479,11 +479,9 @@ void sm3_xmss_sig_to_root(const hash256_bytes_t wots_sig[67], int index, const h int sm3_xmss_height_from_oid(uint32_t *height, uint32_t id) { switch (id) { -/* case XMSS_SM3_10: *height = 10; break; case XMSS_SM3_16: *height = 16; break; case XMSS_SM3_20: *height = 20; break; -*/ case XMSS_SHA256_10: *height = 10; break; case XMSS_SHA256_16: *height = 16; break; case XMSS_SHA256_20: *height = 20; break; @@ -553,6 +551,11 @@ int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen) size_t tree_size; uint8_t *p; + if (!outlen) { + error_print(); + return -1; + } + if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { error_print(); return -1; @@ -563,6 +566,11 @@ int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen) return -1; } + if (!out) { + *outlen = 4 + 32*4 + 4 + tree_size; + return 1; + } + p = out; uint32_to_bytes(key->oid, p); p += 4; memcpy(p, key->seed, 32); p += 32; @@ -594,7 +602,7 @@ int sm3_xmss_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen) return -1; } tree_size = 32 * ((1 << (height + 1)) - 1); - if (inlen != (4 + 32 * 4 + 4 + 32 * tree_size)) { + if (inlen != (4 + 32 * 4 + 4 + tree_size)) { error_print(); return -1; } @@ -622,11 +630,21 @@ int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t * uint32_t height; uint8_t *p; + if (!outlen) { + error_print(); + return -1; + } + if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { error_print(); return -1; } + if (!out) { + *outlen = 4 + 32 + 32; + return 1; + } + p = out; uint32_to_bytes(key->oid, p); p += 4; memcpy(p, key->seed, 32); p += 32; @@ -636,6 +654,7 @@ int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t * return 1; } +// FIXME: check input length int sm3_xmss_public_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen) { uint32_t height; diff --git a/tools/gmssl.c b/tools/gmssl.c index ef2bd6d2..08a88eda 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -34,6 +34,7 @@ extern int sm2encrypt_main(int argc, char **argv); extern int sm2decrypt_main(int argc, char **argv); extern int sm3_main(int argc, char **argv); extern int sm3hmac_main(int argc, char **argv); +extern int sm3xmss_keygen_main(int argc, char **argv); extern int sm4_main(int argc, char **argv); extern int zuc_main(int argc, char **argv); extern int sm9setup_main(int argc, char **argv); @@ -72,6 +73,7 @@ static const char *options = " sm2decrypt Decrypt with SM2 private key\n" " sm3 Generate SM3 hash\n" " sm3hmac Generate SM3 HMAC tag\n" + " sm3xmss_keygen Generate SM3-XMSS keypair\n" " sm4 Encrypt or decrypt with SM4\n" " zuc Encrypt or decrypt with ZUC\n" " sm9setup Generate SM9 master secret\n" @@ -169,6 +171,8 @@ int main(int argc, char **argv) return sm3_main(argc, argv); } else if (!strcmp(*argv, "sm3hmac")) { return sm3hmac_main(argc, argv); + } else if (!strcmp(*argv, "sm3xmss_keygen")) { + return sm3xmss_keygen_main(argc, argv); } else if (!strcmp(*argv, "sm4")) { return sm4_main(argc, argv); } else if (!strcmp(*argv, "zuc")) { diff --git a/tools/sm3xmss_keygen.c b/tools/sm3xmss_keygen.c new file mode 100644 index 00000000..8959b4ba --- /dev/null +++ b/tools/sm3xmss_keygen.c @@ -0,0 +1,159 @@ +/* + * Copyright 2014-2023 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 +#include +#include +#include +#include +#include +#include + + +static const char *usage = "-oid oid [-out file] [-pubout file]\n"; + +static const char *help = +"Options\n" +" -oid oid XMSS algorithm OID\n" +" XMSS_SM3_10\n" +" XMSS_SM3_16\n" +" XMSS_SM3_20\n" +" -out file Output private key\n" +" -pubout file Output public key\n" +"\n"; + +int sm3xmss_keygen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *oid = NULL; + uint32_t oid_val = 0; + char *outfile = NULL; + char *puboutfile = NULL; + FILE *outfp = stdout; + FILE *puboutfp = stdout; + SM3_XMSS_KEY key; + uint8_t *out = NULL; + uint8_t *pubout = NULL; + size_t outlen, puboutlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, help); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, usage); + printf("%s\n", help); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-oid")) { + if (--argc < 1) goto bad; + oid = *(++argv); + if (strcmp(oid, "XMSS_SM3_10") == 0) { + oid_val = XMSS_SM3_10; + } else if (strcmp(oid, "XMSS_SM3_16") == 0) { + oid_val = XMSS_SM3_16; + } else if (strcmp(oid, "XMSS_SM3_20") == 0) { + oid_val = XMSS_SM3_20; + } else { + fprintf(stderr, "%s: invalid XMSS algor ID `%s`\n", prog, oid); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pubout")) { + if (--argc < 1) goto bad; + puboutfile = *(++argv); + if (!(puboutfp = fopen(puboutfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!oid) { + fprintf(stderr, "%s: `-oid` option required\n", prog); + goto end; + } + + + if (sm3_xmss_key_generate(&key, oid_val) != 1) { + error_print(); + return -1; + } + + if (sm3_xmss_key_to_bytes(&key, NULL, &outlen) != 1) { + error_print(); + goto end; + } + if (!(out = malloc(outlen))) { + error_print(); + goto end; + } + if (sm3_xmss_key_to_bytes(&key, out, &outlen) != 1) { + error_print(); + } + + if (sm3_xmss_public_key_to_bytes(&key, NULL, &puboutlen) != 1) { + error_print(); + goto end; + } + if (!(pubout = malloc(puboutlen))) { + error_print(); + goto end; + } + if (sm3_xmss_public_key_to_bytes(&key, pubout, &puboutlen) != 1) { + error_print(); + goto end; + } + + if (fwrite(out, 1, outlen, outfp) != outlen) { + error_print(); + goto end; + } + if (fwrite(pubout, 1, puboutlen, puboutfp) != puboutlen) { + error_print(); + goto end; + } + + ret = 0; +end: + gmssl_secure_clear(&key, sizeof(key)); + if (out) { + gmssl_secure_clear(out, outlen); + free(out); + } + if (pubout) { + gmssl_secure_clear(pubout, puboutlen); + free(pubout); + } + if (outfile && outfp) fclose(outfp); + if (puboutfile && puboutfp) fclose(puboutfp); + return ret; +}