1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project 3*f0865ec9SKyle Evans * 4*f0865ec9SKyle Evans * Authors: 5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans * 9*f0865ec9SKyle Evans * Contributors: 10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans * 13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans */ 16*f0865ec9SKyle Evans #include <libecc/external_deps/rand.h> 17*f0865ec9SKyle Evans 18*f0865ec9SKyle Evans /* Unix and compatible case (including macOS) */ 19*f0865ec9SKyle Evans #if defined(WITH_STDLIB) && (defined(__unix__) || defined(__APPLE__)) 20*f0865ec9SKyle Evans #include <stdio.h> 21*f0865ec9SKyle Evans #include <stdlib.h> 22*f0865ec9SKyle Evans #include <string.h> 23*f0865ec9SKyle Evans #include <limits.h> 24*f0865ec9SKyle Evans 25*f0865ec9SKyle Evans #include <sys/types.h> 26*f0865ec9SKyle Evans #include <sys/stat.h> 27*f0865ec9SKyle Evans #include <fcntl.h> 28*f0865ec9SKyle Evans #include <unistd.h> 29*f0865ec9SKyle Evans #include <libecc/words/words.h> 30*f0865ec9SKyle Evans 31*f0865ec9SKyle Evans /* 32*f0865ec9SKyle Evans * Copy file content to buffer. Return 0 on success, i.e. if the request 33*f0865ec9SKyle Evans * size has been read and copied to buffer and -1 otherwise. 34*f0865ec9SKyle Evans */ 35*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int fimport(unsigned char *buf, u16 buflen, 36*f0865ec9SKyle Evans const char *path) 37*f0865ec9SKyle Evans { 38*f0865ec9SKyle Evans u16 rem = buflen, copied = 0; 39*f0865ec9SKyle Evans ssize_t ret; 40*f0865ec9SKyle Evans int fd; 41*f0865ec9SKyle Evans 42*f0865ec9SKyle Evans if ((buf == NULL) || (path == NULL)) { 43*f0865ec9SKyle Evans ret = -1; 44*f0865ec9SKyle Evans goto err; 45*f0865ec9SKyle Evans } 46*f0865ec9SKyle Evans 47*f0865ec9SKyle Evans fd = open(path, O_RDONLY); 48*f0865ec9SKyle Evans if (fd == -1) { 49*f0865ec9SKyle Evans printf("Unable to open input file %s\n", path); 50*f0865ec9SKyle Evans ret = -1; 51*f0865ec9SKyle Evans goto err; 52*f0865ec9SKyle Evans } 53*f0865ec9SKyle Evans 54*f0865ec9SKyle Evans while (rem) { 55*f0865ec9SKyle Evans ret = (int)read(fd, buf + copied, rem); 56*f0865ec9SKyle Evans if (ret <= 0) { 57*f0865ec9SKyle Evans break; 58*f0865ec9SKyle Evans } else { 59*f0865ec9SKyle Evans rem = (u16)(rem - ret); 60*f0865ec9SKyle Evans copied = (u16)(copied + ret); 61*f0865ec9SKyle Evans } 62*f0865ec9SKyle Evans } 63*f0865ec9SKyle Evans 64*f0865ec9SKyle Evans if (close(fd)) { 65*f0865ec9SKyle Evans printf("Unable to close input file %s\n", path); 66*f0865ec9SKyle Evans ret = -1; 67*f0865ec9SKyle Evans goto err; 68*f0865ec9SKyle Evans } 69*f0865ec9SKyle Evans 70*f0865ec9SKyle Evans ret = (copied == buflen) ? 0 : -1; 71*f0865ec9SKyle Evans 72*f0865ec9SKyle Evans err: 73*f0865ec9SKyle Evans return (int)ret; 74*f0865ec9SKyle Evans } 75*f0865ec9SKyle Evans 76*f0865ec9SKyle Evans int get_random(unsigned char *buf, u16 len) 77*f0865ec9SKyle Evans { 78*f0865ec9SKyle Evans return fimport(buf, len, "/dev/urandom"); 79*f0865ec9SKyle Evans } 80*f0865ec9SKyle Evans 81*f0865ec9SKyle Evans /* Windows case */ 82*f0865ec9SKyle Evans #elif defined(WITH_STDLIB) && defined(__WIN32__) 83*f0865ec9SKyle Evans #include <windows.h> 84*f0865ec9SKyle Evans #include <wincrypt.h> 85*f0865ec9SKyle Evans 86*f0865ec9SKyle Evans int get_random(unsigned char *buf, u16 len) 87*f0865ec9SKyle Evans { 88*f0865ec9SKyle Evans int ret; 89*f0865ec9SKyle Evans HCRYPTPROV hCryptProv = 0; 90*f0865ec9SKyle Evans 91*f0865ec9SKyle Evans if (CryptAcquireContext(&hCryptProv, NULL, NULL, 92*f0865ec9SKyle Evans PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { 93*f0865ec9SKyle Evans ret = -1; 94*f0865ec9SKyle Evans goto err; 95*f0865ec9SKyle Evans } 96*f0865ec9SKyle Evans 97*f0865ec9SKyle Evans if (CryptGenRandom(hCryptProv, len, buf) == FALSE) { 98*f0865ec9SKyle Evans CryptReleaseContext(hCryptProv, 0); 99*f0865ec9SKyle Evans ret = -1; 100*f0865ec9SKyle Evans goto err; 101*f0865ec9SKyle Evans } 102*f0865ec9SKyle Evans CryptReleaseContext(hCryptProv, 0); 103*f0865ec9SKyle Evans ret = 0; 104*f0865ec9SKyle Evans 105*f0865ec9SKyle Evans err: 106*f0865ec9SKyle Evans return ret; 107*f0865ec9SKyle Evans } 108*f0865ec9SKyle Evans 109*f0865ec9SKyle Evans /* No platform detected, the user must provide an implementation! */ 110*f0865ec9SKyle Evans #else 111*f0865ec9SKyle Evans /* WARNING: when providing/implementing the get_random function, one must: 112*f0865ec9SKyle Evans * - Use a proper entropy source with a TRNG (True Random Number Generator) 113*f0865ec9SKyle Evans * basis and clean PRNG (Pseudo-Random Number Generator) post-processing 114*f0865ec9SKyle Evans * when needed. 115*f0865ec9SKyle Evans * - Use a non-leaking generator in contexts where attackers that have access 116*f0865ec9SKyle Evans * to side channels are a plausible threat (a process in an OS sharing memory 117*f0865ec9SKyle Evans * and caches with other possibly malicious processes, a microcontroller 118*f0865ec9SKyle Evans * that can be observed using EM probes or power consumtion, ...). 119*f0865ec9SKyle Evans */ 120*f0865ec9SKyle Evans #error "rand.c: you have to implement get_random with a proper entropy source!" 121*f0865ec9SKyle Evans #endif 122