eng_rdrand.c revision 296341
1/* ==================================================================== 2 * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * licensing@OpenSSL.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * ==================================================================== 48 */ 49 50#include <openssl/opensslconf.h> 51 52#include <stdio.h> 53#include <string.h> 54#include <openssl/engine.h> 55#include <openssl/rand.h> 56#include <openssl/err.h> 57 58#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 59 defined(__x86_64) || defined(__x86_64__) || \ 60 defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) 61 62size_t OPENSSL_ia32_rdrand(void); 63 64static int get_random_bytes(unsigned char *buf, int num) 65{ 66 size_t rnd; 67 68 while (num >= (int)sizeof(size_t)) { 69 if ((rnd = OPENSSL_ia32_rdrand()) == 0) 70 return 0; 71 72 *((size_t *)buf) = rnd; 73 buf += sizeof(size_t); 74 num -= sizeof(size_t); 75 } 76 if (num) { 77 if ((rnd = OPENSSL_ia32_rdrand()) == 0) 78 return 0; 79 80 memcpy(buf, &rnd, num); 81 } 82 83 return 1; 84} 85 86static int random_status(void) 87{ 88 return 1; 89} 90 91static RAND_METHOD rdrand_meth = { 92 NULL, /* seed */ 93 get_random_bytes, 94 NULL, /* cleanup */ 95 NULL, /* add */ 96 get_random_bytes, 97 random_status, 98}; 99 100static int rdrand_init(ENGINE *e) 101{ 102 return 1; 103} 104 105static const char *engine_e_rdrand_id = "rdrand"; 106static const char *engine_e_rdrand_name = "Intel RDRAND engine"; 107 108static int bind_helper(ENGINE *e) 109{ 110 if (!ENGINE_set_id(e, engine_e_rdrand_id) || 111 !ENGINE_set_name(e, engine_e_rdrand_name) || 112 !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) || 113 !ENGINE_set_init_function(e, rdrand_init) || 114 !ENGINE_set_RAND(e, &rdrand_meth)) 115 return 0; 116 117 return 1; 118} 119 120static ENGINE *ENGINE_rdrand(void) 121{ 122 ENGINE *ret = ENGINE_new(); 123 if (!ret) 124 return NULL; 125 if (!bind_helper(ret)) { 126 ENGINE_free(ret); 127 return NULL; 128 } 129 return ret; 130} 131 132void ENGINE_load_rdrand(void) 133{ 134 extern unsigned int OPENSSL_ia32cap_P[]; 135 136 if (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) { 137 ENGINE *toadd = ENGINE_rdrand(); 138 if (!toadd) 139 return; 140 ENGINE_add(toadd); 141 ENGINE_free(toadd); 142 ERR_clear_error(); 143 } 144} 145#else 146void ENGINE_load_rdrand(void) 147{ 148} 149#endif 150