mirror of https://github.com/getdnsapi/getdns.git
Abstract out HMAC functions in request-internal.c.
This commit is contained in:
parent
4ec93a3df0
commit
bc3106af94
|
@ -34,6 +34,10 @@
|
|||
#ifndef _GETDNS_TLS_INTERNAL_H
|
||||
#define _GETDNS_TLS_INTERNAL_H
|
||||
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "getdns/getdns.h"
|
||||
|
||||
#ifndef HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||
|
@ -64,4 +68,12 @@ typedef struct _getdns_tls_x509
|
|||
X509* ssl;
|
||||
} _getdns_tls_x509;
|
||||
|
||||
typedef struct _getdns_tls_hmac
|
||||
{
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
} _getdns_tls_hmac;
|
||||
|
||||
#endif /* _GETDNS_TLS_INTERNAL_H */
|
||||
|
|
|
@ -609,4 +609,126 @@ int _getdns_tls_x509_to_der(_getdns_tls_x509* cert, uint8_t** buf)
|
|||
return i2d_X509(cert->ssl, buf);
|
||||
}
|
||||
|
||||
unsigned char* _getdns_tls_hmac_hash(int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size)
|
||||
{
|
||||
const EVP_MD* digester;
|
||||
unsigned char* res;
|
||||
unsigned int md_len;
|
||||
|
||||
switch (algorithm) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return NULL;
|
||||
}
|
||||
|
||||
res = (unsigned char*) malloc(EVP_MAX_MD_SIZE);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
(void) HMAC(digester, key, key_size, data, data_size, res, &md_len);
|
||||
|
||||
if (output_size)
|
||||
*output_size = md_len;
|
||||
return res;
|
||||
}
|
||||
|
||||
_getdns_tls_hmac* _getdns_tls_hmac_new(int algorithm, const void* key, size_t key_size)
|
||||
{
|
||||
const EVP_MD *digester;
|
||||
_getdns_tls_hmac* res;
|
||||
|
||||
switch (algorithm) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return NULL;
|
||||
}
|
||||
|
||||
if (!(res = malloc(sizeof(struct _getdns_tls_hmac))))
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
res->ctx = HMAC_CTX_new();
|
||||
if (!res->ctx) {
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
res->ctx = &res->ctx_space;
|
||||
HMAC_CTX_init(res->ctx);
|
||||
#endif
|
||||
if (!HMAC_Init_ex(res->ctx, key, key_size, digester, NULL)) {
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX_free(res->ctx);
|
||||
#endif
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size)
|
||||
{
|
||||
if (!h || !h->ctx || !data)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if (!HMAC_Update(h->ctx, data, data_size))
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
else
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
unsigned char* _getdns_tls_hmac_end(_getdns_tls_hmac* h, size_t* output_size)
|
||||
{
|
||||
unsigned char* res;
|
||||
unsigned int md_len;
|
||||
|
||||
res = (unsigned char*) malloc(EVP_MAX_MD_SIZE);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
(void) HMAC_Final(h->ctx, res, &md_len);
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX_free(h->ctx);
|
||||
#endif
|
||||
free(h);
|
||||
|
||||
if (output_size)
|
||||
*output_size = md_len;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* tls.c */
|
||||
|
|
|
@ -401,9 +401,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer gbuf;
|
||||
uint16_t arcount;
|
||||
const getdns_tsig_info *tsig_info;
|
||||
uint8_t md_buf[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len = EVP_MAX_MD_SIZE;
|
||||
const EVP_MD *digester;
|
||||
unsigned char* md_buf;
|
||||
size_t md_len;
|
||||
|
||||
/* Should only be called when in stub mode */
|
||||
assert(req->query);
|
||||
|
@ -436,31 +435,9 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
switch (upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return req->response - req->query;
|
||||
}
|
||||
|
||||
(void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
|
||||
(void *)req->query, gldns_buffer_current(&gbuf) - req->query,
|
||||
md_buf, &md_len);
|
||||
md_buf = _getdns_tls_hmac_hash(upstream->tsig_alg, upstream->tsig_key, upstream->tsig_size, (void *)req->query, gldns_buffer_current(&gbuf) - req->query, &md_len);
|
||||
if (!md_buf)
|
||||
return req->response - req->query;
|
||||
|
||||
gldns_buffer_rewind(&gbuf);
|
||||
gldns_buffer_write(&gbuf,
|
||||
|
@ -480,6 +457,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
|||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
free(md_buf);
|
||||
|
||||
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
||||
return req->response - req->query;
|
||||
|
||||
|
@ -506,14 +485,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
const uint8_t *response_mac;
|
||||
uint16_t response_mac_len;
|
||||
uint8_t other_len;
|
||||
uint8_t result_mac[EVP_MAX_MD_SIZE];
|
||||
unsigned int result_mac_len = EVP_MAX_MD_SIZE;
|
||||
unsigned char *result_mac;
|
||||
size_t result_mac_len;
|
||||
uint16_t original_id;
|
||||
const EVP_MD *digester;
|
||||
HMAC_CTX *ctx;
|
||||
#ifndef HAVE_HMAC_CTX_NEW
|
||||
HMAC_CTX ctx_space;
|
||||
#endif
|
||||
_getdns_tls_hmac *hmac;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
|
||||
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
|
||||
|
@ -620,39 +595,16 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
gldns_read_uint16(req->response + 10) - 1);
|
||||
gldns_write_uint16(req->response, original_id);
|
||||
|
||||
switch (req->upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return;
|
||||
}
|
||||
#ifdef HAVE_HMAC_CTX_NEW
|
||||
ctx = HMAC_CTX_new();
|
||||
#else
|
||||
ctx = &ctx_space;
|
||||
HMAC_CTX_init(ctx);
|
||||
#endif
|
||||
(void) HMAC_Init_ex(ctx, req->upstream->tsig_key,
|
||||
req->upstream->tsig_size, digester, NULL);
|
||||
(void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2);
|
||||
(void) HMAC_Update(ctx, req->response, rr->pos - req->response);
|
||||
(void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
HMAC_Final(ctx, result_mac, &result_mac_len);
|
||||
hmac = _getdns_tls_hmac_new(req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
|
||||
if (!hmac)
|
||||
return;
|
||||
|
||||
_getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
|
||||
_getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
|
||||
_getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
|
||||
result_mac = _getdns_tls_hmac_end(hmac, &result_mac_len);
|
||||
if (!result_mac)
|
||||
return;
|
||||
|
||||
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
||||
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
|
||||
|
@ -660,11 +612,6 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
|||
memcmp(result_mac, response_mac, result_mac_len) == 0)
|
||||
req->tsig_status = GETDNS_DNSSEC_SECURE;
|
||||
|
||||
#ifdef HAVE_HMAC_CTX_FREE
|
||||
HMAC_CTX_free(ctx);
|
||||
#else
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
#endif
|
||||
gldns_write_uint16(req->response, gldns_read_uint16(req->query));
|
||||
gldns_write_uint16(req->response + 10,
|
||||
gldns_read_uint16(req->response + 10) + 1);
|
||||
|
|
44
src/tls.h
44
src/tls.h
|
@ -316,4 +316,48 @@ int _getdns_tls_x509_to_der(_getdns_tls_x509* cert, uint8_t** buf);
|
|||
*/
|
||||
getdns_return_t _getdns_tls_get_api_information(getdns_dict* dict);
|
||||
|
||||
/**
|
||||
* Return buffer with HMAC hash.
|
||||
*
|
||||
* @param algorithm hash algorithm to use (<code>GETDNS_HMAC_?</code>).
|
||||
* @param key the key.
|
||||
* @param key_size the key size.
|
||||
* @param data the data to hash.
|
||||
* @param data_size the data size.
|
||||
* @param output_size the output size will be written here if not NULL.
|
||||
* @return output malloc'd buffer with output, NULL on error.
|
||||
*/
|
||||
unsigned char* _getdns_tls_hmac_hash(int algorithm, const void* key, size_t key_size, const void* data, size_t data_size, size_t* output_size);
|
||||
|
||||
/**
|
||||
* Return a new HMAC handle.
|
||||
*
|
||||
* @param algorithm hash algorithm to use (<code>GETDNS_HMAC_?</code>).
|
||||
* @param key the key.
|
||||
* @param key_size the key size.
|
||||
* @return HMAC handle or NULL on error.
|
||||
*/
|
||||
_getdns_tls_hmac* _getdns_tls_hmac_new(int algorithm, const void* key, size_t key_size);
|
||||
|
||||
/**
|
||||
* Add data to a HMAC.
|
||||
*
|
||||
* @param h the HMAC.
|
||||
* @param data the data to add.
|
||||
* @param data_size the size of data to add.
|
||||
* @return GETDNS_RETURN_GOOD if added.
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if h is null or has no HMAC.
|
||||
* @return GETDNS_RETURN_GENERIC_ERROR on error.
|
||||
*/
|
||||
getdns_return_t _getdns_tls_hmac_add(_getdns_tls_hmac* h, const void* data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Return the HMAC digest and free the handle.
|
||||
*
|
||||
* @param h the HMAC.
|
||||
* @param output_size the output size will be written here if not NULL.
|
||||
* @return output malloc'd buffer with output, NULL on error.
|
||||
*/
|
||||
unsigned char* _getdns_tls_hmac_end(_getdns_tls_hmac* h, size_t* output_size);
|
||||
|
||||
#endif /* _GETDNS_TLS_H */
|
||||
|
|
Loading…
Reference in New Issue