Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
randLIB.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <stdint.h> 00017 #include <stdlib.h> 00018 #include <stdbool.h> 00019 #include <limits.h> 00020 #include "randLIB.h" 00021 #include "platform/arm_hal_random.h" 00022 00023 #if ((RAND_MAX+1) & RAND_MAX) != 0 00024 #error "RAND_MAX isn't 2^n-1 :(" 00025 #endif 00026 00027 /** 00028 * This library is made for getting random numbers for Timing needs in protocols. 00029 * 00030 * **not safe to use for security or cryptographic operations.** 00031 * 00032 */ 00033 00034 00035 /** 00036 * \brief Init seed for Pseudo Random. 00037 * 00038 * \return None 00039 * 00040 */ 00041 void randLIB_seed_random(void) 00042 { 00043 uint32_t rand_seed; 00044 arm_random_module_init(); 00045 rand_seed = arm_random_seed_get(); 00046 srand(rand_seed); 00047 } 00048 00049 /** 00050 * \brief Generate 8-bit random number. 00051 * 00052 * \param None 00053 * \return 8-bit random number 00054 * 00055 */ 00056 uint8_t randLIB_get_8bit(void) 00057 { 00058 return rand(); 00059 } 00060 00061 /** 00062 * \brief Generate 16-bit random number. 00063 * 00064 * \param None 00065 * \return 16-bit random number 00066 * 00067 */ 00068 uint16_t randLIB_get_16bit(void) 00069 { 00070 uint16_t ret_val; 00071 00072 ret_val = rand(); 00073 #if RAND_MAX == 0x7FFF 00074 ret_val |= (uint16_t) rand() << 15; 00075 #endif 00076 00077 return ret_val; 00078 } 00079 /** 00080 * \brief Generate 32-bit random number. 00081 * 00082 * \param None 00083 * \return 32-bit random number 00084 * 00085 */ 00086 uint32_t randLIB_get_32bit(void) 00087 { 00088 uint32_t ret_val; 00089 00090 ret_val = rand(); 00091 #if RAND_MAX == 0x7FFF 00092 ret_val |= (uint32_t) rand() << 15; 00093 ret_val |= (uint32_t) rand() << 30; 00094 #elif RAND_MAX == 0x3FFFFFFF /* IAR */ 00095 ret_val |= (uint32_t) rand() << 30; 00096 #elif RAND_MAX == 0x7FFFFFFF 00097 ret_val |= (uint32_t) rand() << 31; 00098 #else 00099 #error "randLIB_get_32bit - odd RAND_MAX" 00100 #endif 00101 00102 return ret_val; 00103 } 00104 00105 00106 /** 00107 * \brief Generate n-bytes random numbers. 00108 * 00109 * \param data_ptr pointer where random will be stored 00110 * \param eight_bit_boundary how many bytes need random 00111 * \return 0 process valid 00112 * \return -1 Unsupported Parameters 00113 * 00114 */ 00115 int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary) 00116 { 00117 if ((data_ptr == 0) || (eight_bit_boundary == 0)) { 00118 return -1; 00119 } 00120 00121 while (eight_bit_boundary) { 00122 *data_ptr++ = randLIB_get_8bit(); 00123 eight_bit_boundary--; 00124 } 00125 return 0; 00126 } 00127 00128 /** 00129 * \brief Generate a random number within a range. 00130 * 00131 * The result is linearly distributed in the range [min..max], inclusive. 00132 * 00133 * \param min minimum value that can be generated 00134 * \param max maximum value that can be generated 00135 */ 00136 uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) 00137 { 00138 /* This special case is potentially common, particularly in this routine's 00139 * first user (Trickle), so worth catching immediately */ 00140 if (min == max) { 00141 return min; 00142 } 00143 00144 /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ 00145 if (max - min == 0xFFFF) { 00146 return randLIB_get_16bit(); 00147 } 00148 00149 /* We get RAND_MAX+1 values from rand() in the range [0..RAND_MAX], and 00150 * need to divvy them up into the number of values we need. And reroll any 00151 * odd values off the end as we insist every value having equal chance. 00152 * 00153 * Special handling for systems where RAND_MAX is 0x7FFF; we use our 00154 * randLIB_get_16bit() and have to be a bit more careful about 00155 * unsigned integer overflow. (On other systems rand() returns int, 00156 * so we can't overflow if we use unsigned int). 00157 * 00158 * Eg, range(1,3), RAND_MAX = 0x7FFFFFFF: 00159 * We have 3 bands of size 0x2AAAAAAA (0x80000000/3). 00160 * 00161 * We roll: 0x00000000..0x2AAAAAAA9 -> 1 00162 * 0x2AAAAAAA..0x555555553 -> 2 00163 * 0x55555554..0x7FFFFFFFD -> 3 00164 * 0x7FFFFFFE..0x7FFFFFFFF -> reroll 00165 * 00166 * (Bias problem clearly pretty insignificant there, but gets worse as 00167 * range increases). 00168 */ 00169 unsigned int values_needed = max + 1 - min; 00170 #if RAND_MAX > 0xFFFF 00171 unsigned int band_size = (RAND_MAX + 1u) / values_needed; 00172 #elif UINT_MAX > 0xFFFF 00173 unsigned int band_size = 0x10000u / values_needed; 00174 #else 00175 /* Avoid the need for long division, at the expense of fractionally 00176 * increasing reroll chance. */ 00177 unsigned int band_size = 0xFFFFu / values_needed; 00178 #endif 00179 unsigned int top_of_bands = band_size * values_needed; 00180 unsigned int result; 00181 do { 00182 #if RAND_MAX > 0xFFFF 00183 result = rand(); 00184 #else 00185 result = randLIB_get_16bit(); 00186 #endif 00187 } while (result >= top_of_bands); 00188 00189 return min + (uint16_t)(result / band_size); 00190 } 00191 00192 /** 00193 * \brief Randomise a base 32-bit number by a jitter factor 00194 * 00195 * The result is linearly distributed in the jitter range, which is expressed 00196 * as fixed-point unsigned 1.15 values. For example, to produce a number in the 00197 * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to 00198 * 0xA000. 00199 * 00200 * Result is clamped to 0xFFFFFFFF if it overflows. 00201 * 00202 * \param base The base 32-bit value 00203 * \param min_factor The minimum value for the random factor 00204 * \param max_factor The maximum value for the random factor 00205 */ 00206 uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) 00207 { 00208 uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); 00209 00210 /* 32x16-bit long multiplication, to get 48-bit result */ 00211 uint32_t hi = (base >> 16) * random_factor; 00212 uint32_t lo = (base & 0xFFFF) * random_factor; 00213 /* Add halves, and take top 32 bits of 48-bit result */ 00214 uint32_t res = hi + (lo >> 16); 00215 00216 /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ 00217 if (res & 0x80000000) { 00218 res = 0xFFFFFFFF; 00219 } else { 00220 res = (res << 1) | ((lo >> 15) & 1); 00221 } 00222 00223 return res; 00224 }
Generated on Tue Jul 12 2022 17:34:52 by
 1.7.2