xref: /freebsd/usr.sbin/pkg/ecc.c (revision 3d0a0dda3a7d57bbd4eaf65ba8da0f2a36089c0e)
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