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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #define ELF_TARGET_ALL /* get definitions of all section flags */ 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <fcntl.h> 32 #include <unistd.h> 33 #include <strings.h> 34 #include <stddef.h> 35 #include <stdlib.h> 36 #include <libintl.h> 37 #include <dirent.h> 38 #include <errno.h> 39 #include <libelf.h> 40 #include <gelf.h> 41 #include <sys/mman.h> 42 #include <cryptoutil.h> 43 #include <sha1.h> 44 #include <sys/crypto/elfsign.h> 45 #include <libelfsign.h> 46 47 #ifndef SHA1_DIGEST_LENGTH 48 #define SHA1_DIGEST_LENGTH 20 49 #endif /* SHA1_DIGEST_LENGTH */ 50 51 const char SUNW_ELF_SIGNATURE_ID[] = ELF_SIGNATURE_SECTION; 52 const char OID_sha1WithRSAEncryption[] = "1.2.840.113549.1.1.5"; 53 54 static ELFsign_status_t elfsign_adjustoffsets(ELFsign_t ess, 55 Elf_Scn *scn, uint64_t new_size); 56 static ELFsign_status_t elfsign_verify_esa(ELFsign_t ess, 57 uchar_t *sig, size_t sig_len); 58 static uint32_t elfsign_switch_uint32(uint32_t i); 59 static ELFsign_status_t elfsign_switch(ELFsign_t ess, 60 struct filesignatures *fssp, enum ES_ACTION action); 61 62 struct filesig_extraction { 63 filesig_vers_t fsx_version; 64 char *fsx_format; 65 char fsx_signer_DN[ELFCERT_MAX_DN_LEN]; 66 size_t fsx_signer_DN_len; 67 uchar_t fsx_signature[SIG_MAX_LENGTH]; 68 size_t fsx_sig_len; 69 char fsx_sig_oid[100]; 70 size_t fsx_sig_oid_len; 71 time_t fsx_time; 72 }; 73 74 static char * 75 version_to_str(filesig_vers_t v) 76 { 77 char *ret; 78 79 switch (v) { 80 case FILESIG_VERSION1: 81 ret = "VERSION1"; 82 break; 83 case FILESIG_VERSION2: 84 ret = "VERSION2"; 85 break; 86 case FILESIG_VERSION3: 87 ret = "VERSION3"; 88 break; 89 case FILESIG_VERSION4: 90 ret = "VERSION4"; 91 break; 92 default: 93 ret = "UNKNOWN"; 94 break; 95 } 96 return (ret); 97 } 98 99 /* 100 * Update filesignatures to include the v1/v2 filesig, 101 * composed of signer DN, signature, and OID. 102 */ 103 static struct filesignatures * 104 filesig_insert_dso(struct filesignatures *fssp, 105 filesig_vers_t version, 106 const char *dn, 107 int dn_len, 108 const uchar_t *sig, 109 int sig_len, 110 const char *oid, 111 int oid_len) 112 { 113 struct filesig *fsgp; 114 char *fsdatap; 115 116 if (oid == NULL) { 117 /* 118 * This OID is used for the rsa_md5_sha1 format signature also. 119 * This use is historical, and is hence continued, 120 * despite its lack of technical accuracy. 121 */ 122 oid = OID_sha1WithRSAEncryption; 123 oid_len = strlen(oid); 124 } 125 126 /* 127 * for now, always insert a single-signature signature block 128 */ 129 if (fssp != NULL) 130 free(fssp); 131 fssp = (struct filesignatures *) 132 malloc(filesig_ALIGN(sizeof (struct filesignatures) + 133 dn_len + sig_len + oid_len)); 134 if (fssp == NULL) 135 return (fssp); 136 137 fssp->filesig_cnt = 1; 138 fssp->filesig_pad = 0; /* reserve for future use */ 139 140 fsgp = &fssp->filesig_sig; 141 fsgp->filesig_size = sizeof (struct filesig) + 142 dn_len + sig_len + oid_len; 143 fsgp->filesig_version = version; 144 switch (version) { 145 case FILESIG_VERSION1: 146 case FILESIG_VERSION2: 147 fsgp->filesig_size -= sizeof (struct filesig) - 148 offsetof(struct filesig, filesig_v1_data[0]); 149 fsgp->filesig_v1_dnsize = dn_len; 150 fsgp->filesig_v1_sigsize = sig_len; 151 fsgp->filesig_v1_oidsize = oid_len; 152 fsdatap = &fsgp->filesig_v1_data[0]; 153 break; 154 case FILESIG_VERSION3: 155 case FILESIG_VERSION4: 156 fsgp->filesig_size -= sizeof (struct filesig) - 157 offsetof(struct filesig, filesig_v3_data[0]); 158 fsgp->filesig_v3_time = time(NULL); 159 fsgp->filesig_v3_dnsize = dn_len; 160 fsgp->filesig_v3_sigsize = sig_len; 161 fsgp->filesig_v3_oidsize = oid_len; 162 fsdatap = &fsgp->filesig_v3_data[0]; 163 break; 164 default: 165 cryptodebug("filesig_insert_dso: unknown version: %d", 166 version); 167 free(fssp); 168 return (NULL); 169 } 170 (void) memcpy(fsdatap, dn, dn_len); 171 fsdatap += dn_len; 172 (void) memcpy(fsdatap, (char *)sig, sig_len); 173 fsdatap += sig_len; 174 (void) memcpy(fsdatap, oid, oid_len); 175 fsdatap += oid_len; 176 fsgp = filesig_next(fsgp); 177 (void) memset(fsdatap, 0, (char *)(fsgp) - fsdatap); 178 179 return (fssp); 180 } 181 182 /* 183 * filesig_extract - extract filesig structure to internal form 184 */ 185 static filesig_vers_t 186 filesig_extract(struct filesig *fsgp, struct filesig_extraction *fsxp) 187 { 188 char *fsdp; 189 190 #define filesig_extract_common(cp, field, data_var, len_var, len_limit) { \ 191 len_var = len_limit; \ 192 if (len_var > fsgp->field) \ 193 len_var = fsgp->field; \ 194 (void) memcpy(data_var, cp, len_var); \ 195 cp += fsgp->field; } 196 #define filesig_extract_str(cp, field, data_var, len_var) \ 197 filesig_extract_common(cp, field, data_var, len_var, \ 198 sizeof (data_var) - 1); \ 199 data_var[len_var] = '\0'; 200 #define filesig_extract_opaque(cp, field, data_var, len_var) \ 201 filesig_extract_common(cp, field, data_var, len_var, sizeof (data_var)) 202 203 fsxp->fsx_version = fsgp->filesig_version; 204 cryptodebug("filesig_extract: version=%s", 205 version_to_str(fsxp->fsx_version)); 206 switch (fsxp->fsx_version) { 207 case FILESIG_VERSION1: 208 case FILESIG_VERSION2: 209 /* 210 * extract VERSION1 DN, signature, and OID 211 */ 212 fsdp = fsgp->filesig_v1_data; 213 fsxp->fsx_format = ES_FMT_RSA_MD5_SHA1; 214 fsxp->fsx_time = 0; 215 filesig_extract_str(fsdp, filesig_v1_dnsize, 216 fsxp->fsx_signer_DN, fsxp->fsx_signer_DN_len); 217 filesig_extract_opaque(fsdp, filesig_v1_sigsize, 218 fsxp->fsx_signature, fsxp->fsx_sig_len); 219 filesig_extract_str(fsdp, filesig_v1_oidsize, 220 fsxp->fsx_sig_oid, fsxp->fsx_sig_oid_len); 221 break; 222 case FILESIG_VERSION3: 223 case FILESIG_VERSION4: 224 fsdp = fsgp->filesig_v3_data; 225 fsxp->fsx_format = ES_FMT_RSA_SHA1; 226 fsxp->fsx_time = fsgp->filesig_v3_time; 227 filesig_extract_str(fsdp, filesig_v3_dnsize, 228 fsxp->fsx_signer_DN, fsxp->fsx_signer_DN_len); 229 filesig_extract_opaque(fsdp, filesig_v3_sigsize, 230 fsxp->fsx_signature, fsxp->fsx_sig_len); 231 filesig_extract_str(fsdp, filesig_v3_oidsize, 232 fsxp->fsx_sig_oid, fsxp->fsx_sig_oid_len); 233 break; 234 default: 235 break; 236 } 237 238 return (fsxp->fsx_version); 239 } 240 241 ELFsign_status_t 242 elfsign_begin(const char *filename, enum ES_ACTION action, ELFsign_t *essp) 243 { 244 Elf_Cmd elfcmd; 245 int oflags = 0; 246 short l_type; 247 ELFsign_t ess; 248 struct stat stb; 249 union { 250 char c[2]; 251 short s; 252 } uorder; 253 GElf_Ehdr elfehdr; 254 char *ident; 255 256 switch (action) { 257 case ES_GET: 258 case ES_GET_CRYPTO: 259 case ES_GET_FIPS140: 260 cryptodebug("elfsign_begin for get"); 261 elfcmd = ELF_C_READ; 262 oflags = O_RDONLY | O_NOCTTY | O_NDELAY; 263 l_type = F_RDLCK; 264 break; 265 case ES_UPDATE_RSA_MD5_SHA1: 266 case ES_UPDATE_RSA_SHA1: 267 cryptodebug("elfsign_begin for update"); 268 elfcmd = ELF_C_RDWR; 269 oflags = O_RDWR | O_NOCTTY | O_NDELAY; 270 l_type = F_WRLCK; 271 break; 272 default: 273 return (ELFSIGN_UNKNOWN); 274 } 275 276 if ((ess = malloc(sizeof (struct ELFsign_s))) == NULL) { 277 return (ELFSIGN_UNKNOWN); 278 } 279 (void) memset((void *)ess, 0, sizeof (struct ELFsign_s)); 280 281 if (!elfcertlib_init(ess)) { 282 cryptodebug("elfsign_begin: failed initialization"); 283 return (ELFSIGN_UNKNOWN); 284 } 285 286 ess->es_elf = NULL; 287 ess->es_action = action; 288 ess->es_version = FILESIG_UNKNOWN; 289 ess->es_pathname = NULL; 290 ess->es_certpath = NULL; 291 292 if (filename == NULL) { 293 *essp = ess; 294 return (ELFSIGN_SUCCESS); 295 } 296 297 if ((ess->es_fd = open(filename, oflags)) == -1) { 298 elfsign_end(ess); 299 return (ELFSIGN_INVALID_ELFOBJ); 300 } 301 if ((fstat(ess->es_fd, &stb) == -1) || !S_ISREG(stb.st_mode)) { 302 elfsign_end(ess); 303 return (ELFSIGN_INVALID_ELFOBJ); 304 } 305 if ((ess->es_pathname = strdup(filename)) == NULL) { 306 elfsign_end(ess); 307 return (ELFSIGN_UNKNOWN); 308 } 309 /* 310 * The following lock is released in elfsign_end() when we close(2) 311 * the es_fd. This ensures that we aren't trying verify a file 312 * we are currently updating. 313 */ 314 ess->es_flock.l_type = l_type; 315 ess->es_flock.l_whence = SEEK_CUR; 316 ess->es_flock.l_start = 0; 317 ess->es_flock.l_len = 0; 318 if (fcntl(ess->es_fd, F_SETLK, &ess->es_flock) == -1) { 319 cryptodebug("fcntl(F_SETLK) of %s failed with: %s", 320 ess->es_pathname, strerror(errno)); 321 elfsign_end(ess); 322 return (ELFSIGN_UNKNOWN); 323 } 324 325 if (elf_version(EV_CURRENT) == EV_NONE) { 326 elfsign_end(ess); 327 return (ELFSIGN_UNKNOWN); 328 } 329 330 if ((ess->es_elf = elf_begin(ess->es_fd, elfcmd, 331 (Elf *)NULL)) == NULL) { 332 cryptodebug("elf_begin() failed: %s", elf_errmsg(-1)); 333 elfsign_end(ess); 334 return (ELFSIGN_INVALID_ELFOBJ); 335 } 336 337 if (gelf_getehdr(ess->es_elf, &elfehdr) == NULL) { 338 cryptodebug("elf_getehdr() failed: %s", elf_errmsg(-1)); 339 elfsign_end(ess); 340 return (ELFSIGN_INVALID_ELFOBJ); 341 } 342 ess->es_has_phdr = (elfehdr.e_phnum != 0); 343 344 uorder.s = ELFDATA2MSB << 8 | ELFDATA2LSB; 345 ident = elf_getident(ess->es_elf, NULL); 346 if (ident == NULL) { 347 cryptodebug("elf_getident() failed: %s", elf_errmsg(-1)); 348 elfsign_end(ess); 349 return (ELFSIGN_INVALID_ELFOBJ); 350 } 351 ess->es_same_endian = (ident[EI_DATA] == uorder.c[0]); 352 ess->es_ei_class = ident[EI_CLASS]; 353 354 /* 355 * Call elf_getshstrndx to be sure we have a real ELF object 356 * this is required because elf_begin doesn't check that. 357 */ 358 if (elf_getshstrndx(ess->es_elf, &ess->es_shstrndx) == 0) { 359 elfsign_end(ess); 360 cryptodebug("elfsign_begin: elf_getshstrndx failed"); 361 return (ELFSIGN_INVALID_ELFOBJ); 362 } 363 364 /* 365 * Make sure libelf doesn't rearrange section ordering / offsets. 366 */ 367 (void) elf_flagelf(ess->es_elf, ELF_C_SET, ELF_F_LAYOUT); 368 369 *essp = ess; 370 371 return (ELFSIGN_SUCCESS); 372 } 373 374 /* 375 * elfsign_end - cleanup the ELFsign_t 376 * 377 * IN/OUT: ess 378 */ 379 void 380 elfsign_end(ELFsign_t ess) 381 { 382 if (ess == NULL) 383 return; 384 385 if (ess->es_elf != NULL && ES_ACTISUPDATE(ess->es_action)) { 386 if (elf_update(ess->es_elf, ELF_C_WRITE) == -1) { 387 cryptodebug("elf_update() failed: %s", 388 elf_errmsg(-1)); 389 return; 390 } 391 } 392 393 if (ess->es_fd != -1) { 394 (void) close(ess->es_fd); 395 ess->es_fd = -1; 396 } 397 398 if (ess->es_pathname != NULL) { 399 free(ess->es_pathname); 400 ess->es_pathname = NULL; 401 } 402 if (ess->es_certpath != NULL) { 403 free(ess->es_certpath); 404 ess->es_certpath = NULL; 405 } 406 407 if (ess->es_elf != NULL) { 408 (void) elf_end(ess->es_elf); 409 ess->es_elf = NULL; 410 } 411 412 elfcertlib_fini(ess); 413 414 free(ess); 415 } 416 417 /* 418 * set the certificate path 419 */ 420 ELFsign_status_t 421 elfsign_setcertpath(ELFsign_t ess, const char *certpath) 422 { 423 /* 424 * Normally use of access(2) is insecure, here we are only 425 * doing it to help provide early failure and better error 426 * checking, so there is no race condition. 427 */ 428 if (access(certpath, R_OK) != 0) 429 return (ELFSIGN_INVALID_CERTPATH); 430 431 if ((ess->es_certpath = strdup(certpath)) == NULL) 432 return (ELFSIGN_FAILED); 433 434 if (ES_ACTISUPDATE(ess->es_action)) { 435 ELFCert_t cert = NULL; 436 char *subject; 437 438 /* set the version based on the certificate */ 439 if (elfcertlib_getcert(ess, ess->es_certpath, NULL, 440 &cert, ess->es_action)) { 441 if ((subject = elfcertlib_getdn(cert)) != NULL) { 442 if (strstr(subject, ELFSIGN_CRYPTO)) 443 ess->es_version = (ess->es_action == 444 ES_UPDATE_RSA_MD5_SHA1) ? 445 FILESIG_VERSION1 : FILESIG_VERSION3; 446 else 447 ess->es_version = (ess->es_action == 448 ES_UPDATE_RSA_MD5_SHA1) ? 449 FILESIG_VERSION2 : FILESIG_VERSION4; 450 } 451 elfcertlib_releasecert(ess, cert); 452 } 453 if (ess->es_version == FILESIG_UNKNOWN) 454 return (ELFSIGN_FAILED); 455 } 456 return (ELFSIGN_SUCCESS); 457 } 458 459 /* 460 * set the callback context 461 */ 462 void 463 elfsign_setcallbackctx(ELFsign_t ess, void *ctx) 464 { 465 ess->es_callbackctx = ctx; 466 } 467 468 /* 469 * set the signature extraction callback 470 */ 471 void 472 elfsign_setsigvercallback(ELFsign_t ess, 473 void (*cb)(void *, void *, size_t, ELFCert_t)) 474 { 475 ess->es_sigvercallback = cb; 476 } 477 478 /* 479 * elfsign_signatures 480 * 481 * IN: ess, fsspp, action 482 * OUT: fsspp 483 */ 484 ELFsign_status_t 485 elfsign_signatures(ELFsign_t ess, 486 struct filesignatures **fsspp, 487 size_t *fslen, 488 enum ES_ACTION action) 489 { 490 Elf_Scn *scn = NULL, *sig_scn = NULL; 491 GElf_Shdr shdr; 492 Elf_Data *data = NULL; 493 const char *elf_section = SUNW_ELF_SIGNATURE_ID; 494 int fscnt, fssize; 495 struct filesig *fsgp, *fsgpnext; 496 uint64_t sig_offset = 0; 497 498 cryptodebug("elfsign_signature"); 499 if ((ess == NULL) || (fsspp == NULL)) { 500 cryptodebug("invalid arguments"); 501 return (ELFSIGN_UNKNOWN); 502 } 503 504 cryptodebug("elfsign_signature %s for %s", 505 ES_ACTISUPDATE(action) ? "ES_UPDATE" : "ES_GET", elf_section); 506 507 (void) elf_errno(); 508 while ((scn = elf_nextscn(ess->es_elf, scn)) != NULL) { 509 const char *sh_name; 510 /* 511 * Do a string compare to examine each section header 512 * to see if this is the section that needs to be updated. 513 */ 514 if (gelf_getshdr(scn, &shdr) == NULL) { 515 cryptodebug("gelf_getshdr() failed: %s", 516 elf_errmsg(-1)); 517 return (ELFSIGN_FAILED); 518 } 519 sh_name = elf_strptr(ess->es_elf, ess->es_shstrndx, 520 (size_t)shdr.sh_name); 521 if (strcmp(sh_name, elf_section) == 0) { 522 cryptodebug("elfsign_signature: found %s", elf_section); 523 sig_scn = scn; 524 break; 525 } 526 if (shdr.sh_type != SHT_NOBITS && 527 sig_offset < shdr.sh_offset + shdr.sh_size) { 528 sig_offset = shdr.sh_offset + shdr.sh_size; 529 } 530 } 531 if (elf_errmsg(0) != NULL) { 532 cryptodebug("unexpected error: %s", elf_section, 533 elf_errmsg(-1)); 534 return (ELFSIGN_FAILED); 535 } 536 537 if (ES_ACTISUPDATE(action) && (sig_scn == NULL)) { 538 size_t old_size, new_size; 539 char *new_d_buf; 540 541 cryptodebug("elfsign_signature: %s not found - creating", 542 elf_section); 543 544 /* 545 * insert section name in .shstrtab 546 */ 547 if ((scn = elf_getscn(ess->es_elf, ess->es_shstrndx)) == 0) { 548 cryptodebug("elf_getscn() failed: %s", 549 elf_errmsg(-1)); 550 return (ELFSIGN_FAILED); 551 } 552 if (gelf_getshdr(scn, &shdr) == NULL) { 553 cryptodebug("gelf_getshdr() failed: %s", 554 elf_errmsg(-1)); 555 return (ELFSIGN_FAILED); 556 } 557 if ((data = elf_getdata(scn, data)) == NULL) { 558 cryptodebug("elf_getdata() failed: %s", 559 elf_errmsg(-1)); 560 return (ELFSIGN_FAILED); 561 } 562 old_size = data->d_size; 563 if (old_size != shdr.sh_size) { 564 cryptodebug("mismatch between data size %d " 565 "and section size %lld", old_size, shdr.sh_size); 566 return (ELFSIGN_FAILED); 567 } 568 new_size = old_size + strlen(elf_section) + 1; 569 if ((new_d_buf = malloc(new_size)) == NULL) 570 return (ELFSIGN_FAILED); 571 572 (void) memcpy(new_d_buf, data->d_buf, old_size); 573 (void) strlcpy(new_d_buf + old_size, elf_section, 574 new_size - old_size); 575 data->d_buf = new_d_buf; 576 data->d_size = new_size; 577 data->d_align = 1; 578 /* 579 * Add the section name passed in to the end of the file. 580 * Initialize the fields in the Section Header that 581 * libelf will not fill in. 582 */ 583 if ((sig_scn = elf_newscn(ess->es_elf)) == 0) { 584 cryptodebug("elf_newscn() failed: %s", 585 elf_errmsg(-1)); 586 return (ELFSIGN_FAILED); 587 } 588 if (gelf_getshdr(sig_scn, &shdr) == 0) { 589 cryptodebug("gelf_getshdr() failed: %s", 590 elf_errmsg(-1)); 591 return (ELFSIGN_FAILED); 592 } 593 shdr.sh_name = old_size; 594 shdr.sh_type = SHT_SUNW_SIGNATURE; 595 shdr.sh_flags = SHF_EXCLUDE; 596 shdr.sh_addr = 0; 597 shdr.sh_link = 0; 598 shdr.sh_info = 0; 599 shdr.sh_size = 0; 600 shdr.sh_offset = sig_offset; 601 shdr.sh_addralign = 1; 602 603 /* 604 * Flush the changes to the underlying elf32 or elf64 605 * section header. 606 */ 607 if (gelf_update_shdr(sig_scn, &shdr) == 0) { 608 cryptodebug("gelf_update_shdr failed"); 609 return (ELFSIGN_FAILED); 610 } 611 612 if ((data = elf_newdata(sig_scn)) == NULL) { 613 cryptodebug("can't add elf data area for %s: %s", 614 elf_section, elf_errmsg(-1)); 615 return (ELFSIGN_FAILED); 616 } 617 if (elfsign_adjustoffsets(ess, scn, 618 old_size + strlen(elf_section) + 1) != ELFSIGN_SUCCESS) { 619 cryptodebug("can't adjust for new section name %s", 620 elf_section); 621 return (ELFSIGN_FAILED); 622 } 623 } else { 624 if (sig_scn == NULL) { 625 cryptodebug("can't find signature section"); 626 *fsspp = NULL; 627 return (ELFSIGN_NOTSIGNED); 628 } 629 if ((data = elf_getdata(sig_scn, NULL)) == 0) { 630 cryptodebug("can't get section data for %s", 631 elf_section); 632 return (ELFSIGN_FAILED); 633 } 634 } 635 636 if (ES_ACTISUPDATE(action)) { 637 fssize = offsetof(struct filesignatures, _u1); 638 if (*fsspp != NULL) { 639 fsgp = &(*fsspp)->filesig_sig; 640 for (fscnt = 0; fscnt < (*fsspp)->filesig_cnt; 641 fscnt++) { 642 fsgpnext = filesig_next(fsgp); 643 fssize += (char *)(fsgpnext) - (char *)(fsgp); 644 fsgp = fsgpnext; 645 } 646 } 647 if (shdr.sh_addr != 0) { 648 cryptodebug("section %s is part of a loadable segment, " 649 "it cannot be changed.\n", elf_section); 650 return (ELFSIGN_FAILED); 651 } 652 if ((data->d_buf = malloc(fssize)) == NULL) 653 return (ELFSIGN_FAILED); 654 if (*fsspp != NULL) { 655 (void) memcpy(data->d_buf, *fsspp, fssize); 656 (void) elfsign_switch(ess, 657 (struct filesignatures *)data->d_buf, action); 658 } 659 data->d_size = fssize; 660 data->d_align = 1; 661 data->d_type = ELF_T_BYTE; 662 cryptodebug("elfsign_signature: data->d_size = %d", 663 data->d_size); 664 if (elfsign_adjustoffsets(ess, sig_scn, fssize) != 665 ELFSIGN_SUCCESS) { 666 cryptodebug("can't adjust for revised signature " 667 "section contents"); 668 return (ELFSIGN_FAILED); 669 } 670 } else { 671 *fsspp = malloc(data->d_size); 672 if (*fsspp == NULL) 673 return (ELFSIGN_FAILED); 674 (void) memcpy(*fsspp, data->d_buf, data->d_size); 675 if (elfsign_switch(ess, *fsspp, ES_GET) != ELFSIGN_SUCCESS) { 676 free(*fsspp); 677 *fsspp = NULL; 678 return (ELFSIGN_FAILED); 679 } 680 *fslen = data->d_size; 681 } 682 683 return (ELFSIGN_SUCCESS); 684 } 685 686 static ELFsign_status_t 687 elfsign_adjustoffsets(ELFsign_t ess, Elf_Scn *scn, uint64_t new_size) 688 { 689 GElf_Ehdr elfehdr; 690 GElf_Shdr shdr; 691 uint64_t prev_end, scn_offset; 692 char *name; 693 Elf_Scn *scnp; 694 Elf_Data *data; 695 ELFsign_status_t retval = ELFSIGN_FAILED; 696 struct scninfo { 697 struct scninfo *scni_next; 698 Elf_Scn *scni_scn; 699 uint64_t scni_offset; 700 } *scnip = NULL, *tmpscnip, **scnipp; 701 702 /* get the size of the current section */ 703 if (gelf_getshdr(scn, &shdr) == NULL) 704 return (ELFSIGN_FAILED); 705 if (shdr.sh_size == new_size) 706 return (ELFSIGN_SUCCESS); 707 scn_offset = shdr.sh_offset; 708 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 709 (size_t)shdr.sh_name); 710 if (shdr.sh_flags & SHF_ALLOC && ess->es_has_phdr) { 711 cryptodebug("elfsign_adjustoffsets: " 712 "can't move allocated section %s", name ? name : "NULL"); 713 return (ELFSIGN_FAILED); 714 } 715 716 /* resize the desired section */ 717 cryptodebug("elfsign_adjustoffsets: " 718 "resizing %s at 0x%llx from 0x%llx to 0x%llx", 719 name ? name : "NULL", shdr.sh_offset, shdr.sh_size, new_size); 720 shdr.sh_size = new_size; 721 if (gelf_update_shdr(scn, &shdr) == 0) { 722 cryptodebug("gelf_update_shdr failed"); 723 goto bad; 724 } 725 prev_end = shdr.sh_offset + shdr.sh_size; 726 727 /* 728 * find sections whose data follows the changed section 729 * must scan all sections since section data may not 730 * be in same order as section headers 731 */ 732 scnp = elf_getscn(ess->es_elf, 0); /* "seek" to start */ 733 while ((scnp = elf_nextscn(ess->es_elf, scnp)) != NULL) { 734 if (gelf_getshdr(scnp, &shdr) == NULL) 735 goto bad; 736 if (shdr.sh_offset <= scn_offset) 737 continue; 738 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 739 (size_t)shdr.sh_name); 740 if (shdr.sh_flags & SHF_ALLOC && ess->es_has_phdr) { 741 if (shdr.sh_type == SHT_NOBITS) { 742 /* .bss can occasionally overlap .shrtab */ 743 continue; 744 } 745 cryptodebug("elfsign_adjustoffsets: " 746 "can't move allocated section %s", 747 name ? name : "NULL"); 748 goto bad; 749 } 750 /* 751 * force reading of data to memory image 752 */ 753 data = NULL; 754 while ((data = elf_rawdata(scnp, data)) != NULL) 755 ; 756 /* 757 * capture section information 758 * insert into list in order of sh_offset 759 */ 760 cryptodebug("elfsign_adjustoffsets: " 761 "may have to adjust section %s, offset 0x%llx", 762 name ? name : "NULL", shdr.sh_offset); 763 tmpscnip = (struct scninfo *)malloc(sizeof (struct scninfo)); 764 if (tmpscnip == NULL) { 765 cryptodebug("elfsign_adjustoffsets: " 766 "memory allocation failure"); 767 goto bad; 768 } 769 tmpscnip->scni_scn = scnp; 770 tmpscnip->scni_offset = shdr.sh_offset; 771 for (scnipp = &scnip; *scnipp != NULL; 772 scnipp = &(*scnipp)->scni_next) { 773 if ((*scnipp)->scni_offset > tmpscnip->scni_offset) 774 break; 775 } 776 tmpscnip->scni_next = *scnipp; 777 *scnipp = tmpscnip; 778 } 779 780 /* move following sections as necessary */ 781 for (tmpscnip = scnip; tmpscnip != NULL; 782 tmpscnip = tmpscnip->scni_next) { 783 scnp = tmpscnip->scni_scn; 784 if (gelf_getshdr(scnp, &shdr) == NULL) { 785 cryptodebug("elfsign_adjustoffsets: " 786 "elf_getshdr for section %d failed", 787 elf_ndxscn(scnp)); 788 goto bad; 789 } 790 if (shdr.sh_offset >= prev_end) 791 break; 792 prev_end = (prev_end + shdr.sh_addralign - 1) & 793 (-shdr.sh_addralign); 794 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 795 (size_t)shdr.sh_name); 796 cryptodebug("elfsign_adjustoffsets: " 797 "moving %s size 0x%llx from 0x%llx to 0x%llx", 798 name ? name : "NULL", shdr.sh_size, 799 shdr.sh_offset, prev_end); 800 shdr.sh_offset = prev_end; 801 if (gelf_update_shdr(scnp, &shdr) == 0) { 802 cryptodebug("gelf_update_shdr failed"); 803 goto bad; 804 } 805 prev_end = shdr.sh_offset + shdr.sh_size; 806 } 807 808 /* 809 * adjust section header offset in elf header 810 */ 811 if (gelf_getehdr(ess->es_elf, &elfehdr) == NULL) { 812 cryptodebug("elf_getehdr() failed: %s", elf_errmsg(-1)); 813 goto bad; 814 } 815 if (elfehdr.e_shoff < prev_end) { 816 if (ess->es_ei_class == ELFCLASS32) 817 prev_end = (prev_end + ELF32_FSZ_OFF - 1) & 818 (-ELF32_FSZ_OFF); 819 else if (ess->es_ei_class == ELFCLASS64) 820 prev_end = (prev_end + ELF64_FSZ_OFF - 1) & 821 (-ELF64_FSZ_OFF); 822 cryptodebug("elfsign_adjustoffsets: " 823 "move sh_off from 0x%llx to 0x%llx", 824 elfehdr.e_shoff, prev_end); 825 elfehdr.e_shoff = prev_end; 826 if (gelf_update_ehdr(ess->es_elf, &elfehdr) == 0) { 827 cryptodebug("elf_update_ehdr() failed: %s", 828 elf_errmsg(-1)); 829 goto bad; 830 } 831 } 832 833 retval = ELFSIGN_SUCCESS; 834 835 bad: 836 while (scnip != NULL) { 837 tmpscnip = scnip->scni_next; 838 free(scnip); 839 scnip = tmpscnip; 840 } 841 return (retval); 842 } 843 844 struct filesignatures * 845 elfsign_insert_dso(ELFsign_t ess, 846 struct filesignatures *fssp, 847 const char *dn, 848 int dn_len, 849 const uchar_t *sig, 850 int sig_len, 851 const char *oid, 852 int oid_len) 853 { 854 return (filesig_insert_dso(fssp, ess->es_version, dn, dn_len, 855 sig, sig_len, oid, oid_len)); 856 } 857 858 /*ARGSUSED*/ 859 filesig_vers_t 860 elfsign_extract_sig(ELFsign_t ess, 861 struct filesignatures *fssp, 862 uchar_t *sig, 863 size_t *sig_len) 864 { 865 struct filesig_extraction fsx; 866 filesig_vers_t version; 867 868 if (fssp == NULL) 869 return (FILESIG_UNKNOWN); 870 if (fssp->filesig_cnt != 1) 871 return (FILESIG_UNKNOWN); 872 version = filesig_extract(&fssp->filesig_sig, &fsx); 873 switch (version) { 874 case FILESIG_VERSION1: 875 case FILESIG_VERSION2: 876 case FILESIG_VERSION3: 877 case FILESIG_VERSION4: 878 if (*sig_len >= fsx.fsx_sig_len) { 879 (void) memcpy((char *)sig, (char *)fsx.fsx_signature, 880 *sig_len); 881 *sig_len = fsx.fsx_sig_len; 882 } else 883 version = FILESIG_UNKNOWN; 884 break; 885 default: 886 version = FILESIG_UNKNOWN; 887 break; 888 } 889 890 if (ess->es_version == FILESIG_UNKNOWN) { 891 ess->es_version = version; 892 } 893 894 return (version); 895 } 896 897 static ELFsign_status_t 898 elfsign_hash_common(ELFsign_t ess, uchar_t *hash, size_t *hash_len, 899 boolean_t hash_mem_resident) 900 { 901 Elf_Scn *scn = NULL; 902 ELFsign_status_t elfstat; 903 GElf_Shdr shdr; 904 SHA1_CTX ctx; 905 906 /* The buffer must be large enough to hold the hash */ 907 if (*hash_len < SHA1_DIGEST_LENGTH) 908 return (ELFSIGN_FAILED); 909 910 bzero(hash, *hash_len); 911 912 /* Initialize the digest session */ 913 SHA1Init(&ctx); 914 915 scn = elf_getscn(ess->es_elf, 0); /* "seek" to start */ 916 (void) elf_errno(); 917 while ((scn = elf_nextscn(ess->es_elf, scn)) != 0) { 918 char *name = NULL; 919 Elf_Data *data = NULL; 920 921 if (gelf_getshdr(scn, &shdr) == NULL) { 922 elfstat = ELFSIGN_FAILED; 923 goto done; 924 } 925 926 name = elf_strptr(ess->es_elf, ess->es_shstrndx, 927 (size_t)shdr.sh_name); 928 if (name == NULL) 929 name = "NULL"; 930 931 if (!hash_mem_resident && 932 (ess->es_version == FILESIG_VERSION1 || 933 ess->es_version == FILESIG_VERSION3)) { 934 /* 935 * skip the signature section only 936 */ 937 if (shdr.sh_type == SHT_SUNW_SIGNATURE) { 938 cryptodebug("elfsign_hash: skipping %s", name); 939 continue; 940 } 941 } else if (!(shdr.sh_flags & SHF_ALLOC)) { 942 /* 943 * select only memory resident sections 944 */ 945 cryptodebug("elfsign_hash: skipping %s", name); 946 continue; 947 } 948 949 /* 950 * throw this section into the hash 951 * use elf_rawdata for endian-independence 952 * use elf_getdata to get update of .shstrtab 953 */ 954 while ((data = (shdr.sh_type == SHT_STRTAB ? 955 elf_getdata(scn, data) : elf_rawdata(scn, data))) != NULL) { 956 if (data->d_buf == NULL) { 957 cryptodebug("elfsign_hash: %s has NULL data", 958 name); 959 continue; 960 } 961 cryptodebug("elfsign_hash: updating hash " 962 "with %s data size=%d", name, data->d_size); 963 SHA1Update(&ctx, data->d_buf, data->d_size); 964 } 965 } 966 if (elf_errmsg(0) != NULL) { 967 cryptodebug("elfsign_hash: %s", elf_errmsg(-1)); 968 elfstat = ELFSIGN_FAILED; 969 goto done; 970 } 971 972 SHA1Final(hash, &ctx); 973 *hash_len = SHA1_DIGEST_LENGTH; 974 { /* DEBUG START */ 975 const int hashstr_len = (*hash_len) * 2 + 1; 976 char *hashstr = malloc(hashstr_len); 977 978 if (hashstr != NULL) { 979 tohexstr(hash, *hash_len, hashstr, hashstr_len); 980 cryptodebug("hash value is: %s", hashstr); 981 free(hashstr); 982 } 983 } /* DEBUG END */ 984 elfstat = ELFSIGN_SUCCESS; 985 done: 986 return (elfstat); 987 } 988 989 /* 990 * elfsign_hash - return the hash of the ELF sections affecting execution. 991 * 992 * IN: ess, hash_len 993 * OUT: hash, hash_len 994 */ 995 ELFsign_status_t 996 elfsign_hash(ELFsign_t ess, uchar_t *hash, size_t *hash_len) 997 { 998 return (elfsign_hash_common(ess, hash, hash_len, B_FALSE)); 999 } 1000 1001 /* 1002 * elfsign_hash_mem_resident - return the hash of the ELF sections 1003 * with only memory resident sections. 1004 * 1005 * IN: ess, hash_len 1006 * OUT: hash, hash_len 1007 */ 1008 ELFsign_status_t 1009 elfsign_hash_mem_resident(ELFsign_t ess, uchar_t *hash, size_t *hash_len) 1010 { 1011 return (elfsign_hash_common(ess, hash, hash_len, B_TRUE)); 1012 } 1013 1014 /* 1015 * elfsign_hash_esa = return the hash of the esa_buffer 1016 * 1017 * IN: ess, esa_buf, esa_buf_len, hash_len 1018 * OUT: hash, hash_len 1019 */ 1020 ELFsign_status_t 1021 elfsign_hash_esa(ELFsign_t ess, uchar_t *esa_buf, size_t esa_buf_len, 1022 uchar_t **hash, size_t *hash_len) 1023 { 1024 SHA1_CTX ctx; 1025 1026 cryptodebug("esa_hash version is: %s", 1027 version_to_str(ess->es_version)); 1028 if (ess->es_version <= FILESIG_VERSION2) { 1029 /* 1030 * old rsa_md5_sha1 format 1031 * signed with MD5 digest, just pass full esa_buf 1032 */ 1033 *hash = esa_buf; 1034 *hash_len = esa_buf_len; 1035 return (ELFSIGN_SUCCESS); 1036 } 1037 1038 if (*hash_len < SHA1_DIGEST_LENGTH) 1039 return (ELFSIGN_FAILED); 1040 1041 bzero(*hash, *hash_len); 1042 SHA1Init(&ctx); 1043 SHA1Update(&ctx, esa_buf, esa_buf_len); 1044 SHA1Final(*hash, &ctx); 1045 *hash_len = SHA1_DIGEST_LENGTH; 1046 1047 { /* DEBUG START */ 1048 const int hashstr_len = (*hash_len) * 2 + 1; 1049 char *hashstr = malloc(hashstr_len); 1050 1051 if (hashstr != NULL) { 1052 tohexstr(*hash, *hash_len, hashstr, hashstr_len); 1053 cryptodebug("esa_hash value is: %s", hashstr); 1054 free(hashstr); 1055 } 1056 } /* DEBUG END */ 1057 1058 return (ELFSIGN_SUCCESS); 1059 } 1060 1061 /* 1062 * elfsign_verify_signature - Verify the signature of the ELF object. 1063 * 1064 * IN: ess 1065 * OUT: esipp 1066 * RETURNS: 1067 * ELFsign_status_t 1068 */ 1069 ELFsign_status_t 1070 elfsign_verify_signature(ELFsign_t ess, struct ELFsign_sig_info **esipp) 1071 { 1072 ELFsign_status_t ret = ELFSIGN_FAILED; 1073 struct filesignatures *fssp; 1074 struct filesig *fsgp; 1075 size_t fslen; 1076 struct filesig_extraction fsx; 1077 uchar_t hash[SIG_MAX_LENGTH]; 1078 size_t hash_len; 1079 ELFCert_t cert = NULL; 1080 int sigcnt; 1081 int nocert = 0; 1082 struct ELFsign_sig_info *esip = NULL; 1083 1084 if (esipp != NULL) { 1085 esip = (struct ELFsign_sig_info *) 1086 calloc(1, sizeof (struct ELFsign_sig_info)); 1087 *esipp = esip; 1088 } 1089 1090 /* 1091 * Find out which cert we need, based on who signed the ELF object 1092 */ 1093 if (elfsign_signatures(ess, &fssp, &fslen, ES_GET) != ELFSIGN_SUCCESS) { 1094 return (ELFSIGN_NOTSIGNED); 1095 } 1096 1097 if (fssp->filesig_cnt < 1) { 1098 ret = ELFSIGN_FAILED; 1099 goto cleanup; 1100 } 1101 1102 fsgp = &fssp->filesig_sig; 1103 1104 /* 1105 * Scan the signature block, looking for a verifiable signature 1106 */ 1107 for (sigcnt = 0; sigcnt < fssp->filesig_cnt; 1108 sigcnt++, fsgp = filesig_next(fsgp)) { 1109 ess->es_version = filesig_extract(fsgp, &fsx); 1110 cryptodebug("elfsign_verify_signature: version=%s", 1111 version_to_str(ess->es_version)); 1112 switch (ess->es_version) { 1113 case FILESIG_VERSION1: 1114 case FILESIG_VERSION2: 1115 case FILESIG_VERSION3: 1116 case FILESIG_VERSION4: 1117 break; 1118 default: 1119 ret = ELFSIGN_FAILED; 1120 goto cleanup; 1121 } 1122 1123 cryptodebug("elfsign_verify_signature: signer_DN=\"%s\"", 1124 fsx.fsx_signer_DN); 1125 cryptodebug("elfsign_verify_signature: algorithmOID=\"%s\"", 1126 fsx.fsx_sig_oid); 1127 /* return signer DN if requested */ 1128 if (esipp != NULL) { 1129 esip->esi_format = fsx.fsx_format; 1130 if (esip->esi_signer != NULL) 1131 free(esip->esi_signer); 1132 esip->esi_signer = strdup(fsx.fsx_signer_DN); 1133 esip->esi_time = fsx.fsx_time; 1134 } 1135 1136 /* 1137 * look for certificate 1138 */ 1139 if (cert != NULL) 1140 elfcertlib_releasecert(ess, cert); 1141 1142 /* 1143 * skip unfound certificates 1144 */ 1145 if (!elfcertlib_getcert(ess, ess->es_certpath, 1146 fsx.fsx_signer_DN, &cert, ess->es_action)) { 1147 cryptodebug("unable to find certificate " 1148 "with DN=\"%s\" for %s", 1149 fsx.fsx_signer_DN, ess->es_pathname); 1150 nocert++; 1151 continue; 1152 } 1153 1154 /* 1155 * skip unverified certificates 1156 * force verification of crypto certs 1157 */ 1158 if ((ess->es_action == ES_GET_CRYPTO || 1159 ess->es_action == ES_GET_FIPS140 || 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