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 #include <stdio.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <gmssl/sm2.h>
16 #include <gmssl/x509.h>
17
18
19 static const char *options = "(-pubkey pem | -cert pem) [-in file] [-out file]";
20
sm2encrypt_main(int argc,char ** argv)21 int sm2encrypt_main(int argc, char **argv)
22 {
23 int ret = 1;
24 char *prog = argv[0];
25 char *pubkeyfile = NULL;
26 char *certfile = NULL;
27 char *infile = NULL;
28 char *outfile = NULL;
29 FILE *pubkeyfp = NULL;
30 FILE *certfp = NULL;
31 FILE *infp = stdin;
32 FILE *outfp = stdout;
33 uint8_t cert[1024];
34 size_t certlen;
35 SM2_KEY key;
36 uint8_t inbuf[SM2_MAX_PLAINTEXT_SIZE + 1];
37 uint8_t outbuf[SM2_MAX_CIPHERTEXT_SIZE];
38 size_t inlen, outlen = sizeof(outbuf);
39
40 argc--;
41 argv++;
42
43 if (argc < 1) {
44 fprintf(stderr, "usage: %s %s\n", prog, options);
45 return 1;
46 }
47
48 while (argc > 1) {
49 if (!strcmp(*argv, "-help")) {
50 printf("usage: %s %s\n", prog, options);
51 ret = 0;
52 goto end;
53 } else if (!strcmp(*argv, "-pubkey")) {
54 if (certfile) {
55 fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog);
56 goto end;
57 }
58 if (--argc < 1) goto bad;
59 pubkeyfile = *(++argv);
60 if (!(pubkeyfp = fopen(pubkeyfile, "r"))) {
61 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, pubkeyfile, strerror(errno));
62 goto end;
63 }
64 } else if (!strcmp(*argv, "-cert")) {
65 if (pubkeyfile) {
66 fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog);
67 goto end;
68 }
69 if (--argc < 1) goto bad;
70 certfile = *(++argv);
71 if (!(certfp = fopen(certfile, "r"))) {
72 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
73 goto end;
74 }
75 } else if (!strcmp(*argv, "-in")) {
76 if (--argc < 1) goto bad;
77 infile = *(++argv);
78 if (!(infp = fopen(infile, "r"))) {
79 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
80 goto end;
81 }
82 } else if (!strcmp(*argv, "-out")) {
83 if (--argc < 1) goto bad;
84 outfile = *(++argv);
85 if (!(outfp = fopen(outfile, "w"))) {
86 fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
87 goto end;
88 }
89 } else {
90 fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
91 goto end;
92 bad:
93 fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
94 goto end;
95 }
96
97 argc--;
98 argv++;
99 }
100
101
102 if (pubkeyfile) {
103 if (sm2_public_key_info_from_pem(&key, pubkeyfp) != 1) {
104 fprintf(stderr, "%s: parse public key failed\n", prog);
105 goto end;
106 }
107 } else if (certfile) {
108 if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1
109 || x509_cert_get_subject_public_key(cert, certlen, &key) != 1) {
110 fprintf(stderr, "%s: parse certificate failed\n", prog);
111 goto end;
112 }
113 } else {
114 fprintf(stderr, "%s: '-pubkey' or '-cert' option required\n", prog);
115 goto end;
116 }
117
118 if ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) <= 0) {
119 fprintf(stderr, "%s: read input error : %s\n", prog, strerror(errno));
120 goto end;
121 }
122 if (inlen > SM2_MAX_PLAINTEXT_SIZE) {
123 fprintf(stderr, "%s: input long than SM2_MAX_PLAINTEXT_SIZE (%d)\n", prog, SM2_MAX_PLAINTEXT_SIZE);
124 goto end;
125 }
126
127 if (sm2_encrypt(&key, inbuf, inlen, outbuf, &outlen) != 1) {
128 fprintf(stderr, "%s: inner error\n", prog);
129 goto end;
130 }
131
132 if (outlen != fwrite(outbuf, 1, outlen, outfp)) {
133 fprintf(stderr, "%s: output error : %s\n", prog, strerror(errno));
134 goto end;
135 }
136 ret = 0;
137
138 end:
139 if (infile && infp) fclose(infp);
140 if (outfile && outfp) fclose(outfp);
141 if (pubkeyfp) fclose(pubkeyfp);
142 if (certfp) fclose(certfp);
143 return ret;
144 }
145