diff --git a/CMakeLists.txt b/CMakeLists.txt index e2051ab5..e2d05d3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -552,7 +552,7 @@ if (ENABLE_SDF) src/sdf/sdf_meth.c src/sdf/sdf_ext.c src/sdf/sdf_sansec.c) - list(APPEND tools tools/sdfutil.c tools/sdftest.c) + list(APPEND tools tools/sdfutil.c tools/sdfinfo.c tools/sdfexport.c tools/sdftest.c) endif() diff --git a/include/gmssl/sdf.h b/include/gmssl/sdf.h index 6a1d3d37..1d056767 100644 --- a/include/gmssl/sdf.h +++ b/include/gmssl/sdf.h @@ -60,6 +60,8 @@ int sdf_load_library(const char *so_path, const char *vendor); int sdf_open_device(SDF_DEVICE *dev); int sdf_print_device_info(FILE *fp, int fmt, int ind, const char *lable, SDF_DEVICE *dev); int sdf_rand_bytes(SDF_DEVICE *dev, uint8_t *buf, size_t len); +int sdf_export_sign_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_key); +int sdf_export_enc_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_key); int sdf_load_sign_key(SDF_DEVICE *dev, SDF_KEY *key, int index, const char *pass); int sdf_sign(SDF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); int sdf_release_key(SDF_KEY *key); diff --git a/src/sdf/sdf.c b/src/sdf/sdf.c index 3428a1db..316d5213 100755 --- a/src/sdf/sdf.c +++ b/src/sdf/sdf.c @@ -144,6 +144,72 @@ int sdf_rand_bytes(SDF_DEVICE *dev, uint8_t *buf, size_t len) return ret; } +int sdf_export_sign_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_key) +{ + void *hSession; + ECCrefPublicKey eccPublicKey; + + if (!dev || !public_key) { + error_print(); + return -1; + } + + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK) { + error_print(); + return -1; + } + if (SDF_ExportSignPublicKey_ECC(hSession, key_index, &eccPublicKey) != SDR_OK) { + (void)SDF_CloseSession(hSession); + error_print(); + return -1; + } + (void)SDF_CloseSession(hSession); + + if (SDF_ECCrefPublicKey_to_SM2_KEY(&eccPublicKey, public_key) != SDR_OK) { + error_print(); + return -1; + } + + return 1; +} + +int sdf_export_enc_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_key) +{ + void *hSession; + ECCrefPublicKey eccPublicKey; + + if (!dev || !public_key) { + error_print(); + return -1; + } + + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK) { + error_print(); + return -1; + } + if (SDF_ExportEncPublicKey_ECC(hSession, key_index, &eccPublicKey) != SDR_OK) { + (void)SDF_CloseSession(hSession); + error_print(); + return -1; + } + (void)SDF_CloseSession(hSession); + + if (SDF_ECCrefPublicKey_to_SM2_KEY(&eccPublicKey, public_key) != SDR_OK) { + error_print(); + return -1; + } + + return 1; +} + + + + + + + + + int sdf_load_sign_key(SDF_DEVICE *dev, SDF_KEY *key, int index, const char *pass) { int ret = -1; diff --git a/tools/gmssl.c b/tools/gmssl.c index aadbbf87..f76fea7b 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -67,6 +67,8 @@ extern int tls13_client_main(int argc, char **argv); extern int tls13_server_main(int argc, char **argv); #ifdef ENABLE_SDF extern int sdfutil_main(int argc, char **argv); +extern int sdfinfo_main(int argc, char **argv); +extern int sdfexport_main(int argc, char **argv); extern int sdftest_main(int argc, char **argv); #endif #ifdef ENABLE_SKF @@ -127,6 +129,8 @@ static const char *options = " cmsverify Verify CMS SignedData\n" #ifdef ENABLE_SDF " sdfutil SDF crypto device utility\n" + " sdfinfo Print SDF device info\n" + " sdfexport Export public key from SDF device\n" " sdftest Test vendor's SDF library and device\n" #endif #ifdef ENABLE_SKF @@ -277,6 +281,10 @@ int main(int argc, char **argv) } else if (!strcmp(*argv, "tls13_server")) { return tls13_server_main(argc, argv); #ifdef ENABLE_SDF + } else if (!strcmp(*argv, "sdfinfo")) { + return sdfinfo_main(argc, argv); + } else if (!strcmp(*argv, "sdfexport")) { + return sdfexport_main(argc, argv); } else if (!strcmp(*argv, "sdfutil")) { return sdfutil_main(argc, argv); } else if (!strcmp(*argv, "sdftest")) { diff --git a/tools/sdfexport.c b/tools/sdfexport.c new file mode 100644 index 00000000..530a5299 --- /dev/null +++ b/tools/sdfexport.c @@ -0,0 +1,151 @@ +/* + * Copyright 2014-2024 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 + + +static const char *usage = "-lib so_path {-sign_public_key|-encrypt_public_key} -index num [-out file]"; + +static const char *options = +"\n" +"Options\n" +"\n" +" -lib so_path Vendor's SDF dynamic library\n" +" -sign_public_key Export signing public key\n" +" -encrypt_public_key Export encryption public key\n" +" -index num Private key index number\n" +" -out file | stdout Output public key in PEM format\n" +"\n" +"Examples\n" +"\n" +" $ gmssl sdfexport -sign_public_key -index 1 -out sm2signpub.pem\n" +" $ gmssl sdfexport -encrypt_public_key -index 1 -out sm2encpub.pem\n" +"\n"; + + +int sdfexport_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *lib = NULL; + int sign_public_key = 0; + int enc_public_key = 0; + int index = -1; + char *outfile = NULL; + FILE *outfp = stdout; + SDF_DEVICE dev; + SM2_KEY sm2_key; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-lib")) { + if (--argc < 1) goto bad; + lib = *(++argv); + } else if (!strcmp(*argv, "-sign_public_key")) { + if (enc_public_key) { + fprintf(stderr, "gmssl %s: '-sign_public_key' and '-encrypt_public_key' should not used together\n", prog); + goto end; + } + sign_public_key = 1; + } else if (!strcmp(*argv, "-encrypt_public_key")) { + if (sign_public_key) { + fprintf(stderr, "gmssl %s: '-sign_public_key' and '-encrypt_public_key' should not used together\n", prog); + goto end; + } + enc_public_key = 1; + } else if (!strcmp(*argv, "-index")) { + if (--argc < 1) goto bad; + index = atoi(*(++argv)); + if (index < 0) { + fprintf(stderr, "gmssl %s: illegal key index %d\n", prog, index); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!lib) { + fprintf(stderr, "gmssl %s: option '-lib' required\n", prog); + goto end; + } + if (!sign_public_key && !enc_public_key) { + fprintf(stderr, "gmssl %s: option '-sign_public_key' or '-encrypt_public_key' is required\n", prog); + goto end; + } + if (index < 0) { + fprintf(stderr, "gmssl %s: '-index' option required\n", prog); + goto end; + } + + if (sdf_load_library(lib, NULL) != 1) { + fprintf(stderr, "gmssl %s: load library failure\n", prog); + goto end; + } + if (sdf_open_device(&dev) != 1) { + fprintf(stderr, "gmssl %s: open device failure\n", prog); + goto end; + } + + if (sign_public_key) { + if (sdf_export_sign_public_key(&dev, index, &sm2_key) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + } else { + if (sdf_export_enc_public_key(&dev, index, &sm2_key) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + } + + if (sm2_public_key_info_to_pem(&sm2_key, outfp) != 1) { + fprintf(stderr, "gmssl %s: output public key to PEM failed\n", prog); + goto end; + } + + sdf_close_device(&dev); + + ret = 0; +end: + if (lib) sdf_unload_library(); + return ret; +} diff --git a/tools/sdfinfo.c b/tools/sdfinfo.c new file mode 100644 index 00000000..6e393692 --- /dev/null +++ b/tools/sdfinfo.c @@ -0,0 +1,94 @@ +/* + * Copyright 2014-2024 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 + + +static const char *usage = "-lib so_path"; + +static const char *options = +"\n" +"Options\n" +"\n" +" -lib so_path Vendor's SDF dynamic library\n" +"\n" +"Examples\n" +"\n" +" $ gmssl sdfinfo\n" +"\n"; + + +int sdfinfo_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *lib = NULL; + SDF_DEVICE dev; + + memset(&dev, 0, sizeof(dev)); + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-lib")) { + if (--argc < 1) goto bad; + lib = *(++argv); + } else { + fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!lib) { + fprintf(stderr, "gmssl %s: option '-lib' required\n", prog); + goto end; + } + + if (sdf_load_library(lib, NULL) != 1) { + fprintf(stderr, "gmssl %s: load library failure\n", prog); + goto end; + } + + if (sdf_open_device(&dev) != 1) { + fprintf(stderr, "gmssl %s: open device failure\n", prog); + goto end; + } + + sdf_print_device_info(stdout, 0, 0, "SDF", &dev); + + sdf_close_device(&dev); + + ret = 0; +end: + if (lib) sdf_unload_library(); + return ret; +}