xref: /onnv-gate/usr/src/common/crypto/fips/fips_checksum.c (revision 12929:f2051cc42292)
1*12929SMisaki.Miyashita@Oracle.COM /*
2*12929SMisaki.Miyashita@Oracle.COM  * CDDL HEADER START
3*12929SMisaki.Miyashita@Oracle.COM  *
4*12929SMisaki.Miyashita@Oracle.COM  * The contents of this file are subject to the terms of the
5*12929SMisaki.Miyashita@Oracle.COM  * Common Development and Distribution License (the "License").
6*12929SMisaki.Miyashita@Oracle.COM  * You may not use this file except in compliance with the License.
7*12929SMisaki.Miyashita@Oracle.COM  *
8*12929SMisaki.Miyashita@Oracle.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12929SMisaki.Miyashita@Oracle.COM  * or http://www.opensolaris.org/os/licensing.
10*12929SMisaki.Miyashita@Oracle.COM  * See the License for the specific language governing permissions
11*12929SMisaki.Miyashita@Oracle.COM  * and limitations under the License.
12*12929SMisaki.Miyashita@Oracle.COM  *
13*12929SMisaki.Miyashita@Oracle.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12929SMisaki.Miyashita@Oracle.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12929SMisaki.Miyashita@Oracle.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12929SMisaki.Miyashita@Oracle.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12929SMisaki.Miyashita@Oracle.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12929SMisaki.Miyashita@Oracle.COM  *
19*12929SMisaki.Miyashita@Oracle.COM  * CDDL HEADER END
20*12929SMisaki.Miyashita@Oracle.COM  */
21*12929SMisaki.Miyashita@Oracle.COM /*
22*12929SMisaki.Miyashita@Oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*12929SMisaki.Miyashita@Oracle.COM  */
24*12929SMisaki.Miyashita@Oracle.COM 
25*12929SMisaki.Miyashita@Oracle.COM 
26*12929SMisaki.Miyashita@Oracle.COM #include <fips/fips_checksum.h>
27*12929SMisaki.Miyashita@Oracle.COM 
28*12929SMisaki.Miyashita@Oracle.COM 
29*12929SMisaki.Miyashita@Oracle.COM #ifdef	_KERNEL
30*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_ALLOC(size)	kmem_alloc(size, KM_SLEEP)
31*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_FREE(buf, size)	kmem_free(buf, size)
32*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_READ_FILE		kobj_read_file
33*12929SMisaki.Miyashita@Oracle.COM #define	ERRLOG0(str)		cmn_err(CE_NOTE, str)
34*12929SMisaki.Miyashita@Oracle.COM #define	ERRLOG1(fmt, arg)	cmn_err(CE_NOTE, fmt, arg)
35*12929SMisaki.Miyashita@Oracle.COM #include <sys/sunddi.h>
36*12929SMisaki.Miyashita@Oracle.COM 
37*12929SMisaki.Miyashita@Oracle.COM struct _buf *kobj_open_file(char *name);
38*12929SMisaki.Miyashita@Oracle.COM int kobj_read_file(struct _buf *file, char *buf, uint_t size, uint_t off);
39*12929SMisaki.Miyashita@Oracle.COM #else
40*12929SMisaki.Miyashita@Oracle.COM 
41*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_ALLOC(size)	malloc(size)
42*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_FREE(buf, size)	free(buf)
43*12929SMisaki.Miyashita@Oracle.COM #define	FIPS_READ_FILE		fips_read_file
44*12929SMisaki.Miyashita@Oracle.COM #define	ERRLOG0(str)		(void) printf(str)
45*12929SMisaki.Miyashita@Oracle.COM #define	ERRLOG1(fmt, arg)	(void) printf(fmt, arg)
46*12929SMisaki.Miyashita@Oracle.COM #endif
47*12929SMisaki.Miyashita@Oracle.COM 
48*12929SMisaki.Miyashita@Oracle.COM #define	NUM_SECTIONS	(sizeof (checked_sec_names) / sizeof (char *))
49*12929SMisaki.Miyashita@Oracle.COM 
50*12929SMisaki.Miyashita@Oracle.COM static char *checked_sec_names[] = {
51*12929SMisaki.Miyashita@Oracle.COM 	".strtab",
52*12929SMisaki.Miyashita@Oracle.COM 	".dynamic",
53*12929SMisaki.Miyashita@Oracle.COM 	".compcom",
54*12929SMisaki.Miyashita@Oracle.COM 	".comment",
55*12929SMisaki.Miyashita@Oracle.COM 	".dynstr",
56*12929SMisaki.Miyashita@Oracle.COM 	".shstrtab",
57*12929SMisaki.Miyashita@Oracle.COM 	".rela.text",
58*12929SMisaki.Miyashita@Oracle.COM 	".rela.data",
59*12929SMisaki.Miyashita@Oracle.COM 	".text",
60*12929SMisaki.Miyashita@Oracle.COM 	".rodata",
61*12929SMisaki.Miyashita@Oracle.COM 	".rodata1",
62*12929SMisaki.Miyashita@Oracle.COM 	".data",
63*12929SMisaki.Miyashita@Oracle.COM 	".symtab",
64*12929SMisaki.Miyashita@Oracle.COM 	".SUNW_ctf",
65*12929SMisaki.Miyashita@Oracle.COM 	".bss"
66*12929SMisaki.Miyashita@Oracle.COM };
67*12929SMisaki.Miyashita@Oracle.COM 
68*12929SMisaki.Miyashita@Oracle.COM 
69*12929SMisaki.Miyashita@Oracle.COM static int
70*12929SMisaki.Miyashita@Oracle.COM #ifdef	_KERNEL
process_section(SHA1_CTX * shactx,Elf64_Shdr * section,struct _buf * file,char * shstrtab)71*12929SMisaki.Miyashita@Oracle.COM process_section(SHA1_CTX *shactx, Elf64_Shdr *section, struct _buf *file,
72*12929SMisaki.Miyashita@Oracle.COM     char *shstrtab)
73*12929SMisaki.Miyashita@Oracle.COM #else
74*12929SMisaki.Miyashita@Oracle.COM process_section(SHA1_CTX *shactx, Elf64_Shdr *section, int file,
75*12929SMisaki.Miyashita@Oracle.COM     char *shstrtab)
76*12929SMisaki.Miyashita@Oracle.COM #endif
77*12929SMisaki.Miyashita@Oracle.COM {
78*12929SMisaki.Miyashita@Oracle.COM 	size_t		size, offs;
79*12929SMisaki.Miyashita@Oracle.COM 	char		*name;
80*12929SMisaki.Miyashita@Oracle.COM 	int		doit = 0;
81*12929SMisaki.Miyashita@Oracle.COM 	char		*buf;
82*12929SMisaki.Miyashita@Oracle.COM 	int		i;
83*12929SMisaki.Miyashita@Oracle.COM 
84*12929SMisaki.Miyashita@Oracle.COM 	size = section->sh_size;
85*12929SMisaki.Miyashita@Oracle.COM 	offs = section->sh_offset;
86*12929SMisaki.Miyashita@Oracle.COM 	name = shstrtab + section->sh_name;
87*12929SMisaki.Miyashita@Oracle.COM 	for (i = 0; i < NUM_SECTIONS; i++) {
88*12929SMisaki.Miyashita@Oracle.COM 		if (strncmp(name, checked_sec_names[i],
89*12929SMisaki.Miyashita@Oracle.COM 		    strlen(checked_sec_names[i]) + 1) == 0) {
90*12929SMisaki.Miyashita@Oracle.COM 			doit++;
91*12929SMisaki.Miyashita@Oracle.COM 			break;
92*12929SMisaki.Miyashita@Oracle.COM 		}
93*12929SMisaki.Miyashita@Oracle.COM 	}
94*12929SMisaki.Miyashita@Oracle.COM 
95*12929SMisaki.Miyashita@Oracle.COM 	if (!doit) {
96*12929SMisaki.Miyashita@Oracle.COM 		return (0);
97*12929SMisaki.Miyashita@Oracle.COM 	}
98*12929SMisaki.Miyashita@Oracle.COM 
99*12929SMisaki.Miyashita@Oracle.COM 	/* hash the size of .bss section */
100*12929SMisaki.Miyashita@Oracle.COM 	if (strcmp(name, ".bss") == 0) {
101*12929SMisaki.Miyashita@Oracle.COM 		char	szstr[32];
102*12929SMisaki.Miyashita@Oracle.COM 		(void) snprintf(szstr, sizeof (szstr), "%ld", size);
103*12929SMisaki.Miyashita@Oracle.COM 		SHA1Update(shactx, szstr, strlen(szstr));
104*12929SMisaki.Miyashita@Oracle.COM 		return (0);
105*12929SMisaki.Miyashita@Oracle.COM 	}
106*12929SMisaki.Miyashita@Oracle.COM 
107*12929SMisaki.Miyashita@Oracle.COM 
108*12929SMisaki.Miyashita@Oracle.COM 	/* hash the contents of the section */
109*12929SMisaki.Miyashita@Oracle.COM 	if ((buf = FIPS_ALLOC(size)) == NULL) {
110*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG1("Not enough memory for section %s\n", name);
111*12929SMisaki.Miyashita@Oracle.COM 		return (-1);
112*12929SMisaki.Miyashita@Oracle.COM 	}
113*12929SMisaki.Miyashita@Oracle.COM 
114*12929SMisaki.Miyashita@Oracle.COM 	if (FIPS_READ_FILE(file, buf, size, offs) < 0) {
115*12929SMisaki.Miyashita@Oracle.COM 		FIPS_FREE(buf, size);
116*12929SMisaki.Miyashita@Oracle.COM 		return (-2);
117*12929SMisaki.Miyashita@Oracle.COM 	}
118*12929SMisaki.Miyashita@Oracle.COM 
119*12929SMisaki.Miyashita@Oracle.COM 	SHA1Update(shactx, buf, size);
120*12929SMisaki.Miyashita@Oracle.COM 
121*12929SMisaki.Miyashita@Oracle.COM 	FIPS_FREE(buf, size);
122*12929SMisaki.Miyashita@Oracle.COM 
123*12929SMisaki.Miyashita@Oracle.COM 	return (0);
124*12929SMisaki.Miyashita@Oracle.COM }
125*12929SMisaki.Miyashita@Oracle.COM 
126*12929SMisaki.Miyashita@Oracle.COM int
127*12929SMisaki.Miyashita@Oracle.COM #ifdef	_KERNEL
fips_calc_checksum(struct _buf * file,Elf64_Ehdr * ehdr,char * sha1buf)128*12929SMisaki.Miyashita@Oracle.COM fips_calc_checksum(struct _buf *file, Elf64_Ehdr *ehdr, char *sha1buf)
129*12929SMisaki.Miyashita@Oracle.COM #else
130*12929SMisaki.Miyashita@Oracle.COM fips_calc_checksum(int file, Elf64_Ehdr *ehdr, char *sha1buf)
131*12929SMisaki.Miyashita@Oracle.COM #endif
132*12929SMisaki.Miyashita@Oracle.COM {
133*12929SMisaki.Miyashita@Oracle.COM 	unsigned int	size, numsec;
134*12929SMisaki.Miyashita@Oracle.COM 	Elf64_Shdr	*shdrs;
135*12929SMisaki.Miyashita@Oracle.COM 	Elf64_Shdr	*section;
136*12929SMisaki.Miyashita@Oracle.COM 	SHA1_CTX	sha1ctx;
137*12929SMisaki.Miyashita@Oracle.COM 	char		*shstrtab;
138*12929SMisaki.Miyashita@Oracle.COM 	int		i;
139*12929SMisaki.Miyashita@Oracle.COM 
140*12929SMisaki.Miyashita@Oracle.COM 	numsec = ehdr->e_shnum;
141*12929SMisaki.Miyashita@Oracle.COM 	size = ehdr->e_shentsize * numsec;
142*12929SMisaki.Miyashita@Oracle.COM 	if ((shdrs = (Elf64_Shdr *)FIPS_ALLOC(size)) == NULL) {
143*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG0("Not enough memory for shdrs\n");
144*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
145*12929SMisaki.Miyashita@Oracle.COM 	}
146*12929SMisaki.Miyashita@Oracle.COM 	if (FIPS_READ_FILE(file, (char *)shdrs, size, ehdr->e_shoff) < 0) {
147*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
148*12929SMisaki.Miyashita@Oracle.COM 	}
149*12929SMisaki.Miyashita@Oracle.COM 
150*12929SMisaki.Miyashita@Oracle.COM 	/* Obtain the .shstrtab data buffer */
151*12929SMisaki.Miyashita@Oracle.COM 	section = &(shdrs[ehdr->e_shstrndx]);
152*12929SMisaki.Miyashita@Oracle.COM 	size = section->sh_size;
153*12929SMisaki.Miyashita@Oracle.COM 	if ((shstrtab = (char *)FIPS_ALLOC(size)) == NULL) {
154*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG0("Not enough memory for shstrtab\n");
155*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
156*12929SMisaki.Miyashita@Oracle.COM 	}
157*12929SMisaki.Miyashita@Oracle.COM 	if (FIPS_READ_FILE(file, shstrtab, size, section->sh_offset) < 0) {
158*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
159*12929SMisaki.Miyashita@Oracle.COM 	}
160*12929SMisaki.Miyashita@Oracle.COM 
161*12929SMisaki.Miyashita@Oracle.COM 	SHA1Init(&sha1ctx);
162*12929SMisaki.Miyashita@Oracle.COM 	for (i = 0; i < numsec; i++) {
163*12929SMisaki.Miyashita@Oracle.COM 		if (process_section(&sha1ctx, &(shdrs[i]),
164*12929SMisaki.Miyashita@Oracle.COM 		    file, shstrtab) < 0) {
165*12929SMisaki.Miyashita@Oracle.COM 			return (FAILURE);
166*12929SMisaki.Miyashita@Oracle.COM 		}
167*12929SMisaki.Miyashita@Oracle.COM 	}
168*12929SMisaki.Miyashita@Oracle.COM 	SHA1Final(sha1buf, &sha1ctx);
169*12929SMisaki.Miyashita@Oracle.COM 
170*12929SMisaki.Miyashita@Oracle.COM 	return (0);
171*12929SMisaki.Miyashita@Oracle.COM }
172*12929SMisaki.Miyashita@Oracle.COM 
173*12929SMisaki.Miyashita@Oracle.COM 
174*12929SMisaki.Miyashita@Oracle.COM #ifndef	_KERNEL
175*12929SMisaki.Miyashita@Oracle.COM 
176*12929SMisaki.Miyashita@Oracle.COM int
fips_read_file(int fd,char * buf,int size,int offs)177*12929SMisaki.Miyashita@Oracle.COM fips_read_file(int fd, char *buf, int size, int offs)
178*12929SMisaki.Miyashita@Oracle.COM {
179*12929SMisaki.Miyashita@Oracle.COM 	int	i;
180*12929SMisaki.Miyashita@Oracle.COM 
181*12929SMisaki.Miyashita@Oracle.COM 	if (lseek(fd, offs, SEEK_SET) == (off_t)(-1)) {
182*12929SMisaki.Miyashita@Oracle.COM 		(void) fprintf(stderr,
183*12929SMisaki.Miyashita@Oracle.COM 		    "lseek returned an error for file %d\n", fd);
184*12929SMisaki.Miyashita@Oracle.COM 		return (-1);
185*12929SMisaki.Miyashita@Oracle.COM 	}
186*12929SMisaki.Miyashita@Oracle.COM 	while ((i = read(fd, buf, size)) >= 0) {
187*12929SMisaki.Miyashita@Oracle.COM 		if (size == i) {
188*12929SMisaki.Miyashita@Oracle.COM 			break;
189*12929SMisaki.Miyashita@Oracle.COM 		} else {
190*12929SMisaki.Miyashita@Oracle.COM 			size -= i;
191*12929SMisaki.Miyashita@Oracle.COM 			buf += i;
192*12929SMisaki.Miyashita@Oracle.COM 		}
193*12929SMisaki.Miyashita@Oracle.COM 	}
194*12929SMisaki.Miyashita@Oracle.COM 	if (i < 0) {
195*12929SMisaki.Miyashita@Oracle.COM 		(void) fprintf(stderr, "read failed for file %d\n", fd);
196*12929SMisaki.Miyashita@Oracle.COM 		return (-2);
197*12929SMisaki.Miyashita@Oracle.COM 	}
198*12929SMisaki.Miyashita@Oracle.COM 
199*12929SMisaki.Miyashita@Oracle.COM 	return (0);
200*12929SMisaki.Miyashita@Oracle.COM }
201*12929SMisaki.Miyashita@Oracle.COM 
202*12929SMisaki.Miyashita@Oracle.COM #else
203*12929SMisaki.Miyashita@Oracle.COM 
204*12929SMisaki.Miyashita@Oracle.COM static int
get_fips_section(Elf64_Ehdr * ehdr,struct _buf * file,char * expected_checksum)205*12929SMisaki.Miyashita@Oracle.COM get_fips_section(Elf64_Ehdr *ehdr, struct _buf *file, char *expected_checksum)
206*12929SMisaki.Miyashita@Oracle.COM {
207*12929SMisaki.Miyashita@Oracle.COM 	unsigned int	shdrssz, shstrtabsz, numsec;
208*12929SMisaki.Miyashita@Oracle.COM 	Elf64_Shdr	*shdrs = NULL;
209*12929SMisaki.Miyashita@Oracle.COM 	Elf64_Shdr	*section;
210*12929SMisaki.Miyashita@Oracle.COM 	char		*shstrtab = NULL;
211*12929SMisaki.Miyashita@Oracle.COM 	char		*name;
212*12929SMisaki.Miyashita@Oracle.COM 	int		rv = FAILURE;
213*12929SMisaki.Miyashita@Oracle.COM 	int		i;
214*12929SMisaki.Miyashita@Oracle.COM 
215*12929SMisaki.Miyashita@Oracle.COM 	numsec = ehdr->e_shnum;
216*12929SMisaki.Miyashita@Oracle.COM 	shdrssz = ehdr->e_shentsize * numsec;
217*12929SMisaki.Miyashita@Oracle.COM 	if ((shdrs = (Elf64_Shdr *)FIPS_ALLOC(shdrssz)) == NULL) {
218*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG0("Not enough memory for shdrs\n");
219*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
220*12929SMisaki.Miyashita@Oracle.COM 	}
221*12929SMisaki.Miyashita@Oracle.COM 	if (FIPS_READ_FILE(file, (char *)shdrs, shdrssz, ehdr->e_shoff) < 0) {
222*12929SMisaki.Miyashita@Oracle.COM 		goto exit;
223*12929SMisaki.Miyashita@Oracle.COM 	}
224*12929SMisaki.Miyashita@Oracle.COM 
225*12929SMisaki.Miyashita@Oracle.COM 	/* Obtain the .shstrtab data buffer */
226*12929SMisaki.Miyashita@Oracle.COM 	section = &(shdrs[ehdr->e_shstrndx]);
227*12929SMisaki.Miyashita@Oracle.COM 	shstrtabsz = section->sh_size;
228*12929SMisaki.Miyashita@Oracle.COM 	if ((shstrtab = (char *)FIPS_ALLOC(shstrtabsz)) == NULL) {
229*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG0("Not enough memory for shstrtab\n");
230*12929SMisaki.Miyashita@Oracle.COM 		goto exit;
231*12929SMisaki.Miyashita@Oracle.COM 	}
232*12929SMisaki.Miyashita@Oracle.COM 	if (FIPS_READ_FILE(file, shstrtab, shstrtabsz,
233*12929SMisaki.Miyashita@Oracle.COM 	    section->sh_offset) < 0) {
234*12929SMisaki.Miyashita@Oracle.COM 		goto exit;
235*12929SMisaki.Miyashita@Oracle.COM 	}
236*12929SMisaki.Miyashita@Oracle.COM 
237*12929SMisaki.Miyashita@Oracle.COM 	for (i = 0; i < numsec; i++) {
238*12929SMisaki.Miyashita@Oracle.COM 		section = &shdrs[i];
239*12929SMisaki.Miyashita@Oracle.COM 		name = shstrtab + section->sh_name;
240*12929SMisaki.Miyashita@Oracle.COM 		/* Get the checksum stored in the .SUNW_fips section */
241*12929SMisaki.Miyashita@Oracle.COM 		if (strcmp(name, ".SUNW_fips") == 0) {
242*12929SMisaki.Miyashita@Oracle.COM 			if (section->sh_size != SHA1_DIGEST_LENGTH) {
243*12929SMisaki.Miyashita@Oracle.COM 				goto exit;
244*12929SMisaki.Miyashita@Oracle.COM 			}
245*12929SMisaki.Miyashita@Oracle.COM 			if (FIPS_READ_FILE(file, expected_checksum,
246*12929SMisaki.Miyashita@Oracle.COM 			    section->sh_size, section->sh_offset) < 0) {
247*12929SMisaki.Miyashita@Oracle.COM 				goto exit;
248*12929SMisaki.Miyashita@Oracle.COM 			}
249*12929SMisaki.Miyashita@Oracle.COM 			rv = 0;
250*12929SMisaki.Miyashita@Oracle.COM 			goto exit;
251*12929SMisaki.Miyashita@Oracle.COM 		}
252*12929SMisaki.Miyashita@Oracle.COM 	}
253*12929SMisaki.Miyashita@Oracle.COM 
254*12929SMisaki.Miyashita@Oracle.COM 
255*12929SMisaki.Miyashita@Oracle.COM exit:
256*12929SMisaki.Miyashita@Oracle.COM 	if (shdrs != NULL) {
257*12929SMisaki.Miyashita@Oracle.COM 		FIPS_FREE(shdrs, shdrssz);
258*12929SMisaki.Miyashita@Oracle.COM 	}
259*12929SMisaki.Miyashita@Oracle.COM 	if (shstrtab != NULL) {
260*12929SMisaki.Miyashita@Oracle.COM 		FIPS_FREE(shstrtab, shstrtabsz);
261*12929SMisaki.Miyashita@Oracle.COM 	}
262*12929SMisaki.Miyashita@Oracle.COM 
263*12929SMisaki.Miyashita@Oracle.COM 	return (rv);
264*12929SMisaki.Miyashita@Oracle.COM }
265*12929SMisaki.Miyashita@Oracle.COM 
266*12929SMisaki.Miyashita@Oracle.COM 
267*12929SMisaki.Miyashita@Oracle.COM int
fips_check_module(char * modname,void * _initaddr)268*12929SMisaki.Miyashita@Oracle.COM fips_check_module(char *modname, void *_initaddr)
269*12929SMisaki.Miyashita@Oracle.COM {
270*12929SMisaki.Miyashita@Oracle.COM 	struct modctl	*modctlp = NULL;
271*12929SMisaki.Miyashita@Oracle.COM 	struct module	*mp = NULL;
272*12929SMisaki.Miyashita@Oracle.COM 	struct _buf	*file;
273*12929SMisaki.Miyashita@Oracle.COM 	char		*filename;
274*12929SMisaki.Miyashita@Oracle.COM 	Elf64_Ehdr	ehdr;
275*12929SMisaki.Miyashita@Oracle.COM 	unsigned int	size, i;
276*12929SMisaki.Miyashita@Oracle.COM 	char		sha1buf[SHA1_DIGEST_LENGTH];
277*12929SMisaki.Miyashita@Oracle.COM 	char		expected_checksum[SHA1_DIGEST_LENGTH];
278*12929SMisaki.Miyashita@Oracle.COM 
279*12929SMisaki.Miyashita@Oracle.COM 	modctlp = mod_find_by_filename(NULL, modname);
280*12929SMisaki.Miyashita@Oracle.COM 	if (modctlp == NULL) {
281*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG1("module with modname %s not found\n", modname);
282*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
283*12929SMisaki.Miyashita@Oracle.COM 	}
284*12929SMisaki.Miyashita@Oracle.COM 	mp = (struct module *)modctlp->mod_mp;
285*12929SMisaki.Miyashita@Oracle.COM 	if (mp != NULL && mp->filename != NULL) {
286*12929SMisaki.Miyashita@Oracle.COM 		filename = mp->filename;
287*12929SMisaki.Miyashita@Oracle.COM 	} else {
288*12929SMisaki.Miyashita@Oracle.COM 		/* filename does not exist */
289*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
290*12929SMisaki.Miyashita@Oracle.COM 	}
291*12929SMisaki.Miyashita@Oracle.COM 	if ((mp->text > (char *)_initaddr) ||
292*12929SMisaki.Miyashita@Oracle.COM 	    (mp->text + mp->text_size < (char *)_initaddr)) {
293*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG1("_init() is not in module %s\n", modname);
294*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
295*12929SMisaki.Miyashita@Oracle.COM 	}
296*12929SMisaki.Miyashita@Oracle.COM 
297*12929SMisaki.Miyashita@Oracle.COM 	if ((file = kobj_open_file(filename)) == (struct _buf *)-1) {
298*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG1("Cannot open %s\n", filename);
299*12929SMisaki.Miyashita@Oracle.COM 		return (FAILURE);
300*12929SMisaki.Miyashita@Oracle.COM 	}
301*12929SMisaki.Miyashita@Oracle.COM 	/* Read the ELF header */
302*12929SMisaki.Miyashita@Oracle.COM 	size =  sizeof (ehdr);
303*12929SMisaki.Miyashita@Oracle.COM 	if (kobj_read_file(file, (char *)(&ehdr), size, 0) < 0) {
304*12929SMisaki.Miyashita@Oracle.COM 		goto fail_exit;
305*12929SMisaki.Miyashita@Oracle.COM 	}
306*12929SMisaki.Miyashita@Oracle.COM 
307*12929SMisaki.Miyashita@Oracle.COM 	/* check if it is an ELF file */
308*12929SMisaki.Miyashita@Oracle.COM 	for (i = 0; i < SELFMAG; i++) {
309*12929SMisaki.Miyashita@Oracle.COM 		if (ehdr.e_ident[i] != ELFMAG[i]) {
310*12929SMisaki.Miyashita@Oracle.COM 			ERRLOG1("%s not an elf file\n", filename);
311*12929SMisaki.Miyashita@Oracle.COM 			goto fail_exit;
312*12929SMisaki.Miyashita@Oracle.COM 		}
313*12929SMisaki.Miyashita@Oracle.COM 	}
314*12929SMisaki.Miyashita@Oracle.COM 
315*12929SMisaki.Miyashita@Oracle.COM 	/* check if it is relocatable */
316*12929SMisaki.Miyashita@Oracle.COM 	if (ehdr.e_type != ET_REL) {
317*12929SMisaki.Miyashita@Oracle.COM 		ERRLOG1("%s isn't a relocatable (ET_REL) "
318*12929SMisaki.Miyashita@Oracle.COM 		    "module\n", filename);
319*12929SMisaki.Miyashita@Oracle.COM 		goto fail_exit;
320*12929SMisaki.Miyashita@Oracle.COM 	}
321*12929SMisaki.Miyashita@Oracle.COM 
322*12929SMisaki.Miyashita@Oracle.COM 	if (fips_calc_checksum(file, &ehdr, sha1buf) < 0) {
323*12929SMisaki.Miyashita@Oracle.COM 		goto fail_exit;
324*12929SMisaki.Miyashita@Oracle.COM 	}
325*12929SMisaki.Miyashita@Oracle.COM 
326*12929SMisaki.Miyashita@Oracle.COM 	if (get_fips_section(&ehdr, file, expected_checksum) < 0) {
327*12929SMisaki.Miyashita@Oracle.COM 		goto fail_exit;
328*12929SMisaki.Miyashita@Oracle.COM 	}
329*12929SMisaki.Miyashita@Oracle.COM 
330*12929SMisaki.Miyashita@Oracle.COM 	if (memcmp(sha1buf, expected_checksum, SHA1_DIGEST_LENGTH) != 0) {
331*12929SMisaki.Miyashita@Oracle.COM 		goto fail_exit;
332*12929SMisaki.Miyashita@Oracle.COM 	}
333*12929SMisaki.Miyashita@Oracle.COM 
334*12929SMisaki.Miyashita@Oracle.COM 	kobj_close_file(file);
335*12929SMisaki.Miyashita@Oracle.COM 
336*12929SMisaki.Miyashita@Oracle.COM 	return (SUCCESS);
337*12929SMisaki.Miyashita@Oracle.COM 
338*12929SMisaki.Miyashita@Oracle.COM fail_exit:
339*12929SMisaki.Miyashita@Oracle.COM 
340*12929SMisaki.Miyashita@Oracle.COM 	kobj_close_file(file);
341*12929SMisaki.Miyashita@Oracle.COM 
342*12929SMisaki.Miyashita@Oracle.COM 	return (FAILURE);
343*12929SMisaki.Miyashita@Oracle.COM 
344*12929SMisaki.Miyashita@Oracle.COM }
345*12929SMisaki.Miyashita@Oracle.COM 
346*12929SMisaki.Miyashita@Oracle.COM #endif
347