summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcryptoutil/common/keyfile.c
diff options
context:
space:
mode:
authordinak <none@none>2007-10-12 17:45:37 -0700
committerdinak <none@none>2007-10-12 17:45:37 -0700
commit1c9bd843ebc00801cc418156a3893362a1dc872e (patch)
tree374088cd20caa2bb60a2fcc4e95bed1183d863a9 /usr/src/lib/libcryptoutil/common/keyfile.c
parent36945f796054e8cb46d88ec0a84213123cf2b036 (diff)
downloadillumos-joyent-1c9bd843ebc00801cc418156a3893362a1dc872e.tar.gz
6552557 provide helper function that generates pkcs#5 keys from passphrases
6554395 consolidate duplicated code in decrypt and digest 6607990 SUNW_C_KeyToObject fails to set wrap/unwrap capability on object created from raw key 6607994 SUNW_C_KeyToObject looks like it may destroy an object that was never created 6607998 C_GetSessionInfo never returns CKR_ARGUMENTS_BAD 6608391 consolidate code that reads key data from file
Diffstat (limited to 'usr/src/lib/libcryptoutil/common/keyfile.c')
-rw-r--r--usr/src/lib/libcryptoutil/common/keyfile.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/usr/src/lib/libcryptoutil/common/keyfile.c b/usr/src/lib/libcryptoutil/common/keyfile.c
new file mode 100644
index 0000000000..0d5403bd28
--- /dev/null
+++ b/usr/src/lib/libcryptoutil/common/keyfile.c
@@ -0,0 +1,144 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <locale.h>
+#include <cryptoutil.h>
+
+/*
+ * Read file into buffer. Used to read raw key data or initialization
+ * vector data. Buffer must be freed by caller using free().
+ *
+ * If file is a regular file, entire file is read and dlen is set
+ * to the number of bytes read. Otherwise, dlen should first be set
+ * to the number of bytes requested and will be reset to actual number
+ * of bytes returned.
+ *
+ * Return 0 on success, -1 on error.
+ */
+int
+pkcs11_read_data(char *filename, void **dbuf, size_t *dlen)
+{
+ int fd;
+ struct stat statbuf;
+ boolean_t plain_file;
+ void *filebuf = NULL;
+ size_t filesize = 0;
+
+ if (filename == NULL || dbuf == NULL || dlen == NULL)
+ return (-1);
+
+ if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) {
+ cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename);
+ return (-1);
+ }
+
+ if (fstat(fd, &statbuf) == -1) {
+ cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename);
+ (void) close(fd);
+ return (-1);
+ }
+
+ if (S_ISREG(statbuf.st_mode)) {
+ /* read the entire regular file */
+ filesize = statbuf.st_size;
+ plain_file = B_TRUE;
+ } else {
+ /* read requested bytes from special file */
+ filesize = *dlen;
+ plain_file = B_FALSE;
+ }
+
+ if (filesize == 0) {
+ /*
+ * for decrypt this is an error; for digest this is ok;
+ * make it ok here but also set dbuf = NULL and dlen = 0
+ * to indicate there was no data to read and caller can
+ * retranslate that to an error if it wishes.
+ */
+ (void) close(fd);
+ *dbuf = NULL;
+ *dlen = 0;
+ return (0);
+ }
+
+ if ((filebuf = malloc(filesize)) == NULL) {
+ int err = errno;
+ cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(err));
+ (void) close(fd);
+ return (-1);
+ }
+
+ if (plain_file) {
+ /* either it got read or it didn't */
+ if (read(fd, filebuf, filesize) != filesize) {
+ int err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("error reading file %s: %s"), filename,
+ strerror(err));
+ (void) close(fd);
+ return (-1);
+ }
+ } else {
+ /* reading from special file may need some coaxing */
+ char *marker = (char *)filebuf;
+ size_t left = filesize;
+ ssize_t nread;
+ int err;
+
+ for (/* */; left > 0; marker += nread, left -= nread) {
+ /* keep reading it's going well */
+ nread = read(fd, marker, left);
+ if (nread > 0 || (nread == 0 && errno == EINTR))
+ continue;
+
+ /* might have to be good enough for caller */
+ if (nread == 0 && errno == EAGAIN)
+ break;
+
+ /* anything else is an error */
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("error reading file %s: %s"), filename,
+ strerror(err));
+ (void) close(fd);
+ return (-1);
+ }
+ /* reset to actual number of bytes read */
+ filesize -= left;
+ }
+
+ (void) close(fd);
+ *dbuf = filebuf;
+ *dlen = filesize;
+ return (0);
+}