1 1.1 christos /* 2 1.1 christos * tsig-openssl.h -- Interface to OpenSSL for TSIG support. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * See LICENSE for the license. 7 1.1 christos * 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include "config.h" 11 1.1 christos 12 1.1 christos #if defined(HAVE_SSL) 13 1.1 christos 14 1.1.1.2 christos #ifdef HAVE_OPENSSL_CORE_NAMES_H 15 1.1.1.2 christos #include <openssl/core_names.h> 16 1.1.1.2 christos #endif 17 1.1 christos #include "tsig-openssl.h" 18 1.1 christos #include "tsig.h" 19 1.1 christos #include "util.h" 20 1.1 christos 21 1.1 christos static void *create_context(region_type *region); 22 1.1 christos static void init_context(void *context, 23 1.1 christos tsig_algorithm_type *algorithm, 24 1.1 christos tsig_key_type *key); 25 1.1 christos static void update(void *context, const void *data, size_t size); 26 1.1 christos static void final(void *context, uint8_t *digest, size_t *size); 27 1.1 christos 28 1.1.1.2 christos #ifdef HAVE_EVP_MAC_CTX_NEW 29 1.1.1.2 christos struct tsig_openssl_data { 30 1.1.1.2 christos /* the MAC for the algorithm, 'hmac' */ 31 1.1.1.2 christos EVP_MAC* mac; 32 1.1.1.2 christos /* the digest name for creating the EVP_MAC_CTX with, 'sha256' */ 33 1.1.1.2 christos const char* digest; 34 1.1.1.2 christos }; 35 1.1.1.2 christos 36 1.1.1.2 christos struct tsig_openssl_context { 37 1.1.1.2 christos /* the evp mac context, if notNULL it has algo and key set. */ 38 1.1.1.2 christos EVP_MAC_CTX* hmac_ctx; 39 1.1.1.2 christos /* the size of destination buffers */ 40 1.1.1.2 christos size_t outsize; 41 1.1.1.2 christos }; 42 1.1.1.2 christos 43 1.1.1.2 christos static void 44 1.1.1.2 christos cleanup_tsig_openssl_data(void *data) 45 1.1.1.2 christos { 46 1.1.1.2 christos struct tsig_openssl_data* d = (struct tsig_openssl_data*)data; 47 1.1.1.2 christos EVP_MAC_free(d->mac); 48 1.1.1.2 christos d->mac = NULL; 49 1.1.1.2 christos } 50 1.1.1.2 christos #endif 51 1.1.1.2 christos 52 1.1 christos static int 53 1.1 christos tsig_openssl_init_algorithm(region_type* region, 54 1.1 christos const char* digest, const char* name, const char* wireformat) 55 1.1 christos { 56 1.1 christos tsig_algorithm_type* algorithm; 57 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 58 1.1 christos const EVP_MD *hmac_algorithm; 59 1.1 christos 60 1.1 christos hmac_algorithm = EVP_get_digestbyname(digest); 61 1.1 christos if (!hmac_algorithm) { 62 1.1 christos /* skip but don't error */ 63 1.1 christos return 0; 64 1.1 christos } 65 1.1.1.2 christos #else 66 1.1.1.2 christos struct tsig_openssl_data* data; 67 1.1.1.2 christos EVP_MAC_CTX* hmac_ctx; 68 1.1.1.2 christos OSSL_PARAM params[3]; 69 1.1.1.2 christos data = region_alloc(region, sizeof(*data)); 70 1.1.1.2 christos data->digest = digest; 71 1.1.1.2 christos data->mac = EVP_MAC_fetch(NULL, "hmac", NULL); 72 1.1.1.2 christos if(!data->mac) { 73 1.1.1.2 christos log_msg(LOG_ERR, "could not fetch MAC implementation 'hmac' with EVP_MAC_fetch"); 74 1.1.1.2 christos return 0; 75 1.1.1.2 christos } 76 1.1.1.2 christos /* this context is created to see what size the output is */ 77 1.1.1.2 christos hmac_ctx = EVP_MAC_CTX_new(data->mac); 78 1.1.1.2 christos if(!hmac_ctx) { 79 1.1.1.2 christos EVP_MAC_free(data->mac); 80 1.1.1.2 christos return 0; 81 1.1.1.2 christos } 82 1.1.1.2 christos params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 83 1.1.1.2 christos (char*)digest, 0); 84 1.1.1.2 christos params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 85 1.1.1.2 christos "", 1); 86 1.1.1.2 christos params[2] = OSSL_PARAM_construct_end(); 87 1.1.1.2 christos #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 88 1.1.1.2 christos if(EVP_MAC_CTX_set_params(hmac_ctx, params) <= 0) { 89 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_CTX_set_params"); 90 1.1.1.2 christos EVP_MAC_CTX_free(hmac_ctx); 91 1.1.1.2 christos EVP_MAC_free(data->mac); 92 1.1.1.2 christos return 0; 93 1.1.1.2 christos } 94 1.1.1.2 christos #else 95 1.1.1.2 christos if(EVP_MAC_set_ctx_params(hmac_ctx, params) <= 0) { 96 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_set_ctx_params"); 97 1.1.1.2 christos EVP_MAC_CTX_free(hmac_ctx); 98 1.1.1.2 christos EVP_MAC_free(data->mac); 99 1.1.1.2 christos return 0; 100 1.1.1.2 christos } 101 1.1.1.2 christos #endif 102 1.1.1.2 christos #endif 103 1.1 christos 104 1.1 christos algorithm = (tsig_algorithm_type *) region_alloc( 105 1.1 christos region, sizeof(tsig_algorithm_type)); 106 1.1 christos algorithm->short_name = name; 107 1.1 christos algorithm->wireformat_name 108 1.1 christos = dname_parse(region, wireformat); 109 1.1 christos if (!algorithm->wireformat_name) { 110 1.1 christos log_msg(LOG_ERR, "cannot parse %s algorithm", wireformat); 111 1.1.1.2 christos #ifdef HAVE_EVP_MAC_CTX_NEW 112 1.1.1.2 christos EVP_MAC_CTX_free(hmac_ctx); 113 1.1.1.2 christos EVP_MAC_free(data->mac); 114 1.1.1.2 christos #endif 115 1.1 christos return 0; 116 1.1 christos } 117 1.1.1.3 christos #ifdef HAVE_EVP_MAC_CTX_GET_MAC_SIZE 118 1.1.1.3 christos algorithm->maximum_digest_size = EVP_MAC_CTX_get_mac_size(hmac_ctx); 119 1.1.1.3 christos #elif !defined(HAVE_EVP_MAC_CTX_NEW) 120 1.1 christos algorithm->maximum_digest_size = EVP_MD_size(hmac_algorithm); 121 1.1.1.2 christos #else 122 1.1.1.2 christos algorithm->maximum_digest_size = EVP_MAC_size(hmac_ctx); 123 1.1.1.2 christos #endif 124 1.1 christos if(algorithm->maximum_digest_size < 20) 125 1.1 christos algorithm->maximum_digest_size = EVP_MAX_MD_SIZE; 126 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 127 1.1 christos algorithm->data = hmac_algorithm; 128 1.1.1.2 christos #else 129 1.1.1.2 christos algorithm->data = data; 130 1.1.1.2 christos region_add_cleanup(region, cleanup_tsig_openssl_data, data); 131 1.1.1.2 christos #endif 132 1.1 christos algorithm->hmac_create_context = create_context; 133 1.1 christos algorithm->hmac_init_context = init_context; 134 1.1 christos algorithm->hmac_update = update; 135 1.1 christos algorithm->hmac_final = final; 136 1.1 christos tsig_add_algorithm(algorithm); 137 1.1 christos 138 1.1.1.2 christos #ifdef HAVE_EVP_MAC_CTX_NEW 139 1.1.1.2 christos EVP_MAC_CTX_free(hmac_ctx); 140 1.1.1.2 christos #endif 141 1.1 christos return 1; 142 1.1 christos } 143 1.1 christos 144 1.1 christos int 145 1.1 christos tsig_openssl_init(region_type *region) 146 1.1 christos { 147 1.1 christos int count = 0; 148 1.1 christos #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) 149 1.1 christos OpenSSL_add_all_digests(); 150 1.1 christos #else 151 1.1 christos OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); 152 1.1 christos #endif 153 1.1 christos 154 1.1 christos count += tsig_openssl_init_algorithm(region, 155 1.1 christos "md5", "hmac-md5","hmac-md5.sig-alg.reg.int."); 156 1.1 christos count += tsig_openssl_init_algorithm(region, 157 1.1 christos "sha1", "hmac-sha1", "hmac-sha1."); 158 1.1 christos count += tsig_openssl_init_algorithm(region, 159 1.1 christos "sha224", "hmac-sha224", "hmac-sha224."); 160 1.1 christos count += tsig_openssl_init_algorithm(region, 161 1.1 christos "sha256", "hmac-sha256", "hmac-sha256."); 162 1.1 christos count += tsig_openssl_init_algorithm(region, 163 1.1 christos "sha384", "hmac-sha384", "hmac-sha384."); 164 1.1 christos count += tsig_openssl_init_algorithm(region, 165 1.1 christos "sha512", "hmac-sha512", "hmac-sha512."); 166 1.1 christos 167 1.1 christos return count; 168 1.1 christos } 169 1.1 christos 170 1.1 christos static void 171 1.1 christos cleanup_context(void *data) 172 1.1 christos { 173 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 174 1.1 christos HMAC_CTX *context = (HMAC_CTX *) data; 175 1.1 christos #ifdef HAVE_HMAC_CTX_NEW 176 1.1 christos HMAC_CTX_free(context); 177 1.1 christos #else 178 1.1 christos HMAC_CTX_cleanup(context); 179 1.1 christos free(context); 180 1.1 christos #endif 181 1.1.1.2 christos #else 182 1.1.1.2 christos struct tsig_openssl_context* c = (struct tsig_openssl_context*)data; 183 1.1.1.2 christos EVP_MAC_CTX_free(c->hmac_ctx); 184 1.1.1.2 christos c->hmac_ctx = NULL; 185 1.1.1.2 christos #endif 186 1.1 christos } 187 1.1 christos 188 1.1 christos static void * 189 1.1 christos create_context(region_type *region) 190 1.1 christos { 191 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 192 1.1 christos #ifdef HAVE_HMAC_CTX_NEW 193 1.1 christos HMAC_CTX *context = HMAC_CTX_new(); 194 1.1 christos #else 195 1.1 christos HMAC_CTX *context = (HMAC_CTX *) malloc(sizeof(HMAC_CTX)); 196 1.1 christos #endif 197 1.1 christos region_add_cleanup(region, cleanup_context, context); 198 1.1 christos #ifdef HAVE_HMAC_CTX_RESET 199 1.1 christos HMAC_CTX_reset(context); 200 1.1 christos #else 201 1.1 christos HMAC_CTX_init(context); 202 1.1 christos #endif 203 1.1.1.2 christos #else 204 1.1.1.2 christos struct tsig_openssl_context* context = region_alloc(region, 205 1.1.1.2 christos sizeof(*context)); 206 1.1.1.2 christos memset(context, 0, sizeof(*context)); 207 1.1.1.2 christos region_add_cleanup(region, cleanup_context, context); 208 1.1.1.2 christos #endif 209 1.1 christos return context; 210 1.1 christos } 211 1.1 christos 212 1.1 christos static void 213 1.1 christos init_context(void *context, 214 1.1 christos tsig_algorithm_type *algorithm, 215 1.1 christos tsig_key_type *key) 216 1.1 christos { 217 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 218 1.1 christos HMAC_CTX *ctx = (HMAC_CTX *) context; 219 1.1 christos const EVP_MD *md = (const EVP_MD *) algorithm->data; 220 1.1 christos HMAC_Init_ex(ctx, key->data, key->size, md, NULL); 221 1.1.1.2 christos #else 222 1.1.1.2 christos OSSL_PARAM params[3]; 223 1.1.1.2 christos struct tsig_openssl_data* algo_data = (struct tsig_openssl_data*) 224 1.1.1.2 christos algorithm->data; 225 1.1.1.2 christos struct tsig_openssl_context* c = (struct tsig_openssl_context*)context; 226 1.1.1.2 christos if(c->hmac_ctx) { 227 1.1.1.2 christos EVP_MAC_CTX_free(c->hmac_ctx); 228 1.1.1.2 christos } 229 1.1.1.2 christos c->hmac_ctx = EVP_MAC_CTX_new(algo_data->mac); 230 1.1.1.2 christos if(!c->hmac_ctx) { 231 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_CTX_new"); 232 1.1.1.2 christos return; 233 1.1.1.2 christos } 234 1.1.1.2 christos params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 235 1.1.1.2 christos (char*)algo_data->digest, 0); 236 1.1.1.2 christos params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 237 1.1.1.2 christos key->data, key->size); 238 1.1.1.2 christos params[2] = OSSL_PARAM_construct_end(); 239 1.1.1.2 christos #ifdef HAVE_EVP_MAC_CTX_SET_PARAMS 240 1.1.1.2 christos if(EVP_MAC_CTX_set_params(c->hmac_ctx, params) <= 0) { 241 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_CTX_set_params"); 242 1.1.1.2 christos EVP_MAC_CTX_free(c->hmac_ctx); 243 1.1.1.2 christos c->hmac_ctx = NULL; 244 1.1.1.2 christos return; 245 1.1.1.2 christos } 246 1.1.1.2 christos #else 247 1.1.1.2 christos if(EVP_MAC_set_ctx_params(hmac_ctx, params) <= 0) { 248 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_set_ctx_params"); 249 1.1.1.2 christos EVP_MAC_CTX_free(c->hmac_ctx); 250 1.1.1.2 christos c->hmac_ctx = NULL; 251 1.1.1.2 christos return; 252 1.1.1.2 christos } 253 1.1.1.2 christos #endif 254 1.1.1.2 christos c->outsize = algorithm->maximum_digest_size; 255 1.1.1.2 christos #endif 256 1.1 christos } 257 1.1 christos 258 1.1 christos static void 259 1.1 christos update(void *context, const void *data, size_t size) 260 1.1 christos { 261 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 262 1.1 christos HMAC_CTX *ctx = (HMAC_CTX *) context; 263 1.1 christos HMAC_Update(ctx, (unsigned char *) data, (int) size); 264 1.1.1.2 christos #else 265 1.1.1.2 christos struct tsig_openssl_context* c = (struct tsig_openssl_context*)context; 266 1.1.1.2 christos if(EVP_MAC_update(c->hmac_ctx, data, size) <= 0) { 267 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_update"); 268 1.1.1.2 christos } 269 1.1.1.2 christos #endif 270 1.1 christos } 271 1.1 christos 272 1.1 christos static void 273 1.1 christos final(void *context, uint8_t *digest, size_t *size) 274 1.1 christos { 275 1.1.1.2 christos #ifndef HAVE_EVP_MAC_CTX_NEW 276 1.1 christos HMAC_CTX *ctx = (HMAC_CTX *) context; 277 1.1 christos unsigned len = (unsigned) *size; 278 1.1 christos HMAC_Final(ctx, digest, &len); 279 1.1 christos *size = (size_t) len; 280 1.1.1.2 christos #else 281 1.1.1.2 christos struct tsig_openssl_context* c = (struct tsig_openssl_context*)context; 282 1.1.1.2 christos if(EVP_MAC_final(c->hmac_ctx, digest, size, c->outsize) <= 0) { 283 1.1.1.2 christos log_msg(LOG_ERR, "could not EVP_MAC_final"); 284 1.1.1.2 christos } 285 1.1.1.2 christos #endif 286 1.1 christos } 287 1.1 christos 288 1.1 christos void 289 1.1 christos tsig_openssl_finalize() 290 1.1 christos { 291 1.1 christos #ifdef HAVE_EVP_CLEANUP 292 1.1 christos EVP_cleanup(); 293 1.1 christos #endif 294 1.1 christos } 295 1.1 christos 296 1.1 christos #endif /* defined(HAVE_SSL) */ 297