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