From c4e5cf0debf11ddd53bee5ec8c8065a7e3627b59 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Fri, 7 Jun 2024 19:45:10 +0800 Subject: [PATCH] Add `sdfsign` command --- CMakeLists.txt | 2 +- include/gmssl/sdf.h | 24 +++-- src/sdf/sdf.c | 234 ++++++++++++++++++++++++-------------------- tools/gmssl.c | 10 +- tools/sdfexport.c | 41 ++------ tools/sdfsign.c | 174 ++++++++++++++++++++++++++++++++ 6 files changed, 330 insertions(+), 155 deletions(-) create mode 100644 tools/sdfsign.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e2d05d3e..5c43d5a9 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/sdfinfo.c tools/sdfexport.c tools/sdftest.c) + list(APPEND tools tools/sdfinfo.c tools/sdfexport.c tools/sdfsign.c tools/sdftest.c) endif() diff --git a/include/gmssl/sdf.h b/include/gmssl/sdf.h index 1d056767..68581533 100644 --- a/include/gmssl/sdf.h +++ b/include/gmssl/sdf.h @@ -29,11 +29,18 @@ typedef struct { } SDF_DEVICE; typedef struct { - SM2_KEY public_key; + SM2_Z256_POINT public_key; void *session; int index; -} SDF_KEY; +} SDF_SIGN_KEY; +typedef struct { + SM3_CTX sm3_ctx; + SM3_CTX saved_sm3_ctx; + SDF_SIGN_KEY key; +} SDF_SIGN_CTX; + +/* typedef struct { void *hSession; } SDF_SM3_CTX; @@ -54,17 +61,20 @@ typedef struct { uint8_t passlen; unsigned char pass[26 + 1]; } SDF_PRIVATE_KEY; +*/ 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); +int sdf_load_sign_key(SDF_DEVICE *dev, SDF_SIGN_KEY *key, int key_index, const char *pass); +int sdf_sign(SDF_SIGN_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +int sdf_sign_init(SDF_SIGN_CTX *ctx, const SDF_SIGN_KEY *key, const char *id, size_t idlen); +int sdf_sign_update(SDF_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sdf_sign_finish(SDF_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int sdf_sign_reset(SDF_SIGN_CTX *ctx); +int sdf_release_sign_key(SDF_SIGN_KEY *key); int sdf_close_device(SDF_DEVICE *dev); void sdf_unload_library(void); diff --git a/src/sdf/sdf.c b/src/sdf/sdf.c index 316d5213..43f9858d 100755 --- a/src/sdf/sdf.c +++ b/src/sdf/sdf.c @@ -18,50 +18,46 @@ #include "sdf_ext.h" - -static const uint8_t zeros[ECCref_MAX_LEN - 32] = {0}; - -static int SDF_ECCrefPublicKey_to_SM2_KEY(const ECCrefPublicKey *ref, SM2_KEY *sm2_key) +static int SDF_ECCrefPublicKey_to_SM2_Z256_POINT(const ECCrefPublicKey *ref, SM2_Z256_POINT *z256_point) { - uint8_t bytes[64] = {0}; - SM2_Z256_POINT point; + static const uint8_t zeros[ECCref_MAX_LEN - 32] = {0}; + SM2_POINT point; if (ref->bits != 256) { error_print(); return -1; } - if (memcmp(ref->x, zeros, sizeof(zeros)) != 0 - || memcmp(ref->y, zeros, sizeof(zeros)) != 0) { + if (memcmp(ref->x, zeros, sizeof(zeros)) != 0) { error_print(); return -1; } - - memcpy(bytes , ref->x + ECCref_MAX_LEN - 32, 32); - memcpy(bytes + 32, ref->y + ECCref_MAX_LEN - 32, 32); - - if (sm2_z256_point_from_bytes(&point, bytes) != 1) { + if (memcmp(ref->y, zeros, sizeof(zeros)) != 0) { error_print(); return -1; } - - if (sm2_key_set_public_key(sm2_key, &point) != 1) { + memcpy(point.x, ref->x + sizeof(zeros), 32); + memcpy(point.y, ref->y + sizeof(zeros), 32); + if (sm2_z256_point_from_bytes(z256_point, (uint8_t *)&point) != 1) { error_print(); return -1; } - return SDR_OK; } static int SDF_ECCSignature_to_SM2_SIGNATURE(const ECCSignature *ref, SM2_SIGNATURE *sig) { - if (memcmp(ref->r, zeros, sizeof(zeros)) != 0 - || memcmp(ref->s, zeros, sizeof(zeros)) != 0) { + static const uint8_t zeros[ECCref_MAX_LEN - 32] = {0}; + + if (memcmp(ref->r, zeros, sizeof(zeros)) != 0) { error_print(); return -1; } - memset(sig, 0, sizeof(SM2_SIGNATURE)); - memcpy(sig->r, ref->r + ECCref_MAX_LEN - 32, 32); - memcpy(sig->s, ref->s + ECCref_MAX_LEN - 32, 32); + if (memcmp(ref->s, zeros, sizeof(zeros)) != 0) { + error_print(); + return -1; + } + memcpy(sig->r, ref->r + sizeof(zeros), 32); + memcpy(sig->s, ref->s + sizeof(zeros), 32); return SDR_OK; } @@ -86,70 +82,57 @@ int sdf_open_device(SDF_DEVICE *dev) void *hSession = NULL; DEVICEINFO devInfo; - if (SDF_OpenDevice(&hDevice) != SDR_OK - || SDF_OpenSession(hDevice, &hSession) != SDR_OK - || SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { + if (SDF_OpenDevice(&hDevice) != SDR_OK) { + error_print(); + return -1; + } + if (SDF_OpenSession(hDevice, &hSession) != SDR_OK) { + (void)SDF_CloseDevice(hDevice); error_print(); - goto end; + return -1; } + if (SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { + (void)SDF_CloseSession(hSession); + (void)SDF_CloseDevice(hDevice); + error_print(); + return -1; + } + (void)SDF_CloseSession(hSession); memset(dev, 0, sizeof(SDF_DEVICE)); dev->handle = hDevice; - hDevice = NULL; memcpy(dev->issuer, devInfo.IssuerName, 40); memcpy(dev->name, devInfo.DeviceName, 16); memcpy(dev->serial, devInfo.DeviceSerial, 16); - ret = 1; -end: - if (hSession) SDF_CloseSession(hSession); - if (hDevice) SDF_CloseDevice(hDevice); - return ret; + return 1; } int sdf_print_device_info(FILE *fp, int fmt, int ind, const char *lable, SDF_DEVICE *dev) { - int ret = -1; void *hSession = NULL; DEVICEINFO devInfo; - if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK - || SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { - error_print(); - goto end; - } - SDF_PrintDeviceInfo(fp, &devInfo); - ret = 1; -end: - if (hSession) SDF_CloseSession(hSession); - return ret; -} - -int sdf_rand_bytes(SDF_DEVICE *dev, uint8_t *buf, size_t len) -{ - int ret = -1; - void *hSession = NULL; - - if (!dev || !buf || !len) { + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK) { error_print(); return -1; } - if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK - || SDF_GenerateRandom(hSession, (unsigned int)len, buf) != SDR_OK) { + if (SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { + (void)SDF_CloseSession(hSession); error_print(); - goto end; + return -1; } - ret = 1; -end: - if (hSession) SDF_CloseSession(hSession); - return ret; + (void)SDF_CloseSession(hSession); + + (void)SDF_PrintDeviceInfo(fp, &devInfo); + return 1; } -int sdf_export_sign_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_key) +int sdf_export_sign_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *sm2_key) { void *hSession; ECCrefPublicKey eccPublicKey; - if (!dev || !public_key) { + if (!dev || !sm2_key) { error_print(); return -1; } @@ -165,20 +148,24 @@ int sdf_export_sign_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_k } (void)SDF_CloseSession(hSession); - if (SDF_ECCrefPublicKey_to_SM2_KEY(&eccPublicKey, public_key) != SDR_OK) { + memset(sm2_key, 0, sizeof(SM2_KEY)); + if (SDF_ECCrefPublicKey_to_SM2_Z256_POINT(&eccPublicKey, &sm2_key->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) +int sdf_load_sign_key(SDF_DEVICE *dev, SDF_SIGN_KEY *key, int key_index, const char *pass) { - void *hSession; + void *hSession = NULL; ECCrefPublicKey eccPublicKey; - if (!dev || !public_key) { + if (!dev || !key || !pass) { + error_print(); + return -1; + } + if (key_index < 0) { error_print(); return -1; } @@ -187,93 +174,124 @@ int sdf_export_enc_public_key(SDF_DEVICE *dev, int key_index, SM2_KEY *public_ke error_print(); return -1; } - if (SDF_ExportEncPublicKey_ECC(hSession, key_index, &eccPublicKey) != SDR_OK) { + 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) { + if (SDF_GetPrivateKeyAccessRight(hSession, key_index, (unsigned char *)pass, (unsigned int)strlen(pass)) != SDR_OK) { + (void)SDF_CloseSession(hSession); error_print(); return -1; } + if (SDF_ECCrefPublicKey_to_SM2_Z256_POINT(&eccPublicKey, &key->public_key) != SDR_OK) { + error_print(); + return -1; + } + key->session = hSession; + key->index = key_index; return 1; } +int sdf_sign(SDF_SIGN_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen) +{ + ECCSignature ecc_sig; + SM2_SIGNATURE sm2_sig; + if (!key || !dgst || !sig || !siglen) { + error_print(); + return -1; + } + if (SDF_InternalSign_ECC(key->session, key->index, (unsigned char *)dgst, 32, &ecc_sig) != SDR_OK) { + error_print(); + return -1; + } + if (SDF_ECCSignature_to_SM2_SIGNATURE(&ecc_sig, &sm2_sig) != SDR_OK) { + error_print(); + return -1; + } + *siglen = 0; + if (sm2_signature_to_der(&sm2_sig, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} +int sdf_sign_init(SDF_SIGN_CTX *ctx, const SDF_SIGN_KEY *key, const char *id, size_t idlen) +{ + if (!ctx || !key) { + error_print(); + return -1; + } + sm3_init(&ctx->sm3_ctx); + if (id) { + uint8_t z[SM3_DIGEST_SIZE]; + if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH) { + error_print(); + return -1; + } + sm2_compute_z(z, &key->public_key, id, idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + } + ctx->saved_sm3_ctx = ctx->sm3_ctx; + ctx->key = *key; + return 1; +} - - -int sdf_load_sign_key(SDF_DEVICE *dev, SDF_KEY *key, int index, const char *pass) +int sdf_sign_update(SDF_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) { - int ret = -1; - void *hSession = NULL; - ECCrefPublicKey eccPublicKey; - SM2_KEY public_key; - - if (!dev || !key || !pass) { + if (!ctx) { error_print(); return -1; } - if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK - || SDF_ExportSignPublicKey_ECC(hSession, index, &eccPublicKey) != SDR_OK - || SDF_ECCrefPublicKey_to_SM2_KEY(&eccPublicKey, &public_key) != SDR_OK - || SDF_GetPrivateKeyAccessRight(hSession, index, (unsigned char *)pass, (unsigned int)strlen(pass)) != SDR_OK) { - error_print(); - goto end; + if (data && datalen > 0) { + sm3_update(&ctx->sm3_ctx, data, datalen); } - - memset(key, 0, sizeof(SDF_KEY)); - key->public_key = public_key; - key->session = hSession; - key->index = index; - hSession = NULL; - ret = 1; -end: - if (hSession) SDF_CloseSession(hSession); - return ret; + return 1; } -int sdf_sign(SDF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen) +int sdf_sign_finish(SDF_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) { - ECCSignature ecc_sig; - SM2_SIGNATURE sm2_sig; + uint8_t dgst[SM3_DIGEST_SIZE]; - if (!key || !dgst || !sig || !siglen) { + if (!ctx || !sig || !siglen) { error_print(); return -1; } - if (SDF_InternalSign_ECC(key->session, key->index, (unsigned char *)dgst, 32, &ecc_sig) != SDR_OK - || SDF_ECCSignature_to_SM2_SIGNATURE(&ecc_sig, &sm2_sig) != SDR_OK) { + + sm3_finish(&ctx->sm3_ctx, dgst); + + if (sdf_sign(&ctx->key, dgst, sig, siglen) != 1) { error_print(); return -1; } + return 1; +} - - - - *siglen = 0; - if (sm2_signature_to_der(&sm2_sig, &sig, siglen) != 1) { +int sdf_sign_reset(SDF_SIGN_CTX *ctx) +{ + if (!ctx) { error_print(); return -1; } + ctx->sm3_ctx = ctx->saved_sm3_ctx; return 1; } -int sdf_release_key(SDF_KEY *key) +int sdf_release_key(SDF_SIGN_KEY *key) { - if (SDF_ReleasePrivateKeyAccessRight(key->session, key->index) != SDR_OK - || SDF_CloseSession(key->session) != SDR_OK) { + if (SDF_ReleasePrivateKeyAccessRight(key->session, key->index) != SDR_OK) { + error_print(); + } + if (SDF_CloseSession(key->session) != SDR_OK) { error_print(); return -1; } - memset(key, 0, sizeof(SDF_KEY)); return 1; } diff --git a/tools/gmssl.c b/tools/gmssl.c index f76fea7b..2e4e47e2 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -66,9 +66,9 @@ extern int tls12_server_main(int argc, char **argv); 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 sdfsign_main(int argc, char **argv); extern int sdftest_main(int argc, char **argv); #endif #ifdef ENABLE_SKF @@ -128,9 +128,9 @@ static const char *options = " cmssign Generate CMS SignedData\n" " 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" + " sdfexport Export SM2 signing public key from SDF device\n" + " sdfsign Generate SM2 signature with SDF internal private key\n" " sdftest Test vendor's SDF library and device\n" #endif #ifdef ENABLE_SKF @@ -285,8 +285,8 @@ int main(int argc, char **argv) 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, "sdfsign")) { + return sdfsign_main(argc, argv); } else if (!strcmp(*argv, "sdftest")) { return sdftest_main(argc, argv); #endif diff --git a/tools/sdfexport.c b/tools/sdfexport.c index 530a5299..4f83d9ea 100644 --- a/tools/sdfexport.c +++ b/tools/sdfexport.c @@ -16,22 +16,19 @@ #include -static const char *usage = "-lib so_path {-sign_public_key|-encrypt_public_key} -index num [-out file]"; +static const char *usage = "-lib so_path -key 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" +" -key 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" +" $ gmssl sdfexport -key 1 -out sm2signpub.pem\n" "\n"; @@ -65,19 +62,7 @@ int sdfexport_main(int argc, char **argv) } 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")) { + } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; index = atoi(*(++argv)); if (index < 0) { @@ -107,10 +92,6 @@ int sdfexport_main(int argc, char **argv) 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; @@ -125,18 +106,10 @@ int sdfexport_main(int argc, char **argv) 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 (sdf_export_sign_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; diff --git a/tools/sdfsign.c b/tools/sdfsign.c new file mode 100644 index 00000000..6fbaedef --- /dev/null +++ b/tools/sdfsign.c @@ -0,0 +1,174 @@ +/* + * 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 +#include + + +static const char *usage = "-lib so_path -key num -pass str [-id str] [-in file] [-out file]"; + +static const char *options = +"\n" +"Options\n" +"\n" +" -lib so_path Vendor's SDF dynamic library\n" +" -key num Signing private key index number\n" +" -pass str Password to get the private key access right\n" +" -id str Signer's identity string, '1234567812345678' by default\n" +" -in file | stdin To be signed file or data\n" +" -out file | stdout Output signature in binary DER encoding\n" +"\n" +"Examples\n" +"\n" +" $ echo -n 'message to be signed' | gmssl sdfsign -lib libsoftsdf.so -key 1 -pass P@ssw0rd -out sm2.sig\n" +" $ gmssl sdfexport -lib libsoftsdf.so -key 1 -out sm2pub.pem\n" +" $ echo -n 'message to be signed' | gmssl sm2verify -pubkey sm2pub.pem -sig sm2.sig\n" +"\n"; + + +int sdfsign_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *lib = NULL; + int key_index = -1; + char *pass = NULL; + char *id = SM2_DEFAULT_ID; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t buf[4096]; + size_t len; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + SDF_DEVICE dev; + SDF_SIGN_KEY key; + SDF_SIGN_CTX ctx; + + 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, "-key")) { + if (--argc < 1) goto bad; + key_index = atoi(*(++argv)); + if (key_index < 0) { + fprintf(stderr, "gmssl %s: illegal key index %d\n", prog, key_index); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + 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: '-lib' option required\n", prog); + goto end; + } + if (key_index < 0) { + fprintf(stderr, "gmssl %s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "gmssl %s: '-pass' 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 (sdf_load_sign_key(&dev, &key, key_index, pass) != 1) { + (void)sdf_close_device(&dev); + fprintf(stderr, "gmssl %s: load signing key #%d failure\n", prog, key_index); + goto end; + } + + if (sdf_sign_init(&ctx, &key, id, strlen(id)) != 1) { + (void)sdf_close_device(&dev); + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sdf_sign_update(&ctx, buf, len) != 1) { + (void)sdf_close_device(&dev); + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + } + if (sdf_sign_finish(&ctx, sig, &siglen) != 1) { + (void)sdf_close_device(&dev); + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + (void)sdf_close_device(&dev); + + if (fwrite(sig, 1, siglen, outfp) != siglen) { + fprintf(stderr, "gmssl %s: output signature failed : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; + +end: + sdf_unload_library(); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +}