1*defd0d96SSchrodinger ZHU Yifan //===-- Linux implementation of getentropy --------------------------------===// 2*defd0d96SSchrodinger ZHU Yifan // 3*defd0d96SSchrodinger ZHU Yifan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*defd0d96SSchrodinger ZHU Yifan // See https://llvm.org/LICENSE.txt for license information. 5*defd0d96SSchrodinger ZHU Yifan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*defd0d96SSchrodinger ZHU Yifan // 7*defd0d96SSchrodinger ZHU Yifan //===----------------------------------------------------------------------===// 8*defd0d96SSchrodinger ZHU Yifan 9*defd0d96SSchrodinger ZHU Yifan #include "src/unistd/getentropy.h" 10*defd0d96SSchrodinger ZHU Yifan #include "hdr/errno_macros.h" 11*defd0d96SSchrodinger ZHU Yifan #include "src/__support/OSUtil/syscall.h" 12*defd0d96SSchrodinger ZHU Yifan #include "src/__support/common.h" 13*defd0d96SSchrodinger ZHU Yifan #include "src/errno/libc_errno.h" 14*defd0d96SSchrodinger ZHU Yifan 15*defd0d96SSchrodinger ZHU Yifan #include <sys/syscall.h> // For syscall numbers. 16*defd0d96SSchrodinger ZHU Yifan 17*defd0d96SSchrodinger ZHU Yifan namespace LIBC_NAMESPACE_DECL { 18*defd0d96SSchrodinger ZHU Yifan LLVM_LIBC_FUNCTION(int, getentropy, (void *buffer, size_t length)) { 19*defd0d96SSchrodinger ZHU Yifan // check the length limit 20*defd0d96SSchrodinger ZHU Yifan if (length > 256) { 21*defd0d96SSchrodinger ZHU Yifan libc_errno = EIO; 22*defd0d96SSchrodinger ZHU Yifan return -1; 23*defd0d96SSchrodinger ZHU Yifan } 24*defd0d96SSchrodinger ZHU Yifan 25*defd0d96SSchrodinger ZHU Yifan char *cursor = static_cast<char *>(buffer); 26*defd0d96SSchrodinger ZHU Yifan while (length != 0) { 27*defd0d96SSchrodinger ZHU Yifan // 0 flag means urandom and blocking, which meets the assumption of 28*defd0d96SSchrodinger ZHU Yifan // getentropy 29*defd0d96SSchrodinger ZHU Yifan auto ret = syscall_impl<long>(SYS_getrandom, cursor, length, 0); 30*defd0d96SSchrodinger ZHU Yifan 31*defd0d96SSchrodinger ZHU Yifan // on success, advance the buffer pointer 32*defd0d96SSchrodinger ZHU Yifan if (ret >= 0) { 33*defd0d96SSchrodinger ZHU Yifan length -= static_cast<size_t>(ret); 34*defd0d96SSchrodinger ZHU Yifan cursor += ret; 35*defd0d96SSchrodinger ZHU Yifan continue; 36*defd0d96SSchrodinger ZHU Yifan } 37*defd0d96SSchrodinger ZHU Yifan 38*defd0d96SSchrodinger ZHU Yifan auto error = -static_cast<int>(ret); 39*defd0d96SSchrodinger ZHU Yifan 40*defd0d96SSchrodinger ZHU Yifan // on EINTR, try again 41*defd0d96SSchrodinger ZHU Yifan if (error == EINTR) 42*defd0d96SSchrodinger ZHU Yifan continue; 43*defd0d96SSchrodinger ZHU Yifan 44*defd0d96SSchrodinger ZHU Yifan // on ENOSYS, forward errno and exit; 45*defd0d96SSchrodinger ZHU Yifan // otherwise, set EIO and exit 46*defd0d96SSchrodinger ZHU Yifan libc_errno = (error == ENOSYS) ? ENOSYS : EIO; 47*defd0d96SSchrodinger ZHU Yifan return -1; 48*defd0d96SSchrodinger ZHU Yifan } 49*defd0d96SSchrodinger ZHU Yifan return 0; 50*defd0d96SSchrodinger ZHU Yifan } 51*defd0d96SSchrodinger ZHU Yifan } // namespace LIBC_NAMESPACE_DECL 52