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