1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #define ELF_TARGET_ALL /* get definitions of all section flags */ 30 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 #include <unistd.h> 35 #include <strings.h> 36 #include <stddef.h> 37 #include <stdlib.h> 38 #include <libintl.h> 39 #include <dirent.h> 40 #include <errno.h> 41 #include <libelf.h> 42 #include <gelf.h> 43 #include <sys/mman.h> 44 #include <cryptoutil.h> 45 #include <sha1.h> 46 #include <sys/crypto/elfsign.h> 47 #include <libelfsign.h> 48 49 #ifndef SHA1_DIGEST_LENGTH 50 #define SHA1_DIGEST_LENGTH 20 51 #endif /* SHA1_DIGEST_LENGTH */ 52 53 const char SUNW_ELF_SIGNATURE_ID[] = ELF_SIGNATURE_SECTION; 54 const char OID_sha1WithRSAEncryption[] = "1.2.840.113549.1.1.5"; 55 56 static ELFsign_status_t elfsign_adjustoffsets(ELFsign_t ess, 57 Elf_Scn *scn, uint64_t new_size); 58 static ELFsign_status_t elfsign_verify_esa(ELFsign_t ess, 59 uchar_t *sig, size_t sig_len); 60 static uint32_t elfsign_switch_uint32(uint32_t i); 61 static ELFsign_status_t elfsign_switch(ELFsign_t ess, 62 struct filesignatures *fssp, enum ES_ACTION action); 63 64 struct filesig_extraction { 65 filesig_vers_t fsx_version; 66 char *fsx_format; 67 char fsx_signer_DN[ELFCERT_MAX_DN_LEN]; 68 size_t fsx_signer_DN_len; 69 uchar_t fsx_signature[SIG_MAX_LENGTH]; 70 size_t fsx_sig_len; 71 char fsx_sig_oid[100]; 72 size_t fsx_sig_oid_len; 73 time_t fsx_time; 74 }; 75 76 static char * 77 version_to_str(filesig_vers_t v) 78 { 79 char *ret; 80 81 switch (v) { 82 case FILESIG_VERSION1: 83 ret = "VERSION1"; 84 break; 85 case FILESIG_VERSION2: 86 ret = "VERSION2"; 87 break; 88 case FILESIG_VERSION3: 89 ret = "VERSION3"; 90 break; 91 case FILESIG_VERSION4: 92 ret = "VERSION4"; 93 break; 94 default: 95 ret = "UNKNOWN"; 96 break; 97 } 98 return (ret); 99 } 100 101 /* 102 * Update filesignatures to include the v1/v2 filesig, 103 * composed of signer DN, signature, and OID. 104 */ 105 static struct filesignatures * 106 filesig_insert_dso(struct filesignatures *fssp, 107 filesig_vers_t version, 108 const char *dn, 109 int dn_len, 110 const uchar_t *sig, 111 int sig_len, 112 const char *oid, 113 int oid_len) 114 { 115 struct filesig *fsgp; 116 char *fsdatap; 117 118 if (oid == NULL) { 119 /* 120 * This OID is used for the rsa_md5_sha1 format signature also. 121 * This use is historical, and is hence continued, 122 * despite its lack of technical accuracy. 123 */ 124 oid = OID_sha1WithRSAEncryption; 125 oid_len = strlen(oid); 126 } 127 128 /* 129 * for now, always insert a single-signature signature block 130 */ 131 if (fssp != NULL) 132 free(fssp); 133 fssp = (struct filesignatures *) 134 malloc(filesig_ALIGN(sizeof (struct filesignatures) + 135 dn_len + sig_len + oid_len)); 136 if (fssp == NULL) 137 return (fssp); 138 139 fssp->filesig_cnt = 1; 140 fssp->filesig_pad = 0; /* reserve for future use */ 141 142 fsgp = &fssp->filesig_sig; 143 fsgp->filesig_size = sizeof (struct filesig) + 144 dn_len + sig_len + oid_len; 145 fsgp->filesig_version = version; 146 switch (version) { 147 case FILESIG_VERSION1: 148 case FILESIG_VERSION2: 149 fsgp->filesig_size -= sizeof (struct filesig) - 150 offsetof(struct filesig, filesig_v1_data[0]); 151 fsgp->filesig_v1_dnsize = dn_len; 152 fsgp->filesig_v1_sigsize = sig_len; 153 fsgp->filesig_v1_oidsize = oid_len; 154 fsdatap = &fsgp->filesig_v1_data[0]; 155 break; 156 case FILESIG_VERSION3: 157 case FILESIG_VERSION4: 158 fsgp->filesig_size -= sizeof (struct filesig) - 159 offsetof(struct filesig, filesig_v3_data[0]); 160 fsgp->filesig_v3_time = time(NULL); 161 fsgp->filesig_v3_dnsize = dn_len; 162 fsgp->filesig_v3_sigsize = sig_len; 163 fsgp->filesig_v3_oidsize = oid_len; 164 fsdatap = &fsgp->filesig_v3_data[0]; 165 break; 166 default: 167 cryptodebug("filesig_insert_dso: unknown version: %d", 168 version); 169 free(fssp); 170 return (NULL); 171 } 172 (void) memcpy(fsdatap, dn, dn_len); 173 fsdatap += dn_len; 174 (void) memcpy(fsdatap, (char *)sig, sig_len); 175 fsdatap += sig_len; 176 (void) memcpy(fsdatap, oid, oid_len); 177 fsdatap += oid_len; 178 fsgp = filesig_next(fsgp); 179 (void) memset(fsdatap, 0, (char *)(fsgp) - fsdatap); 180 181 return (fssp); 182 } 183 184 /* 185 * filesig_extract - extract filesig structure to internal form 186 */ 187 static filesig_vers_t 188 filesig_extract(struct filesig *fsgp, struct filesig_extraction *fsxp) 189 { 190 char *fsdp; 191 192 #define filesig_extract_common(cp, field, data_var, len_var, len_limit) { \ 193 len_var = len_limit; \ 194 if (len_var > fsgp->field) \ 195 len_var = fsgp->field; \ 196 (void) memcpy(data_var, cp, len_var); \ 197 cp += fsgp->field; } 198 #define filesig_extract_str(cp, field, data_var, len_var) \ 199 filesig_extract_common(cp, field, data_var, len_var, \ 200 sizeof (data_var) - 1); \ 201 data_var[len_var] = '\0'; 202 #define filesig_extract_opaque(cp, field, data_var, len_var) \ 203 filesig_extract_common(cp, field, data_var, len_var, sizeof (data_var)) 204 205 fsxp->fsx_version = fsgp->filesig_version; 206 cryptodebug("filesig_extract: version=%s", 207 version_to_str(fsxp->fsx_version)); 208 switch (fsxp->fsx_version) { 209 case FILESIG_VERSION1: 210 case FILESIG_VERSION2: 211 /* 212 * extract VERSION1 DN, signature, and OID 213 */ 214 fsdp = fsgp->filesig_v1_data; 215 fsxp->fsx_format = ES_FMT_RSA_MD5_SHA1; 216 fsxp->fsx_time = 0; 217 filesig_extract_str(fsdp, filesig_v1_dnsize, 218 fsxp->fsx_signer_DN, fsxp->fsx_signer_DN_len); 219 filesig_extract_opaque(fsdp, filesig_v1_sigsize, 220 fsxp->fsx_signature, fsxp->fsx_sig_len); 221 filesig_extract_str(fsdp, filesig_v1_oidsize, 222 fsxp->fsx_sig_oid, fsxp->fsx_sig_oid_len); 223 break; 224 case FILESIG_VERSION3: 225 case FILESIG_VERSION4: 226 fsdp = fsgp->filesig_v3_data; 227 fsxp->fsx_format = ES_FMT_RSA_SHA1; 228 fsxp->fsx_time = fsgp->filesig_v3_time; 229 filesig_extract_str(fsdp, filesig_v3_dnsize, 230 fsxp->fsx_signer_DN, fsxp->fsx_signer_DN_len); 231 filesig_extract_opaque(fsdp, filesig_v3_sigsize, 232 fsxp->fsx_signature, fsxp->fsx_sig_len); 233 filesig_extract_str(fsdp, filesig_v3_oidsize, 234 fsxp->fsx_sig_oid, fsxp->fsx_sig_oid_len); 235 break; 236 default: 237 break; 238 } 239 240 return (fsxp->fsx_version); 241 } 242 243 ELFsign_status_t 244 elfsign_begin(const char *filename, enum ES_ACTION action, ELFsign_t *essp) 245 { 246 Elf_Cmd elfcmd; 247 int oflags = 0; 248 short l_type; 249 ELFsign_t ess; 250 struct stat stb; 251 union { 252 char c[2]; 253 short s; 254 } uorder; 255 GElf_Ehdr elfehdr; 256 char *ident; 257 258 switch (action) { 259 case ES_GET: 260 case ES_GET_CRYPTO: 261 cryptodebug("elfsign_begin for get"); 262 elfcmd = ELF_C_READ; 263 oflags = O_RDONLY | O_NOCTTY | O_NDELAY; 264 l_type = F_RDLCK; 265 break; 266 case ES_UPDATE_RSA_MD5_SHA1: 267 case ES_UPDATE_RSA_SHA1: 268 cryptodebug("elfsign_begin for update"); 269 elfcmd = ELF_C_RDWR; 270 oflags = O_RDWR | O_NOCTTY | O_NDELAY; 271 l_type = F_WRLCK; 272 break; 273 default: 274 return (ELFSIGN_UNKNOWN); 275 } 276 277 if ((ess = malloc(sizeof (struct ELFsign_s))) == NULL) { 278 return (ELFSIGN_UNKNOWN); 279 } 280 (void) memset((void *)ess, 0, sizeof (struct ELFsign_s)); 281 282 if (!elfcertlib_init(ess)) { 283 cryptodebug("elfsign_begin: failed initialization"); 284 return (ELFSIGN_UNKNOWN); 285 } 286 287 ess->es_elf = NULL; 288 ess->es_action = action; 289 ess->es_version = FILESIG_UNKNOWN; 290 ess->es_pathname = NULL; 291 ess->es_certpath = NULL; 292 293 if (filename == NULL) { 294 *essp = ess; 295 return (ELFSIGN_SUCCESS); 296 } 297 298 if ((ess->es_fd = open(filename, oflags)) == -1) { 299 elfsign_end(ess); 300 return (ELFSIGN_INVALID_ELFOBJ); 301 } 302 if ((fstat(ess->es_fd, &stb) == -1) || !S_ISREG(stb.st_mode)) { 303 elfsign_end(ess); 304 return (ELFSIGN_INVALID_ELFOBJ); 305 } 306 if ((ess->es_pathname = strdup(filename)) == NULL) { 307 elfsign_end(ess); 308 return (ELFSIGN_UNKNOWN); 309 } 310 /* 311 * The following lock is released in elfsign_end() when we close(2) 312 * the es_fd. This ensures that we aren't trying verify a file 313 * we are currently updating. 314 */ 315 ess->es_flock.l_type = l_type; 316 ess->es_flock.l_whence = SEEK_CUR; 317 ess->es_flock.l_start = 0; 318 ess->es_flock.l_len = 0; 319 if (fcntl(ess->es_fd, F_SETLK, &ess->es_flock) == -1) { 320 cryptodebug("fcntl(F_SETLK) of %s failed with: %s", 321 ess->es_pathname, strerror(errno)); 322 elfsign_end(ess); 323 return (ELFSIGN_UNKNOWN); 324 } 325 326 if (elf_version(EV_CURRENT) == EV_NONE) { 327 elfsign_end(ess); 328 return (ELFSIGN_UNKNOWN); 329 } 330 331 if ((ess->es_elf = elf_begin(ess->es_fd, elfcmd, 332 (Elf *)NULL)) == NULL) { 333 cryptodebug("elf_begin() failed: %s", elf_errmsg(-1)); 334 elfsign_end(ess); 335 return (ELFSIGN_INVALID_ELFOBJ); 336 } 337 338 if (gelf_getehdr(ess->es_elf, &elfehdr) == NULL) { 339 cryptodebug("elf_getehdr() failed: %s", elf_errmsg(-1)); 340 elfsign_end(ess); 341 return (ELFSIGN_INVALID_ELFOBJ); 342 } 343 ess->es_has_phdr = (elfehdr.e_phnum != 0); 344 345 uorder.s = ELFDATA2MSB << 8 | ELFDATA2LSB; 346 ident = elf_getident(ess->es_elf, NULL); 347 if (ident == NULL) { 348 cryptodebug("elf_getident() failed: %s", elf_errmsg(-1)); 349 elfsign_end(ess); 350 return (ELFSIGN_INVALID_ELFOBJ); 351 } 352 ess->es_same_endian = (ident[EI_DATA] == uorder.c[0]); 353 ess->es_ei_class = ident[EI_CLASS]; 354 355 /* 356 * Call elf_getshstrndx to be sure we have a real ELF object 357 * this is required because elf_begin doesn't check that. 358 */ 359 if (elf_getshstrndx(ess->es_elf, &ess->es_shstrndx) == 0) { 360 elfsign_end(ess); 361 cryptodebug("elfsign_begin: elf_getshstrndx failed"); 362 return (ELFSIGN_INVALID_ELFOBJ); 363 } 364 365 /* 366 * Make sure libelf doesn't rearrange section ordering / offsets. 367 */ 368 (void) elf_flagelf(ess->es_elf, ELF_C_SET, ELF_F_LAYOUT); 369 370 *essp = ess; 371 372 return (ELFSIGN_SUCCESS); 373 } 374 375 /* 376 * elfsign_end - cleanup the ELFsign_t 377 * 378 * IN/OUT: ess 379 */ 380 void 381 elfsign_end(ELFsign_t ess) 382 { 383 if (ess == NULL) 384 return; 385 386 if (ess->es_elf != NULL && ES_ACTISUPDATE(ess->es_action)) { 387 if (elf_update(ess->es_elf, ELF_C_WRITE) == -1) { 388 cryptodebug("elf_update() failed: %s", 389 elf_errmsg(-1)); 390 return; 391 } 392 } 393 394 if (ess->es_fd != -1) { 395 (void) close(ess->es_fd); 396 ess->es_fd = -1; 397 } 398 399 if (ess->es_pathname != NULL) { 400 free(ess->es_pathname); 401 ess->es_pathname = NULL; 402 } 403 if (ess->es_certpath != NULL) { 404 free(ess->es_certpath); 405 ess->es_certpath = NULL; 406 } 407 408 if (ess->es_elf != NULL) { 409 (void) elf_end(ess->es_elf); 410 ess->es_elf = NULL; 411 } 412 413 elfcertlib_fini(ess); 414 415 free(ess); 416 } 417 418 /* 419 * set the certificate path 420 */ 421 ELFsign_status_t 422 elfsign_setcertpath(ELFsign_t ess, const char *certpath) 423 { 424 /* 425 * Normally use of access(2) is insecure, here we are only 426 * doing it to help provide early failure and better error 427 * checking, so there is no race condition. 428 */ 429 if (access(certpath, R_OK) != 0) { 430 elfsign_end(ess); 431 return (ELFSIGN_INVALID_CERTPATH); 432 } 433 ess->es_certpath = strdup(certpath); 434 435 if (ES_ACTISUPDATE(ess->es_action)) { 436 ELFCert_t cert = NULL; 437 char *subject; 438 439 /* set the version based on the certificate */ 440 if (elfcertlib_getcert(ess, ess->es_certpath, NULL, 441 &cert, ess->es_action)) { 442 if ((subject = elfcertlib_getdn(cert)) != NULL) { 443 if (strstr(subject, ELFSIGN_CRYPTO)) 444 ess->es_version = (ess->es_action == 445 ES_UPDATE_RSA_MD5_SHA1) ? 446 FILESIG_VERSION1 : FILESIG_VERSION3; 447 else 448 ess->es_version = (ess->es_action == 449 ES_UPDATE_RSA_MD5_SHA1) ? 450 FILESIG_VERSION2 : FILESIG_VERSION4; 451 } 452 elfcertlib_releasecert(ess, cert); 453 } 454 if (ess->es_version == FILESIG_UNKNOWN) 455 return (ELFSIGN_FAILED); 456 } 457 return (ELFSIGN_SUCCESS); 458 } 459 460 /* 461 * set the callback context 462 */ 463 void 464 elfsign_setcallbackctx(ELFsign_t ess, void *ctx) 465 { 466 ess->es_callbackctx = ctx; 467 } 468 469 /* 470 * set the signature extraction callback 471 */ 472 void 473 elfsign_setsigvercallback(ELFsign_t ess, 474 void (*cb)(void *, void *, size_t, ELFCert_t)) 475 { 476 ess->es_sigvercallback = cb; 477 } 478 479 /* 480 * elfsign_signatures 481 * 482 * IN: ess, fsspp, action 483 * OUT: fsspp 484 */ 485 ELFsign_status_t 486 elfsign_signatures(ELFsign_t ess, 487 struct filesignatures **fsspp, 488 size_t *fslen, 489 enum ES_ACTION action) 490 { 491 Elf_Scn *scn = NULL, *sig_scn = NULL; 492 GElf_Shdr shdr; 493 Elf_Data *data = NULL; 494 const char *elf_section = SUNW_ELF_SIGNATURE_ID; 495 int fscnt, fssize; 496 struct filesig *fsgp, *fsgpnext; 497 uint64_t sig_offset = 0; 498 499 cryptodebug("elfsign_signature"); 500 if ((ess == NULL) || (fsspp == NULL)) { 501 cryptodebug("invalid arguments"); 502 return (ELFSIGN_UNKNOWN); 503 } 504 505 cryptodebug("elfsign_signature %s for %s", 506 ES_ACTISUPDATE(action) ? "ES_UPDATE" : "ES_GET", elf_section); 507 508 (void) elf_errno(); 509 while ((scn = elf_nextscn(ess->es_elf, scn)) != NULL) { 510 const char *sh_name; 511 /* 512 * Do a string compare to examine each section header 513 * to see if this is the section that needs to be updated. 514 */ 515 if (gelf_getshdr(scn, &shdr) == NULL) { 516 cryptodebug("gelf_getshdr() failed: %s", 517 elf_errmsg(-1)); 518 return (ELFSIGN_FAILED); 519 } 520 sh_name = elf_strptr(ess->es_elf, ess->es_shstrndx, 521 (size_t)shdr.sh_name); 522 if (strcmp(sh_name, elf_section) == 0) { 523 cryptodebug("elfsign_signature: found %s", elf_section); 524 sig_scn = scn; 525 break; 526 } 527 if (shdr.sh_type != SHT_NOBITS && 528 sig_offset < shdr.sh_offset + shdr.sh_size) { 529 sig_offset = shdr.sh_offset + shdr.sh_size; 530 } 531 } 532 if (elf_errmsg(0) != NULL) { 533 cryptodebug("unexpected error: %s", elf_section, 534 elf_errmsg(-1)); 535 return (ELFSIGN_FAILED); 536 } 537 538 if (ES_ACTISUPDATE(action) && (sig_scn == NULL)) { 539 size_t old_size, new_size; 540 char *new_d_buf; 541 542 cryptodebug("elfsign_signature: %s not found - creating", 543 elf_section); 544 545 /* 546 * insert section name in .shstrtab 547 */ 548 if ((scn = elf_getscn(ess->es_elf, ess->es_shstrndx)) == 0) { 549 cryptodebug("elf_getscn() failed: %s", 550 elf_errmsg(-1)); 551 return (ELFSIGN_FAILED); 552 } 553 if (gelf_getshdr(scn, &shdr) == NULL) { 554 cryptodebug("gelf_getshdr() failed: %s", 555 elf_errmsg(-1)); 556 return (ELFSIGN_FAILED); 557 } 558 if ((data = elf_getdata(scn, data)) == NULL) { 559 cryptodebug("elf_getdata() failed: %s", 560 elf_errmsg(-1)); 561 return (ELFSIGN_FAILED); 562 } 563 old_size = data->d_size; 564 if (old_size != shdr.sh_size) { 565 cryptodebug("mismatch between data size %d " 566 "and section size %lld", old_size, shdr.sh_size); 567 return (ELFSIGN_FAILED); 568 } 569 new_size = old_size + strlen(elf_section) + 1; 570 if ((new_d_buf = malloc(new_size)) == NULL) 571 return (ELFSIGN_FAILED); 572 573 (void) memcpy(new_d_buf, data->d_buf, old_size); 574 (void) strlcpy(new_d_buf + old_size, elf_section, 575 new_size - old_size); 576 data->d_buf = new_d_buf; 577 data->d_size = new_size; 578 data->d_align = 1; 579 /* 580 * Add the section name passed in to the end of the file. 581 * Initialize the fields in the Section Header that 582 * libelf will not fill in. 583 */ 584 if ((sig_scn = elf_newscn(ess->es_elf)) == 0) { 585 cryptodebug("elf_newscn() failed: %s", 586 elf_errmsg(-1)); 587 return (ELFSIGN_FAILED); 588 } 589 if (gelf_getshdr(sig_scn, &shdr) == 0) { 590 cryptodebug("gelf_getshdr() failed: %s", 591 elf_errmsg(-1)); 592 return (ELFSIGN_FAILED); 593 } 594 shdr.sh_name = old_size; 595 shdr.sh_type = SHT_SUNW_SIGNATURE; 596 shdr.sh_flags = SHF_EXCLUDE; 597 shdr.sh_addr = 0; 598 shdr.sh_link = 0; 599 shdr.sh_info = 0; 600 shdr.sh_size = 0; 601 shdr.sh_offset = sig_offset; 602 shdr.sh_addralign = 1; 603 604 /* 605 * Flush the changes to the underlying elf32 or elf64 606 * section header. 607 */ 608 if (gelf_update_shdr(sig_scn, &shdr) == 0) { 609 cryptodebug("gelf_update_shdr failed"); 610 return (ELFSIGN_FAILED); 611 } 612 613 if ((data = elf_newdata(sig_scn)) == NULL) { 614 cryptodebug("can't add elf data area for %s: %s", 615 elf_section, elf_errmsg(-1)); 616 return (ELFSIGN_FAILED); 617 } 618 if (elfsign_adjustoffsets(ess, scn, 619 old_size + strlen(elf_section) + 1) != ELFSIGN_SUCCESS) { 620 cryptodebug("can't adjust for new section name %s", 621 elf_section); 622 return (ELFSIGN_FAILED); 623 } 624 } else { 625 if (sig_scn == NULL) { 626 cryptodebug("can't find signature section"); 627 *fsspp = NULL; 628 return (ELFSIGN_NOTSIGNED); 629 } 630 if ((data = elf_getdata(sig_scn, NULL)) == 0) { 631 cryptodebug("can't get section data for %s", 632 elf_section); 633 return (ELFSIGN_FAILED); 634 } 635 } 636 637 if (ES_ACTISUPDATE(action)) { 638 fssize = offsetof(struct filesignatures, _u1); 639 if (*fsspp != NULL) { 640 fsgp = &(*fsspp)->filesig_sig; 641 for (fscnt = 0; fscnt < (*fsspp)->filesig_cnt; 642 fscnt++) { 643 fsgpnext = filesig_next(fsgp); 644 fssize += (char *)(fsgpnext) - (char *)(fsgp); 645 fsgp = fsgpnext; 646 } 647 } 648 if (shdr.sh_addr != 0) { 649 cryptodebug("section %s is part of a loadable segment, " 650 "it cannot be changed.\n", elf_section); 651 return (ELFSIGN_FAILED); 652 } 653 if ((data->d_buf = malloc(fssize)) == NULL) 654 return (ELFSIGN_FAILED); 655 if (*fsspp != NULL) { 656 (void) memcpy(data->d_buf, *fsspp, fssize); 657 (void) elfsign_switch(ess, 658 (struct filesignatures *)data->d_buf, action); 659 } 660 data->d_size = fssize; 661 data->d_align = 1; 662 data->d_type = ELF_T_BYTE; 663 cryptodebug("elfsign_signature: data->d_size = %d", 664 data->d_size); 665 if (elfsign_adjustoffsets(ess, sig_scn, fssize) != 666 ELFSIGN_SUCCESS) { 667 cryptodebug("can't adjust for revised signature " 668 "section contents"); 669 return (ELFSIGN_FAILED); 670 } 671 } else { 672 *fsspp = malloc(data->d_size); 673 if (*fsspp == NULL) 674 return (ELFSIGN_FAILED); 675 (void) memcpy(*fsspp, data->d_buf, data->d_size); 676 if (elfsign_switch(ess, *fsspp, ES_GET) != ELFSIGN_SUCCESS) { 677 free(*fsspp); 678 *fsspp = NULL; 679 return (ELFSIGN_FAILED); 680 } 681 *fslen = data->d_size; 682 } 683 684 return (ELFSIGN_SUCCESS); 685 } 686 687 static ELFsign_status_t 688 elfsign_adjustoffsets(ELFsign_t ess, Elf_Scn *scn, uint64_t new_size) 689 { 690 GElf_Ehdr elfehdr; 691 GElf_Shdr shdr; 692 uint64_t prev_end, scn_offset; 693 char *name; 694 Elf_Scn *scnp; 695 Elf_Data *data; 696 ELFsign_status_t retval = ELFSIGN_FAILED; 697 struct scninfo { 698 struct scninfo *scni_next; 699 Elf_Scn *scni_scn; 700 uint64_t scni_offset; 701 } *scnip = NULL, *tmpscnip, **scnipp; 702 703 /* get the size of the current section */ 704 if (gelf_getshdr(scn, &shdr) == NULL) 705 return (ELFSIGN_FAILED); 706 if (shdr.sh_size == new_size) 707 return (ELFSIGN_SUCCESS); 708 scn_offset = shdr.sh_offset; 709 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 710 (size_t)shdr.sh_name); 711 if (shdr.sh_flags & SHF_ALLOC && ess->es_has_phdr) { 712 cryptodebug("elfsign_adjustoffsets: " 713 "can't move allocated section %s", name ? name : "NULL"); 714 return (ELFSIGN_FAILED); 715 } 716 717 /* resize the desired section */ 718 cryptodebug("elfsign_adjustoffsets: " 719 "resizing %s at 0x%llx from 0x%llx to 0x%llx", 720 name ? name : "NULL", shdr.sh_offset, shdr.sh_size, new_size); 721 shdr.sh_size = new_size; 722 if (gelf_update_shdr(scn, &shdr) == 0) { 723 cryptodebug("gelf_update_shdr failed"); 724 goto bad; 725 } 726 prev_end = shdr.sh_offset + shdr.sh_size; 727 728 /* 729 * find sections whose data follows the changed section 730 * must scan all sections since section data may not 731 * be in same order as section headers 732 */ 733 scnp = elf_getscn(ess->es_elf, 0); /* "seek" to start */ 734 while ((scnp = elf_nextscn(ess->es_elf, scnp)) != NULL) { 735 if (gelf_getshdr(scnp, &shdr) == NULL) 736 goto bad; 737 if (shdr.sh_offset <= scn_offset) 738 continue; 739 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 740 (size_t)shdr.sh_name); 741 if (shdr.sh_flags & SHF_ALLOC && ess->es_has_phdr) { 742 if (shdr.sh_type == SHT_NOBITS) { 743 /* .bss can occasionally overlap .shrtab */ 744 continue; 745 } 746 cryptodebug("elfsign_adjustoffsets: " 747 "can't move allocated section %s", 748 name ? name : "NULL"); 749 goto bad; 750 } 751 /* 752 * force reading of data to memory image 753 */ 754 data = NULL; 755 while ((data = elf_rawdata(scnp, data)) != NULL) 756 ; 757 /* 758 * capture section information 759 * insert into list in order of sh_offset 760 */ 761 cryptodebug("elfsign_adjustoffsets: " 762 "may have to adjust section %s, offset 0x%llx", 763 name ? name : "NULL", shdr.sh_offset); 764 tmpscnip = (struct scninfo *)malloc(sizeof (struct scninfo)); 765 if (tmpscnip == NULL) { 766 cryptodebug("elfsign_adjustoffsets: " 767 "memory allocation failure"); 768 goto bad; 769 } 770 tmpscnip->scni_scn = scnp; 771 tmpscnip->scni_offset = shdr.sh_offset; 772 for (scnipp = &scnip; *scnipp != NULL; 773 scnipp = &(*scnipp)->scni_next) { 774 if ((*scnipp)->scni_offset > tmpscnip->scni_offset) 775 break; 776 } 777 tmpscnip->scni_next = *scnipp; 778 *scnipp = tmpscnip; 779 } 780 781 /* move following sections as necessary */ 782 for (tmpscnip = scnip; tmpscnip != NULL; 783 tmpscnip = tmpscnip->scni_next) { 784 scnp = tmpscnip->scni_scn; 785 if (gelf_getshdr(scnp, &shdr) == NULL) { 786 cryptodebug("elfsign_adjustoffsets: " 787 "elf_getshdr for section %d failed", 788 elf_ndxscn(scnp)); 789 goto bad; 790 } 791 if (shdr.sh_offset >= prev_end) 792 break; 793 prev_end = (prev_end + shdr.sh_addralign - 1) & 794 (-shdr.sh_addralign); 795 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 796 (size_t)shdr.sh_name); 797 cryptodebug("elfsign_adjustoffsets: " 798 "moving %s size 0x%llx from 0x%llx to 0x%llx", 799 name ? name : "NULL", shdr.sh_size, 800 shdr.sh_offset, prev_end); 801 shdr.sh_offset = prev_end; 802 if (gelf_update_shdr(scnp, &shdr) == 0) { 803 cryptodebug("gelf_update_shdr failed"); 804 goto bad; 805 } 806 prev_end = shdr.sh_offset + shdr.sh_size; 807 } 808 809 /* 810 * adjust section header offset in elf header 811 */ 812 if (gelf_getehdr(ess->es_elf, &elfehdr) == NULL) { 813 cryptodebug("elf_getehdr() failed: %s", elf_errmsg(-1)); 814 goto bad; 815 } 816 if (elfehdr.e_shoff < prev_end) { 817 if (ess->es_ei_class == ELFCLASS32) 818 prev_end = (prev_end + ELF32_FSZ_OFF - 1) & 819 (-ELF32_FSZ_OFF); 820 else if (ess->es_ei_class == ELFCLASS64) 821 prev_end = (prev_end + ELF64_FSZ_OFF - 1) & 822 (-ELF64_FSZ_OFF); 823 cryptodebug("elfsign_adjustoffsets: " 824 "move sh_off from 0x%llx to 0x%llx", 825 elfehdr.e_shoff, prev_end); 826 elfehdr.e_shoff = prev_end; 827 if (gelf_update_ehdr(ess->es_elf, &elfehdr) == 0) { 828 cryptodebug("elf_update_ehdr() failed: %s", 829 elf_errmsg(-1)); 830 goto bad; 831 } 832 } 833 834 retval = ELFSIGN_SUCCESS; 835 836 bad: 837 while (scnip != NULL) { 838 tmpscnip = scnip->scni_next; 839 free(scnip); 840 scnip = tmpscnip; 841 } 842 return (retval); 843 } 844 845 struct filesignatures * 846 elfsign_insert_dso(ELFsign_t ess, 847 struct filesignatures *fssp, 848 const char *dn, 849 int dn_len, 850 const uchar_t *sig, 851 int sig_len, 852 const char *oid, 853 int oid_len) 854 { 855 return (filesig_insert_dso(fssp, ess->es_version, dn, dn_len, 856 sig, sig_len, oid, oid_len)); 857 } 858 859 /*ARGSUSED*/ 860 filesig_vers_t 861 elfsign_extract_sig(ELFsign_t ess, 862 struct filesignatures *fssp, 863 uchar_t *sig, 864 size_t *sig_len) 865 { 866 struct filesig_extraction fsx; 867 filesig_vers_t version; 868 869 if (fssp == NULL) 870 return (FILESIG_UNKNOWN); 871 if (fssp->filesig_cnt != 1) 872 return (FILESIG_UNKNOWN); 873 version = filesig_extract(&fssp->filesig_sig, &fsx); 874 switch (version) { 875 case FILESIG_VERSION1: 876 case FILESIG_VERSION2: 877 case FILESIG_VERSION3: 878 case FILESIG_VERSION4: 879 if (*sig_len >= fsx.fsx_sig_len) { 880 (void) memcpy((char *)sig, (char *)fsx.fsx_signature, 881 *sig_len); 882 *sig_len = fsx.fsx_sig_len; 883 } else 884 version = FILESIG_UNKNOWN; 885 break; 886 default: 887 version = FILESIG_UNKNOWN; 888 break; 889 } 890 891 if (ess->es_version == FILESIG_UNKNOWN) { 892 ess->es_version = version; 893 } 894 895 return (version); 896 } 897 898 static ELFsign_status_t 899 elfsign_hash_common(ELFsign_t ess, uchar_t *hash, size_t *hash_len, 900 boolean_t hash_mem_resident) 901 { 902 Elf_Scn *scn = NULL; 903 ELFsign_status_t elfstat; 904 GElf_Shdr shdr; 905 SHA1_CTX ctx; 906 907 /* The buffer must be large enough to hold the hash */ 908 if (*hash_len < SHA1_DIGEST_LENGTH) 909 return (ELFSIGN_FAILED); 910 911 bzero(hash, *hash_len); 912 913 /* Initialize the digest session */ 914 SHA1Init(&ctx); 915 916 scn = elf_getscn(ess->es_elf, 0); /* "seek" to start */ 917 (void) elf_errno(); 918 while ((scn = elf_nextscn(ess->es_elf, scn)) != 0) { 919 char *name = NULL; 920 Elf_Data *data = NULL; 921 922 if (gelf_getshdr(scn, &shdr) == NULL) { 923 elfstat = ELFSIGN_FAILED; 924 goto done; 925 } 926 927 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 928 (size_t)shdr.sh_name); 929 if (name == NULL) 930 name = "NULL"; 931 932 if (!hash_mem_resident && 933 (ess->es_version == FILESIG_VERSION1 || 934 ess->es_version == FILESIG_VERSION3)) { 935 /* 936 * skip the signature section only 937 */ 938 if (shdr.sh_type == SHT_SUNW_SIGNATURE) { 939 cryptodebug("elfsign_hash: skipping %s", name); 940 continue; 941 } 942 } else if (!(shdr.sh_flags & SHF_ALLOC)) { 943 /* 944 * select only memory resident sections 945 */ 946 cryptodebug("elfsign_hash: skipping %s", name); 947 continue; 948 } 949 950 /* 951 * throw this section into the hash 952 * use elf_rawdata for endian-independence 953 * use elf_getdata to get update of .shstrtab 954 */ 955 while ((data = (shdr.sh_type == SHT_STRTAB ? 956 elf_getdata(scn, data) : elf_rawdata(scn, data))) != NULL) { 957 if (data->d_buf == NULL) { 958 cryptodebug("elfsign_hash: %s has NULL data", 959 name); 960 continue; 961 } 962 cryptodebug("elfsign_hash: updating hash " 963 "with %s data size=%d", name, data->d_size); 964 SHA1Update(&ctx, data->d_buf, data->d_size); 965 } 966 } 967 if (elf_errmsg(0) != NULL) { 968 cryptodebug("elfsign_hash: %s", elf_errmsg(-1)); 969 elfstat = ELFSIGN_FAILED; 970 goto done; 971 } 972 973 SHA1Final(hash, &ctx); 974 *hash_len = SHA1_DIGEST_LENGTH; 975 { /* DEBUG START */ 976 const int hashstr_len = (*hash_len) * 2 + 1; 977 char *hashstr = malloc(hashstr_len); 978 979 if (hashstr != NULL) { 980 tohexstr(hash, *hash_len, hashstr, hashstr_len); 981 cryptodebug("hash value is: %s", hashstr); 982 free(hashstr); 983 } 984 } /* DEBUG END */ 985 elfstat = ELFSIGN_SUCCESS; 986 done: 987 return (elfstat); 988 } 989 990 /* 991 * elfsign_hash - return the hash of the ELF sections affecting execution. 992 * 993 * IN: ess, hash_len 994 * OUT: hash, hash_len 995 */ 996 ELFsign_status_t 997 elfsign_hash(ELFsign_t ess, uchar_t *hash, size_t *hash_len) 998 { 999 return (elfsign_hash_common(ess, hash, hash_len, B_FALSE)); 1000 } 1001 1002 /* 1003 * elfsign_hash_mem_resident - return the hash of the ELF sections 1004 * with only memory resident sections. 1005 * 1006 * IN: ess, hash_len 1007 * OUT: hash, hash_len 1008 */ 1009 ELFsign_status_t 1010 elfsign_hash_mem_resident(ELFsign_t ess, uchar_t *hash, size_t *hash_len) 1011 { 1012 return (elfsign_hash_common(ess, hash, hash_len, B_TRUE)); 1013 } 1014 1015 /* 1016 * elfsign_hash_esa = return the hash of the esa_buffer 1017 * 1018 * IN: ess, esa_buf, esa_buf_len, hash_len 1019 * OUT: hash, hash_len 1020 */ 1021 ELFsign_status_t 1022 elfsign_hash_esa(ELFsign_t ess, uchar_t *esa_buf, size_t esa_buf_len, 1023 uchar_t **hash, size_t *hash_len) 1024 { 1025 SHA1_CTX ctx; 1026 1027 cryptodebug("esa_hash version is: %s", 1028 version_to_str(ess->es_version)); 1029 if (ess->es_version <= FILESIG_VERSION2) { 1030 /* 1031 * old rsa_md5_sha1 format 1032 * signed with MD5 digest, just pass full esa_buf 1033 */ 1034 *hash = esa_buf; 1035 *hash_len = esa_buf_len; 1036 return (ELFSIGN_SUCCESS); 1037 } 1038 1039 if (*hash_len < SHA1_DIGEST_LENGTH) 1040 return (ELFSIGN_FAILED); 1041 1042 bzero(*hash, *hash_len); 1043 SHA1Init(&ctx); 1044 SHA1Update(&ctx, esa_buf, esa_buf_len); 1045 SHA1Final(*hash, &ctx); 1046 *hash_len = SHA1_DIGEST_LENGTH; 1047 1048 { /* DEBUG START */ 1049 const int hashstr_len = (*hash_len) * 2 + 1; 1050 char *hashstr = malloc(hashstr_len); 1051 1052 if (hashstr != NULL) { 1053 tohexstr(*hash, *hash_len, hashstr, hashstr_len); 1054 cryptodebug("esa_hash value is: %s", hashstr); 1055 free(hashstr); 1056 } 1057 } /* DEBUG END */ 1058 1059 return (ELFSIGN_SUCCESS); 1060 } 1061 1062 /* 1063 * elfsign_verify_signature - Verify the signature of the ELF object. 1064 * 1065 * IN: ess 1066 * OUT: esipp 1067 * RETURNS: 1068 * ELFsign_status_t 1069 */ 1070 ELFsign_status_t 1071 elfsign_verify_signature(ELFsign_t ess, struct ELFsign_sig_info **esipp) 1072 { 1073 ELFsign_status_t ret = ELFSIGN_FAILED; 1074 struct filesignatures *fssp; 1075 struct filesig *fsgp; 1076 size_t fslen; 1077 struct filesig_extraction fsx; 1078 uchar_t hash[SIG_MAX_LENGTH]; 1079 size_t hash_len; 1080 ELFCert_t cert = NULL; 1081 int sigcnt; 1082 int nocert = 0; 1083 struct ELFsign_sig_info *esip = NULL; 1084 1085 if (esipp != NULL) { 1086 esip = (struct ELFsign_sig_info *) 1087 calloc(1, sizeof (struct ELFsign_sig_info)); 1088 *esipp = esip; 1089 } 1090 1091 /* 1092 * Find out which cert we need, based on who signed the ELF object 1093 */ 1094 if (elfsign_signatures(ess, &fssp, &fslen, ES_GET) != ELFSIGN_SUCCESS) { 1095 return (ELFSIGN_NOTSIGNED); 1096 } 1097 1098 if (fssp->filesig_cnt < 1) { 1099 ret = ELFSIGN_FAILED; 1100 goto cleanup; 1101 } 1102 1103 fsgp = &fssp->filesig_sig; 1104 1105 /* 1106 * Scan the signature block, looking for a verifiable signature 1107 */ 1108 for (sigcnt = 0; sigcnt < fssp->filesig_cnt; 1109 sigcnt++, fsgp = filesig_next(fsgp)) { 1110 ess->es_version = filesig_extract(fsgp, &fsx); 1111 cryptodebug("elfsign_verify_signature: version=%s", 1112 version_to_str(ess->es_version)); 1113 switch (ess->es_version) { 1114 case FILESIG_VERSION1: 1115 case FILESIG_VERSION2: 1116 case FILESIG_VERSION3: 1117 case FILESIG_VERSION4: 1118 break; 1119 default: 1120 ret = ELFSIGN_FAILED; 1121 goto cleanup; 1122 } 1123 1124 cryptodebug("elfsign_verify_signature: signer_DN=\"%s\"", 1125 fsx.fsx_signer_DN); 1126 cryptodebug("elfsign_verify_signature: algorithmOID=\"%s\"", 1127 fsx.fsx_sig_oid); 1128 /* return signer DN if requested */ 1129 if (esipp != NULL) { 1130 esip->esi_format = fsx.fsx_format; 1131 if (esip->esi_signer != NULL) 1132 free(esip->esi_signer); 1133 esip->esi_signer = strdup(fsx.fsx_signer_DN); 1134 esip->esi_time = fsx.fsx_time; 1135 } 1136 1137 /* 1138 * look for certificate 1139 */ 1140 if (cert != NULL) 1141 elfcertlib_releasecert(ess, cert); 1142 1143 /* 1144 * skip unfound certificates 1145 */ 1146 if (!elfcertlib_getcert(ess, ess->es_certpath, 1147 fsx.fsx_signer_DN, &cert, ess->es_action)) { 1148 cryptodebug("unable to find certificate " 1149 "with DN=\"%s\" for %s", 1150 fsx.fsx_signer_DN, ess->es_pathname); 1151 nocert++; 1152 continue; 1153 } 1154 1155 /* 1156 * skip unverified certificates 1157 * force verification of crypto certs 1158 */ 1159 if ((ess->es_action == ES_GET_CRYPTO || 1160 strstr(fsx.fsx_signer_DN, ELFSIGN_CRYPTO)) && 1161 !elfcertlib_verifycert(ess, cert)) { 1162 cryptodebug("elfsign_verify_signature: invalid cert"); 1163 nocert++; 1164 continue; 1165 } 1166 1167 /* 1168 * At this time the only sha1WithRSAEncryption is supported, 1169 * so check that is what we have and skip with anything else. 1170 */ 1171 if (strcmp(fsx.fsx_sig_oid, OID_sha1WithRSAEncryption) != 0) { 1172 continue; 1173 } 1174 1175 nocert = 0; 1176 /* 1177 * compute file hash 1178 */ 1179 hash_len = sizeof (hash); 1180 if (elfsign_hash(ess, hash, &hash_len) != ELFSIGN_SUCCESS) { 1181 cryptodebug("elfsign_verify_signature:" 1182 " elfsign_hash failed"); 1183 ret = ELFSIGN_FAILED; 1184 break; 1185 } 1186 1187 { /* DEBUG START */ 1188 const int sigstr_len = fsx.fsx_sig_len * 2 + 1; 1189 char *sigstr = malloc(sigstr_len); 1190 1191 if (sigstr != NULL) { 1192 tohexstr(fsx.fsx_signature, fsx.fsx_sig_len, 1193 sigstr, sigstr_len); 1194 cryptodebug("signature value is: %s", sigstr); 1195 free(sigstr); 1196 } 1197 } /* DEBUG END */ 1198 1199 if (elfcertlib_verifysig(ess, cert, 1200 fsx.fsx_signature, fsx.fsx_sig_len, hash, hash_len)) { 1201 if (ess->es_sigvercallback) 1202 (ess->es_sigvercallback) 1203 (ess->es_callbackctx, fssp, fslen, cert); 1204 /* 1205 * The signature is verified! 1206 * Check if this is a restricted provider 1207 */ 1208 if (strstr(fsx.fsx_signer_DN, USAGELIMITED) == NULL) 1209 ret = ELFSIGN_SUCCESS; 1210 else { 1211 cryptodebug("DN is tagged for usagelimited"); 1212 ret = elfsign_verify_esa(ess, 1213 fsx.fsx_signature, fsx.fsx_sig_len); 1214 } 1215 break; 1216 } 1217 1218 cryptodebug("elfsign_verify_signature: invalid signature"); 1219 } 1220 1221 cleanup: 1222 if (cert != NULL) 1223 elfcertlib_releasecert(ess, cert); 1224 1225 free(fssp); 1226 if (ret == ELFSIGN_FAILED && nocert) 1227 ret = ELFSIGN_INVALID_CERTPATH; 1228 return (ret); 1229 } 1230 1231 /* 1232 * Verify the contents of the .esa file, as per Jumbo export control 1233 * document. Logic in this function should remain unchanged, unless 1234 * a misinterpretation of the jumbo case was found or if there are 1235 * changes in export regulations necessitating a change. 1236 * 1237 * If the .esa file exists, but is somehow corrupted, we just return 1238 * that this is restricted. This is consistent with the Jumbo export 1239 * case covering this library and other compenents of ON. Do not change 1240 * this logic without consulting export control. 1241 * 1242 * Please see do_gen_esa() for a description of the esa file format. 1243 * 1244 */ 1245 static ELFsign_status_t 1246 elfsign_verify_esa(ELFsign_t ess, uchar_t *orig_sig, size_t orig_sig_len) 1247 { 1248 ELFsign_status_t ret = ELFSIGN_RESTRICTED; 1249 char *elfobj_esa = NULL; 1250 size_t elfobj_esa_len; 1251 int esa_fd = -1; 1252 size_t esa_buf_len = 0; 1253 uchar_t *main_sig; 1254 size_t main_sig_len = 0; 1255 uchar_t hash[SIG_MAX_LENGTH], *hash_ptr = hash; 1256 size_t hash_len = SIG_MAX_LENGTH; 1257 char *esa_dn = NULL; 1258 size_t esa_dn_len = 0; 1259 uchar_t *esa_sig; 1260 size_t esa_sig_len = 0; 1261 uchar_t *esa_file_buffer = NULL, *esa_file_ptr; 1262 struct stat statbuf; 1263 ELFCert_t cert = NULL; 1264 1265 cryptodebug("elfsign_verify_esa"); 1266 1267 /* does the activation file exist? */ 1268 elfobj_esa_len = strlen(ess->es_pathname) + ESA_LEN + 1; 1269 elfobj_esa = malloc(elfobj_esa_len); 1270 if (elfobj_esa == NULL) { 1271 cryptoerror(LOG_STDERR, 1272 gettext("Unable to allocate buffer for esa filename.")); 1273 goto cleanup; 1274 } 1275 1276 (void) strlcpy(elfobj_esa, ess->es_pathname, elfobj_esa_len); 1277 (void) strlcat(elfobj_esa, ESA, elfobj_esa_len); 1278 1279 if ((esa_fd = open(elfobj_esa, O_RDONLY|O_NONBLOCK)) == -1) { 1280 cryptodebug("No .esa file was found, or it was unreadable"); 1281 goto cleanup; 1282 } 1283 1284 cryptodebug("Reading contents of esa file %s", elfobj_esa); 1285 1286 if (fstat(esa_fd, &statbuf) == -1) { 1287 cryptoerror(LOG_STDERR, 1288 gettext("Can't stat %s"), elfobj_esa); 1289 goto cleanup; 1290 } 1291 1292 /* 1293 * mmap the buffer to save on syscalls 1294 */ 1295 esa_file_buffer = (uchar_t *)mmap(NULL, statbuf.st_size, PROT_READ, 1296 MAP_PRIVATE, esa_fd, 0); 1297 1298 if (esa_file_buffer == MAP_FAILED) { 1299 cryptoerror(LOG_STDERR, 1300 gettext("Unable to mmap file to a buffer for %s."), 1301 elfobj_esa); 1302 goto cleanup; 1303 } 1304 1305 esa_file_ptr = esa_file_buffer; 1306 elfsign_buffer_len(ess, &main_sig_len, esa_file_ptr, ES_GET); 1307 esa_file_ptr += sizeof (uint32_t); 1308 cryptodebug("Contents of esa file: main_sig_len=%d", main_sig_len); 1309 main_sig = esa_file_ptr; 1310 1311 esa_file_ptr += main_sig_len; 1312 1313 /* verify .esa main signature versus original signature */ 1314 if (main_sig_len != orig_sig_len || 1315 memcmp(main_sig, orig_sig, orig_sig_len) != 0) { 1316 cryptoerror(LOG_STDERR, 1317 gettext("Unable to match original signature from %s."), 1318 elfobj_esa); 1319 goto cleanup; 1320 } 1321 1322 elfsign_buffer_len(ess, &esa_dn_len, esa_file_ptr, ES_GET); 1323 esa_file_ptr += sizeof (uint32_t); 1324 cryptodebug("Contents of esa file: esa_dn_len=%d", esa_dn_len); 1325 1326 esa_dn = malloc(esa_dn_len + 1); 1327 if (esa_dn == NULL) { 1328 cryptoerror(LOG_ERR, 1329 gettext("Unable to allocate memory for dn buffer.")); 1330 goto cleanup; 1331 } 1332 (void) memcpy(esa_dn, esa_file_ptr, esa_dn_len); 1333 esa_dn[esa_dn_len] = '\0'; 1334 esa_file_ptr += esa_dn_len; 1335 cryptodebug("Contents of esa file: esa_dn=%s", esa_dn); 1336 1337 elfsign_buffer_len(ess, &esa_sig_len, esa_file_ptr, ES_GET); 1338 esa_file_ptr += sizeof (uint32_t); 1339 cryptodebug("Contents of esa file: esa_sig_len=%d", esa_sig_len); 1340 1341 esa_sig = esa_file_ptr; 1342 1343 cryptodebug("Read esa contents, now verifying"); 1344 1345 /* 1346 * dn used in .esa file should not be limited. 1347 */ 1348 if (strstr(esa_dn, USAGELIMITED) != NULL) { 1349 cryptoerror(LOG_ERR, 1350 gettext("DN for .esa file is tagged as limited for %s.\n" 1351 "Activation files should only be tagged as unlimited.\n" 1352 "Please contact vendor for this provider"), 1353 ess->es_pathname); 1354 goto cleanup; 1355 } 1356 1357 if (!elfcertlib_getcert(ess, ess->es_certpath, esa_dn, &cert, 1358 ess->es_action)) { 1359 cryptodebug(gettext("unable to find certificate " 1360 "with DN=\"%s\" for %s"), 1361 esa_dn, ess->es_pathname); 1362 goto cleanup; 1363 } 1364 1365 /* 1366 * Since we've already matched the original signature 1367 * and the main file signature, we can just verify the esa signature 1368 * against the main file signature. 1369 */ 1370 esa_buf_len = sizeof (uint32_t) + main_sig_len; 1371 1372 if (elfsign_hash_esa(ess, esa_file_buffer, esa_buf_len, 1373 &hash_ptr, &hash_len) != ELFSIGN_SUCCESS) { 1374 cryptoerror(LOG_STDERR, 1375 gettext("Unable to hash activation contents.")); 1376 goto cleanup; 1377 } 1378 1379 1380 if (!elfcertlib_verifysig(ess, cert, esa_sig, esa_sig_len, 1381 hash_ptr, hash_len)) { 1382 cryptoerror(LOG_STDERR, 1383 gettext("Unable to verify .esa contents for %s"), 1384 ess->es_pathname); 1385 goto cleanup; 1386 } 1387 1388 cryptodebug("Verified esa contents"); 1389 if (ess->es_sigvercallback) 1390 (ess->es_sigvercallback) (ess->es_callbackctx, 1391 esa_file_buffer, statbuf.st_size, cert); 1392 1393 /* 1394 * validate the certificate used to sign the activation file 1395 */ 1396 if (!elfcertlib_verifycert(ess, cert)) { 1397 cryptoerror(LOG_STDERR, 1398 gettext("Unable to verify .esa certificate %s for %s"), 1399 esa_dn, ess->es_pathname); 1400 goto cleanup; 1401 } 1402 1403 cryptodebug("Verified esa certificate"); 1404 ret = ELFSIGN_SUCCESS; 1405 1406 cleanup: 1407 if (elfobj_esa != NULL) 1408 free(elfobj_esa); 1409 1410 if (esa_fd != -1) 1411 (void) close(esa_fd); 1412 1413 if (esa_file_buffer != NULL) 1414 (void) munmap((caddr_t)esa_file_buffer, statbuf.st_size); 1415 1416 if (esa_dn != NULL) 1417 free(esa_dn); 1418 1419 if (cert != NULL) 1420 elfcertlib_releasecert(ess, cert); 1421 1422 return (ret); 1423 } 1424 1425 static uint32_t 1426 elfsign_switch_uint32(uint32_t i) 1427 { 1428 return (((i & 0xff) << 24) | ((i & 0xff00) << 8) | 1429 ((i >> 8) & 0xff00) | ((i >> 24) & 0xff)); 1430 } 1431 1432 static uint64_t 1433 elfsign_switch_uint64(uint64_t i) 1434 { 1435 return (((uint64_t)elfsign_switch_uint32(i) << 32) | 1436 (elfsign_switch_uint32(i >> 32))); 1437 } 1438 1439 /* 1440 * If appropriate, switch the endianness of the filesignatures structure 1441 * Examine the structure only when it is in native endianness 1442 */ 1443 static ELFsign_status_t 1444 elfsign_switch(ELFsign_t ess, struct filesignatures *fssp, 1445 enum ES_ACTION action) 1446 { 1447 int fscnt; 1448 filesig_vers_t version; 1449 struct filesig *fsgp, *fsgpnext; 1450 1451 if (ess->es_same_endian) 1452 return (ELFSIGN_SUCCESS); 1453 1454 if (ES_ACTISUPDATE(action)) 1455 fscnt = fssp->filesig_cnt; 1456 fssp->filesig_cnt = elfsign_switch_uint32(fssp->filesig_cnt); 1457 if (!ES_ACTISUPDATE(action)) 1458 fscnt = fssp->filesig_cnt; 1459 1460 fsgp = &(fssp)->filesig_sig; 1461 for (; fscnt > 0; fscnt--, fsgp = fsgpnext) { 1462 if (ES_ACTISUPDATE(action)) { 1463 version = fsgp->filesig_version; 1464 fsgpnext = filesig_next(fsgp); 1465 } 1466 fsgp->filesig_size = 1467 elfsign_switch_uint32(fsgp->filesig_size); 1468 fsgp->filesig_version = 1469 elfsign_switch_uint32(fsgp->filesig_version); 1470 if (!ES_ACTISUPDATE(action)) { 1471 version = fsgp->filesig_version; 1472 fsgpnext = filesig_next(fsgp); 1473 } 1474 switch (version) { 1475 case FILESIG_VERSION1: 1476 case FILESIG_VERSION2: 1477 fsgp->filesig_v1_dnsize = 1478 elfsign_switch_uint32(fsgp->filesig_v1_dnsize); 1479 fsgp->filesig_v1_sigsize = 1480 elfsign_switch_uint32(fsgp->filesig_v1_sigsize); 1481 fsgp->filesig_v1_oidsize = 1482 elfsign_switch_uint32(fsgp->filesig_v1_oidsize); 1483 break; 1484 case FILESIG_VERSION3: 1485 case FILESIG_VERSION4: 1486 fsgp->filesig_v3_time = 1487 elfsign_switch_uint64(fsgp->filesig_v3_time); 1488 fsgp->filesig_v3_dnsize = 1489 elfsign_switch_uint32(fsgp->filesig_v3_dnsize); 1490 fsgp->filesig_v3_sigsize = 1491 elfsign_switch_uint32(fsgp->filesig_v3_sigsize); 1492 fsgp->filesig_v3_oidsize = 1493 elfsign_switch_uint32(fsgp->filesig_v3_oidsize); 1494 break; 1495 default: 1496 cryptodebug("elfsign_switch: failed"); 1497 return (ELFSIGN_FAILED); 1498 } 1499 } 1500 return (ELFSIGN_SUCCESS); 1501 } 1502 1503 /* 1504 * get/put an integer value from/to a buffer, possibly of opposite endianness 1505 */ 1506 void 1507 elfsign_buffer_len(ELFsign_t ess, size_t *ip, uchar_t *cp, 1508 enum ES_ACTION action) 1509 { 1510 uint32_t tmp; 1511 1512 if (!ES_ACTISUPDATE(action)) { 1513 /* fetch integer from buffer */ 1514 (void) memcpy(&tmp, cp, sizeof (tmp)); 1515 if (!ess->es_same_endian) { 1516 tmp = elfsign_switch_uint32(tmp); 1517 } 1518 *ip = tmp; 1519 } else { 1520 /* put integer into buffer */ 1521 tmp = *ip; 1522 if (!ess->es_same_endian) { 1523 tmp = elfsign_switch_uint32(tmp); 1524 } 1525 (void) memcpy(cp, &tmp, sizeof (tmp)); 1526 } 1527 } 1528 1529 char const * 1530 elfsign_strerror(ELFsign_status_t elferror) 1531 { 1532 char const *msg = NULL; 1533 1534 switch (elferror) { 1535 case ELFSIGN_SUCCESS: 1536 msg = gettext("sign or verify of ELF object succeeded"); 1537 break; 1538 case ELFSIGN_FAILED: 1539 msg = gettext("sign or verify of ELF object failed"); 1540 break; 1541 case ELFSIGN_NOTSIGNED: 1542 msg = gettext("ELF object not signed"); 1543 break; 1544 case ELFSIGN_INVALID_CERTPATH: 1545 msg = gettext("cannot access certificate"); 1546 break; 1547 case ELFSIGN_INVALID_ELFOBJ: 1548 msg = gettext("unable to open as an ELF object"); 1549 break; 1550 case ELFSIGN_RESTRICTED: 1551 msg = gettext("ELF object is restricted"); 1552 break; 1553 case ELFSIGN_UNKNOWN: 1554 default: 1555 msg = gettext("Unknown error"); 1556 break; 1557 } 1558 1559 return (msg); 1560 } 1561 1562 boolean_t 1563 elfsign_sig_info(struct filesignatures *fssp, struct ELFsign_sig_info **esipp) 1564 { 1565 struct filesig_extraction fsx; 1566 struct ELFsign_sig_info *esip; 1567 1568 esip = (struct ELFsign_sig_info *) 1569 calloc(1, sizeof (struct ELFsign_sig_info)); 1570 *esipp = esip; 1571 if (esip == NULL) 1572 return (B_FALSE); 1573 1574 switch (filesig_extract(&fssp->filesig_sig, &fsx)) { 1575 case FILESIG_VERSION1: 1576 case FILESIG_VERSION2: 1577 case FILESIG_VERSION3: 1578 case FILESIG_VERSION4: 1579 esip->esi_format = fsx.fsx_format; 1580 esip->esi_signer = strdup(fsx.fsx_signer_DN); 1581 esip->esi_time = fsx.fsx_time; 1582 break; 1583 default: 1584 free(esip); 1585 *esipp = NULL; 1586 } 1587 1588 return (*esipp != NULL); 1589 } 1590 1591 void 1592 elfsign_sig_info_free(struct ELFsign_sig_info *esip) 1593 { 1594 if (esip != NULL) { 1595 free(esip->esi_signer); 1596 free(esip); 1597 } 1598 } 1599