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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <string.h> 30 #include <fcntl.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <errno.h> 34 #include <locale.h> 35 #include <cryptoutil.h> 36 37 /* 38 * Read file into buffer. Used to read raw key data or initialization 39 * vector data. Buffer must be freed by caller using free(). 40 * 41 * If file is a regular file, entire file is read and dlen is set 42 * to the number of bytes read. Otherwise, dlen should first be set 43 * to the number of bytes requested and will be reset to actual number 44 * of bytes returned. 45 * 46 * Return 0 on success, -1 on error. 47 */ 48 int 49 pkcs11_read_data(char *filename, void **dbuf, size_t *dlen) 50 { 51 int fd; 52 struct stat statbuf; 53 boolean_t plain_file; 54 void *filebuf = NULL; 55 size_t filesize = 0; 56 57 if (filename == NULL || dbuf == NULL || dlen == NULL) 58 return (-1); 59 60 if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) { 61 cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename); 62 return (-1); 63 } 64 65 if (fstat(fd, &statbuf) == -1) { 66 cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename); 67 (void) close(fd); 68 return (-1); 69 } 70 71 if (S_ISREG(statbuf.st_mode)) { 72 /* read the entire regular file */ 73 filesize = statbuf.st_size; 74 plain_file = B_TRUE; 75 } else { 76 /* read requested bytes from special file */ 77 filesize = *dlen; 78 plain_file = B_FALSE; 79 } 80 81 if (filesize == 0) { 82 /* 83 * for decrypt this is an error; for digest this is ok; 84 * make it ok here but also set dbuf = NULL and dlen = 0 85 * to indicate there was no data to read and caller can 86 * retranslate that to an error if it wishes. 87 */ 88 (void) close(fd); 89 *dbuf = NULL; 90 *dlen = 0; 91 return (0); 92 } 93 94 if ((filebuf = malloc(filesize)) == NULL) { 95 int err = errno; 96 cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(err)); 97 (void) close(fd); 98 return (-1); 99 } 100 101 if (plain_file) { 102 /* either it got read or it didn't */ 103 if (read(fd, filebuf, filesize) != filesize) { 104 int err = errno; 105 cryptoerror(LOG_STDERR, 106 gettext("error reading file %s: %s"), filename, 107 strerror(err)); 108 (void) close(fd); 109 return (-1); 110 } 111 } else { 112 /* reading from special file may need some coaxing */ 113 char *marker = (char *)filebuf; 114 size_t left = filesize; 115 ssize_t nread; 116 int err; 117 118 for (/* */; left > 0; marker += nread, left -= nread) { 119 /* keep reading it's going well */ 120 nread = read(fd, marker, left); 121 if (nread > 0 || (nread == 0 && errno == EINTR)) 122 continue; 123 124 /* might have to be good enough for caller */ 125 if (nread == 0 && errno == EAGAIN) 126 break; 127 128 /* anything else is an error */ 129 err = errno; 130 cryptoerror(LOG_STDERR, 131 gettext("error reading file %s: %s"), filename, 132 strerror(err)); 133 (void) close(fd); 134 return (-1); 135 } 136 /* reset to actual number of bytes read */ 137 filesize -= left; 138 } 139 140 (void) close(fd); 141 *dbuf = filebuf; 142 *dlen = filesize; 143 return (0); 144 } 145