1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1b, Real-time extensions
24 // (IEEE Std 1003.1b-1993) specification
26 // For this specific file, see use of clock_gettime,
27 // Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
28 // and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
29 #ifndef _POSIX_C_SOURCE
30 #define _POSIX_C_SOURCE 200809L
33 #include "iotivity_config.h"
46 #elif defined(HAVE_STRINGS_H)
49 #ifdef HAVE_SYS_TIME_H
55 #if defined(__ANDROID__)
57 #include <linux/time.h>
65 #ifdef HAVE_UUID_UUID_H
66 #include <uuid/uuid.h>
69 #define NANO_SEC 1000000000
74 // ARM GCC compiler doesnt define srandom function.
75 #if defined(ARDUINO) && !defined(ARDUINO_ARCH_SAM)
76 #define HAVE_SRANDOM 1
79 uint8_t GetRandomBitRaw()
81 return analogRead((uint8_t)ANALOG_IN) & 0x1;
84 uint8_t GetRandomBitRaw2()
89 a = GetRandomBitRaw() | (GetRandomBitRaw()<<1);
92 return 0; // 1 to 0 transition: log a zero bit
96 return 1;// 0 to 1 transition: log a one bit
98 // For other cases, try again.
102 uint8_t GetRandomBit()
107 a = GetRandomBitRaw2() | (GetRandomBitRaw2()<<1);
110 return 0; // 1 to 0 transition: log a zero bit
114 return 1;// 0 to 1 transition: log a one bit
116 // For other cases, try again.
121 int8_t OCSeedRandom()
124 // Get current time to Seed.
125 uint64_t currentTime = 0;
127 struct timespec getTs;
128 clock_gettime(CLOCK_MONOTONIC, &getTs);
129 currentTime = (getTs.tv_sec * (uint64_t)NANO_SEC + getTs.tv_nsec)/1000;
132 if (QueryPerformanceCounter(&count)) {
133 currentTime = count.QuadPart;
135 #elif _POSIX_TIMERS > 0
137 clock_gettime(CLOCK_MONOTONIC, &ts);
138 currentTime = (ts.tv_sec * (uint64_t)NANO_SEC + ts.tv_nsec)/ 1000;
141 gettimeofday(&tv, NULL);
142 currentTime = tv.tv_sec * (uint64_t)1000000 + tv.tv_usec;
144 #if defined(__unix__) || defined(__APPLE__) || defined(__TIZENRT__)
145 int32_t fd = open("/dev/urandom", O_RDONLY);
148 uint32_t randomSeed = 0;
149 uint32_t totalRead = 0; //how many integers were read
150 int32_t currentRead = 0;
151 while (totalRead < sizeof(randomSeed))
153 currentRead = read(fd, (uint8_t*) &randomSeed + totalRead,
154 sizeof(randomSeed) - totalRead);
157 totalRead += currentRead;
161 srand(randomSeed | currentTime);
166 // Do time based seed when problem in accessing "/dev/urandom"
171 #elif defined ARDUINO
176 result += result + GetRandomBit();
188 void OCFillRandomMem(uint8_t * location, uint16_t len)
198 *location++ = OCGetRandomByte();
200 uint8_t *temp = (char *) OICCalloc(len, sizeof(char));
201 int *mask = (int *) OICCalloc(len, sizeof(int));
202 for (i = 0; i < len; i++)
207 for (i = 0; i < len; i++)
209 rand_idx = lrand48() % len;
210 while((rand_idx < len) && (mask[rand_idx] != 0))
217 while(mask[rand_idx] != 0)
222 temp[rand_idx] = location[j];
226 for (i = 0; i < len; i++)
228 location[i] = temp[i];
234 uint32_t OCGetRandom()
237 OCFillRandomMem((uint8_t*) &result, 4);
241 uint8_t OCGetRandomByte(void)
244 return random() & 0x00FF;
246 return rand() & 0x00FF;
250 uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound)
255 if (firstBound > secondBound)
258 diff = firstBound - secondBound;
260 else if (firstBound < secondBound)
263 diff = secondBound - firstBound;
269 result = ((float)OCGetRandom()/((float)(0xFFFFFFFF))*(float)diff) + (float) base;
273 #if defined(__ANDROID__)
274 uint8_t parseUuidChar(char c)
285 uint8_t parseUuidPart(const char *c)
287 return (parseUuidChar(c[0])<<4) + parseUuidChar(c[1]);
291 OCRandomUuidResult OCGenerateUuid(uint8_t uuid[UUID_SIZE])
295 return RAND_UUID_INVALID_PARAM;
297 #if defined(__ANDROID__)
298 char uuidString[UUID_STRING_SIZE];
299 int8_t ret = OCGenerateUuidString(uuidString);
301 if (RAND_UUID_OK == ret)
303 uuid[ 0] = parseUuidPart(&uuidString[0]);
304 uuid[ 1] = parseUuidPart(&uuidString[2]);
305 uuid[ 2] = parseUuidPart(&uuidString[4]);
306 uuid[ 3] = parseUuidPart(&uuidString[6]);
308 uuid[ 4] = parseUuidPart(&uuidString[9]);
309 uuid[ 5] = parseUuidPart(&uuidString[11]);
311 uuid[ 6] = parseUuidPart(&uuidString[14]);
312 uuid[ 7] = parseUuidPart(&uuidString[16]);
314 uuid[ 8] = parseUuidPart(&uuidString[19]);
315 uuid[ 9] = parseUuidPart(&uuidString[21]);
317 uuid[10] = parseUuidPart(&uuidString[24]);
318 uuid[11] = parseUuidPart(&uuidString[26]);
319 uuid[12] = parseUuidPart(&uuidString[28]);
320 uuid[13] = parseUuidPart(&uuidString[30]);
321 uuid[14] = parseUuidPart(&uuidString[32]);
322 uuid[15] = parseUuidPart(&uuidString[34]);
327 #if defined(HAVE_UUID_UUID_H)
328 // note: uuid_t is typedefed as unsigned char[16] on linux/apple
332 // Fallback for all platforms is filling the array with random data
333 OCFillRandomMem(uuid, UUID_SIZE);
338 OCRandomUuidResult OCGenerateUuidString(char uuidString[UUID_STRING_SIZE])
342 return RAND_UUID_INVALID_PARAM;
344 #if defined(__ANDROID__)
345 int32_t fd = open("/proc/sys/kernel/random/uuid", O_RDONLY);
348 ssize_t readResult = read(fd, uuidString, UUID_STRING_SIZE - 1);
352 return RAND_UUID_READ_ERROR;
354 else if (readResult < UUID_STRING_SIZE - 1)
356 uuidString[0] = '\0';
357 return RAND_UUID_READ_ERROR;
360 uuidString[UUID_STRING_SIZE - 1] = '\0';
361 for (char* p = uuidString; *p; ++p)
369 return RAND_UUID_READ_ERROR;
371 #elif defined(HAVE_UUID_UUID_H)
372 uint8_t uuid[UUID_SIZE];
373 int8_t ret = OCGenerateUuid(uuid);
380 uuid_unparse_lower(uuid, uuidString);
384 uint8_t uuid[UUID_SIZE];
385 OCGenerateUuid(uuid);
387 return OCConvertUuidToString(uuid, uuidString);
391 OCRandomUuidResult OCConvertUuidToString(const uint8_t uuid[UUID_SIZE],
392 char uuidString[UUID_STRING_SIZE])
394 if (uuid == NULL || uuidString == NULL)
396 return RAND_UUID_INVALID_PARAM;
400 int ret = snprintf(uuidString, UUID_STRING_SIZE,
401 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
402 uuid[0], uuid[1], uuid[2], uuid[3],
403 uuid[4], uuid[5], uuid[6], uuid[7],
404 uuid[8], uuid[9], uuid[10], uuid[11],
405 uuid[12], uuid[13], uuid[14], uuid[15]
408 if (ret != UUID_STRING_SIZE - 1)
410 return RAND_UUID_CONVERT_ERROR;
416 OCRandomUuidResult OCConvertStringToUuid(const char uuidString[UUID_STRING_SIZE],
417 uint8_t uuid[UUID_SIZE])
419 if(NULL == uuidString || NULL == uuid)
421 return RAND_UUID_INVALID_PARAM;
426 size_t strUuidLen = 0;
427 char convertedUuid[UUID_SIZE * 2] = {0};
429 strUuidLen = strlen(uuidString);
430 if((UUID_STRING_SIZE - 1) == strUuidLen)
432 for(uuidIdx=0, urnIdx=0; uuidIdx < UUID_SIZE ; uuidIdx++, urnIdx+=2)
434 if(*(uuidString + urnIdx) == '-')
438 sscanf(uuidString + urnIdx, "%2hhx", &convertedUuid[uuidIdx]);
443 return RAND_UUID_CONVERT_ERROR;
446 memcpy(uuid, convertedUuid, UUID_SIZE);