1 /*
2 * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License); you may
5 * not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 */
9
10
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <gmssl/mem.h>
17 #include <gmssl/sm2.h>
18 #include <gmssl/sm3.h>
19 #include <gmssl/sdf.h>
20
21
22 #define OP_NONE 0
23 #define OP_DEVINFO 1
24 #define OP_EXPORTPUBKEY 2
25 #define OP_SIGN 3
26 #define OP_RAND 4
27
28
print_usage(FILE * fp,const char * prog)29 static void print_usage(FILE *fp, const char *prog)
30 {
31 fprintf(fp, "usage:\n");
32 fprintf(fp, " %s -lib so_path -devinfo\n", prog);
33 fprintf(fp, " %s -lib so_path -exportpubkey -key index [-out file]\n", prog);
34 fprintf(fp, " %s -lib so_path -sign [-in file] [-out file]\n", prog);
35 fprintf(fp, " %s -lib so_path -rand num [-out file]\n", prog);
36 }
37
sdfutil_main(int argc,char ** argv)38 int sdfutil_main(int argc, char **argv)
39 {
40 int ret = 1;
41 char *prog = argv[0];
42 char *lib = NULL;
43 int op = 0;
44 int keyindex = -1;
45 char *pass = NULL;
46 char *id = SM2_DEFAULT_ID;
47 int num = 0;
48 char *infile = NULL;
49 char *outfile = NULL;
50 FILE *infp = stdin;
51 FILE *outfp = stdout;
52 unsigned char buf[4096];
53 unsigned int ulen;
54 int len;
55 SDF_DEVICE dev;
56 SDF_KEY key;
57 int dev_opened = 0;
58 int key_opened = 0;
59
60 memset(&dev, 0, sizeof(dev));
61 memset(&key, 0, sizeof(key));
62
63 argc--;
64 argv++;
65
66 if (argc < 1) {
67 print_usage(stderr, prog);
68 return 1;
69 }
70
71 while (argc > 0) {
72 if (!strcmp(*argv, "-help")) {
73 print_usage(stdout, prog);
74 goto end;
75 } else if (!strcmp(*argv, "-lib")) {
76 if (--argc < 1) goto bad;
77 lib = *(++argv);
78 } else if (!strcmp(*argv, "-devinfo")) {
79 op = OP_DEVINFO;
80 } else if (!strcmp(*argv, "-exportpubkey")) {
81 op = OP_EXPORTPUBKEY;
82 } else if (!strcmp(*argv, "-sign")) {
83 op = OP_SIGN;
84 } else if (!strcmp(*argv, "-key")) {
85 if (--argc < 1) goto bad;
86 keyindex = atoi(*(++argv));
87 } else if (!strcmp(*argv, "-pass")) {
88 if (--argc < 1) goto bad;
89 pass = *(++argv);
90 } else if (!strcmp(*argv, "-id")) {
91 if (--argc < 1) goto bad;
92 id = *(++argv);
93 } else if (!strcmp(*argv, "-rand")) {
94 if (--argc < 1) goto bad;
95 len = atoi(*(++argv));
96 } else if (!strcmp(*argv, "-in")) {
97 if (--argc < 1) goto bad;
98 infile = *(++argv);
99 if (!(infp = fopen(infile, "r"))) {
100 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
101 goto end;
102 }
103 } else if (!strcmp(*argv, "-out")) {
104 if (--argc < 1) goto bad;
105 outfile = *(++argv);
106 if (!(outfp = fopen(outfile, "w"))) {
107 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
108 goto end;
109 }
110 } else {
111 fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
112 goto end;
113 bad:
114 fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
115 goto end;
116 }
117
118 argc--;
119 argv++;
120 }
121
122 if (!lib) {
123 fprintf(stderr, "%s: option '-lib' required\n", prog);
124 goto end;
125 }
126 if (sdf_load_library(lib, NULL) != 1) {
127 fprintf(stderr, "%s: load library failure\n", prog);
128 goto end;
129 }
130
131 if (sdf_open_device(&dev) != 1) {
132 fprintf(stderr, "%s: open device failure\n", prog);
133 goto end;
134 }
135 dev_opened = 1;
136
137 switch (op) {
138 case OP_DEVINFO:
139 sdf_print_device_info(stdout, 0, 0, "SDF", &dev);
140 break;
141
142 case OP_EXPORTPUBKEY:
143 if (keyindex < 0) {
144 fprintf(stderr, "%s: invalid key index\n", prog);
145 goto end;
146 }
147 if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) {
148 fprintf(stderr, "%s: load sign key failed\n", prog);
149 goto end;
150 }
151 key_opened = 1;
152 if (sm2_public_key_info_to_pem(&(key.public_key), outfp) != 1) {
153 fprintf(stderr, "%s: output public key to PEM failed\n", prog);
154 goto end;
155 }
156 break;
157
158 case OP_SIGN:
159 {
160 SM3_CTX sm3_ctx;
161 uint8_t dgst[32];
162 uint8_t sig[SM2_MAX_SIGNATURE_SIZE];
163 size_t siglen;
164
165 if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) {
166 fprintf(stderr, "%s: load sign key failed\n", prog);
167 goto end;
168 }
169 key_opened = 1;
170
171 sm3_init(&sm3_ctx);
172 sm2_compute_z(dgst, &(key.public_key.public_key), id, strlen(id));
173 sm3_update(&sm3_ctx, dgst, sizeof(dgst));
174
175 while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) {
176 sm3_update(&sm3_ctx, buf, len);
177 }
178 sm3_finish(&sm3_ctx, dgst);
179
180 if ((ret = sdf_sign(&key, dgst, sig, &siglen)) != 1) {
181 fprintf(stderr, "%s: inner error\n", prog);
182 goto end;
183 }
184 if (fwrite(sig, 1, siglen, outfp) != siglen) {
185 fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno));
186 goto end;
187 }
188 }
189 break;
190
191 case OP_RAND:
192 if (sdf_rand_bytes(&dev, buf, len) != 1) {
193 fprintf(stderr, "%s: inner error\n", prog);
194 goto end;
195 }
196 if (fwrite(buf, 1, len, outfp) != len) {
197 fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno));
198 goto end;
199 }
200 break;
201
202 default:
203 fprintf(stderr, "%s: this should not happen\n", prog);
204 goto end;
205 }
206 ret = 0;
207
208 end:
209 gmssl_secure_clear(buf, sizeof(buf));
210 if (key_opened) sdf_release_key(&key);
211 if (dev_opened) sdf_close_device(&dev);
212 if (lib) sdf_unload_library();
213 if (infile && infp) fclose(infp);
214 if (outfile && outfp) fclose(outfp);
215 return ret;
216 }
217