xref: /onnv-gate/usr/src/lib/libcryptoutil/common/keyfile.c (revision 8309:c32ddef7d3ad)
15252Sdinak /*
25252Sdinak  * CDDL HEADER START
35252Sdinak  *
45252Sdinak  * The contents of this file are subject to the terms of the
55252Sdinak  * Common Development and Distribution License (the "License").
65252Sdinak  * You may not use this file except in compliance with the License.
75252Sdinak  *
85252Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95252Sdinak  * or http://www.opensolaris.org/os/licensing.
105252Sdinak  * See the License for the specific language governing permissions
115252Sdinak  * and limitations under the License.
125252Sdinak  *
135252Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
145252Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155252Sdinak  * If applicable, add the following below this CDDL HEADER, with the
165252Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
175252Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
185252Sdinak  *
195252Sdinak  * CDDL HEADER END
205252Sdinak  */
215252Sdinak /*
22*8309SAnthony.Scarpino@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235252Sdinak  * Use is subject to license terms.
245252Sdinak  */
255252Sdinak 
265252Sdinak #include <stdio.h>
275252Sdinak #include <string.h>
285252Sdinak #include <fcntl.h>
295252Sdinak #include <sys/types.h>
305252Sdinak #include <sys/stat.h>
315252Sdinak #include <errno.h>
325252Sdinak #include <locale.h>
335252Sdinak #include <cryptoutil.h>
345252Sdinak 
355252Sdinak /*
365252Sdinak  * Read file into buffer.  Used to read raw key data or initialization
375252Sdinak  * vector data.  Buffer must be freed by caller using free().
385252Sdinak  *
395252Sdinak  * If file is a regular file, entire file is read and dlen is set
405252Sdinak  * to the number of bytes read.  Otherwise, dlen should first be set
415252Sdinak  * to the number of bytes requested and will be reset to actual number
425252Sdinak  * of bytes returned.
435252Sdinak  *
44*8309SAnthony.Scarpino@Sun.COM  * Return 0 on success and errno on error.
455252Sdinak  */
465252Sdinak int
pkcs11_read_data(char * filename,void ** dbuf,size_t * dlen)475252Sdinak pkcs11_read_data(char *filename, void **dbuf, size_t *dlen)
485252Sdinak {
49*8309SAnthony.Scarpino@Sun.COM 	int	fd = -1;
505252Sdinak 	struct stat statbuf;
515252Sdinak 	boolean_t plain_file;
525252Sdinak 	void	*filebuf = NULL;
535252Sdinak 	size_t	filesize = 0;
54*8309SAnthony.Scarpino@Sun.COM 	int ret = 0;
555252Sdinak 
565252Sdinak 	if (filename == NULL || dbuf == NULL || dlen == NULL)
575252Sdinak 		return (-1);
585252Sdinak 
595252Sdinak 	if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
60*8309SAnthony.Scarpino@Sun.COM 		ret = errno;
615252Sdinak 		cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename);
62*8309SAnthony.Scarpino@Sun.COM 		goto error;
635252Sdinak 	}
645252Sdinak 
655252Sdinak 	if (fstat(fd, &statbuf) == -1) {
66*8309SAnthony.Scarpino@Sun.COM 		ret = errno;
675252Sdinak 		cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename);
68*8309SAnthony.Scarpino@Sun.COM 		goto error;
695252Sdinak 	}
705252Sdinak 
715252Sdinak 	if (S_ISREG(statbuf.st_mode)) {
725252Sdinak 		/* read the entire regular file */
735252Sdinak 		filesize = statbuf.st_size;
745252Sdinak 		plain_file = B_TRUE;
755252Sdinak 	} else {
765252Sdinak 		/* read requested bytes from special file */
775252Sdinak 		filesize = *dlen;
785252Sdinak 		plain_file = B_FALSE;
795252Sdinak 	}
805252Sdinak 
815252Sdinak 	if (filesize == 0) {
825252Sdinak 		/*
835252Sdinak 		 * for decrypt this is an error; for digest this is ok;
845252Sdinak 		 * make it ok here but also set dbuf = NULL and dlen = 0
855252Sdinak 		 * to indicate there was no data to read and caller can
865252Sdinak 		 * retranslate that to an error if it wishes.
875252Sdinak 		 */
885252Sdinak 		(void) close(fd);
895252Sdinak 		*dbuf = NULL;
905252Sdinak 		*dlen = 0;
915252Sdinak 		return (0);
925252Sdinak 	}
935252Sdinak 
945252Sdinak 	if ((filebuf = malloc(filesize)) == NULL) {
95*8309SAnthony.Scarpino@Sun.COM 		ret = errno;
96*8309SAnthony.Scarpino@Sun.COM 		cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(ret));
97*8309SAnthony.Scarpino@Sun.COM 		goto error;
985252Sdinak 	}
995252Sdinak 
1005252Sdinak 	if (plain_file) {
1015252Sdinak 		/* either it got read or it didn't */
1025252Sdinak 		if (read(fd, filebuf, filesize) != filesize) {
103*8309SAnthony.Scarpino@Sun.COM 			ret = errno;
1045252Sdinak 			cryptoerror(LOG_STDERR,
1055252Sdinak 			    gettext("error reading file %s: %s"), filename,
106*8309SAnthony.Scarpino@Sun.COM 			    strerror(ret));
107*8309SAnthony.Scarpino@Sun.COM 			goto error;
1085252Sdinak 		}
1095252Sdinak 	} else {
1105252Sdinak 		/* reading from special file may need some coaxing */
1115252Sdinak 		char	*marker = (char *)filebuf;
1125252Sdinak 		size_t	left = filesize;
1135252Sdinak 		ssize_t	nread;
1145252Sdinak 
1155252Sdinak 		for (/* */; left > 0; marker += nread, left -= nread) {
1165252Sdinak 			/* keep reading it's going well */
1175252Sdinak 			nread = read(fd, marker, left);
118*8309SAnthony.Scarpino@Sun.COM 			if (nread > 0 || (nread == 0 && errno == EINTR)) {
119*8309SAnthony.Scarpino@Sun.COM 				errno = 0;
1205252Sdinak 				continue;
121*8309SAnthony.Scarpino@Sun.COM 			}
1225252Sdinak 
1235252Sdinak 			/* might have to be good enough for caller */
1245252Sdinak 			if (nread == 0 && errno == EAGAIN)
1255252Sdinak 				break;
1265252Sdinak 
1275252Sdinak 			/* anything else is an error */
128*8309SAnthony.Scarpino@Sun.COM 			if (errno) {
129*8309SAnthony.Scarpino@Sun.COM 				ret = errno;
130*8309SAnthony.Scarpino@Sun.COM 				cryptoerror(LOG_STDERR,
131*8309SAnthony.Scarpino@Sun.COM 				    gettext("error reading file %s: %s"),
132*8309SAnthony.Scarpino@Sun.COM 				    filename, strerror(ret));
133*8309SAnthony.Scarpino@Sun.COM 				goto error;
134*8309SAnthony.Scarpino@Sun.COM 			}
1355252Sdinak 		}
1365252Sdinak 		/* reset to actual number of bytes read */
1375252Sdinak 		filesize -= left;
1385252Sdinak 	}
1395252Sdinak 
1405252Sdinak 	(void) close(fd);
1415252Sdinak 	*dbuf = filebuf;
1425252Sdinak 	*dlen = filesize;
1435252Sdinak 	return (0);
144*8309SAnthony.Scarpino@Sun.COM 
145*8309SAnthony.Scarpino@Sun.COM error:
146*8309SAnthony.Scarpino@Sun.COM 	if (fd != -1)
147*8309SAnthony.Scarpino@Sun.COM 		(void) close(fd);
148*8309SAnthony.Scarpino@Sun.COM 
149*8309SAnthony.Scarpino@Sun.COM 	return (ret);
1505252Sdinak }
151