//random.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012 * * This file is part of libroar a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * libroar 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * NOTE for everyone want's to change something and send patches: * read README and HACKING! There a addition information on * the license of this document you need to read before you send * any patches. * * NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc * or libpulse*: * The libs libroaresd, libroararts and libroarpulse link this lib * and are therefore GPL. Because of this it may be illigal to use * them with any software that uses libesd, libartsc or libpulse*. */ #include "libroar.h" #ifdef ROAR_HAVE_LIBGCRYPT #include #endif static void roar_random_init (void) { static int inited = 0; if (inited) return; // add stuff here needed to bring up random source. roar_crypto_init(); inited = 1; } #define TIGER_BLOCKLEN 55 #define TIGER_DIGESTLEN (3*8) static size_t roar_nonce_salt_len = 0; static void * roar_nonce_salt = NULL; static unsigned char roar_nonce_pool[TIGER_DIGESTLEN]; static size_t roar_nonce_pool_len = 0; int roar_random_gen_nonce(void * buffer, size_t len) { static uint32_t buf[14]; static int inited = 0; static int idx = 0; volatile pid_t pid = getpid(); size_t i, writelen; void * off = buf; #ifdef ROAR_HAVE_TIME volatile uint32_t now = time(NULL); #endif roar_random_init(); if ( !inited ) { for (i = 0; i < (sizeof(buf)/sizeof(*buf)); i++) { #ifdef ROAR_HAVE_RAND buf[i] = rand() + pid; #else buf[i] = pid; #endif } #ifdef ROAR_HAVE_TIME buf[11] += now; #endif roar_hash_buffer(off, buf, TIGER_BLOCKLEN, ROAR_HT_TIGER); roar_hash_buffer(off+TIGER_DIGESTLEN, buf, TIGER_BLOCKLEN, ROAR_HT_TIGER); inited = 1; } while (len) { #ifdef ROAR_HAVE_TIME buf[12] += now; #endif #ifdef ROAR_HAVE_RAND buf[12] += rand(); #endif buf[12] += pid; buf[13] += pid; off = buf; if ( idx ) { off += TIGER_DIGESTLEN; idx = 0; } else { idx = 1; } roar_hash_salted_buffer(off, buf, TIGER_BLOCKLEN, ROAR_HT_TIGER, roar_nonce_salt, roar_nonce_salt_len); writelen = len >= TIGER_DIGESTLEN ? TIGER_DIGESTLEN : len; memcpy(buffer, off, writelen); buffer += writelen; len -= writelen; } return 0; } int roar_random_salt_nonce (void * salt, size_t len) { char buf[1]; int ret; roar_nonce_salt = salt; roar_nonce_salt_len = len; ret = roar_random_gen_nonce(buf, sizeof(buf)); roar_nonce_salt = NULL; roar_nonce_salt_len = 0; return ret; } uint16_t roar_random_uint16(void) { uint16_t ret; if ( roar_nonce_pool_len < 2 ) { roar_random_gen_nonce(roar_nonce_pool, sizeof(roar_nonce_pool)); roar_nonce_pool_len = sizeof(roar_nonce_pool); } ret = roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+0] << 0; ret |= roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+1] << 8; roar_nonce_pool_len -= 2; return ret; } uint32_t roar_random_uint32(void) { uint32_t ret; if ( roar_nonce_pool_len < 4 ) { roar_random_gen_nonce(roar_nonce_pool, sizeof(roar_nonce_pool)); roar_nonce_pool_len = sizeof(roar_nonce_pool); } ret = (uint32_t)roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+0] << 0; ret |= (uint32_t)roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+1] << 8; ret |= (uint32_t)roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+2] << 16; ret |= (uint32_t)roar_nonce_pool[sizeof(roar_nonce_pool)-roar_nonce_pool_len+3] << 24; roar_nonce_pool_len -= 4; return ret; } int roar_random_gen(void * buffer, size_t len, int quality) { if ( len == 0 ) return 0; if ( buffer == NULL ) return -1; roar_random_init(); switch (quality) { case ROAR_RANDOM_NONE: // no entropy: memset(buffer, 0, len); break; case ROAR_RANDOM_VERY_WEAK: return roar_random_gen_nonce(buffer, len); break; #ifdef ROAR_HAVE_LIBGCRYPT case ROAR_RANDOM_WEAK: gcry_create_nonce(buffer, len); break; case ROAR_RANDOM_NORMAL: case ROAR_RANDOM_STRONG: gcry_randomize(buffer, len, GCRY_STRONG_RANDOM); break; case ROAR_RANDOM_VERY_STRONG: gcry_randomize(buffer, len, GCRY_VERY_STRONG_RANDOM); break; #endif default: return -1; break; } return 0; } void * roar_random_genbuf(size_t len, int quality, int locked) { void * ret = roar_mm_malloc(len); if (ret == NULL) return NULL; if ( locked ) { if ( roar_mm_mlock(ret, len) == -1 ) { roar_mm_free(ret); return NULL; } } if ( roar_random_gen(ret, len, quality) == -1 ) { roar_mm_free(ret); return NULL; } return ret; } //ll