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 const char * 35 curve_to_sym(int curve) 36 { 37 switch (curve) { 38 case BR_EC_sect163k1: return "BR_EC_sect163k1"; 39 case BR_EC_sect163r1: return "BR_EC_sect163r1"; 40 case BR_EC_sect163r2: return "BR_EC_sect163r2"; 41 case BR_EC_sect193r1: return "BR_EC_sect193r1"; 42 case BR_EC_sect193r2: return "BR_EC_sect193r2"; 43 case BR_EC_sect233k1: return "BR_EC_sect233k1"; 44 case BR_EC_sect233r1: return "BR_EC_sect233r1"; 45 case BR_EC_sect239k1: return "BR_EC_sect239k1"; 46 case BR_EC_sect283k1: return "BR_EC_sect283k1"; 47 case BR_EC_sect283r1: return "BR_EC_sect283r1"; 48 case BR_EC_sect409k1: return "BR_EC_sect409k1"; 49 case BR_EC_sect409r1: return "BR_EC_sect409r1"; 50 case BR_EC_sect571k1: return "BR_EC_sect571k1"; 51 case BR_EC_sect571r1: return "BR_EC_sect571r1"; 52 case BR_EC_secp160k1: return "BR_EC_secp160k1"; 53 case BR_EC_secp160r1: return "BR_EC_secp160r1"; 54 case BR_EC_secp160r2: return "BR_EC_secp160r2"; 55 case BR_EC_secp192k1: return "BR_EC_secp192k1"; 56 case BR_EC_secp192r1: return "BR_EC_secp192r1"; 57 case BR_EC_secp224k1: return "BR_EC_secp224k1"; 58 case BR_EC_secp224r1: return "BR_EC_secp224r1"; 59 case BR_EC_secp256k1: return "BR_EC_secp256k1"; 60 case BR_EC_secp256r1: return "BR_EC_secp256r1"; 61 case BR_EC_secp384r1: return "BR_EC_secp384r1"; 62 case BR_EC_secp521r1: return "BR_EC_secp521r1"; 63 case BR_EC_brainpoolP256r1: return "BR_EC_brainpoolP256r1"; 64 case BR_EC_brainpoolP384r1: return "BR_EC_brainpoolP384r1"; 65 case BR_EC_brainpoolP512r1: return "BR_EC_brainpoolP512r1"; 66 } 67 return NULL; 68 } 69 70 static void 71 print_blob(const char *name, const unsigned char *buf, size_t len) 72 { 73 size_t u; 74 75 printf("\nstatic const unsigned char %s[] = {", name); 76 for (u = 0; u < len; u ++) { 77 if (u != 0) { 78 printf(","); 79 } 80 if (u % 12 == 0) { 81 printf("\n\t"); 82 } else { 83 printf(" "); 84 } 85 printf("0x%02X", buf[u]); 86 } 87 printf("\n};\n"); 88 } 89 90 static int 91 print_ta_internals(br_x509_trust_anchor *ta, long ctr) 92 { 93 char tmp[25]; 94 95 sprintf(tmp, "TA%ld_DN", ctr); 96 print_blob(tmp, ta->dn.data, ta->dn.len); 97 switch (ta->pkey.key_type) { 98 case BR_KEYTYPE_RSA: 99 sprintf(tmp, "TA%ld_RSA_N", ctr); 100 print_blob(tmp, ta->pkey.key.rsa.n, ta->pkey.key.rsa.nlen); 101 sprintf(tmp, "TA%ld_RSA_E", ctr); 102 print_blob(tmp, ta->pkey.key.rsa.e, ta->pkey.key.rsa.elen); 103 break; 104 case BR_KEYTYPE_EC: 105 sprintf(tmp, "TA%ld_EC_Q", ctr); 106 print_blob(tmp, ta->pkey.key.ec.q, ta->pkey.key.ec.qlen); 107 break; 108 default: 109 fprintf(stderr, "ERROR: unknown anchor key type '%d'\n", 110 ta->pkey.key_type); 111 return -1; 112 } 113 return 0; 114 } 115 116 static void 117 print_ta(br_x509_trust_anchor *ta, long ctr) 118 { 119 char tmp[25]; 120 121 printf("\t{\n"); 122 printf("\t\t{ (unsigned char *)TA%ld_DN, sizeof TA%ld_DN },\n", 123 ctr, ctr); 124 printf("\t\t%s,\n", (ta->flags & BR_X509_TA_CA) 125 ? "BR_X509_TA_CA" : "0"); 126 printf("\t\t{\n"); 127 switch (ta->pkey.key_type) { 128 const char *cname; 129 130 case BR_KEYTYPE_RSA: 131 printf("\t\t\tBR_KEYTYPE_RSA,\n"); 132 printf("\t\t\t{ .rsa = {\n"); 133 printf("\t\t\t\t(unsigned char *)TA%ld_RSA_N," 134 " sizeof TA%ld_RSA_N,\n", ctr, ctr); 135 printf("\t\t\t\t(unsigned char *)TA%ld_RSA_E," 136 " sizeof TA%ld_RSA_E,\n", ctr, ctr); 137 printf("\t\t\t} }\n"); 138 break; 139 case BR_KEYTYPE_EC: 140 printf("\t\t\tBR_KEYTYPE_EC,\n"); 141 printf("\t\t\t{ .ec = {\n"); 142 cname = curve_to_sym(ta->pkey.key.ec.curve); 143 if (cname == NULL) { 144 sprintf(tmp, "%d", ta->pkey.key.ec.curve); 145 cname = tmp; 146 } 147 printf("\t\t\t\t%s,\n", cname); 148 printf("\t\t\t\t(unsigned char *)TA%ld_EC_Q," 149 " sizeof TA%ld_EC_Q,\n", ctr, ctr); 150 printf("\t\t\t} }\n"); 151 } 152 printf("\t\t}\n"); 153 printf("\t}"); 154 } 155 156 static void 157 usage_ta(void) 158 { 159 fprintf(stderr, 160 "usage: brssl ta [ options ] file...\n"); 161 fprintf(stderr, 162 "options:\n"); 163 fprintf(stderr, 164 " -q suppress verbose messages\n"); 165 } 166 167 /* see brssl.h */ 168 int 169 do_ta(int argc, char *argv[]) 170 { 171 int retcode; 172 int verbose; 173 int i, num_files; 174 anchor_list tas = VEC_INIT; 175 size_t u, num; 176 177 retcode = 0; 178 verbose = 1; 179 num_files = 0; 180 for (i = 0; i < argc; i ++) { 181 const char *arg; 182 183 arg = argv[i]; 184 if (arg[0] != '-') { 185 num_files ++; 186 continue; 187 } 188 argv[i] = NULL; 189 if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) { 190 verbose = 1; 191 } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) { 192 verbose = 0; 193 } else { 194 fprintf(stderr, "ERROR: unknown option: '%s'\n", arg); 195 usage_ta(); 196 goto ta_exit_error; 197 } 198 } 199 if (num_files == 0) { 200 fprintf(stderr, "ERROR: no certificate file provided\n"); 201 usage_ta(); 202 goto ta_exit_error; 203 } 204 205 for (i = 0; i < argc; i ++) { 206 const char *fname; 207 size_t len1, len2; 208 209 fname = argv[i]; 210 if (fname == NULL) { 211 continue; 212 } 213 if (verbose) { 214 fprintf(stderr, "Reading file '%s': ", fname); 215 fflush(stderr); 216 } 217 len1 = VEC_LEN(tas); 218 if (read_trust_anchors(&tas, fname) == 0) { 219 goto ta_exit_error; 220 } 221 len2 = VEC_LEN(tas) - len1; 222 if (verbose) { 223 fprintf(stderr, "%lu trust anchor%s\n", 224 (unsigned long)len2, len2 > 1 ? "s" : ""); 225 } 226 } 227 num = VEC_LEN(tas); 228 for (u = 0; u < num; u ++) { 229 if (print_ta_internals(&VEC_ELT(tas, u), u) < 0) { 230 goto ta_exit_error; 231 } 232 } 233 printf("\nstatic const br_x509_trust_anchor TAs[%ld] = {", (long)num); 234 for (u = 0; u < num; u ++) { 235 if (u != 0) { 236 printf(","); 237 } 238 printf("\n"); 239 print_ta(&VEC_ELT(tas, u), u); 240 } 241 printf("\n};\n"); 242 printf("\n#define TAs_NUM %ld\n", (long)num); 243 244 /* 245 * Release allocated structures. 246 */ 247 ta_exit: 248 VEC_CLEAREXT(tas, free_ta_contents); 249 return retcode; 250 251 ta_exit_error: 252 retcode = -1; 253 goto ta_exit; 254 } 255