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 } 354