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