Blame random_seed.c

Packit Service def718
/*
Packit Service def718
 * random_seed.c
Packit Service def718
 *
Packit Service def718
 * Copyright (c) 2013 Metaparadigm Pte. Ltd.
Packit Service def718
 * Michael Clark <michael@metaparadigm.com>
Packit Service def718
 *
Packit Service def718
 * This library is free software; you can redistribute it and/or modify
Packit Service def718
 * it under the terms of the MIT license. See COPYING for details.
Packit Service def718
 *
Packit Service def718
 */
Packit Service def718
Packit Service def718
#include "strerror_override.h"
Packit Service def718
#include <stdio.h>
Packit Service def718
#include "config.h"
Packit Service def718
#include "random_seed.h"
Packit Service def718
Packit Service def718
#define DEBUG_SEED(s)
Packit Service def718
Packit Service def718
Packit Service def718
#if defined ENABLE_RDRAND
Packit Service def718
Packit Service def718
/* cpuid */
Packit Service def718
Packit Service def718
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
Packit Service def718
#define HAS_X86_CPUID 1
Packit Service def718
Packit Service def718
static void do_cpuid(int regs[], int h)
Packit Service def718
{
Packit Service def718
    __asm__ __volatile__(
Packit Service def718
#if defined __x86_64__
Packit Service def718
                         "pushq %%rbx;\n"
Packit Service def718
#else
Packit Service def718
                         "pushl %%ebx;\n"
Packit Service def718
#endif
Packit Service def718
                         "cpuid;\n"
Packit Service def718
#if defined __x86_64__
Packit Service def718
                         "popq %%rbx;\n"
Packit Service def718
#else
Packit Service def718
                         "popl %%ebx;\n"
Packit Service def718
#endif
Packit Service def718
                         : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
Packit Service def718
                         : "a"(h));
Packit Service def718
}
Packit Service def718
Packit Service def718
#elif defined _MSC_VER
Packit Service def718
Packit Service def718
#define HAS_X86_CPUID 1
Packit Service def718
#define do_cpuid __cpuid
Packit Service def718
Packit Service def718
#endif
Packit Service def718
Packit Service def718
/* has_rdrand */
Packit Service def718
Packit Service def718
#if HAS_X86_CPUID
Packit Service def718
Packit Service def718
static int has_rdrand()
Packit Service def718
{
Packit Service def718
    // CPUID.01H:ECX.RDRAND[bit 30] == 1
Packit Service def718
    int regs[4];
Packit Service def718
    do_cpuid(regs, 1);
Packit Service def718
    return (regs[2] & (1 << 30)) != 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
#endif
Packit Service def718
Packit Service def718
/* get_rdrand_seed - GCC x86 and X64 */
Packit Service def718
Packit Service def718
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
Packit Service def718
Packit Service def718
#define HAVE_RDRAND 1
Packit Service def718
Packit Service def718
static int get_rdrand_seed()
Packit Service def718
{
Packit Service def718
    DEBUG_SEED("get_rdrand_seed");
Packit Service def718
    int _eax;
Packit Service def718
    // rdrand eax
Packit Service def718
    __asm__ __volatile__("1: .byte 0x0F\n"
Packit Service def718
                         "   .byte 0xC7\n"
Packit Service def718
                         "   .byte 0xF0\n"
Packit Service def718
                         "   jnc 1b;\n"
Packit Service def718
                         : "=a" (_eax));
Packit Service def718
    return _eax;
Packit Service def718
}
Packit Service def718
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#if defined _MSC_VER
Packit Service def718
Packit Service def718
#if _MSC_VER >= 1700
Packit Service def718
#define HAVE_RDRAND 1
Packit Service def718
Packit Service def718
/* get_rdrand_seed - Visual Studio 2012 and above */
Packit Service def718
Packit Service def718
static int get_rdrand_seed()
Packit Service def718
{
Packit Service def718
    DEBUG_SEED("get_rdrand_seed");
Packit Service def718
    int r;
Packit Service def718
    while (_rdrand32_step(&r) == 0);
Packit Service def718
    return r;
Packit Service def718
}
Packit Service def718
Packit Service def718
#elif defined _M_IX86
Packit Service def718
#define HAVE_RDRAND 1
Packit Service def718
Packit Service def718
/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
Packit Service def718
Packit Service def718
static int get_rdrand_seed()
Packit Service def718
{
Packit Service def718
	DEBUG_SEED("get_rdrand_seed");
Packit Service def718
	int _eax;
Packit Service def718
retry:
Packit Service def718
	// rdrand eax
Packit Service def718
	__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
Packit Service def718
	__asm jnc retry
Packit Service def718
	__asm mov _eax, eax
Packit Service def718
	return _eax;
Packit Service def718
}
Packit Service def718
Packit Service def718
#endif
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#endif /* defined ENABLE_RDRAND */
Packit Service def718
Packit Service def718
Packit Service def718
/* has_dev_urandom */
Packit Service def718
Packit Service def718
#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
Packit Service def718
Packit Service def718
#include <string.h>
Packit Service def718
#include <fcntl.h>
Packit Service def718
#include <unistd.h>
Packit Service def718
#include <stdlib.h>
Packit Service def718
#include <sys/stat.h>
Packit Service def718
Packit Service def718
#define HAVE_DEV_RANDOM 1
Packit Service def718
Packit Service def718
static const char *dev_random_file = "/dev/urandom";
Packit Service def718
Packit Service def718
static int has_dev_urandom()
Packit Service def718
{
Packit Service def718
    struct stat buf;
Packit Service def718
    if (stat(dev_random_file, &buf)) {
Packit Service def718
        return 0;
Packit Service def718
    }
Packit Service def718
    return ((buf.st_mode & S_IFCHR) != 0);
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* get_dev_random_seed */
Packit Service def718
Packit Service def718
static int get_dev_random_seed()
Packit Service def718
{
Packit Service def718
    DEBUG_SEED("get_dev_random_seed");
Packit Service def718
Packit Service def718
    int fd = open(dev_random_file, O_RDONLY);
Packit Service def718
    if (fd < 0) {
Packit Service def718
        fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
Packit Service def718
        exit(1);
Packit Service def718
    }
Packit Service def718
Packit Service def718
    int r;
Packit Service def718
    ssize_t nread = read(fd, &r, sizeof(r));
Packit Service def718
    if (nread != sizeof(r)) {
Packit Service def718
        fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
Packit Service def718
        exit(1);
Packit Service def718
    }
Packit Service def718
Packit Service def718
    close(fd);
Packit Service def718
    return r;
Packit Service def718
}
Packit Service def718
Packit Service def718
#endif
Packit Service def718
Packit Service def718
Packit Service def718
/* get_cryptgenrandom_seed */
Packit Service def718
Packit Service def718
#ifdef WIN32
Packit Service def718
Packit Service def718
#define HAVE_CRYPTGENRANDOM 1
Packit Service def718
Packit Service def718
#include <windows.h>
Packit Service def718
#include <wincrypt.h>
Packit Service def718
#ifndef __GNUC__
Packit Service def718
#pragma comment(lib, "advapi32.lib")
Packit Service def718
#endif
Packit Service def718
Packit Service def718
static int get_cryptgenrandom_seed()
Packit Service def718
{
Packit Service def718
    HCRYPTPROV hProvider = 0;
Packit Service def718
    int r;
Packit Service def718
Packit Service def718
    DEBUG_SEED("get_cryptgenrandom_seed");
Packit Service def718
Packit Service def718
    if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
Packit Service def718
        fprintf(stderr, "error CryptAcquireContextW");
Packit Service def718
        exit(1);
Packit Service def718
    }
Packit Service def718
Packit Service def718
    if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
Packit Service def718
        fprintf(stderr, "error CryptGenRandom");
Packit Service def718
        exit(1);
Packit Service def718
    }
Packit Service def718
Packit Service def718
    CryptReleaseContext(hProvider, 0);
Packit Service def718
Packit Service def718
    return r;
Packit Service def718
}
Packit Service def718
Packit Service def718
#endif
Packit Service def718
Packit Service def718
Packit Service def718
/* get_time_seed */
Packit Service def718
Packit Service def718
#include <time.h>
Packit Service def718
Packit Service def718
static int get_time_seed()
Packit Service def718
{
Packit Service def718
    DEBUG_SEED("get_time_seed");
Packit Service def718
Packit Service def718
    return (int)time(NULL) * 433494437;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/* json_c_get_random_seed */
Packit Service def718
Packit Service def718
int json_c_get_random_seed()
Packit Service def718
{
Packit Service def718
#if HAVE_RDRAND
Packit Service def718
    if (has_rdrand()) return get_rdrand_seed();
Packit Service def718
#endif
Packit Service def718
#if HAVE_DEV_RANDOM
Packit Service def718
    if (has_dev_urandom()) return get_dev_random_seed();
Packit Service def718
#endif
Packit Service def718
#if HAVE_CRYPTGENRANDOM
Packit Service def718
    return get_cryptgenrandom_seed();
Packit Service def718
#endif
Packit Service def718
    return get_time_seed();
Packit Service def718
}