19d12795fSRobert Mustacchi /* 29d12795fSRobert Mustacchi * This file and its contents are supplied under the terms of the 39d12795fSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 49d12795fSRobert Mustacchi * You may only use this file in accordance with the terms of version 59d12795fSRobert Mustacchi * 1.0 of the CDDL. 69d12795fSRobert Mustacchi * 79d12795fSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 89d12795fSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 99d12795fSRobert Mustacchi * http://www.illumos.org/license/CDDL. 109d12795fSRobert Mustacchi */ 119d12795fSRobert Mustacchi 129d12795fSRobert Mustacchi /* 139d12795fSRobert Mustacchi * Copyright (c) 2015, Joyent, Inc. 149d12795fSRobert Mustacchi */ 159d12795fSRobert Mustacchi 169d12795fSRobert Mustacchi /* 179d12795fSRobert Mustacchi * getrandom system call implementation 189d12795fSRobert Mustacchi */ 199d12795fSRobert Mustacchi 209d12795fSRobert Mustacchi #include <sys/types.h> 219d12795fSRobert Mustacchi #include <sys/errno.h> 229d12795fSRobert Mustacchi #include <sys/systm.h> 239d12795fSRobert Mustacchi #include <sys/random.h> 249d12795fSRobert Mustacchi #include <sys/ddi.h> 259d12795fSRobert Mustacchi #include <sys/sunddi.h> 269d12795fSRobert Mustacchi #include <sys/sysmacros.h> 279d12795fSRobert Mustacchi 289d12795fSRobert Mustacchi #include <sys/random.h> 299d12795fSRobert Mustacchi 309d12795fSRobert Mustacchi /* 319d12795fSRobert Mustacchi * Impose a maximum upper bound on the number of bytes that we'll read in one 329d12795fSRobert Mustacchi * go, ala a read of /dev/random. For /dev/urandom, we clamp it based on our 339d12795fSRobert Mustacchi * return value, because the system call returns an int, we can't handle more 349d12795fSRobert Mustacchi * than INT_MAX. 359d12795fSRobert Mustacchi */ 369d12795fSRobert Mustacchi #define MAXRANDBYTES 1024 379d12795fSRobert Mustacchi #define MAXURANDBYTES INT_MAX 389d12795fSRobert Mustacchi 399d12795fSRobert Mustacchi int 409d12795fSRobert Mustacchi getrandom(void *bufp, size_t buflen, int flags) 419d12795fSRobert Mustacchi { 429d12795fSRobert Mustacchi int out = 0; 439d12795fSRobert Mustacchi uint8_t rbytes[128]; 449d12795fSRobert Mustacchi uint8_t *buf = bufp; 459d12795fSRobert Mustacchi 469d12795fSRobert Mustacchi if (flags & ~(GRND_NONBLOCK | GRND_RANDOM)) 479d12795fSRobert Mustacchi return (set_errno(EINVAL)); 489d12795fSRobert Mustacchi 499d12795fSRobert Mustacchi if ((flags & GRND_RANDOM) && buflen > MAXRANDBYTES) { 509d12795fSRobert Mustacchi buflen = MAXRANDBYTES; 519d12795fSRobert Mustacchi } else if (buflen > MAXURANDBYTES) { 529d12795fSRobert Mustacchi buflen = MAXURANDBYTES; 539d12795fSRobert Mustacchi } 549d12795fSRobert Mustacchi 55*a17dff0dSRobert Mustacchi while (out < buflen) { 569d12795fSRobert Mustacchi int err; 57*a17dff0dSRobert Mustacchi size_t len = MIN(sizeof (rbytes), buflen - out); 589d12795fSRobert Mustacchi 599d12795fSRobert Mustacchi if (flags & GRND_RANDOM) { 609d12795fSRobert Mustacchi if (flags & GRND_NONBLOCK) 619d12795fSRobert Mustacchi err = random_get_bytes(rbytes, len); 629d12795fSRobert Mustacchi else 639d12795fSRobert Mustacchi err = random_get_blocking_bytes(rbytes, len); 649d12795fSRobert Mustacchi } else { 659d12795fSRobert Mustacchi err = random_get_pseudo_bytes(rbytes, len); 669d12795fSRobert Mustacchi } 679d12795fSRobert Mustacchi 689d12795fSRobert Mustacchi if (err == 0) { 699d12795fSRobert Mustacchi if (ddi_copyout(rbytes, buf + out, len, 0) != 0) 709d12795fSRobert Mustacchi return (set_errno(EFAULT)); 719d12795fSRobert Mustacchi out += len; 729d12795fSRobert Mustacchi } else if (err == EAGAIN && out > 0) { 739d12795fSRobert Mustacchi break; 749d12795fSRobert Mustacchi } else { 759d12795fSRobert Mustacchi return (set_errno(err)); 769d12795fSRobert Mustacchi } 779d12795fSRobert Mustacchi } 789d12795fSRobert Mustacchi 799d12795fSRobert Mustacchi return (out); 809d12795fSRobert Mustacchi } 81