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.
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.
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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
34 #include <cryptoutil.h>
37 #pragma init(pkcs11_random_init)
39 static pthread_mutex_t random_mutex
= PTHREAD_MUTEX_INITIALIZER
;
40 static pthread_mutex_t urandom_mutex
= PTHREAD_MUTEX_INITIALIZER
;
42 static pthread_mutex_t random_seed_mutex
= PTHREAD_MUTEX_INITIALIZER
;
43 static pthread_mutex_t urandom_seed_mutex
= PTHREAD_MUTEX_INITIALIZER
;
45 #define RANDOM_DEVICE "/dev/random" /* random device name */
46 #define URANDOM_DEVICE "/dev/urandom" /* urandom device name */
48 static int random_fd
= -1;
49 static int urandom_fd
= -1;
51 static int random_seed_fd
= -1;
52 static int urandom_seed_fd
= -1;
56 * Equivalent of open(2) insulated from EINTR.
57 * Also sets close-on-exec.
60 open_nointr(const char *path
, int oflag
, ...)
66 va_start(alist
, oflag
);
67 pmode
= va_arg(alist
, mode_t
);
71 if ((fd
= open(path
, oflag
, pmode
)) >= 0) {
72 (void) fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
75 /* errno definitely set by failed open() */
76 } while (errno
== EINTR
);
81 * Equivalent of read(2) insulated from EINTR.
84 readn_nointr(int fd
, void *dbuf
, size_t dlen
)
88 ssize_t nread
= 0, err
;
90 for (err
= 0; left
> 0 && nread
!= -1; marker
+= nread
, left
-= nread
) {
91 if ((nread
= read(fd
, marker
, left
)) < 0) {
92 if (errno
== EINTR
) { /* keep trying */
96 err
= nread
; /* hard error */
98 } else if (nread
== 0) {
102 return (err
!= 0 ? err
: dlen
- left
);
106 * Equivalent of write(2) insulated from EINTR.
109 writen_nointr(int fd
, void *dbuf
, size_t dlen
)
113 ssize_t nwrite
= 0, err
;
115 for (err
= 0; left
> 0 && nwrite
!= -1; marker
+= nwrite
,
117 if ((nwrite
= write(fd
, marker
, left
)) < 0) {
118 if (errno
== EINTR
) { /* keep trying */
122 err
= nwrite
; /* hard error */
124 } else if (nwrite
== 0) {
128 return (err
!= 0 ? err
: dlen
- left
);
132 * Opens the random number generator devices if not already open.
133 * Always returns the opened fd of the device, or error.
136 pkcs11_open_common(int *fd
, pthread_mutex_t
*mtx
, const char *dev
, int oflag
)
138 (void) pthread_mutex_lock(mtx
);
140 *fd
= open_nointr(dev
, oflag
);
141 (void) pthread_mutex_unlock(mtx
);
147 pkcs11_open_random(void)
149 return (pkcs11_open_common(&random_fd
, &random_mutex
,
150 RANDOM_DEVICE
, O_RDONLY
));
154 pkcs11_open_urandom(void)
156 return (pkcs11_open_common(&urandom_fd
, &urandom_mutex
,
157 URANDOM_DEVICE
, O_RDONLY
));
161 pkcs11_open_random_seed(void)
163 return (pkcs11_open_common(&random_seed_fd
, &random_seed_mutex
,
164 RANDOM_DEVICE
, O_WRONLY
));
168 pkcs11_open_urandom_seed(void)
170 return (pkcs11_open_common(&urandom_seed_fd
, &urandom_seed_mutex
,
171 URANDOM_DEVICE
, O_WRONLY
));
175 * Close the random number generator devices if already open.
178 pkcs11_close_common(int *fd
, pthread_mutex_t
*mtx
)
180 (void) pthread_mutex_lock(mtx
);
183 (void) pthread_mutex_unlock(mtx
);
187 pkcs11_close_random(void)
189 pkcs11_close_common(&random_fd
, &random_mutex
);
193 pkcs11_close_urandom(void)
195 pkcs11_close_common(&urandom_fd
, &urandom_mutex
);
199 pkcs11_close_random_seed(void)
201 pkcs11_close_common(&random_seed_fd
, &random_seed_mutex
);
205 pkcs11_close_urandom_seed(void)
207 pkcs11_close_common(&urandom_seed_fd
, &urandom_seed_mutex
);
211 * Read from the random number generator devices.
214 pkcs11_read_common(int *fd
, pthread_mutex_t
*mtx
, void *dbuf
, size_t dlen
)
218 (void) pthread_mutex_lock(mtx
);
219 n
= readn_nointr(*fd
, dbuf
, dlen
);
220 (void) pthread_mutex_unlock(mtx
);
226 pkcs11_read_random(void *dbuf
, size_t dlen
)
228 return (pkcs11_read_common(&random_fd
, &random_mutex
, dbuf
, dlen
));
232 pkcs11_read_urandom(void *dbuf
, size_t dlen
)
234 return (pkcs11_read_common(&urandom_fd
, &urandom_mutex
, dbuf
, dlen
));
238 * Write to the random number generator devices.
241 pkcs11_write_common(int *fd
, pthread_mutex_t
*mtx
, void *dbuf
, size_t dlen
)
245 (void) pthread_mutex_lock(mtx
);
246 n
= writen_nointr(*fd
, dbuf
, dlen
);
247 (void) pthread_mutex_unlock(mtx
);
253 pkcs11_write_random_seed(void *dbuf
, size_t dlen
)
255 return (pkcs11_write_common(&random_seed_fd
, &random_seed_mutex
,
260 pkcs11_write_urandom_seed(void *dbuf
, size_t dlen
)
262 return (pkcs11_write_common(&urandom_seed_fd
, &urandom_seed_mutex
,
267 * Seed /dev/random with the data in the buffer.
270 pkcs11_seed_random(void *sbuf
, size_t slen
)
274 if (sbuf
== NULL
|| slen
== 0)
277 /* Seeding error could mean it's not supported (errno = EACCES) */
278 if (pkcs11_open_random_seed() < 0)
282 if (pkcs11_write_random_seed(sbuf
, slen
) == slen
)
285 pkcs11_close_random_seed();
290 * Seed /dev/urandom with the data in the buffer.
293 pkcs11_seed_urandom(void *sbuf
, size_t slen
)
297 if (sbuf
== NULL
|| slen
== 0)
300 /* Seeding error could mean it's not supported (errno = EACCES) */
301 if (pkcs11_open_urandom_seed() < 0)
305 if (pkcs11_write_urandom_seed(sbuf
, slen
) == slen
)
308 pkcs11_close_urandom_seed();
313 * Put the requested amount of random data into a preallocated buffer.
314 * Good for token key data, persistent objects.
317 pkcs11_get_random(void *dbuf
, size_t dlen
)
319 if (dbuf
== NULL
|| dlen
== 0)
322 /* Read random data directly from /dev/random */
323 if (pkcs11_open_random() < 0)
326 if (pkcs11_read_random(dbuf
, dlen
) == dlen
)
332 * Put the requested amount of random data into a preallocated buffer.
333 * Good for passphrase salts, initialization vectors.
336 pkcs11_get_urandom(void *dbuf
, size_t dlen
)
338 if (dbuf
== NULL
|| dlen
== 0)
341 /* Read random data directly from /dev/urandom */
342 if (pkcs11_open_urandom() < 0)
345 if (pkcs11_read_urandom(dbuf
, dlen
) == dlen
)
351 * Same as pkcs11_get_urandom but ensures non zero data.
354 pkcs11_get_nzero_urandom(void *dbuf
, size_t dlen
)
357 size_t bytesleft
= 0;
360 /* Start with some random data */
361 if (pkcs11_get_urandom(dbuf
, dlen
) < 0)
364 /* Walk through data replacing any 0 bytes with more random data */
366 if (((char *)dbuf
)[i
] != 0) {
371 if (bytesleft
== 0) {
372 bytesleft
= sizeof (extrarand
);
373 if (pkcs11_get_urandom(extrarand
, bytesleft
) < 0)
378 ((char *)dbuf
)[i
] = extrarand
[bytesleft
];
384 pkcs11_random_prepare(void)
387 * NOTE - None of these are acquired more than one at a time.
388 * I can therefore acquire all four without fear of deadlock.
390 (void) pthread_mutex_lock(&random_mutex
);
391 (void) pthread_mutex_lock(&urandom_mutex
);
392 (void) pthread_mutex_lock(&random_seed_mutex
);
393 (void) pthread_mutex_lock(&urandom_seed_mutex
);
397 pkcs11_random_parent_post(void)
399 /* Drop the mutexes and get back to work! */
400 (void) pthread_mutex_unlock(&urandom_seed_mutex
);
401 (void) pthread_mutex_unlock(&random_seed_mutex
);
402 (void) pthread_mutex_unlock(&urandom_mutex
);
403 (void) pthread_mutex_unlock(&random_mutex
);
407 pkcs11_random_child_post(void)
409 pkcs11_random_parent_post();
411 /* Also, close the FDs, just in case. */
412 pkcs11_close_random();
413 pkcs11_close_urandom();
414 pkcs11_close_random_seed();
415 pkcs11_close_urandom_seed();
419 pkcs11_random_init(void)
421 (void) pthread_atfork(pkcs11_random_prepare
, pkcs11_random_parent_post
,
422 pkcs11_random_child_post
);