1*1c9bd843Sdinak /* 2*1c9bd843Sdinak * CDDL HEADER START 3*1c9bd843Sdinak * 4*1c9bd843Sdinak * The contents of this file are subject to the terms of the 5*1c9bd843Sdinak * Common Development and Distribution License (the "License"). 6*1c9bd843Sdinak * You may not use this file except in compliance with the License. 7*1c9bd843Sdinak * 8*1c9bd843Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1c9bd843Sdinak * or http://www.opensolaris.org/os/licensing. 10*1c9bd843Sdinak * See the License for the specific language governing permissions 11*1c9bd843Sdinak * and limitations under the License. 12*1c9bd843Sdinak * 13*1c9bd843Sdinak * When distributing Covered Code, include this CDDL HEADER in each 14*1c9bd843Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1c9bd843Sdinak * If applicable, add the following below this CDDL HEADER, with the 16*1c9bd843Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 17*1c9bd843Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 18*1c9bd843Sdinak * 19*1c9bd843Sdinak * CDDL HEADER END 20*1c9bd843Sdinak */ 21*1c9bd843Sdinak /* 22*1c9bd843Sdinak * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*1c9bd843Sdinak * Use is subject to license terms. 24*1c9bd843Sdinak */ 25*1c9bd843Sdinak 26*1c9bd843Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 27*1c9bd843Sdinak 28*1c9bd843Sdinak #include <stdio.h> 29*1c9bd843Sdinak #include <string.h> 30*1c9bd843Sdinak #include <fcntl.h> 31*1c9bd843Sdinak #include <sys/types.h> 32*1c9bd843Sdinak #include <sys/stat.h> 33*1c9bd843Sdinak #include <errno.h> 34*1c9bd843Sdinak #include <locale.h> 35*1c9bd843Sdinak #include <cryptoutil.h> 36*1c9bd843Sdinak 37*1c9bd843Sdinak /* 38*1c9bd843Sdinak * Read file into buffer. Used to read raw key data or initialization 39*1c9bd843Sdinak * vector data. Buffer must be freed by caller using free(). 40*1c9bd843Sdinak * 41*1c9bd843Sdinak * If file is a regular file, entire file is read and dlen is set 42*1c9bd843Sdinak * to the number of bytes read. Otherwise, dlen should first be set 43*1c9bd843Sdinak * to the number of bytes requested and will be reset to actual number 44*1c9bd843Sdinak * of bytes returned. 45*1c9bd843Sdinak * 46*1c9bd843Sdinak * Return 0 on success, -1 on error. 47*1c9bd843Sdinak */ 48*1c9bd843Sdinak int 49*1c9bd843Sdinak pkcs11_read_data(char *filename, void **dbuf, size_t *dlen) 50*1c9bd843Sdinak { 51*1c9bd843Sdinak int fd; 52*1c9bd843Sdinak struct stat statbuf; 53*1c9bd843Sdinak boolean_t plain_file; 54*1c9bd843Sdinak void *filebuf = NULL; 55*1c9bd843Sdinak size_t filesize = 0; 56*1c9bd843Sdinak 57*1c9bd843Sdinak if (filename == NULL || dbuf == NULL || dlen == NULL) 58*1c9bd843Sdinak return (-1); 59*1c9bd843Sdinak 60*1c9bd843Sdinak if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) { 61*1c9bd843Sdinak cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename); 62*1c9bd843Sdinak return (-1); 63*1c9bd843Sdinak } 64*1c9bd843Sdinak 65*1c9bd843Sdinak if (fstat(fd, &statbuf) == -1) { 66*1c9bd843Sdinak cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename); 67*1c9bd843Sdinak (void) close(fd); 68*1c9bd843Sdinak return (-1); 69*1c9bd843Sdinak } 70*1c9bd843Sdinak 71*1c9bd843Sdinak if (S_ISREG(statbuf.st_mode)) { 72*1c9bd843Sdinak /* read the entire regular file */ 73*1c9bd843Sdinak filesize = statbuf.st_size; 74*1c9bd843Sdinak plain_file = B_TRUE; 75*1c9bd843Sdinak } else { 76*1c9bd843Sdinak /* read requested bytes from special file */ 77*1c9bd843Sdinak filesize = *dlen; 78*1c9bd843Sdinak plain_file = B_FALSE; 79*1c9bd843Sdinak } 80*1c9bd843Sdinak 81*1c9bd843Sdinak if (filesize == 0) { 82*1c9bd843Sdinak /* 83*1c9bd843Sdinak * for decrypt this is an error; for digest this is ok; 84*1c9bd843Sdinak * make it ok here but also set dbuf = NULL and dlen = 0 85*1c9bd843Sdinak * to indicate there was no data to read and caller can 86*1c9bd843Sdinak * retranslate that to an error if it wishes. 87*1c9bd843Sdinak */ 88*1c9bd843Sdinak (void) close(fd); 89*1c9bd843Sdinak *dbuf = NULL; 90*1c9bd843Sdinak *dlen = 0; 91*1c9bd843Sdinak return (0); 92*1c9bd843Sdinak } 93*1c9bd843Sdinak 94*1c9bd843Sdinak if ((filebuf = malloc(filesize)) == NULL) { 95*1c9bd843Sdinak int err = errno; 96*1c9bd843Sdinak cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(err)); 97*1c9bd843Sdinak (void) close(fd); 98*1c9bd843Sdinak return (-1); 99*1c9bd843Sdinak } 100*1c9bd843Sdinak 101*1c9bd843Sdinak if (plain_file) { 102*1c9bd843Sdinak /* either it got read or it didn't */ 103*1c9bd843Sdinak if (read(fd, filebuf, filesize) != filesize) { 104*1c9bd843Sdinak int err = errno; 105*1c9bd843Sdinak cryptoerror(LOG_STDERR, 106*1c9bd843Sdinak gettext("error reading file %s: %s"), filename, 107*1c9bd843Sdinak strerror(err)); 108*1c9bd843Sdinak (void) close(fd); 109*1c9bd843Sdinak return (-1); 110*1c9bd843Sdinak } 111*1c9bd843Sdinak } else { 112*1c9bd843Sdinak /* reading from special file may need some coaxing */ 113*1c9bd843Sdinak char *marker = (char *)filebuf; 114*1c9bd843Sdinak size_t left = filesize; 115*1c9bd843Sdinak ssize_t nread; 116*1c9bd843Sdinak int err; 117*1c9bd843Sdinak 118*1c9bd843Sdinak for (/* */; left > 0; marker += nread, left -= nread) { 119*1c9bd843Sdinak /* keep reading it's going well */ 120*1c9bd843Sdinak nread = read(fd, marker, left); 121*1c9bd843Sdinak if (nread > 0 || (nread == 0 && errno == EINTR)) 122*1c9bd843Sdinak continue; 123*1c9bd843Sdinak 124*1c9bd843Sdinak /* might have to be good enough for caller */ 125*1c9bd843Sdinak if (nread == 0 && errno == EAGAIN) 126*1c9bd843Sdinak break; 127*1c9bd843Sdinak 128*1c9bd843Sdinak /* anything else is an error */ 129*1c9bd843Sdinak err = errno; 130*1c9bd843Sdinak cryptoerror(LOG_STDERR, 131*1c9bd843Sdinak gettext("error reading file %s: %s"), filename, 132*1c9bd843Sdinak strerror(err)); 133*1c9bd843Sdinak (void) close(fd); 134*1c9bd843Sdinak return (-1); 135*1c9bd843Sdinak } 136*1c9bd843Sdinak /* reset to actual number of bytes read */ 137*1c9bd843Sdinak filesize -= left; 138*1c9bd843Sdinak } 139*1c9bd843Sdinak 140*1c9bd843Sdinak (void) close(fd); 141*1c9bd843Sdinak *dbuf = filebuf; 142*1c9bd843Sdinak *dlen = filesize; 143*1c9bd843Sdinak return (0); 144*1c9bd843Sdinak } 145