1238384Sjkim/* ==================================================================== 2238384Sjkim * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 3238384Sjkim * 4238384Sjkim * Redistribution and use in source and binary forms, with or without 5238384Sjkim * modification, are permitted provided that the following conditions 6238384Sjkim * are met: 7238384Sjkim * 8238384Sjkim * 1. Redistributions of source code must retain the above copyright 9238384Sjkim * notice, this list of conditions and the following disclaimer. 10238384Sjkim * 11238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer in 13238384Sjkim * the documentation and/or other materials provided with the 14238384Sjkim * distribution. 15238384Sjkim * 16238384Sjkim * 3. All advertising materials mentioning features or use of this 17238384Sjkim * software must display the following acknowledgment: 18238384Sjkim * "This product includes software developed by the OpenSSL Project 19238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20238384Sjkim * 21238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22238384Sjkim * endorse or promote products derived from this software without 23238384Sjkim * prior written permission. For written permission, please contact 24238384Sjkim * licensing@OpenSSL.org. 25238384Sjkim * 26238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 27238384Sjkim * nor may "OpenSSL" appear in their names without prior written 28238384Sjkim * permission of the OpenSSL Project. 29238384Sjkim * 30238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 31238384Sjkim * acknowledgment: 32238384Sjkim * "This product includes software developed by the OpenSSL Project 33238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34238384Sjkim * 35238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 47238384Sjkim * ==================================================================== 48238384Sjkim */ 49238384Sjkim 50238384Sjkim#include <openssl/opensslconf.h> 51238384Sjkim 52238384Sjkim#include <stdio.h> 53238384Sjkim#include <string.h> 54238384Sjkim#include <openssl/engine.h> 55238384Sjkim#include <openssl/rand.h> 56238384Sjkim#include <openssl/err.h> 57238384Sjkim 58238384Sjkim#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 59238384Sjkim defined(__x86_64) || defined(__x86_64__) || \ 60238384Sjkim defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) 61238384Sjkim 62238384Sjkimsize_t OPENSSL_ia32_rdrand(void); 63238384Sjkim 64280304Sjkimstatic int get_random_bytes(unsigned char *buf, int num) 65280304Sjkim{ 66280304Sjkim size_t rnd; 67238384Sjkim 68280304Sjkim while (num >= (int)sizeof(size_t)) { 69280304Sjkim if ((rnd = OPENSSL_ia32_rdrand()) == 0) 70280304Sjkim return 0; 71238384Sjkim 72280304Sjkim *((size_t *)buf) = rnd; 73280304Sjkim buf += sizeof(size_t); 74280304Sjkim num -= sizeof(size_t); 75280304Sjkim } 76280304Sjkim if (num) { 77280304Sjkim if ((rnd = OPENSSL_ia32_rdrand()) == 0) 78280304Sjkim return 0; 79238384Sjkim 80280304Sjkim memcpy(buf, &rnd, num); 81280304Sjkim } 82238384Sjkim 83280304Sjkim return 1; 84280304Sjkim} 85238384Sjkim 86280304Sjkimstatic int random_status(void) 87280304Sjkim{ 88280304Sjkim return 1; 89280304Sjkim} 90238384Sjkim 91280304Sjkimstatic RAND_METHOD rdrand_meth = { 92280304Sjkim NULL, /* seed */ 93280304Sjkim get_random_bytes, 94280304Sjkim NULL, /* cleanup */ 95280304Sjkim NULL, /* add */ 96280304Sjkim get_random_bytes, 97280304Sjkim random_status, 98280304Sjkim}; 99238384Sjkim 100238384Sjkimstatic int rdrand_init(ENGINE *e) 101280304Sjkim{ 102280304Sjkim return 1; 103280304Sjkim} 104238384Sjkim 105238384Sjkimstatic const char *engine_e_rdrand_id = "rdrand"; 106238384Sjkimstatic const char *engine_e_rdrand_name = "Intel RDRAND engine"; 107238384Sjkim 108238384Sjkimstatic int bind_helper(ENGINE *e) 109280304Sjkim{ 110280304Sjkim if (!ENGINE_set_id(e, engine_e_rdrand_id) || 111280304Sjkim !ENGINE_set_name(e, engine_e_rdrand_name) || 112280304Sjkim !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) || 113280304Sjkim !ENGINE_set_init_function(e, rdrand_init) || 114280304Sjkim !ENGINE_set_RAND(e, &rdrand_meth)) 115280304Sjkim return 0; 116238384Sjkim 117280304Sjkim return 1; 118280304Sjkim} 119238384Sjkim 120238384Sjkimstatic ENGINE *ENGINE_rdrand(void) 121280304Sjkim{ 122280304Sjkim ENGINE *ret = ENGINE_new(); 123280304Sjkim if (!ret) 124280304Sjkim return NULL; 125280304Sjkim if (!bind_helper(ret)) { 126280304Sjkim ENGINE_free(ret); 127280304Sjkim return NULL; 128280304Sjkim } 129280304Sjkim return ret; 130280304Sjkim} 131238384Sjkim 132280304Sjkimvoid ENGINE_load_rdrand(void) 133280304Sjkim{ 134280304Sjkim extern unsigned int OPENSSL_ia32cap_P[]; 135238384Sjkim 136280304Sjkim if (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) { 137280304Sjkim ENGINE *toadd = ENGINE_rdrand(); 138280304Sjkim if (!toadd) 139280304Sjkim return; 140280304Sjkim ENGINE_add(toadd); 141280304Sjkim ENGINE_free(toadd); 142280304Sjkim ERR_clear_error(); 143280304Sjkim } 144280304Sjkim} 145238384Sjkim#else 146280304Sjkimvoid ENGINE_load_rdrand(void) 147280304Sjkim{ 148280304Sjkim} 149238384Sjkim#endif 150