11c9bd843Sdinak /*
21c9bd843Sdinak * CDDL HEADER START
31c9bd843Sdinak *
41c9bd843Sdinak * The contents of this file are subject to the terms of the
51c9bd843Sdinak * Common Development and Distribution License (the "License").
61c9bd843Sdinak * You may not use this file except in compliance with the License.
71c9bd843Sdinak *
81c9bd843Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91c9bd843Sdinak * or http://www.opensolaris.org/os/licensing.
101c9bd843Sdinak * See the License for the specific language governing permissions
111c9bd843Sdinak * and limitations under the License.
121c9bd843Sdinak *
131c9bd843Sdinak * When distributing Covered Code, include this CDDL HEADER in each
141c9bd843Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151c9bd843Sdinak * If applicable, add the following below this CDDL HEADER, with the
161c9bd843Sdinak * fields enclosed by brackets "[]" replaced with your own identifying
171c9bd843Sdinak * information: Portions Copyright [yyyy] [name of copyright owner]
181c9bd843Sdinak *
191c9bd843Sdinak * CDDL HEADER END
201c9bd843Sdinak */
211c9bd843Sdinak /*
22*a7e661a2SAnthony Scarpino * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
231c9bd843Sdinak * Use is subject to license terms.
241c9bd843Sdinak */
251c9bd843Sdinak
261c9bd843Sdinak #include <stdio.h>
271c9bd843Sdinak #include <string.h>
281c9bd843Sdinak #include <fcntl.h>
291c9bd843Sdinak #include <sys/types.h>
301c9bd843Sdinak #include <sys/stat.h>
311c9bd843Sdinak #include <errno.h>
321c9bd843Sdinak #include <locale.h>
331c9bd843Sdinak #include <cryptoutil.h>
341c9bd843Sdinak
351c9bd843Sdinak /*
361c9bd843Sdinak * Read file into buffer. Used to read raw key data or initialization
371c9bd843Sdinak * vector data. Buffer must be freed by caller using free().
381c9bd843Sdinak *
391c9bd843Sdinak * If file is a regular file, entire file is read and dlen is set
401c9bd843Sdinak * to the number of bytes read. Otherwise, dlen should first be set
411c9bd843Sdinak * to the number of bytes requested and will be reset to actual number
421c9bd843Sdinak * of bytes returned.
431c9bd843Sdinak *
44*a7e661a2SAnthony Scarpino * Return 0 on success and errno on error.
451c9bd843Sdinak */
461c9bd843Sdinak int
pkcs11_read_data(char * filename,void ** dbuf,size_t * dlen)471c9bd843Sdinak pkcs11_read_data(char *filename, void **dbuf, size_t *dlen)
481c9bd843Sdinak {
49*a7e661a2SAnthony Scarpino int fd = -1;
501c9bd843Sdinak struct stat statbuf;
511c9bd843Sdinak boolean_t plain_file;
521c9bd843Sdinak void *filebuf = NULL;
531c9bd843Sdinak size_t filesize = 0;
54*a7e661a2SAnthony Scarpino int ret = 0;
551c9bd843Sdinak
561c9bd843Sdinak if (filename == NULL || dbuf == NULL || dlen == NULL)
571c9bd843Sdinak return (-1);
581c9bd843Sdinak
591c9bd843Sdinak if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
60*a7e661a2SAnthony Scarpino ret = errno;
611c9bd843Sdinak cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename);
62*a7e661a2SAnthony Scarpino goto error;
631c9bd843Sdinak }
641c9bd843Sdinak
651c9bd843Sdinak if (fstat(fd, &statbuf) == -1) {
66*a7e661a2SAnthony Scarpino ret = errno;
671c9bd843Sdinak cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename);
68*a7e661a2SAnthony Scarpino goto error;
691c9bd843Sdinak }
701c9bd843Sdinak
711c9bd843Sdinak if (S_ISREG(statbuf.st_mode)) {
721c9bd843Sdinak /* read the entire regular file */
731c9bd843Sdinak filesize = statbuf.st_size;
741c9bd843Sdinak plain_file = B_TRUE;
751c9bd843Sdinak } else {
761c9bd843Sdinak /* read requested bytes from special file */
771c9bd843Sdinak filesize = *dlen;
781c9bd843Sdinak plain_file = B_FALSE;
791c9bd843Sdinak }
801c9bd843Sdinak
811c9bd843Sdinak if (filesize == 0) {
821c9bd843Sdinak /*
831c9bd843Sdinak * for decrypt this is an error; for digest this is ok;
841c9bd843Sdinak * make it ok here but also set dbuf = NULL and dlen = 0
851c9bd843Sdinak * to indicate there was no data to read and caller can
861c9bd843Sdinak * retranslate that to an error if it wishes.
871c9bd843Sdinak */
881c9bd843Sdinak (void) close(fd);
891c9bd843Sdinak *dbuf = NULL;
901c9bd843Sdinak *dlen = 0;
911c9bd843Sdinak return (0);
921c9bd843Sdinak }
931c9bd843Sdinak
941c9bd843Sdinak if ((filebuf = malloc(filesize)) == NULL) {
95*a7e661a2SAnthony Scarpino ret = errno;
96*a7e661a2SAnthony Scarpino cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(ret));
97*a7e661a2SAnthony Scarpino goto error;
981c9bd843Sdinak }
991c9bd843Sdinak
1001c9bd843Sdinak if (plain_file) {
1011c9bd843Sdinak /* either it got read or it didn't */
1021c9bd843Sdinak if (read(fd, filebuf, filesize) != filesize) {
103*a7e661a2SAnthony Scarpino ret = errno;
1041c9bd843Sdinak cryptoerror(LOG_STDERR,
1051c9bd843Sdinak gettext("error reading file %s: %s"), filename,
106*a7e661a2SAnthony Scarpino strerror(ret));
107*a7e661a2SAnthony Scarpino goto error;
1081c9bd843Sdinak }
1091c9bd843Sdinak } else {
1101c9bd843Sdinak /* reading from special file may need some coaxing */
1111c9bd843Sdinak char *marker = (char *)filebuf;
1121c9bd843Sdinak size_t left = filesize;
1131c9bd843Sdinak ssize_t nread;
1141c9bd843Sdinak
1151c9bd843Sdinak for (/* */; left > 0; marker += nread, left -= nread) {
1161c9bd843Sdinak /* keep reading it's going well */
1171c9bd843Sdinak nread = read(fd, marker, left);
118*a7e661a2SAnthony Scarpino if (nread > 0 || (nread == 0 && errno == EINTR)) {
119*a7e661a2SAnthony Scarpino errno = 0;
1201c9bd843Sdinak continue;
121*a7e661a2SAnthony Scarpino }
1221c9bd843Sdinak
1231c9bd843Sdinak /* might have to be good enough for caller */
1241c9bd843Sdinak if (nread == 0 && errno == EAGAIN)
1251c9bd843Sdinak break;
1261c9bd843Sdinak
1271c9bd843Sdinak /* anything else is an error */
128*a7e661a2SAnthony Scarpino if (errno) {
129*a7e661a2SAnthony Scarpino ret = errno;
1301c9bd843Sdinak cryptoerror(LOG_STDERR,
131*a7e661a2SAnthony Scarpino gettext("error reading file %s: %s"),
132*a7e661a2SAnthony Scarpino filename, strerror(ret));
133*a7e661a2SAnthony Scarpino goto error;
134*a7e661a2SAnthony Scarpino }
1351c9bd843Sdinak }
1361c9bd843Sdinak /* reset to actual number of bytes read */
1371c9bd843Sdinak filesize -= left;
1381c9bd843Sdinak }
1391c9bd843Sdinak
1401c9bd843Sdinak (void) close(fd);
1411c9bd843Sdinak *dbuf = filebuf;
1421c9bd843Sdinak *dlen = filesize;
1431c9bd843Sdinak return (0);
144*a7e661a2SAnthony Scarpino
145*a7e661a2SAnthony Scarpino error:
146*a7e661a2SAnthony Scarpino if (fd != -1)
147*a7e661a2SAnthony Scarpino (void) close(fd);
148*a7e661a2SAnthony Scarpino
149*a7e661a2SAnthony Scarpino return (ret);
1501c9bd843Sdinak }
151