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