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