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