123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- /* 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 <https://www.gnu.org/licenses/>.
- */
- #include "crypto/random/seed/RandomSeed.h"
- #include "util/Identity.h"
- #include "util/log/Log.h"
- #include "util/Bits.h"
- #include <sodium/crypto_hash_sha512.h>
- struct RandomSeed_pvt
- {
- RandomSeed_t pub;
- RandomSeed_t** rsList;
- int rsCount;
- struct Log* logger;
- Identity
- };
- struct RandomSeed_Buffer
- {
- uint64_t output[8];
- uint64_t input[8];
- };
- #define RandomSeed_Buffer_SIZE 128
- Assert_compileTime(sizeof(struct RandomSeed_Buffer) == RandomSeed_Buffer_SIZE);
- static int get(RandomSeed_t* rs, uint64_t buffer[8])
- {
- struct RandomSeed_pvt* ctx = Identity_check((struct RandomSeed_pvt*) rs);
- Log_info(ctx->logger, "Attempting to seed random number generator");
- // each provider overwrites input and output is a rolling hash.
- struct RandomSeed_Buffer buff = { .output = {0} };
- int successCount = 0;
- for (int i = 0; i < ctx->rsCount; i++) {
- if (!ctx->rsList[i]->get(ctx->rsList[i], buff.input)) {
- Log_info(ctx->logger, "Trying random seed [%s] Success", ctx->rsList[i]->name);
- crypto_hash_sha512((uint8_t*)buff.output,
- (uint8_t*)&buff,
- RandomSeed_Buffer_SIZE);
- successCount++;
- } else {
- Log_info(ctx->logger, "Trying random seed [%s] Failed", ctx->rsList[i]->name);
- }
- }
- Assert_true(sizeof(buff.output) == 64);
- Bits_memcpy(buffer, buff.output, 64);
- if (successCount > 0) {
- Log_info(ctx->logger, "Seeding random number generator succeeded with [%d] sources",
- successCount);
- return 0;
- } else {
- Log_error(ctx->logger, "Seeding random number generator failed");
- return -1;
- }
- }
- int RandomSeed_get(RandomSeed_t* rs, uint64_t buffer[8])
- {
- return rs->get(rs, buffer);
- }
- RandomSeed_t* RandomSeed_new(RandomSeed_Provider* providers,
- int providerCount,
- struct Log* logger,
- struct Allocator* alloc)
- {
- RandomSeed_t** rsList = Allocator_calloc(alloc, sizeof(RandomSeed_t), providerCount);
- int i = 0;
- for (int j = 0; j < providerCount; j++) {
- RandomSeed_t* rs = providers[j](alloc);
- if (rs) {
- rsList[i++] = rs;
- }
- }
- Assert_true(i > 0);
- struct RandomSeed_pvt* out = Allocator_malloc(alloc, sizeof(struct RandomSeed_pvt));
- out->rsList = rsList;
- out->rsCount = i;
- out->logger = logger;
- out->pub.get = get;
- out->pub.name = "RandomSeed conglomeration of random seed providers";
- Identity_set(out);
- return &out->pub;
- }
|