/ tools / verify.c
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  }