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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Random Number Generation Functions 31 * (as defined in PKCS#11 spec section 11.15) 32 * 33 */ 34 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <fcntl.h> 38 #include <errno.h> 39 #include <string.h> 40 41 #include "metaGlobal.h" 42 43 /* 44 * meta_SeedRandom 45 * 46 * Unlike most other metaslot functions, meta_SeedRandom does not distribute 47 * the call to a specific provider. Rather, we assume that the /dev/urandom 48 * implementation is a kCF consumer, and is pulling randomness from everywhere 49 * it can. Thus, by seeding /dev/urandom we let kCF potentially do all the 50 * work. 51 * 52 * NOTES: 53 * 1) /dev/urandom vs. /dev/random... Unfortunately P11 does not allow app 54 * to request a "quality", so we'll just assume urandom is good enough. 55 * Concerned apps can pull hardcore randomness from specific places they 56 * trust (eg by checking for CKF_HW?).. 57 * 58 */ 59 CK_RV 60 meta_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, 61 CK_ULONG ulSeedLen) 62 { 63 CK_RV rv; 64 meta_session_t *session; 65 int fd; 66 ssize_t n; 67 68 if (pSeed == NULL || ulSeedLen == 0) 69 return (CKR_ARGUMENTS_BAD); 70 71 /* Just check handle for validity, we don't need it for anything. */ 72 rv = meta_handle2session(hSession, &session); 73 if (rv != CKR_OK) 74 return (rv); 75 REFRELEASE(session); 76 77 while ((fd = open(RANDOM_DEVICE, O_WRONLY)) < 0) { 78 if (errno != EINTR) 79 break; 80 } 81 if (fd == -1) { 82 if (errno == EACCES) 83 return (CKR_RANDOM_SEED_NOT_SUPPORTED); 84 else 85 return (CKR_DEVICE_ERROR); 86 } 87 88 n = looping_write(fd, pSeed, ulSeedLen); 89 if (n <= 0) { 90 (void) close(fd); 91 return (CKR_DEVICE_ERROR); 92 } 93 94 (void) close(fd); 95 96 return (CKR_OK); 97 } 98 99 /* 100 * meta_GenerateRandom 101 * 102 * Unlike most other metaslot functions, meta_GenerateRandom does not distribute 103 * the call to a specific provider. Rather, we assume that the /dev/urandom 104 * implementation is a kCF consumer, and is pulling randomness from everywhere 105 * it can. Thus, by reading /dev/urandom we let kCF potentially do all the 106 * work. 107 * 108 */ 109 CK_RV 110 meta_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, 111 CK_ULONG ulRandomLen) 112 { 113 CK_RV rv; 114 meta_session_t *session; 115 int fd; 116 ssize_t n; 117 118 if (pRandomData == NULL || ulRandomLen < 1) 119 return (CKR_ARGUMENTS_BAD); 120 121 /* Just check handle for validity, we don't need it for anything. */ 122 rv = meta_handle2session(hSession, &session); 123 if (rv != CKR_OK) 124 return (rv); 125 REFRELEASE(session); 126 127 while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) { 128 if (errno != EINTR) 129 break; 130 } 131 if (fd == -1) { 132 return (CKR_DEVICE_ERROR); 133 } 134 135 n = looping_read(fd, pRandomData, ulRandomLen); 136 if (n <= 0) { 137 (void) close(fd); 138 return (CKR_DEVICE_ERROR); 139 } 140 141 (void) close(fd); 142 143 return (CKR_OK); 144 } 145