1 /*-
2 * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
3 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 * All rights reserved.
5 * Copyright (c) 2021 Kyle Evans <kevans@FreeBSD.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/stat.h>
30 #include <sys/param.h>
31
32 #include <assert.h>
33 #include <ctype.h>
34 #include <err.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40
41 #include <libder.h>
42
43 #define WITH_STDLIB
44 #include <libecc/libsig.h>
45 #undef WITH_STDLIB
46
47 #include "pkg.h"
48 #include "hash.h"
49
50 /* libpkg shim */
51 #define STREQ(l, r) (strcmp(l, r) == 0)
52
53 struct ecc_sign_ctx {
54 struct pkgsign_ctx sctx;
55 ec_params params;
56 ec_key_pair keypair;
57 ec_alg_type sig_alg;
58 hash_alg_type sig_hash;
59 bool loaded;
60 };
61
62 /* Grab the ossl context from a pkgsign_ctx. */
63 #define ECC_CCTX(c) (__containerof(c, const struct ecc_sign_ctx, sctx))
64 #define ECC_CTX(c) (__containerof(c, struct ecc_sign_ctx, sctx))
65
66 #define PUBKEY_UNCOMPRESSED 0x04
67
68 #ifndef MAX
69 #define MAX(a,b) (((a)>(b))?(a):(b))
70 #endif
71
72 static const uint8_t oid_ecpubkey[] = \
73 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
74
75 static const uint8_t oid_secp[] = \
76 { 0x2b, 0x81, 0x04, 0x00 };
77 static const uint8_t oid_secp256k1[] = \
78 { 0x2b, 0x81, 0x04, 0x00, 0x0a };
79 static const uint8_t oid_brainpoolP[] = \
80 { 0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01 };
81
82 #define ENTRY(name, params) { #name, sizeof(#name) - 1, params }
83 static const struct pkgkey_map_entry {
84 const char *name;
85 size_t namesz;
86 const ec_str_params *params;
87 } pkgkey_map[] = {
88 ENTRY(WEI25519, &wei25519_str_params),
89 ENTRY(SECP256K1, &secp256k1_str_params),
90 ENTRY(SECP384R1, &secp384r1_str_params),
91 ENTRY(SECP512R1, &secp521r1_str_params),
92 ENTRY(BRAINPOOLP256R1, &brainpoolp256r1_str_params),
93 ENTRY(BRAINPOOLP256T1, &brainpoolp256t1_str_params),
94 ENTRY(BRAINPOOLP320R1, &brainpoolp320r1_str_params),
95 ENTRY(BRAINPOOLP320T1, &brainpoolp320t1_str_params),
96 ENTRY(BRAINPOOLP384R1, &brainpoolp384r1_str_params),
97 ENTRY(BRAINPOOLP384T1, &brainpoolp384t1_str_params),
98 ENTRY(BRAINPOOLP512R1, &brainpoolp512r1_str_params),
99 ENTRY(BRAINPOOLP512T1, &brainpoolp512t1_str_params),
100 };
101
102 static const char pkgkey_app[] = "pkg";
103 static const char pkgkey_signer[] = "ecc";
104
105 static const ec_str_params *
ecc_pkgkey_params(const uint8_t * curve,size_t curvesz)106 ecc_pkgkey_params(const uint8_t *curve, size_t curvesz)
107 {
108 const struct pkgkey_map_entry *entry;
109
110 for (size_t i = 0; i < nitems(pkgkey_map); i++) {
111 entry = &pkgkey_map[i];
112 if (curvesz != entry->namesz)
113 continue;
114 if (memcmp(curve, entry->name, curvesz) == 0)
115 return (entry->params);
116 }
117
118 return (NULL);
119 }
120
121 static int
ecc_read_pkgkey(struct libder_object * root,ec_params * params,int public,uint8_t * rawkey,size_t * rawlen)122 ecc_read_pkgkey(struct libder_object *root, ec_params *params, int public,
123 uint8_t *rawkey, size_t *rawlen)
124 {
125 struct libder_object *obj;
126 const uint8_t *data;
127 const ec_str_params *sparams;
128 size_t datasz;
129 int ret;
130
131 if (libder_obj_type_simple(root) != BT_SEQUENCE)
132 return (1);
133
134 /* Application */
135 obj = libder_obj_child(root, 0);
136 if (obj == NULL || libder_obj_type_simple(obj) != BT_UTF8STRING)
137 return (1);
138 data = libder_obj_data(obj, &datasz);
139 if (datasz != sizeof(pkgkey_app) - 1 ||
140 memcmp(data, pkgkey_app, datasz) != 0)
141 return (1);
142
143 /* Version */
144 obj = libder_obj_child(root, 1);
145 if (obj == NULL || libder_obj_type_simple(obj) != BT_INTEGER)
146 return (1);
147 data = libder_obj_data(obj, &datasz);
148 if (datasz != 1 || *data != 1 /* XXX */)
149 return (1);
150
151 /* Signer */
152 obj = libder_obj_child(root, 2);
153 if (obj == NULL || libder_obj_type_simple(obj) != BT_UTF8STRING)
154 return (1);
155 data = libder_obj_data(obj, &datasz);
156 if (datasz != sizeof(pkgkey_signer) - 1 ||
157 memcmp(data, pkgkey_signer, datasz) != 0)
158 return (1);
159
160 /* KeyType (curve) */
161 obj = libder_obj_child(root, 3);
162 if (obj == NULL || libder_obj_type_simple(obj) != BT_UTF8STRING)
163 return (1);
164 data = libder_obj_data(obj, &datasz);
165 sparams = ecc_pkgkey_params(data, datasz);
166 if (sparams == NULL)
167 return (1);
168
169 ret = import_params(params, sparams);
170 if (ret != 0)
171 return (1);
172
173 /* Public? */
174 obj = libder_obj_child(root, 4);
175 if (obj == NULL || libder_obj_type_simple(obj) != BT_BOOLEAN)
176 return (1);
177 data = libder_obj_data(obj, &datasz);
178 if (datasz != 1 || !data[0] != !public)
179 return (1);
180
181 /* Key */
182 obj = libder_obj_child(root, 5);
183 if (obj == NULL || libder_obj_type_simple(obj) != BT_BITSTRING)
184 return (1);
185 data = libder_obj_data(obj, &datasz);
186 if (datasz <= 2 || data[0] != 0 || data[1] != PUBKEY_UNCOMPRESSED)
187 return (1);
188
189 data += 2;
190 datasz -= 2;
191
192 if (datasz > *rawlen)
193 return (1);
194
195
196 memcpy(rawkey, data, datasz);
197 *rawlen = datasz;
198
199 return (0);
200 }
201
202 static int
ecc_extract_signature(const uint8_t * sig,size_t siglen,uint8_t * rawsig,size_t rawlen)203 ecc_extract_signature(const uint8_t *sig, size_t siglen, uint8_t *rawsig,
204 size_t rawlen)
205 {
206 struct libder_ctx *ctx;
207 struct libder_object *obj, *root;
208 const uint8_t *sigdata;
209 size_t compsz, datasz, sigoff;
210 int rc;
211
212 ctx = libder_open();
213 if (ctx == NULL)
214 return (1);
215
216 rc = 1;
217 root = libder_read(ctx, sig, &siglen);
218 if (root == NULL || libder_obj_type_simple(root) != BT_SEQUENCE)
219 goto out;
220
221 /* Descend into the sequence's payload, extract both numbers. */
222 compsz = rawlen / 2;
223 sigoff = 0;
224 for (int i = 0; i < 2; i++) {
225 obj = libder_obj_child(root, i);
226 if (libder_obj_type_simple(obj) != BT_INTEGER)
227 goto out;
228
229 sigdata = libder_obj_data(obj, &datasz);
230 if (datasz < 2 || datasz > compsz + 1)
231 goto out;
232
233 /*
234 * We may see an extra lead byte if our high bit of the first
235 * byte was set, since these numbers are positive by definition.
236 */
237 if (sigdata[0] == 0 && (sigdata[1] & 0x80) != 0) {
238 sigdata++;
239 datasz--;
240 }
241
242 /* Sanity check: don't overflow the output. */
243 if (sigoff + datasz > rawlen)
244 goto out;
245
246 /* Padding to the significant end if we're too small. */
247 if (datasz < compsz) {
248 memset(&rawsig[sigoff], 0, compsz - datasz);
249 sigoff += compsz - datasz;
250 }
251
252 memcpy(&rawsig[sigoff], sigdata, datasz);
253 sigoff += datasz;
254 }
255
256 /* Sanity check: must have exactly the required # of signature bits. */
257 rc = (sigoff == rawlen) ? 0 : 1;
258
259 out:
260 libder_obj_free(root);
261 libder_close(ctx);
262 return (rc);
263 }
264
265 static int
ecc_extract_pubkey_string(const uint8_t * data,size_t datalen,uint8_t * rawkey,size_t * rawlen)266 ecc_extract_pubkey_string(const uint8_t *data, size_t datalen, uint8_t *rawkey,
267 size_t *rawlen)
268 {
269 uint8_t prefix, usebit;
270
271 if (datalen <= 2)
272 return (1);
273
274 usebit = *data++;
275 datalen--;
276
277 if (usebit != 0)
278 return (1);
279
280 prefix = *data++;
281 datalen--;
282
283 if (prefix != PUBKEY_UNCOMPRESSED)
284 return (1);
285
286 if (datalen > *rawlen)
287 return (1);
288
289 memcpy(rawkey, data, datalen);
290 *rawlen = datalen;
291
292 return (0);
293 }
294
295 static int
ecc_extract_key_params(const uint8_t * oid,size_t oidlen,ec_params * rawparams)296 ecc_extract_key_params(const uint8_t *oid, size_t oidlen,
297 ec_params *rawparams)
298 {
299 int ret;
300
301 if (oidlen >= sizeof(oid_secp) &&
302 memcmp(oid, oid_secp, sizeof(oid_secp)) >= 0) {
303 oid += sizeof(oid_secp);
304 oidlen -= sizeof(oid_secp);
305
306 if (oidlen != 1)
307 return (1);
308
309 ret = -1;
310 switch (*oid) {
311 case 0x0a: /* secp256k1 */
312 ret = import_params(rawparams, &secp256k1_str_params);
313 break;
314 case 0x22: /* secp384r1 */
315 ret = import_params(rawparams, &secp384r1_str_params);
316 break;
317 case 0x23: /* secp521r1 */
318 ret = import_params(rawparams, &secp521r1_str_params);
319 break;
320 default:
321 return (1);
322 }
323
324 if (ret == 0)
325 return (0);
326 return (1);
327 }
328
329 if (oidlen >= sizeof(oid_brainpoolP) &&
330 memcmp(oid, oid_brainpoolP, sizeof(oid_brainpoolP)) >= 0) {
331 oid += sizeof(oid_brainpoolP);
332 oidlen -= sizeof(oid_brainpoolP);
333
334 if (oidlen != 1)
335 return (1);
336
337 ret = -1;
338 switch (*oid) {
339 case 0x07: /* brainpoolP256r1 */
340 ret = import_params(rawparams, &brainpoolp256r1_str_params);
341 break;
342 case 0x08: /* brainpoolP256t1 */
343 ret = import_params(rawparams, &brainpoolp256t1_str_params);
344 break;
345 case 0x09: /* brainpoolP320r1 */
346 ret = import_params(rawparams, &brainpoolp320r1_str_params);
347 break;
348 case 0x0a: /* brainpoolP320t1 */
349 ret = import_params(rawparams, &brainpoolp320t1_str_params);
350 break;
351 case 0x0b: /* brainpoolP384r1 */
352 ret = import_params(rawparams, &brainpoolp384r1_str_params);
353 break;
354 case 0x0c: /* brainpoolP384t1 */
355 ret = import_params(rawparams, &brainpoolp384t1_str_params);
356 break;
357 case 0x0d: /* brainpoolP512r1 */
358 ret = import_params(rawparams, &brainpoolp512r1_str_params);
359 break;
360 case 0x0e: /* brainpoolP512t1 */
361 ret = import_params(rawparams, &brainpoolp512t1_str_params);
362 break;
363 default:
364 return (1);
365 }
366
367 if (ret == 0)
368 return (0);
369 return (1);
370 }
371
372 #ifdef ECC_DEBUG
373 for (size_t i = 0; i < oidlen; i++) {
374 fprintf(stderr, "%.02x ", oid[i]);
375 }
376
377 fprintf(stderr, "\n");
378 #endif
379
380 return (1);
381 }
382
383 /*
384 * On entry, *rawparams should point to an ec_params that we can import the
385 * key parameters to. We'll either do that, or we'll set it to NULL if we could
386 * not deduce the curve.
387 */
388 static int
ecc_extract_pubkey(FILE * keyfp,const uint8_t * key,size_t keylen,uint8_t * rawkey,size_t * rawlen,ec_params * rawparams)389 ecc_extract_pubkey(FILE *keyfp, const uint8_t *key, size_t keylen,
390 uint8_t *rawkey, size_t *rawlen, ec_params *rawparams)
391 {
392 const uint8_t *oidp;
393 struct libder_ctx *ctx;
394 struct libder_object *keydata, *oid, *params, *root;
395 size_t oidsz;
396 int rc;
397
398 ctx = libder_open();
399 if (ctx == NULL)
400 return (1);
401
402 rc = 1;
403 assert((keyfp != NULL) ^ (key != NULL));
404 if (keyfp != NULL) {
405 root = libder_read_file(ctx, keyfp, &keylen);
406 } else {
407 root = libder_read(ctx, key, &keylen);
408 }
409
410 if (root == NULL || libder_obj_type_simple(root) != BT_SEQUENCE)
411 goto out;
412
413 params = libder_obj_child(root, 0);
414
415 if (params == NULL) {
416 goto out;
417 } else if (libder_obj_type_simple(params) != BT_SEQUENCE) {
418 rc = ecc_read_pkgkey(root, rawparams, 1, rawkey, rawlen);
419 goto out;
420 }
421
422 /* Is a sequence */
423 keydata = libder_obj_child(root, 1);
424 if (keydata == NULL || libder_obj_type_simple(keydata) != BT_BITSTRING)
425 goto out;
426
427 /* Key type */
428 oid = libder_obj_child(params, 0);
429 if (oid == NULL || libder_obj_type_simple(oid) != BT_OID)
430 goto out;
431
432 oidp = libder_obj_data(oid, &oidsz);
433 if (oidsz != sizeof(oid_ecpubkey) ||
434 memcmp(oidp, oid_ecpubkey, oidsz) != 0)
435 return (1);
436
437 /* Curve */
438 oid = libder_obj_child(params, 1);
439 if (oid == NULL || libder_obj_type_simple(oid) != BT_OID)
440 goto out;
441
442 oidp = libder_obj_data(oid, &oidsz);
443 if (ecc_extract_key_params(oidp, oidsz, rawparams) != 0)
444 goto out;
445
446 /* Finally, peel off the key material */
447 key = libder_obj_data(keydata, &keylen);
448 if (ecc_extract_pubkey_string(key, keylen, rawkey, rawlen) != 0)
449 goto out;
450
451 rc = 0;
452 out:
453 libder_obj_free(root);
454 libder_close(ctx);
455 return (rc);
456 }
457
458 struct ecc_verify_cbdata {
459 const struct pkgsign_ctx *sctx;
460 FILE *keyfp;
461 const unsigned char *key;
462 size_t keylen;
463 unsigned char *sig;
464 size_t siglen;
465 };
466
467 static int
ecc_verify_internal(struct ecc_verify_cbdata * cbdata,const uint8_t * hash,size_t hashsz)468 ecc_verify_internal(struct ecc_verify_cbdata *cbdata, const uint8_t *hash,
469 size_t hashsz)
470 {
471 ec_pub_key pubkey;
472 ec_params derparams;
473 const struct ecc_sign_ctx *keyinfo = ECC_CCTX(cbdata->sctx);
474 uint8_t keybuf[EC_PUB_KEY_MAX_SIZE];
475 uint8_t rawsig[EC_MAX_SIGLEN];
476 size_t keysz;
477 int ret;
478 uint8_t ecsiglen;
479
480 keysz = MIN(sizeof(keybuf), cbdata->keylen / 2);
481
482 keysz = sizeof(keybuf);
483 if (ecc_extract_pubkey(cbdata->keyfp, cbdata->key, cbdata->keylen,
484 keybuf, &keysz, &derparams) != 0) {
485 warnx("failed to parse key");
486 return (1);
487 }
488
489 ret = ec_get_sig_len(&derparams, keyinfo->sig_alg, keyinfo->sig_hash,
490 &ecsiglen);
491 if (ret != 0)
492 return (1);
493
494 /*
495 * Signatures are DER-encoded, whether by OpenSSL or pkg.
496 */
497 if (ecc_extract_signature(cbdata->sig, cbdata->siglen,
498 rawsig, ecsiglen) != 0) {
499 warnx("failed to decode signature");
500 return (1);
501 }
502
503 ret = ec_pub_key_import_from_aff_buf(&pubkey, &derparams,
504 keybuf, keysz, keyinfo->sig_alg);
505 if (ret != 0) {
506 warnx("failed to import key");
507 return (1);
508 }
509
510 ret = ec_verify(rawsig, ecsiglen, &pubkey, hash, hashsz, keyinfo->sig_alg,
511 keyinfo->sig_hash, NULL, 0);
512 if (ret != 0) {
513 warnx("failed to verify signature");
514 return (1);
515 }
516
517 return (0);
518 }
519
520 static bool
ecc_verify_data(const struct pkgsign_ctx * sctx,const char * data,size_t datasz,const char * sigfile,const unsigned char * key,int keylen,unsigned char * sig,int siglen)521 ecc_verify_data(const struct pkgsign_ctx *sctx,
522 const char *data, size_t datasz, const char *sigfile,
523 const unsigned char *key, int keylen,
524 unsigned char *sig, int siglen)
525 {
526 int ret;
527 struct ecc_verify_cbdata cbdata;
528
529 ret = 1;
530
531 if (sigfile != NULL) {
532 cbdata.keyfp = fopen(sigfile, "r");
533 if (cbdata.keyfp == NULL) {
534 warn("fopen: %s", sigfile);
535 return (false);
536 }
537 } else {
538 cbdata.keyfp = NULL;
539 cbdata.key = key;
540 cbdata.keylen = keylen;
541 }
542
543 cbdata.sctx = sctx;
544 cbdata.sig = sig;
545 cbdata.siglen = siglen;
546
547 ret = ecc_verify_internal(&cbdata, data, datasz);
548
549 if (cbdata.keyfp != NULL)
550 fclose(cbdata.keyfp);
551
552 return (ret == 0);
553 }
554
555 static bool
ecc_verify_cert(const struct pkgsign_ctx * sctx,int fd,const char * sigfile,const unsigned char * key,int keylen,unsigned char * sig,int siglen)556 ecc_verify_cert(const struct pkgsign_ctx *sctx, int fd,
557 const char *sigfile, const unsigned char *key, int keylen,
558 unsigned char *sig, int siglen)
559 {
560 bool ret;
561 char *sha256;
562
563 ret = false;
564 if (lseek(fd, 0, SEEK_SET) == -1) {
565 warn("lseek");
566 return (false);
567 }
568
569 if ((sha256 = sha256_fd(fd)) != NULL) {
570 ret = ecc_verify_data(sctx, sha256, strlen(sha256), sigfile, key,
571 keylen, sig, siglen);
572 free(sha256);
573 }
574
575 return (ret);
576 }
577
578 static int
ecc_new(const char * name __unused,struct pkgsign_ctx * sctx)579 ecc_new(const char *name __unused, struct pkgsign_ctx *sctx)
580 {
581 struct ecc_sign_ctx *keyinfo = ECC_CTX(sctx);
582 int ret;
583
584 ret = 1;
585 if (STREQ(name, "ecc") || STREQ(name, "eddsa")) {
586 keyinfo->sig_alg = EDDSA25519;
587 keyinfo->sig_hash = SHA512;
588 ret = import_params(&keyinfo->params, &wei25519_str_params);
589 } else if (STREQ(name, "ecdsa")) {
590 keyinfo->sig_alg = ECDSA;
591 keyinfo->sig_hash = SHA256;
592 ret = import_params(&keyinfo->params, &secp256k1_str_params);
593 }
594
595 if (ret != 0)
596 return (1);
597
598 return (0);
599 }
600
601 const struct pkgsign_ops pkgsign_ecc = {
602 .pkgsign_ctx_size = sizeof(struct ecc_sign_ctx),
603 .pkgsign_new = ecc_new,
604 .pkgsign_verify_cert = ecc_verify_cert,
605 .pkgsign_verify_data = ecc_verify_data,
606 };
607