Get random bytes, attempts to get an initial seed from /dev/urandom and * the uses a one way hash function in counter mode to generate a random * stream. However if /dev/urandom is not available, a weaker seed is used. * * This function is not thread safe, since the state is global. */
| 645 | * |
| 646 | * This function is not thread safe, since the state is global. */ |
| 647 | void getRandomBytes(unsigned char *p, size_t len) { |
| 648 | /* Global state. */ |
| 649 | static int seed_initialized = 0; |
| 650 | static unsigned char seed[64]; /* 512 bit internal block size. */ |
| 651 | static uint64_t counter = 0; /* The counter we hash with the seed. */ |
| 652 | |
| 653 | if (!seed_initialized) { |
| 654 | /* Initialize a seed and use SHA1 in counter mode, where we hash |
| 655 | * the same seed with a progressive counter. For the goals of this |
| 656 | * function we just need non-colliding strings, there are no |
| 657 | * cryptographic security needs. */ |
| 658 | FILE *fp = fopen("/dev/urandom","r"); |
| 659 | if (fp == NULL || fread(seed,sizeof(seed),1,fp) != 1) { |
| 660 | /* Revert to a weaker seed, and in this case reseed again |
| 661 | * at every call.*/ |
| 662 | for (unsigned int j = 0; j < sizeof(seed); j++) { |
| 663 | struct timeval tv; |
| 664 | gettimeofday(&tv,NULL); |
| 665 | pid_t pid = getpid(); |
| 666 | seed[j] = tv.tv_sec ^ tv.tv_usec ^ pid ^ (long)fp; |
| 667 | } |
| 668 | } else { |
| 669 | seed_initialized = 1; |
| 670 | } |
| 671 | if (fp) fclose(fp); |
| 672 | } |
| 673 | |
| 674 | while(len) { |
| 675 | /* This implements SHA256-HMAC. */ |
| 676 | unsigned char digest[SHA256_BLOCK_SIZE]; |
| 677 | unsigned char kxor[64]; |
| 678 | unsigned int copylen = |
| 679 | len > SHA256_BLOCK_SIZE ? SHA256_BLOCK_SIZE : len; |
| 680 | |
| 681 | /* IKEY: key xored with 0x36. */ |
| 682 | memcpy(kxor,seed,sizeof(kxor)); |
| 683 | for (unsigned int i = 0; i < sizeof(kxor); i++) kxor[i] ^= 0x36; |
| 684 | |
| 685 | /* Obtain HASH(IKEY||MESSAGE). */ |
| 686 | SHA256_CTX ctx; |
| 687 | sha256_init(&ctx); |
| 688 | sha256_update(&ctx,kxor,sizeof(kxor)); |
| 689 | sha256_update(&ctx,(unsigned char*)&counter,sizeof(counter)); |
| 690 | sha256_final(&ctx,digest); |
| 691 | |
| 692 | /* OKEY: key xored with 0x5c. */ |
| 693 | memcpy(kxor,seed,sizeof(kxor)); |
| 694 | for (unsigned int i = 0; i < sizeof(kxor); i++) kxor[i] ^= 0x5C; |
| 695 | |
| 696 | /* Obtain HASH(OKEY || HASH(IKEY||MESSAGE)). */ |
| 697 | sha256_init(&ctx); |
| 698 | sha256_update(&ctx,kxor,sizeof(kxor)); |
| 699 | sha256_update(&ctx,digest,SHA256_BLOCK_SIZE); |
| 700 | sha256_final(&ctx,digest); |
| 701 | |
| 702 | /* Increment the counter for the next iteration. */ |
| 703 | counter++; |
| 704 |
no test coverage detected