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 2006 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 /* 29 * Random Number Generation Functions 30 * (as defined in PKCS#11 spec section 11.15) 31 * 32 */ 33 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <errno.h> 38 #include <string.h> 39 40 #include "metaGlobal.h" 41 42 /* 43 * meta_SeedRandom 44 * 45 * Unlike most other metaslot functions, meta_SeedRandom does not distribute 46 * the call to a specific provider. Rather, we assume that the /dev/urandom 47 * implementation is a kCF consumer, and is pulling randomness from everywhere 48 * it can. Thus, by seeding /dev/urandom we let kCF potentially do all the 49 * work. 50 * 51 * NOTES: 52 * 1) /dev/urandom vs. /dev/random... Unfortunately P11 does not allow app 53 * to request a "quality", so we'll just assume urandom is good enough. 54 * Concerned apps can pull hardcore randomness from specific places they 55 * trust (eg by checking for CKF_HW?).. 56 * 57 */ 58 CK_RV 59 meta_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, 60 CK_ULONG ulSeedLen) 61 { 62 CK_RV rv; 63 meta_session_t *session; 64 ssize_t n; 65 66 if (pSeed == NULL || ulSeedLen == 0) 67 return (CKR_ARGUMENTS_BAD); 68 69 /* Just check handle for validity, we don't need it for anything. */ 70 rv = meta_handle2session(hSession, &session); 71 if (rv != CKR_OK) 72 return (rv); 73 REFRELEASE(session); 74 75 if (meta_urandom_seed_fd < 0) { 76 (void) pthread_mutex_lock(&initmutex); 77 /* Check again holding the mutex */ 78 if (meta_urandom_seed_fd < 0) { 79 while ((meta_urandom_seed_fd = open( 80 RANDOM_DEVICE, O_WRONLY)) < 0) { 81 if (errno != EINTR) 82 break; 83 } 84 if (meta_urandom_seed_fd < 0) { 85 (void) pthread_mutex_unlock(&initmutex); 86 if (errno == EACCES) 87 return ( 88 CKR_RANDOM_SEED_NOT_SUPPORTED); 89 return (CKR_DEVICE_ERROR); 90 } 91 (void) fcntl(meta_urandom_seed_fd, F_SETFD, 92 FD_CLOEXEC); 93 } 94 (void) pthread_mutex_unlock(&initmutex); 95 } 96 97 n = looping_write(meta_urandom_seed_fd, pSeed, ulSeedLen); 98 if (n <= 0) { 99 return (CKR_DEVICE_ERROR); 100 } 101 102 return (CKR_OK); 103 } 104 105 /* 106 * meta_GenerateRandom 107 * 108 * Unlike most other metaslot functions, meta_GenerateRandom does not distribute 109 * the call to a specific provider. Rather, we assume that the /dev/urandom 110 * implementation is a kCF consumer, and is pulling randomness from everywhere 111 * it can. Thus, by reading /dev/urandom we let kCF potentially do all the 112 * work. 113 * 114 */ 115 CK_RV 116 meta_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, 117 CK_ULONG ulRandomLen) 118 { 119 CK_RV rv; 120 meta_session_t *session; 121 int fd; 122 ssize_t n; 123 124 if (pRandomData == NULL || ulRandomLen < 1) 125 return (CKR_ARGUMENTS_BAD); 126 127 /* Just check handle for validity, we don't need it for anything. */ 128 rv = meta_handle2session(hSession, &session); 129 if (rv != CKR_OK) 130 return (rv); 131 REFRELEASE(session); 132 133 while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) { 134 if (errno != EINTR) 135 break; 136 } 137 if (fd == -1) { 138 return (CKR_DEVICE_ERROR); 139 } 140 141 n = looping_read(fd, pRandomData, ulRandomLen); 142 if (n <= 0) { 143 (void) close(fd); 144 return (CKR_DEVICE_ERROR); 145 } 146 147 (void) close(fd); 148 149 return (CKR_OK); 150 } 151