]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libsecureboot/openpgp/opgp_sig.c
Merge r345574 from vendor-crypto:
[FreeBSD/FreeBSD.git] / lib / libsecureboot / openpgp / opgp_sig.c
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  * RCSid:
27  *      from: signer.c,v 1.10 2018/03/23 01:14:30 sjg
28  *
29  *      @(#) Copyright (c) 2012 Simon J. Gerraty
30  *
31  *      This file is provided in the hope that it will
32  *      be of use.  There is absolutely NO WARRANTY.
33  *      Permission to copy, redistribute or otherwise
34  *      use this file is hereby granted provided that
35  *      the above copyright notice and this notice are
36  *      left intact.
37  *
38  *      Please send copies of changes and bug-fixes to:
39  *      sjg@crufty.net
40  */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 #include "../libsecureboot-priv.h"
46 #ifdef _STANDALONE
47 #define warnx printf
48 #else
49
50 #include <sys/param.h>
51 #include <sys/stat.h>
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <fcntl.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <err.h>
58 #endif
59
60 #include "decode.h"
61 #include "packet.h"
62
63 #ifdef USE_BEARSSL
64
65 #define get_error_string ve_error_get
66
67 void
68 initialize (void)
69 {
70 #ifdef _STANDALONE
71     ve_trust_init();
72 #endif
73 }
74
75 #else
76
77 #include <openssl/err.h>
78
79 /**
80  * @brief intialize OpenSSL
81  */
82 void
83 initialize(void)
84 {
85         static int once;
86
87         if (once)
88                 return);
89         once = 1;
90         //CRYPTO_malloc_init();
91         ERR_load_crypto_strings();
92         OpenSSL_add_all_algorithms();
93 }
94
95 /**
96  * @brief
97  * last error from OpenSSL as a string
98  */
99 char *
100 get_error_string(void)
101 {
102         initialize();
103         return (ERR_error_string(ERR_get_error(), NULL));
104 }
105 #endif
106
107 /**
108  * @brief decode a signature packet
109  *
110  * We only support RSA
111  *
112  * @sa rfc4880:5.2
113  */
114 ssize_t
115 decode_sig(int tag, unsigned char **pptr, size_t len, OpenPGP_sig *sig)
116 {
117         unsigned char *ptr;
118         unsigned char *pgpbytes;
119         unsigned char *sp;
120         int version;
121         int hcount = 0;
122         int ucount = 0;
123         int stag = 0;
124         int n;
125
126         n = tag;                        /* avoid unused */
127
128         /*
129          * We need to keep a reference to the packet bytes
130          * as these form part of the signature data.
131          *
132          * @sa rfc4880:5.2.4
133          */
134         pgpbytes = ptr = *pptr;
135         version = *ptr++;
136         if (version == 3) {
137                 ptr++;
138                 sig->pgpbytes = malloc(5);
139                 if (!sig->pgpbytes)
140                         return (-1);
141                 memcpy(sig->pgpbytes, ptr, 5);
142                 sig->pgpbytes_len = 5;
143                 sig->sig_type = *ptr++;
144                 ptr += 4;
145                 sig->key_id = octets2hex(ptr, 8);
146                 ptr += 8;
147                 sig->sig_alg = *ptr++;
148                 sig->hash_alg = *ptr++;
149         } else if (version == 4) {
150                 sig->sig_type = *ptr++;
151                 sig->sig_alg = *ptr++;
152                 sig->hash_alg = *ptr++;
153                 hcount = octets2i(ptr, 2);
154                 ptr += 2;
155                 sig->pgpbytes_len = (size_t)hcount + 6;
156                 sig->pgpbytes = malloc(sig->pgpbytes_len + 6);
157                 if (!sig->pgpbytes)
158                         return (-1);
159                 memcpy(sig->pgpbytes, pgpbytes, sig->pgpbytes_len);
160                 sp = &sig->pgpbytes[sig->pgpbytes_len];
161                 *sp++ = 4;
162                 *sp++ = 255;
163                 memcpy(sp, i2octets(4, (int)sig->pgpbytes_len), 4);
164                 sig->pgpbytes_len += 6;
165
166                 while (hcount > 0) {
167                         sp = decode_subpacket(&ptr, &stag, &n);
168                         hcount -= n;
169                         /* can check stag to see if we care */
170                 }
171                 ucount = octets2i(ptr, 2);
172                 ptr += 2;
173                 while (ucount > 0) {
174                         sp = decode_subpacket(&ptr, &stag, &n);
175                         ucount -= n;
176                         /* can check stag to see if we care */
177                         if (stag == 16) {
178                                 free(sig->key_id);
179                                 sig->key_id = octets2hex(sp, 8);
180                         }
181                 }
182         } else
183                 return (-1);
184         ptr += 2;                       /* skip hash16 */
185         if (sig->sig_alg == 1) {        /* RSA */
186                 sig->sig = decode_mpi(&ptr, &sig->sig_len);
187         }
188         /* we are done */
189         return ((ssize_t)len);
190 }
191
192 /**
193  * @brief map OpenPGP hash algorithm id's to name
194  *
195  * @sa rfc4880:9.4
196  */
197 static struct hash_alg_map {
198         int halg;
199         const char *hname;
200 } hash_algs[] = {
201         {1, "md5"},
202         {2, "sha1"},
203         {8, "sha256"},
204         {9, "sha384"},
205         {10, "sha512"},
206         {11, "sha224"},
207         {0, NULL},
208 };
209
210 static const char *
211 get_hname(int hash_alg)
212 {
213         struct hash_alg_map *hmp;
214
215         for (hmp = hash_algs; hmp->halg > 0; hmp++) {
216                 if (hmp->halg == hash_alg)
217                         return (hmp->hname);
218         }
219         return (NULL);
220 }
221
222 /* lifted from signer.c */
223 /**
224  * @brief verify a digest
225  *
226  * The public key, digest name, file and signature data.
227  *
228  * @return 1 on success 0 on failure, -1 on error
229  */
230 #ifndef USE_BEARSSL
231 static int
232 verify_digest (EVP_PKEY *pkey,
233     const char *digest,
234     unsigned char *mdata, size_t mlen,
235     unsigned char *sdata, size_t slen)
236 {
237         EVP_MD_CTX ctx;
238         const EVP_MD *md = NULL;
239         EVP_PKEY_CTX *pctx = NULL;
240         int rc = 0;
241         int i = -1;
242
243         initialize();
244         md = EVP_get_digestbyname(digest);
245         EVP_DigestInit(&ctx, md);
246
247         pctx = EVP_PKEY_CTX_new(pkey, NULL);
248         if (!pctx)
249                 goto fail;
250         if (EVP_PKEY_verify_init(pctx) <= 0)
251                 goto fail;
252         if (EVP_PKEY_CTX_set_signature_md(pctx, ctx.digest) <= 0)
253                 goto fail;
254         i = EVP_PKEY_verify(pctx, sdata, slen, mdata, mlen);
255         if (i >= 0)
256                 rc = i;
257 fail:
258         EVP_PKEY_CTX_free(pctx);
259         return (rc);
260 }
261 #endif
262
263
264 /**
265  * @brief verify OpenPGP signed file
266  *
267  *
268  * @param[in] filename
269  *      used to determine the signature name
270  *
271  * @param[in] fdata
272  *      content of filename
273  *
274  * @param[in] fbytes
275  *      of fdata
276  *
277  * @param[in] sdata
278  *      content of signature
279  *
280  * @param[in] sbytes
281  *      of sdata
282  *
283  * @param[in] flags
284  *
285  * @return 0 on success
286  */
287 int
288 openpgp_verify(const char *filename,
289     unsigned char *fdata, size_t fbytes,
290     unsigned char *sdata, size_t sbytes,
291     int flags)
292 {
293         OpenPGP_key *key;
294         OpenPGP_sig *sig;
295 #ifdef USE_BEARSSL
296         const br_hash_class *md;
297         br_hash_compat_context mctx;
298         const unsigned char *hash_oid;
299 #else
300         const EVP_MD *md = NULL;
301         EVP_MD_CTX mctx;
302 #endif
303         unsigned char mdata[64];
304         unsigned char *ptr;
305         unsigned char *ddata = NULL;
306         const char *hname;
307         size_t mlen;
308         int rc = -1;
309
310         initialize();
311
312         sig = NEW(OpenPGP_sig);
313         if (!sdata || !sig) {
314                 warnx("cannot verify %s", filename);
315                 goto oops;
316         }
317         if (!(sdata[0] & OPENPGP_TAG_ISTAG))
318                 sdata = ddata = dearmor((char *)sdata, sbytes, &sbytes);
319         ptr = sdata;
320         rc = decode_packet(2, &ptr, sbytes, (decoder_t)decode_sig, sig);
321         if (rc == 0 && sig->key_id) {
322                 key = load_key_id(sig->key_id);
323                 if (!key) {
324                         warnx("cannot find key-id: %s", sig->key_id);
325                         rc = -1;
326                 } else if (!(hname = get_hname(sig->hash_alg))) {
327                         warnx("unsupported hash algorithm: %d", sig->hash_alg);
328                         rc = -1;
329                 } else {
330                         /*
331                          * Hash fdata according to the OpenPGP recipe
332                          *
333                          * @sa rfc4880:5.2.4
334                          */
335 #ifdef USE_BEARSSL
336                         switch (sig->hash_alg) { /* see hash_algs above */
337                         case 2:                  /* sha1 */
338                                 md = &br_sha1_vtable;
339                                 mlen = br_sha1_SIZE;
340                                 hash_oid = BR_HASH_OID_SHA1;
341                                 break;
342                         case 8:                 /* sha256 */
343                                 md = &br_sha256_vtable;
344                                 mlen = br_sha256_SIZE;
345                                 hash_oid = BR_HASH_OID_SHA256;
346                                 break;
347                         default:
348                                 warnx("unsupported hash algorithm: %s", hname);
349                                 goto oops;
350                         }
351                         md->init(&mctx.vtable);
352                         md->update(&mctx.vtable, fdata, fbytes);
353                         md->update(&mctx.vtable, sig->pgpbytes,
354                             sig->pgpbytes_len);
355                         md->out(&mctx.vtable, mdata);
356
357                         rc = verify_rsa_digest(key->key, hash_oid,
358                             mdata, mlen, sig->sig, sig->sig_len);
359 #else
360                         md = EVP_get_digestbyname(hname);
361                         EVP_DigestInit(&mctx, md);
362                         EVP_DigestUpdate(&mctx, fdata, fbytes);
363                         EVP_DigestUpdate(&mctx, sig->pgpbytes,
364                             sig->pgpbytes_len);
365                         mlen = sizeof(mdata);
366                         EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
367
368                         rc = verify_digest(key->key, hname, mdata, mlen,
369                             sig->sig, sig->sig_len);
370 #endif
371
372                         if (rc > 0) {
373                                 if ((flags & 1))
374                                         printf("Verified %s signed by %s\n",
375                                             filename,
376                                             key->user ? key->user->name : "someone");
377                                 rc = 0; /* success */
378                         } else if (rc == 0) {
379                                 printf("Unverified %s: %s\n",
380                                     filename, get_error_string());
381                                 rc = 1;
382                         } else {
383                                 printf("Unverified %s\n", filename);
384                         }
385                 }
386         } else {
387                 warnx("cannot decode signature for %s", filename);
388                 rc = -1;
389         }
390 oops:
391         free(ddata);
392         free(sig);
393         return (rc);
394 }
395
396 #ifndef _STANDALONE
397 /**
398  * @brief list of extensions we handle
399  *
400  * ".asc" is preferred as it works seamlessly with openpgp
401  */
402 static const char *sig_exts[] = {
403         ".asc",
404         ".pgp",
405         ".psig",
406         NULL,
407 };
408
409 /**
410  * @brief verify OpenPGP signed file
411  *
412  *
413  * @param[in] filename
414  *      used to determine the signature name
415  *
416  * @param[in] fdata
417  *      content of filename
418  *
419  * @param[in] nbytes
420  *      of fdata
421  *
422  * @return
423  */
424
425 int
426 openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
427 {
428         char pbuf[MAXPATHLEN];
429         unsigned char *sdata;
430         const char *sname = NULL;
431         const char **ep;
432         size_t sz;
433         int n;
434
435         for (ep = sig_exts; *ep; ep++) {
436                 n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
437                 if (n >= (int)sizeof(pbuf)) {
438                         warnx("cannot form signature name for %s", filename);
439                         return (-1);
440                 }
441                 if (access(pbuf, R_OK) == 0) {
442                         sname = pbuf;
443                         break;
444                 }
445         }
446         if (!sname) {
447                 warnx("cannot find signature for %s", filename);
448                 return (-1);
449         }
450         sdata = read_file(sname, &sz);
451         return (openpgp_verify(filename, fdata, nbytes, sdata, sz, 1));
452 }
453 #endif
454
455 /**
456  * @brief verify OpenPGP signature
457  *
458  * @return content of signed file
459  */
460 unsigned char *
461 verify_asc(const char *sigfile, int flags)
462 {
463         char pbuf[MAXPATHLEN];
464         char *cp;
465         size_t n;
466         unsigned char *fdata, *sdata;
467         size_t fbytes, sbytes;
468     
469         if ((sdata = read_file(sigfile, &sbytes))) {
470                 n = strlcpy(pbuf, sigfile, sizeof(pbuf));
471                 if ((cp = strrchr(pbuf, '.')))
472                         *cp = '\0';
473                 if ((fdata = read_file(pbuf, &fbytes))) {
474                         if (openpgp_verify(pbuf, fdata, fbytes, sdata,
475                                 sbytes, flags)) {
476                                 free(fdata);
477                                 fdata = NULL;
478                         }
479                 }
480         } else
481                 fdata = NULL;
482         free(sdata);
483         return (fdata);
484 }