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.
Dependents: blinky_max32630fthr
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 14:21:18 by
1.7.2