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 * 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 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 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 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 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 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 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 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 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 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