• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sys/stat.h>
16 #include <gmssl/x509.h>
17 #include <gmssl/cms.h>
18 
19 
20 
21 static const char *options = "-key file -pass str -cert file -in file [-out file]";
22 
cmsdecrypt_main(int argc,char ** argv)23 int cmsdecrypt_main(int argc, char **argv)
24 {
25 	int ret = 1;
26 	char *prog = argv[0];
27 	char *keyfile = NULL;
28 	char *pass = NULL;
29 	char *certfile = NULL;
30 	char *infile = NULL;
31 	char *outfile = NULL;
32 	FILE *keyfp = NULL;
33 	FILE *certfp = NULL;
34 	FILE *infp = NULL;
35 	FILE *outfp = stdout;
36 	uint8_t cert[1024];
37 	size_t certlen;
38 	struct stat st;
39 	uint8_t *cms = NULL;
40 	size_t cmslen, cms_maxlen;
41 	SM2_KEY key;
42 	int content_type;
43 	uint8_t *content = NULL;
44 	size_t content_len;
45 	const uint8_t *rcpt_infos;
46 	size_t rcpt_infos_len;
47 	const uint8_t *shared_info1;
48 	const uint8_t *shared_info2;
49 	size_t shared_info1_len, shared_info2_len;
50 
51 	argc--;
52 	argv++;
53 
54 	if (argc < 1) {
55 		fprintf(stderr, "usage: %s %s\n", prog, options);
56 		return 1;
57 	}
58 
59 	while (argc > 1) {
60 		if (!strcmp(*argv, "-help")) {
61 			printf("usage: %s %s\n", prog, options);
62 			ret = 0;
63 			goto end;
64 		} else if (!strcmp(*argv, "-key")) {
65 			if (--argc < 1) goto bad;
66 			keyfile = *(++argv);
67 			if (!(keyfp = fopen(keyfile, "r"))) {
68 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno));
69 				goto end;
70 			}
71 		} else if (!strcmp(*argv, "-pass")) {
72 			if (--argc < 1) goto bad;
73 			pass = *(++argv);
74 		} else if (!strcmp(*argv, "-cert")) {
75 			if (--argc < 1) goto bad;
76 			certfile = *(++argv);
77 			if (!(certfp = fopen(certfile, "r"))) {
78 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
79 				goto end;
80 			}
81 		} else if (!strcmp(*argv, "-in")) {
82 			if (--argc < 1) goto bad;
83 			infile = *(++argv);
84 			if (!(infp = fopen(infile, "r"))) {
85 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
86 				goto end;
87 			}
88 		} else if (!strcmp(*argv, "-out")) {
89 			if (--argc < 1) goto bad;
90 			outfile = *(++argv);
91 			if (!(outfp = fopen(outfile, "w"))) {
92 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
93 				goto end;
94 			}
95 		} else {
96 			fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
97 			goto end;
98 bad:
99 			fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
100 			goto end;
101 		}
102 
103 		argc--;
104 		argv++;
105 	}
106 
107 	if (!keyfile) {
108 		fprintf(stderr, "%s: '-key' option required\n", prog);
109 		goto end;
110 	}
111 	if (!pass) {
112 		fprintf(stderr, "%s: '-pass' option required\n", prog);
113 		goto end;
114 	}
115 	if (!certfile) {
116 		fprintf(stderr, "%s: '-cert' option required\n", prog);
117 		goto end;
118 	}
119 	if (!infile) {
120 		fprintf(stderr, "%s: '-in' option required\n", prog);
121 		goto end;
122 	}
123 
124 	if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) {
125 		fprintf(stderr, "%s: private key decryption failure\n", prog);
126 		goto end;
127 	}
128 	if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) {
129 		fprintf(stderr, "%s: load certificate failure\n", prog);
130 		goto end;
131 	}
132 
133 	fstat(fileno(infp), &st);
134 	cms_maxlen = (st.st_size * 3)/4 + 1;
135 	if (!(cms = malloc(cms_maxlen))) {
136 		fprintf(stderr, "%s: malloc failure\n", prog);
137 		goto end;
138 	}
139 	if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) {
140 		fprintf(stderr, "%s: read CMS failure\n", prog);
141 		goto end;
142 	}
143 
144 	if (!(content = malloc(cmslen))) {
145 		fprintf(stderr, "%s: malloc failure\n", prog);
146 		goto end;
147 	}
148 
149 	if (cms_deenvelop(cms, cmslen,
150 		&key, cert, certlen,
151 		&content_type, content, &content_len,
152 		&rcpt_infos, &rcpt_infos_len,
153 		&shared_info1, &shared_info1_len,
154 		&shared_info2, &shared_info2_len) != 1) {
155 		fprintf(stderr, "%s: decryption failure\n", prog);
156 		goto end;
157 	}
158 	if (content_type != OID_cms_data) {
159 		fprintf(stderr, "%s: invalid CMS content type: %s\n", prog, cms_content_type_name(content_type));
160 		goto end;
161 	}
162 
163 	if (fwrite(content, 1, content_len, outfp) != content_len) {
164 		fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno));
165 		goto end;
166 	}
167 
168 	ret = 0;
169 
170 end:
171 	if (infile && infp) fclose(infp);
172 	if (outfile && outfp) fclose(outfp);
173 	if (keyfile && keyfp) fclose(keyfp);
174 	if (cms) free(cms);
175 	if (content) free(content);
176 	return ret;
177 }
178