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 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