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 <sys/types.h> 00019 #include <sys/stat.h> 00020 #include <fcntl.h> 00021 #include <unistd.h> 00022 #include "randLIB.h" 00023 00024 /** 00025 * \brief Init seed for Pseudo Random. 00026 * On a Linux, this does nothing. 00027 * 00028 * \return None 00029 * 00030 */ 00031 void randLIB_seed_random(void) 00032 { 00033 } 00034 00035 /** 00036 * \brief Generate 8-bit random number. 00037 * 00038 * \param None 00039 * \return 8-bit random number 00040 * 00041 */ 00042 uint8_t randLIB_get_8bit(void) 00043 { 00044 uint8_t ret_val; 00045 randLIB_get_n_bytes_random(&ret_val, 1); 00046 return ret_val; 00047 } 00048 00049 /** 00050 * \brief Generate 16-bit random number. 00051 * 00052 * \param None 00053 * \return 16-bit random number 00054 * 00055 */ 00056 uint16_t randLIB_get_16bit(void) 00057 { 00058 uint16_t ret_val; 00059 00060 randLIB_get_n_bytes_random((uint8_t*)&ret_val, 2); 00061 return ret_val; 00062 } 00063 /** 00064 * \brief Generate 32-bit random number. 00065 * 00066 * \param None 00067 * \return 32-bit random number 00068 * 00069 */ 00070 uint32_t randLIB_get_32bit(void) 00071 { 00072 uint32_t ret_val; 00073 randLIB_get_n_bytes_random((uint8_t*)&ret_val, 4); 00074 return ret_val; 00075 } 00076 00077 00078 /** 00079 * \brief Generate n-bytes random numbers. 00080 * 00081 * \param data_ptr pointer where random will be stored 00082 * \param eight_bit_boundary how many bytes need random 00083 * \return 0 process valid 00084 * \return -1 Unsupported Parameters or failed to get random data. 00085 * 00086 */ 00087 int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary) 00088 { 00089 if ((data_ptr == 0) || (eight_bit_boundary == 0)) { 00090 return -1; 00091 } 00092 00093 int fd = open("/dev/urandom", O_RDONLY); 00094 if (fd != -1) { 00095 size_t len = read(fd, data_ptr, eight_bit_boundary); 00096 close(fd); 00097 if (len == eight_bit_boundary) 00098 return 0; 00099 } 00100 00101 return -1; 00102 } 00103 00104 /** 00105 * \brief Generate a random number within a range. 00106 * 00107 * The result is linearly distributed in the range [min..max], inclusive. 00108 * 00109 * \param min minimum value that can be generated 00110 * \param max maximum value that can be generated 00111 */ 00112 uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) 00113 { 00114 /* This special case is potentially common, particularly in this routine's 00115 * first user (Trickle), so worth catching immediately */ 00116 if (min == max) { 00117 return min; 00118 } 00119 00120 /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ 00121 if (max - min == 0xFFFF) { 00122 return randLIB_get_16bit(); 00123 } 00124 00125 unsigned int values_needed = max + 1 - min; 00126 unsigned int band_size = 0x10000u / values_needed; 00127 unsigned int top_of_bands = band_size * values_needed; 00128 unsigned int result; 00129 do { 00130 result = randLIB_get_16bit(); 00131 } while (result >= top_of_bands); 00132 00133 return min + (uint16_t)(result / band_size); 00134 } 00135 00136 /** 00137 * \brief Randomise a base 32-bit number by a jitter factor 00138 * 00139 * The result is linearly distributed in the jitter range, which is expressed 00140 * as fixed-point unsigned 1.15 values. For example, to produce a number in the 00141 * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to 00142 * 0xA000. 00143 * 00144 * Result is clamped to 0xFFFFFFFF if it overflows. 00145 * 00146 * \param base The base 32-bit value 00147 * \param min_factor The minimum value for the random factor 00148 * \param max_factor The maximum value for the random factor 00149 */ 00150 uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) 00151 { 00152 uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); 00153 00154 /* 32x16-bit long multiplication, to get 48-bit result */ 00155 uint32_t hi = (base >> 16) * random_factor; 00156 uint32_t lo = (base & 0xFFFF) * random_factor; 00157 /* Add halves, and take top 32 bits of 48-bit result */ 00158 uint32_t res = hi + (lo >> 16); 00159 00160 /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ 00161 if (res & 0x80000000) { 00162 res = 0xFFFFFFFF; 00163 } else { 00164 res = (res << 1) | ((lo >> 15) & 1); 00165 } 00166 00167 return res; 00168 }
Generated on Tue Jul 12 2022 13:05:27 by
1.7.2