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