]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/tools/verify.c
Add support for loader veriexec
[FreeBSD/FreeBSD.git] / contrib / bearssl / tools / verify.c
1 /*
2  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining 
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be 
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <errno.h>
30
31 #include "brssl.h"
32 #include "bearssl.h"
33
34 static unsigned
35 rsa_bit_length(const br_rsa_public_key *pk)
36 {
37         size_t u;
38         unsigned x, bl;
39
40         for (u = 0; u < pk->nlen; u ++) {
41                 if (pk->n[u] != 0) {
42                         break;
43                 }
44         }
45         if (u == pk->nlen) {
46                 return 0;
47         }
48         bl = (unsigned)(pk->nlen - u - 1) << 3;
49         x = pk->n[u];
50         while (x != 0) {
51                 bl ++;
52                 x >>= 1;
53         }
54         return bl;
55 }
56
57 static void
58 print_rsa(const br_rsa_public_key *pk, int print_text, int print_C)
59 {
60         if (print_text) {
61                 size_t u;
62
63                 printf("n = ");
64                 for (u = 0; u < pk->nlen; u ++) {
65                         printf("%02X", pk->n[u]);
66                 }
67                 printf("\n");
68                 printf("e = ");
69                 for (u = 0; u < pk->elen; u ++) {
70                         printf("%02X", pk->e[u]);
71                 }
72                 printf("\n");
73         }
74         if (print_C) {
75                 size_t u;
76
77                 printf("\nstatic const unsigned char RSA_N[] = {");
78                 for (u = 0; u < pk->nlen; u ++) {
79                         if (u != 0) {
80                                 printf(",");
81                         }
82                         if (u % 12 == 0) {
83                                 printf("\n\t");
84                         } else {
85                                 printf(" ");
86                         }
87                         printf("0x%02X", pk->n[u]);
88                 }
89                 printf("\n};\n");
90                 printf("\nstatic const unsigned char RSA_E[] = {");
91                 for (u = 0; u < pk->elen; u ++) {
92                         if (u != 0) {
93                                 printf(",");
94                         }
95                         if (u % 12 == 0) {
96                                 printf("\n\t");
97                         } else {
98                                 printf(" ");
99                         }
100                         printf("0x%02X", pk->e[u]);
101                 }
102                 printf("\n};\n");
103                 printf("\nstatic const br_rsa_public_key RSA = {\n");
104                 printf("\t(unsigned char *)RSA_N, sizeof RSA_N,\n");
105                 printf("\t(unsigned char *)RSA_E, sizeof RSA_E\n");
106                 printf("};\n");
107         }
108 }
109
110 static void
111 print_ec(const br_ec_public_key *pk, int print_text, int print_C)
112 {
113         if (print_text) {
114                 size_t u;
115
116                 printf("Q = ");
117                 for (u = 0; u < pk->qlen; u ++) {
118                         printf("%02X", pk->q[u]);
119                 }
120                 printf("\n");
121         }
122         if (print_C) {
123                 size_t u;
124
125                 printf("\nstatic const unsigned char EC_Q[] = {");
126                 for (u = 0; u < pk->qlen; u ++) {
127                         if (u != 0) {
128                                 printf(",");
129                         }
130                         if (u % 12 == 0) {
131                                 printf("\n\t");
132                         } else {
133                                 printf(" ");
134                         }
135                         printf("0x%02X", pk->q[u]);
136                 }
137                 printf("\n};\n");
138                 printf("\nstatic const br_ec_public_key EC = {\n");
139                 printf("\t%d,\n", pk->curve);
140                 printf("\t(unsigned char *)EC_Q, sizeof EC_Q\n");
141                 printf("};\n");
142         }
143 }
144
145 static void
146 usage_verify(void)
147 {
148         fprintf(stderr,
149 "usage: brssl verify [ options ] file...\n");
150         fprintf(stderr,
151 "options:\n");
152         fprintf(stderr,
153 "   -q            suppress verbose messages\n");
154         fprintf(stderr,
155 "   -sni name     check presence of a specific server name\n");
156         fprintf(stderr,
157 "   -CA file      add certificates in 'file' to trust anchors\n");
158         fprintf(stderr,
159 "   -text         print public key details (human-readable)\n");
160         fprintf(stderr,
161 "   -C            print public key details (C code)\n");
162 }
163
164 typedef VECTOR(br_x509_certificate) cert_list;
165
166 static void
167 free_cert_contents(br_x509_certificate *xc)
168 {
169         xfree(xc->data);
170 }
171
172 /* see brssl.h */
173 int
174 do_verify(int argc, char *argv[])
175 {
176         int retcode;
177         int verbose;
178         int i;
179         const char *sni;
180         anchor_list anchors = VEC_INIT;
181         cert_list chain = VEC_INIT;
182         size_t u;
183         br_x509_minimal_context mc;
184         int err;
185         int print_text, print_C;
186         br_x509_pkey *pk;
187         const br_x509_pkey *tpk;
188         unsigned usages;
189
190         retcode = 0;
191         verbose = 1;
192         sni = NULL;
193         print_text = 0;
194         print_C = 0;
195         pk = NULL;
196         for (i = 0; i < argc; i ++) {
197                 const char *arg;
198
199                 arg = argv[i];
200                 if (arg[0] != '-') {
201                         br_x509_certificate *xcs;
202                         size_t num;
203
204                         xcs = read_certificates(arg, &num);
205                         if (xcs == NULL) {
206                                 usage_verify();
207                                 goto verify_exit_error;
208                         }
209                         VEC_ADDMANY(chain, xcs, num);
210                         xfree(xcs);
211                         continue;
212                 }
213                 if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
214                         verbose = 1;
215                 } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
216                         verbose = 0;
217                 } else if (eqstr(arg, "-sni")) {
218                         if (++ i >= argc) {
219                                 fprintf(stderr,
220                                         "ERROR: no argument for '-sni'\n");
221                                 usage_verify();
222                                 goto verify_exit_error;
223                         }
224                         if (sni != NULL) {
225                                 fprintf(stderr, "ERROR: duplicate SNI\n");
226                                 usage_verify();
227                                 goto verify_exit_error;
228                         }
229                         sni = argv[i];
230                         continue;
231                 } else if (eqstr(arg, "-CA")) {
232                         if (++ i >= argc) {
233                                 fprintf(stderr,
234                                         "ERROR: no argument for '-CA'\n");
235                                 usage_verify();
236                                 goto verify_exit_error;
237                         }
238                         arg = argv[i];
239                         if (read_trust_anchors(&anchors, arg) == 0) {
240                                 usage_verify();
241                                 goto verify_exit_error;
242                         }
243                         continue;
244                 } else if (eqstr(arg, "-text")) {
245                         print_text = 1;
246                 } else if (eqstr(arg, "-C")) {
247                         print_C = 1;
248                 } else {
249                         fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
250                         usage_verify();
251                         goto verify_exit_error;
252                 }
253         }
254         if (VEC_LEN(chain) == 0) {
255                 fprintf(stderr, "ERROR: no certificate chain provided\n");
256                 usage_verify();
257                 goto verify_exit_error;
258         }
259         br_x509_minimal_init(&mc, &br_sha256_vtable,
260                 &VEC_ELT(anchors, 0), VEC_LEN(anchors));
261         br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
262         br_x509_minimal_set_hash(&mc, br_sha224_ID, &br_sha224_vtable);
263         br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
264         br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
265         br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
266         br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
267         br_x509_minimal_set_ecdsa(&mc,
268                 &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
269
270         mc.vtable->start_chain(&mc.vtable, sni);
271         for (u = 0; u < VEC_LEN(chain); u ++) {
272                 br_x509_certificate *xc;
273
274                 xc = &VEC_ELT(chain, u);
275                 mc.vtable->start_cert(&mc.vtable, xc->data_len);
276                 mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
277                 mc.vtable->end_cert(&mc.vtable);
278         }
279         err = mc.vtable->end_chain(&mc.vtable);
280         tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
281         if (tpk != NULL) {
282                 pk = xpkeydup(tpk);
283         }
284
285         if (err == 0) {
286                 if (verbose) {
287                         int hkx;
288
289                         fprintf(stderr, "Validation success; usages:");
290                         hkx = 0;
291                         if (usages & BR_KEYTYPE_KEYX) {
292                                 fprintf(stderr, " key exchange");
293                                 hkx = 1;
294                         }
295                         if (usages & BR_KEYTYPE_SIGN) {
296                                 if (hkx) {
297                                         fprintf(stderr, ",");
298                                 }
299                                 fprintf(stderr, " signature");
300                         }
301                         fprintf(stderr, "\n");
302                 }
303         } else {
304                 if (verbose) {
305                         const char *errname, *errmsg;
306
307                         fprintf(stderr, "Validation failed, err = %d", err);
308                         errname = find_error_name(err, &errmsg);
309                         if (errname != NULL) {
310                                 fprintf(stderr, " (%s): %s\n", errname, errmsg);
311                         } else {
312                                 fprintf(stderr, " (unknown)\n");
313                         }
314                 }
315                 retcode = -1;
316         }
317         if (pk != NULL) {
318                 switch (pk->key_type) {
319                 case BR_KEYTYPE_RSA:
320                         if (verbose) {
321                                 fprintf(stderr, "Key type: RSA (%u bits)\n",
322                                         rsa_bit_length(&pk->key.rsa));
323                         }
324                         print_rsa(&pk->key.rsa, print_text, print_C);
325                         break;
326                 case BR_KEYTYPE_EC:
327                         if (verbose) {
328                                 fprintf(stderr, "Key type: EC (%s)\n",
329                                         ec_curve_name(pk->key.ec.curve));
330                         }
331                         print_ec(&pk->key.ec, print_text, print_C);
332                         break;
333                 default:
334                         if (verbose) {
335                                 fprintf(stderr, "Unknown key type\n");
336                                 break;
337                         }
338                 }
339         }
340
341         /*
342          * Release allocated structures.
343          */
344 verify_exit:
345         VEC_CLEAREXT(anchors, &free_ta_contents);
346         VEC_CLEAREXT(chain, &free_cert_contents);
347         xfreepkey(pk);
348         return retcode;
349
350 verify_exit_error:
351         retcode = -1;
352         goto verify_exit;
353 }