1/* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15#include <openssl/engine.h> 16 17#include <openssl/dh.h> 18#include <openssl/dsa.h> 19#include <openssl/ec_key.h> 20#include <openssl/mem.h> 21#include <openssl/rsa.h> 22#include <openssl/thread.h> 23 24 25struct engine_st { 26 DH_METHOD *dh_method; 27 DSA_METHOD *dsa_method; 28 RSA_METHOD *rsa_method; 29 ECDSA_METHOD *ecdsa_method; 30}; 31 32ENGINE *ENGINE_new(void) { 33 ENGINE *engine = OPENSSL_malloc(sizeof(ENGINE)); 34 if (engine == NULL) { 35 return NULL; 36 } 37 38 memset(engine, 0, sizeof(ENGINE)); 39 return engine; 40} 41 42void ENGINE_free(ENGINE *engine) { 43 if (engine->dh_method != NULL) { 44 METHOD_unref(engine->dh_method); 45 } 46 47 OPENSSL_free(engine); 48} 49 50/* set_method takes a pointer to a method and its given size and sets 51 * |*out_member| to point to a copy of it. The copy is |compiled_size| bytes 52 * long and has zero padding if needed. */ 53static int set_method(void **out_member, const void *method, size_t method_size, 54 size_t compiled_size) { 55 void *copy = OPENSSL_malloc(compiled_size); 56 if (copy == NULL) { 57 return 0; 58 } 59 60 memset(copy, 0, compiled_size); 61 62 if (method_size > compiled_size) { 63 method_size = compiled_size; 64 } 65 memcpy(copy, method, method_size); 66 67 METHOD_unref(*out_member); 68 *out_member = copy; 69 70 return 1; 71} 72 73int ENGINE_set_DH_method(ENGINE *engine, const DH_METHOD *method, 74 size_t method_size) { 75 return set_method((void **)&engine->dh_method, method, method_size, 76 sizeof(DH_METHOD)); 77} 78 79DH_METHOD *ENGINE_get_DH_method(const ENGINE *engine) { 80 return engine->dh_method; 81} 82 83int ENGINE_set_DSA_method(ENGINE *engine, const DSA_METHOD *method, 84 size_t method_size) { 85 return set_method((void **)&engine->dsa_method, method, method_size, 86 sizeof(DSA_METHOD)); 87} 88 89DSA_METHOD *ENGINE_get_DSA_method(const ENGINE *engine) { 90 return engine->dsa_method; 91} 92 93int ENGINE_set_RSA_method(ENGINE *engine, const RSA_METHOD *method, 94 size_t method_size) { 95 return set_method((void **)&engine->rsa_method, method, method_size, 96 sizeof(RSA_METHOD)); 97} 98 99RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine) { 100 return engine->rsa_method; 101} 102 103int ENGINE_set_ECDSA_method(ENGINE *engine, const ECDSA_METHOD *method, 104 size_t method_size) { 105 return set_method((void **)&engine->ecdsa_method, method, method_size, 106 sizeof(ECDSA_METHOD)); 107} 108 109ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine) { 110 return engine->ecdsa_method; 111} 112 113void METHOD_ref(void *method_in) { 114 struct openssl_method_common_st *method = method_in; 115 116 if (method->is_static) { 117 return; 118 } 119 120 CRYPTO_add(&method->references, 1, CRYPTO_LOCK_ENGINE); 121} 122 123void METHOD_unref(void *method_in) { 124 struct openssl_method_common_st *method = method_in; 125 126 if (method == NULL || method->is_static) { 127 return; 128 } 129 130 if (CRYPTO_add(&method->references, -1, CRYPTO_LOCK_ENGINE) == 0) { 131 OPENSSL_free(method); 132 } 133} 134