1 /*############################################################################ 2 # Copyright 2016-2017 Intel Corporation 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 ############################################################################*/ 16 17 /*! 18 * \file 19 * \brief Pseudo random number generator implementation. 20 */ 21 #include <ippcp.h> 22 #include <stdlib.h> 23 #include <time.h> 24 25 #include "src/prng.h" 26 27 EpidStatus PrngCreate(void** prng) { 28 // Security note: 29 // Random number generator used in the samples not claimed to be a 30 // cryptographically secure pseudo-random number generator. 31 EpidStatus sts = kEpidErr; 32 int prng_ctx_size = 0; 33 IppsPRNGState* prng_ctx = NULL; 34 int seed_ctx_size = 0; 35 IppsBigNumState* seed_ctx = NULL; 36 time_t seed_value; 37 38 if (!prng) return kEpidBadArgErr; 39 40 if (ippStsNoErr != ippsPRNGGetSize(&prng_ctx_size)) return kEpidErr; 41 if (ippStsNoErr != 42 ippsBigNumGetSize((sizeof(seed_value) + 3) / 4, &seed_ctx_size)) 43 return kEpidErr; 44 45 do { 46 prng_ctx = (IppsPRNGState*)calloc(1, prng_ctx_size); 47 48 if (!prng_ctx) { 49 sts = kEpidNoMemErr; 50 break; 51 } 52 if (ippStsNoErr != ippsPRNGInit(sizeof(seed_value) * 8, prng_ctx)) { 53 sts = kEpidErr; 54 break; 55 } 56 57 // seed PRNG 58 seed_ctx = (IppsBigNumState*)calloc(1, seed_ctx_size); 59 if (!seed_ctx) { 60 sts = kEpidNoMemErr; 61 break; 62 } 63 if (ippStsNoErr != ippsBigNumInit((sizeof(seed_value) + 3) / 4, seed_ctx)) { 64 sts = kEpidErr; 65 break; 66 } 67 time(&seed_value); 68 if (ippStsNoErr != 69 ippsSetOctString_BN((void*)&seed_value, sizeof(seed_value), seed_ctx)) { 70 sts = kEpidErr; 71 break; 72 } 73 if (ippStsNoErr != ippsPRNGSetSeed(seed_ctx, prng_ctx)) { 74 sts = kEpidErr; 75 break; 76 } 77 78 *prng = prng_ctx; 79 prng_ctx = NULL; 80 sts = kEpidNoErr; 81 } while (0); 82 83 if (seed_ctx) free(seed_ctx); 84 if (prng_ctx) free(prng_ctx); 85 return sts; 86 } 87 88 void PrngDelete(void** prng) { 89 if (prng && *prng) { 90 free(*prng); 91 *prng = NULL; 92 } 93 } 94 95 // simple wrapper to hide IPP implementation. 96 int __STDCALL PrngGen(unsigned int* rand_data, int num_bits, void* user_data) { 97 return ippsPRNGen(rand_data, num_bits, (IppsPRNGState*)user_data); 98 } 99