1 /*- 2 * Copyright (c) 2018, Juniper Networks, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include "../libsecureboot-priv.h" 30 31 #include "decode.h" 32 #include "packet.h" 33 34 /** 35 * @brief decode user-id packet 36 * 37 * This is trivial 38 * 39 * @sa rfc4880:5.11 40 */ 41 ssize_t 42 decode_user(int tag, unsigned char **pptr, size_t len, OpenPGP_user *user) 43 { 44 char *cp; 45 46 if (tag == 13) { 47 user->id = malloc(len + 1); 48 strncpy(user->id, (char *)*pptr, len); 49 user->id[len] = '\0'; 50 user->name = user->id; 51 cp = strchr(user->id, '<'); 52 if (cp > user->id) { 53 user->id = strdup(user->id); 54 cp[-1] = '\0'; 55 } 56 } 57 *pptr += len; 58 return ((ssize_t)len); 59 } 60 61 /** 62 * @brief decode a key packet 63 * 64 * We only really support v4 and RSA 65 * 66 * @sa rfc4880:5.5.1.1 67 */ 68 ssize_t 69 decode_key(int tag, unsigned char **pptr, size_t len, OpenPGP_key *key) 70 { 71 unsigned char *ptr; 72 int version; 73 #ifdef USE_BEARSSL 74 br_sha1_context mctx; 75 unsigned char mdata[br_sha512_SIZE]; 76 size_t mlen; 77 #else 78 RSA *rsa = NULL; 79 const EVP_MD *md = NULL; 80 EVP_MD_CTX mctx; 81 unsigned char mdata[EVP_MAX_MD_SIZE]; 82 unsigned int mlen; 83 #endif 84 85 if (tag != 6) 86 return (-1); 87 88 key->key = NULL; 89 ptr = *pptr; 90 version = *ptr; 91 if (version == 4) { /* all we support really */ 92 /* comput key fingerprint and id @sa rfc4880:12.2 */ 93 mdata[0] = 0x99; /* rfc4880: 12.2.a.1 */ 94 mdata[1] = (len >> 8) & 0xff; 95 mdata[2] = len & 0xff; 96 97 #ifdef USE_BEARSSL 98 br_sha1_init(&mctx); 99 br_sha1_update(&mctx, mdata, 3); 100 br_sha1_update(&mctx, ptr, len); 101 br_sha1_out(&mctx, mdata); 102 mlen = br_sha1_SIZE; 103 #else 104 md = EVP_get_digestbyname("sha1"); 105 EVP_DigestInit(&mctx, md); 106 EVP_DigestUpdate(&mctx, mdata, 3); 107 EVP_DigestUpdate(&mctx, ptr, len); 108 mlen = (unsigned int)sizeof(mdata); 109 EVP_DigestFinal(&mctx, mdata, &mlen); 110 #endif 111 key->id = octets2hex(&mdata[mlen - 8], 8); 112 } 113 ptr += 1; /* done with version */ 114 ptr += 4; /* skip ctime */ 115 if (version == 3) 116 ptr += 2; /* valid days */ 117 key->sig_alg = *ptr++; 118 if (key->sig_alg == 1) { /* RSA */ 119 #ifdef USE_BEARSSL 120 key->key = NEW(br_rsa_public_key); 121 if (!key->key) 122 goto oops; 123 key->key->n = mpi2bn(&ptr, &key->key->nlen); 124 key->key->e = mpi2bn(&ptr, &key->key->elen); 125 #else 126 rsa = RSA_new(); 127 if (!rsa) 128 goto oops; 129 rsa->n = mpi2bn(&ptr); 130 rsa->e = mpi2bn(&ptr); 131 key->key = EVP_PKEY_new(); 132 if (!key->key || !rsa->n || !rsa->e) { 133 goto oops; 134 } 135 if (!EVP_PKEY_set1_RSA(key->key, rsa)) 136 goto oops; 137 #endif 138 } 139 /* we are done */ 140 return ((ssize_t)len); 141 oops: 142 #ifdef USE_BEARSSL 143 free(key->key); 144 key->key = NULL; 145 #else 146 if (rsa) 147 RSA_free(rsa); 148 if (key->key) { 149 EVP_PKEY_free(key->key); 150 key->key = NULL; 151 } 152 #endif 153 return (-1); 154 } 155 156 static OpenPGP_key * 157 load_key_buf(unsigned char *buf, size_t nbytes) 158 { 159 unsigned char *data = NULL; 160 unsigned char *ptr; 161 ssize_t rc; 162 int tag; 163 OpenPGP_key *key; 164 165 if (!buf) 166 return (NULL); 167 168 initialize(); 169 170 if (!(buf[0] & OPENPGP_TAG_ISTAG)) { 171 data = dearmor((char *)buf, nbytes, &nbytes); 172 ptr = data; 173 } else 174 ptr = buf; 175 key = NEW(OpenPGP_key); 176 if (key) { 177 rc = decode_packet(0, &ptr, nbytes, (decoder_t)decode_key, 178 key); 179 if (rc < 0) { 180 free(key); 181 key = NULL; 182 } else if (rc > 8) { 183 int isnew, ltype; 184 185 tag = decode_tag(ptr, &isnew, <ype); 186 if (tag == 13) { 187 key->user = NEW(OpenPGP_user); 188 rc = decode_packet(0, &ptr, (size_t)rc, 189 (decoder_t)decode_user, key->user); 190 } 191 } 192 } 193 free(data); 194 return (key); 195 } 196 197 static LIST_HEAD(, OpenPGP_key_) trust_list; 198 199 /** 200 * @brief add a key to our list 201 */ 202 void 203 openpgp_trust_add(OpenPGP_key *key) 204 { 205 static int once = 0; 206 207 if (!once) { 208 once = 1; 209 210 LIST_INIT(&trust_list); 211 } 212 if (key) 213 LIST_INSERT_HEAD(&trust_list, key, entries); 214 } 215 216 /** 217 * @brief if keyID is in our list return the key 218 * 219 * @return key or NULL 220 */ 221 OpenPGP_key * 222 openpgp_trust_get(const char *keyID) 223 { 224 OpenPGP_key *key; 225 226 openpgp_trust_add(NULL); /* initialize if needed */ 227 228 LIST_FOREACH(key, &trust_list, entries) { 229 if (strcmp(key->id, keyID) == 0) 230 return (key); 231 } 232 return (NULL); 233 } 234 235 /** 236 * @brief load a key from file 237 */ 238 OpenPGP_key * 239 load_key_file(const char *kfile) 240 { 241 unsigned char *data = NULL; 242 size_t n; 243 OpenPGP_key *key; 244 245 data = read_file(kfile, &n); 246 key = load_key_buf(data, n); 247 free(data); 248 openpgp_trust_add(key); 249 return (key); 250 } 251 252 #include <ta_asc.h> 253 254 #ifndef _STANDALONE 255 /* we can lookup keyID in filesystem */ 256 257 static const char *trust_store[] = { 258 "/var/db/trust", 259 "/etc/db/trust", 260 NULL, 261 }; 262 263 /** 264 * @brief lookup key id in trust store 265 * 266 */ 267 static OpenPGP_key * 268 load_trusted_key_id(const char *keyID) 269 { 270 char kfile[MAXPATHLEN]; 271 const char **tp; 272 size_t n; 273 274 for (tp = trust_store; *tp; tp++) { 275 n = (size_t)snprintf(kfile, sizeof(kfile), "%s/%s", *tp, keyID); 276 if (n >= sizeof(kfile)) 277 return (NULL); 278 if (access(kfile, R_OK) == 0) { 279 return (load_key_file(kfile)); 280 } 281 } 282 return (NULL); 283 } 284 #endif 285 286 /** 287 * @brief return key if trusted 288 */ 289 OpenPGP_key * 290 load_key_id(const char *keyID) 291 { 292 static int once = 0; 293 OpenPGP_key *key; 294 295 if (!once) { 296 #ifdef HAVE_TA_ASC 297 const char **tp; 298 char *cp; 299 size_t n; 300 301 for (tp = ta_ASC; *tp; tp++) { 302 if ((cp = strdup(*tp))) { 303 n = strlen(cp); 304 key = load_key_buf((unsigned char *)cp, n); 305 free(cp); 306 openpgp_trust_add(key); 307 } 308 } 309 #endif 310 once = 1; 311 } 312 key = openpgp_trust_get(keyID); 313 #ifndef _STANDALONE 314 if (!key) 315 key = load_trusted_key_id(keyID); 316 #endif 317 return (key); 318 } 319 320 /** 321 * @brief test that we can verify a signature 322 * 323 * Unlike X.509 certificates, we only support RSA keys 324 * so we stop after first successful signature verification 325 * (which should also be the first attempt ;-) 326 */ 327 int 328 openpgp_self_tests(void) 329 { 330 static int rc = -1; /* remember result */ 331 #ifdef HAVE_VC_ASC 332 const char **vp, **tp; 333 char *fdata, *sdata = NULL; 334 size_t fbytes, sbytes; 335 336 for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) { 337 if ((fdata = strdup(*tp)) && 338 (sdata = strdup(*vp))) { 339 fbytes = strlen(fdata); 340 sbytes = strlen(sdata); 341 rc = openpgp_verify("ta_ASC", 342 (unsigned char *)fdata, fbytes, 343 (unsigned char *)sdata, sbytes, 0); 344 printf("Testing verify OpenPGP signature:\t\t%s\n", 345 rc ? "Failed" : "Passed"); 346 } 347 free(fdata); 348 free(sdata); 349 } 350 #endif 351 return (rc); 352 } 353