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