1/* 2 * random.c 3 * Copyright (C) 2015, Broadcom Corporation 4 * All Rights Reserved. 5 * 6 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 7 * the contents of this file may not be disclosed to third parties, copied 8 * or duplicated in any form, in whole or in part, without the prior 9 * written permission of Broadcom Corporation. 10 * 11 * $Id: random.c 241182 2011-02-17 21:50:03Z $ 12 */ 13#include <stdio.h> 14#if defined(__linux__) 15#include <stdlib.h> 16#include <unistd.h> 17#include <string.h> 18#include <signal.h> 19#include <errno.h> 20#include <sys/types.h> 21#include <sys/socket.h> 22#include <sys/ioctl.h> 23#include <netinet/in.h> 24#include <net/if.h> 25#include <fcntl.h> 26#include <linux/if_packet.h> 27#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) 28#include <stdlib.h> 29#elif WIN32 30#include <stdio.h> 31#include <windows.h> 32#include <Wincrypt.h> 33#endif /* __linux__ */ 34 35#include <assert.h> 36#include <typedefs.h> 37#include <bcmcrypto/bn.h> 38 39#if defined(__linux__) 40void linux_random(uint8 *rand, int len); 41#elif WIN32 42void windows_random(uint8 *rand, int len); 43#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) 44void generic_random(uint8* rand, int len); 45#elif defined(TARGETOS_symbian) 46void generic_random(uint8* rand, int len); 47#endif /* __linux__ */ 48 49void RAND_bytes(unsigned char *buf, int num) 50{ 51#if defined(__linux__) 52 linux_random(buf, num); 53#elif WIN32 54 windows_random(buf, num); 55#elif (defined(__ECOS) || defined(TARGETOS_nucleus)) 56 generic_random(buf, num); 57#elif defined(TARGETOS_symbian) 58 generic_random(buf, num); 59#endif /* __linux__ */ 60} 61 62#if defined(__linux__) 63void RAND_linux_init() 64{ 65 BN_register_RAND(linux_random); 66} 67 68#ifndef RANDOM_READ_TRY_MAX 69#define RANDOM_READ_TRY_MAX 10 70#endif 71 72void linux_random(uint8 *rand, int len) 73{ 74 static int dev_random_fd = -1; 75 int status; 76 int i; 77 78 if (dev_random_fd == -1) 79 dev_random_fd = open("/dev/urandom", O_RDONLY|O_NONBLOCK); 80 81 assert(dev_random_fd != -1); 82 83 for (i = 0; i < RANDOM_READ_TRY_MAX; i++) { 84 status = read(dev_random_fd, rand, len); 85 if (status == -1) { 86 if (errno == EINTR) 87 continue; 88 89 assert(status != -1); 90 } 91 92 return; 93 } 94 95 assert(i != RANDOM_READ_TRY_MAX); 96} 97#elif __ECOS 98void RAND_ecos_init() 99{ 100 BN_register_RAND(generic_random); 101} 102 103#elif WIN32 104void RAND_windows_init() 105{ 106 BN_register_RAND(windows_random); 107} 108 109void windows_random(uint8 *rand, int len) 110{ 111 /* Declare and initialize variables */ 112 113 HCRYPTPROV hCryptProv = NULL; 114 LPCSTR UserName = "{56E9D11F-76B8-42fa-8645-76980E4E8648}"; 115 116 /* 117 Attempt to acquire a context and a key 118 container. The context will use the default CSP 119 for the RSA_FULL provider type. DwFlags is set to 0 120 to attempt to open an existing key container. 121 */ 122 if (CryptAcquireContext(&hCryptProv, 123 UserName, 124 NULL, 125 PROV_RSA_FULL, 126 0)) 127 { 128 /* do nothing */ 129 } 130 else 131 { 132 /* 133 An error occurred in acquiring the context. This could mean 134 that the key container requested does not exist. In this case, 135 the function can be called again to attempt to create a new key 136 container. Error codes are defined in winerror.h. 137 */ 138 if (GetLastError() == NTE_BAD_KEYSET) 139 { 140 if (!CryptAcquireContext(&hCryptProv, 141 UserName, 142 NULL, 143 PROV_RSA_FULL, 144 CRYPT_NEWKEYSET)) 145 { 146 printf("Could not create a new key container.\n"); 147 } 148 } 149 else 150 { 151 printf("A cryptographic service handle could not be acquired.\n"); 152 } 153 } 154 155 if (hCryptProv) 156 { 157 /* Generate a random initialization vector. */ 158 if (!CryptGenRandom(hCryptProv, len, rand)) 159 { 160 printf("Error during CryptGenRandom.\n"); 161 } 162 if (!CryptReleaseContext(hCryptProv, 0)) 163 printf("Failed CryptReleaseContext\n"); 164 } 165 return; 166} 167#elif TARGETOS_nucleus 168void RAND_generic_init() 169{ 170 BN_register_RAND(generic_random); 171} 172#elif TARGETOS_symbian 173void RAND_generic_init() 174{ 175 BN_register_RAND(generic_random); 176} 177#endif /* __linux__ */ 178 179#if (defined(__ECOS) || defined(TARGETOS_nucleus) || defined(TARGETOS_symbian)) 180void 181generic_random(uint8 * random, int len) 182{ 183 int tlen = len; 184 while (tlen--) { 185 *random = (uint8)rand(); 186 *random++; 187 } 188 return; 189} 190#endif 191