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