• 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 <gmssl/x509.h>
16 
17 
18 static const char *options = "-in pem [-double_certs] -cacert pem\n";
19 
certverify_main(int argc,char ** argv)20 int certverify_main(int argc, char **argv)
21 {
22 	int ret = 1;
23 	char *prog = argv[0];
24 	char *infile = NULL;
25 	char *cacertfile = NULL;
26 	FILE *infp = stdin;
27 	FILE *cacertfp = NULL;
28 	uint8_t cert[1024];
29 	size_t certlen;
30 	uint8_t cacert[1024];
31 	size_t cacertlen;
32 	const uint8_t *subject;
33 	size_t subject_len;
34 	const uint8_t *subj;
35 	size_t subj_len;
36 
37 	int double_certs = 0;
38 	uint8_t enc_cert[1024];
39 	size_t enc_cert_len;
40 	int rv;
41 
42 	argc--;
43 	argv++;
44 
45 	if (argc < 1) {
46 		fprintf(stderr, "usage: %s %s\n", prog, options);
47 		return 1;
48 	}
49 
50 	while (argc > 0) {
51 		if (!strcmp(*argv, "-help")) {
52 			printf("usage: %s %s\n", prog, options);
53 			ret = 0;
54 			goto end;
55 		} else if (!strcmp(*argv, "-in")) {
56 			if (--argc < 1) goto bad;
57 			infile = *(++argv);
58 			if (!(infp = fopen(infile, "r"))) {
59 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
60 				goto end;
61 			}
62 		} else if (!strcmp(*argv, "-double_certs")) {
63 			double_certs = 1;
64 		} else if (!strcmp(*argv, "-cacert")) {
65 			if (--argc < 1) goto bad;
66 			cacertfile = *(++argv);
67 			if (!(cacertfp = fopen(cacertfile, "r"))) {
68 				fprintf(stderr, "%s: open '%s' failure : %s\n", prog, cacertfile, strerror(errno));
69 				goto end;
70 			}
71 		} else {
72 			fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
73 			goto end;
74 bad:
75 			fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
76 			goto end;
77 		}
78 
79 		argc--;
80 		argv++;
81 	}
82 
83 
84 	if (!infile) {
85 		fprintf(stderr, "%s: '-in' option required\n", prog);
86 		goto end;
87 	}
88 	if (!cacertfile) {
89 		fprintf(stderr, "%s: '-cacert' option required\n", prog);
90 		goto end;
91 	}
92 
93 	if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1
94 		|| x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) {
95 		fprintf(stderr, "%s: read certificate failure\n", prog);
96 		goto end;
97 	}
98 	x509_name_print(stdout, 0, 0, "Certificate", subject, subject_len);
99 
100 	if (double_certs) {
101 
102 		if (x509_cert_from_pem(enc_cert, &enc_cert_len, sizeof(enc_cert), infp) != 1
103 			|| x509_cert_get_subject(enc_cert, enc_cert_len, &subj, &subj_len) != 1) {
104 			fprintf(stderr, "%s: read encryption certficate failure\n", prog);
105 			goto end;
106 		}
107 
108 		if (subj_len != subject_len
109 			|| memcmp(subject, subj, subj_len) != 0) {
110 			fprintf(stderr, "%s: double certificates not compatible\n", prog);
111 			goto end;
112 		}
113 	}
114 
115 	for (;;) {
116 		if ((rv = x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), infp)) != 1) {
117 			if (rv < 0) goto end;
118 			goto final;
119 		}
120 		if (x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) {
121 			goto end;
122 		}
123 
124 		if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) {
125 			fprintf(stderr, "%s: inner error\n", prog);
126 			goto end;
127 		}
128 		printf("Verification %s\n", rv ? "success" : "failure");
129 
130 		if (double_certs) {
131 			x509_name_print(stdout, 0, 0, "Certificate", subj, subj_len);
132 
133 			if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) {
134 				fprintf(stderr, "%s: inner error\n", prog);
135 				goto end;
136 			}
137 			printf("Verification %s\n", rv ? "success" : "failure");
138 			double_certs = 0;
139 		}
140 		x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len);
141 
142 		memcpy(cert, cacert, cacertlen);
143 		certlen = cacertlen;
144 	}
145 
146 final:
147 	if (x509_cert_get_issuer(cert, certlen, &subject, &subject_len) != 1) {
148 		fprintf(stderr, "%s: parse certificate error\n", prog);
149 		goto end;
150 	}
151 	if (x509_cert_from_pem_by_subject(cacert, &cacertlen, sizeof(cacert), subject, subject_len, cacertfp) != 1) {
152 		fprintf(stderr, "%s: load CA certificate failure\n", prog);
153 		goto end;
154 	}
155 	if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) {
156 		fprintf(stderr, "%s: inner error\n", prog);
157 		goto end;
158 	}
159 	printf("Verification %s\n", rv ? "success" : "failure");
160 	x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len);
161 
162 	if (double_certs) {
163 		if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) {
164 			fprintf(stderr, "%s: inner error\n", prog);
165 			goto end;
166 		}
167 		printf("Verification %s\n", rv ? "success" : "failure");
168 	}
169 
170 	ret = 0;
171 end:
172 	if (infile && infp) fclose(infp);
173 	if (cacertfp) fclose(cacertfp);
174 	return ret;
175 }
176