2 * Copyright (c) 2018, Juniper Networks, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include "../libsecureboot-priv.h"
35 * @brief decode user-id packet
42 decode_user(int tag, unsigned char **pptr, size_t len, OpenPGP_user *user)
47 user->id = malloc(len + 1);
48 strncpy(user->id, (char *)*pptr, len);
50 user->name = user->id;
51 cp = strchr(user->id, '<');
53 user->id = strdup(user->id);
58 return ((ssize_t)len);
62 * @brief decode a key packet
64 * We only really support v4 and RSA
69 decode_key(int tag, unsigned char **pptr, size_t len, OpenPGP_key *key)
75 unsigned char mdata[br_sha512_SIZE];
79 const EVP_MD *md = NULL;
81 unsigned char mdata[EVP_MAX_MD_SIZE];
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;
99 br_sha1_update(&mctx, mdata, 3);
100 br_sha1_update(&mctx, ptr, len);
101 br_sha1_out(&mctx, mdata);
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);
111 key->id = octets2hex(&mdata[mlen - 8], 8);
113 ptr += 1; /* done with version */
114 ptr += 4; /* skip ctime */
116 ptr += 2; /* valid days */
117 key->sig_alg = *ptr++;
118 if (key->sig_alg == 1) { /* RSA */
120 key->key = NEW(br_rsa_public_key);
123 key->key->n = mpi2bn(&ptr, &key->key->nlen);
124 key->key->e = mpi2bn(&ptr, &key->key->elen);
129 rsa->n = mpi2bn(&ptr);
130 rsa->e = mpi2bn(&ptr);
131 key->key = EVP_PKEY_new();
132 if (!key->key || !rsa->n || !rsa->e) {
135 if (!EVP_PKEY_set1_RSA(key->key, rsa))
140 return ((ssize_t)len);
149 EVP_PKEY_free(key->key);
157 load_key_buf(unsigned char *buf, size_t nbytes)
159 unsigned char *data = NULL;
170 if (!(buf[0] & OPENPGP_TAG_ISTAG)) {
171 /* Note: we do *not* free data */
172 data = dearmor((char *)buf, nbytes, &nbytes);
176 key = NEW(OpenPGP_key);
178 rc = decode_packet(0, &ptr, nbytes, (decoder_t)decode_key,
186 tag = decode_tag(ptr, &isnew, <ype);
188 key->user = NEW(OpenPGP_user);
189 rc = decode_packet(0, &ptr, (size_t)rc,
190 (decoder_t)decode_user, key->user);
197 static LIST_HEAD(, OpenPGP_key_) trust_list;
200 * @brief add a key to our list
203 openpgp_trust_add(OpenPGP_key *key)
210 LIST_INIT(&trust_list);
212 if (key && openpgp_trust_get(key->id) == NULL) {
213 if (ve_anchor_verbose_get())
214 printf("openpgp_trust_add(%s)\n", key->id);
215 LIST_INSERT_HEAD(&trust_list, key, entries);
220 * @brief add trust anchor from buf
223 openpgp_trust_add_buf(unsigned char *buf, size_t nbytes)
227 if ((key = load_key_buf(buf, nbytes))) {
228 openpgp_trust_add(key);
230 return (key != NULL);
235 * @brief if keyID is in our list clobber it
237 * @return true if keyID removed
240 openpgp_trust_revoke(const char *keyID)
242 OpenPGP_key *key, *tkey;
244 openpgp_trust_add(NULL); /* initialize if needed */
246 LIST_FOREACH(key, &trust_list, entries) {
247 if (strcmp(key->id, keyID) == 0) {
249 LIST_REMOVE(tkey, entries);
250 printf("openpgp_trust_revoke(%s)\n", key->id);
251 memset(key, 0, sizeof(OpenPGP_key));
260 * @brief if keyID is in our list return the key
262 * @return key or NULL
265 openpgp_trust_get(const char *keyID)
269 openpgp_trust_add(NULL); /* initialize if needed */
271 LIST_FOREACH(key, &trust_list, entries) {
272 if (strcmp(key->id, keyID) == 0)
279 * @brief load a key from file
282 load_key_file(const char *kfile)
284 unsigned char *data = NULL;
288 data = read_file(kfile, &n);
289 key = load_key_buf(data, n);
291 openpgp_trust_add(key);
300 /* we can lookup keyID in filesystem */
302 static const char *trust_store[] = {
309 * @brief lookup key id in trust store
313 load_trusted_key_id(const char *keyID)
315 char kfile[MAXPATHLEN];
319 for (tp = trust_store; *tp; tp++) {
320 n = (size_t)snprintf(kfile, sizeof(kfile), "%s/%s", *tp, keyID);
321 if (n >= sizeof(kfile))
323 if (access(kfile, R_OK) == 0) {
324 return (load_key_file(kfile));
332 * @brief return key if trusted
335 load_key_id(const char *keyID)
339 key = openpgp_trust_get(keyID);
342 key = load_trusted_key_id(keyID);
344 DEBUG_PRINTF(2, ("load_key_id(%s): %s\n", keyID, key ? "found" : "nope"));
349 * @brief initialize our internal trust store if any
352 openpgp_trust_init(void)
354 static int once = -1;
365 for (tp = ta_ASC; *tp; tp++) {
366 if ((cp = strdup(*tp))) {
368 key = load_key_buf((unsigned char *)cp, n);
371 openpgp_trust_add(key);
382 * @brief test that we can verify a signature
384 * Unlike X.509 certificates, we only support RSA keys
385 * so we stop after first successful signature verification
386 * (which should also be the first attempt ;-)
389 openpgp_self_tests(void)
391 static int rc = -1; /* remember result */
393 const char **vp, **tp;
394 char *fdata, *sdata = NULL;
395 size_t fbytes, sbytes;
397 if (openpgp_trust_init() > 0) {
398 for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
399 if ((fdata = strdup(*tp)) &&
400 (sdata = strdup(*vp))) {
401 fbytes = strlen(fdata);
402 sbytes = strlen(sdata);
403 rc = openpgp_verify("ta_ASC",
404 (unsigned char *)fdata, fbytes,
405 (unsigned char *)sdata, sbytes, 0);
406 printf("Testing verify OpenPGP signature:\t\t%s\n",
407 rc ? "Failed" : "Passed");