/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "crypto/random/Random.h" #include "crypto/random/test/DeterminentRandomSeed.h" #include "io/FileWriter.h" #include "memory/Allocator.h" #include "memory/MallocAllocator.h" #include "util/Assert.h" #include "util/Bits.h" #include "util/log/Log.h" #include "util/log/WriterLog.h" static void checkBytes(struct Random* rand, int alignment, int length) { Assert_true(length < 128 && alignment < 8); uint64_t buff64[20] = {0}; uint8_t* buff = (uint8_t*) (&buff64[1]); buff += alignment; // Check for bytes which are always the same, a few \0s are ok // but if every cycle they are always zero then there's a bug. uint8_t oldBuff[128] = {0}; // Preload into the output buff so alignment is same. Random_bytes(rand, buff, length); Bits_memcpy(oldBuff, buff, length); uint8_t sameAsOld[128]; Bits_memset(sameAsOld, 0xff, 128); // Check for bytes which are the same as other bytes every time. // if buff[3] always equals buff[8] then there's a bug. uint8_t sameBytes[128+128]; Bits_memset(sameBytes, 0xff, 128+128); for (int i = 0; i < 100; i++) { Random_bytes(rand, buff, length); for (int j = 0; j < length; j++) { for (int jj = j; jj < length; jj++) { sameBytes[j+jj] &= (jj != j && buff[j] == buff[jj]); } } for (int j = 0; j < length; j++) { sameAsOld[j] &= (oldBuff[i] == buff[i]); } // Check that the function did not write after or before the buffer. uint8_t* origBuff = (uint8_t*) (buff64); Assert_true(Bits_isZero(origBuff, 8+alignment)); Assert_true(Bits_isZero(buff+length, 8)); } for (int i = 0; i < length+length-1; i++) { Assert_true(!sameBytes[i]); } for (int i = 0; i < length; i++) { Assert_true(!sameAsOld[i]); } } /** https://github.com/cjdelisle/cjdns/issues/179 */ static void test179(struct Allocator* alloc, struct Log* logger) { uint8_t buff[32] = {0}; uint8_t buff2[32] = {0}; struct Random* rand = Random_new(alloc, logger, NULL); struct Random* rand2 = Random_new(alloc, logger, NULL); Random_bytes(rand, buff, 32); Random_bytes(rand2, buff, 32); Assert_true(Bits_memcmp(buff, buff2, 32)); } int main() { struct Allocator* alloc = MallocAllocator_new(1<<20); struct RandomSeed* seed = DeterminentRandomSeed_new(alloc, NULL); struct Writer* w = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(w, alloc); struct Random* rand = Random_newWithSeed(alloc, logger, seed, NULL); // < 8 length checkBytes(rand, 0, 3); checkBytes(rand, 3, 6); // unaligned beginning (length and align add up to a multiple of 8) checkBytes(rand, 3, 29); // 1 byte aligned checkBytes(rand, 6, 10); // 2 byte aligned checkBytes(rand, 4, 20); // 4 byte aligned // unaligned end checkBytes(rand, 0, 9); // 1 byte checkBytes(rand, 0, 14); // 2 byte checkBytes(rand, 0, 20); // 4 byte // both unaligned checkBytes(rand, 1, 28); // 1,1 byte aligned checkBytes(rand, 3, 19); // 1,2 byte aligned checkBytes(rand, 5, 23); // 1,4 byte aligned checkBytes(rand, 2, 9); // 2,1 byte aligned checkBytes(rand, 6, 12); // 2,2 byte aligned checkBytes(rand, 6, 14); // 2,4 byte aligned checkBytes(rand, 4, 19); // 4,1 byte aligned checkBytes(rand, 4, 10); // 4,2 byte aligned checkBytes(rand, 4, 32); // 4,4 byte aligned test179(alloc, logger); /* torture uint8_t selections[2]; for (int i = 0; i < 100000; i++) { Random_bytes(rand, selections, 2); checkBytes(rand, selections[0] % 8, selections[1] % 128); }*/ Allocator_free(alloc); return 0; }