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