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 62 size_t OPENSSL_ia32_rdrand(void); 63 64 static 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) return 0; 70 71 *((size_t *)buf) = rnd; 72 buf += sizeof(size_t); 73 num -= sizeof(size_t); 74 } 75 if (num) { 76 if ((rnd = OPENSSL_ia32_rdrand()) == 0) return 0; 77 78 memcpy (buf,&rnd,num); 79 } 80 81 return 1; 82 } 83 84 static int random_status (void) 85 { return 1; } 86 87 static RAND_METHOD rdrand_meth = 88 { 89 NULL, /* seed */ 90 get_random_bytes, 91 NULL, /* cleanup */ 92 NULL, /* add */ 93 get_random_bytes, 94 random_status, 95 }; 96 97 static int rdrand_init(ENGINE *e) 98 { return 1; } 99 100 static const char *engine_e_rdrand_id = "rdrand"; 101 static const char *engine_e_rdrand_name = "Intel RDRAND engine"; 102 103 static int bind_helper(ENGINE *e) 104 { 105 if (!ENGINE_set_id(e, engine_e_rdrand_id) || 106 !ENGINE_set_name(e, engine_e_rdrand_name) || 107 !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) || 108 !ENGINE_set_init_function(e, rdrand_init) || 109 !ENGINE_set_RAND(e, &rdrand_meth) ) 110 return 0; 111 112 return 1; 113 } 114 115 static ENGINE *ENGINE_rdrand(void) 116 { 117 ENGINE *ret = ENGINE_new(); 118 if(!ret) 119 return NULL; 120 if(!bind_helper(ret)) 121 { 122 ENGINE_free(ret); 123 return NULL; 124 } 125 return ret; 126 } 127 128 void ENGINE_load_rdrand (void) 129 { 130 extern unsigned int OPENSSL_ia32cap_P[]; 131 132 if (OPENSSL_ia32cap_P[1] & (1<<(62-32))) 133 { 134 ENGINE *toadd = ENGINE_rdrand(); 135 if(!toadd) return; 136 ENGINE_add(toadd); 137 ENGINE_free(toadd); 138 ERR_clear_error(); 139 } 140 } 141 #else 142 void ENGINE_load_rdrand (void) {} 143 #endif