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