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
|
#ifndef _GETDNS_TLS_INTERNAL_H
|
||||||
#define _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"
|
#include "getdns/getdns.h"
|
||||||
|
|
||||||
#ifndef HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
#ifndef HAVE_DECL_SSL_CTX_SET1_CURVES_LIST
|
||||||
|
@ -64,4 +68,12 @@ typedef struct _getdns_tls_x509
|
||||||
X509* ssl;
|
X509* ssl;
|
||||||
} _getdns_tls_x509;
|
} _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 */
|
#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);
|
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 */
|
/* tls.c */
|
||||||
|
|
|
@ -401,9 +401,8 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
|
||||||
gldns_buffer gbuf;
|
gldns_buffer gbuf;
|
||||||
uint16_t arcount;
|
uint16_t arcount;
|
||||||
const getdns_tsig_info *tsig_info;
|
const getdns_tsig_info *tsig_info;
|
||||||
uint8_t md_buf[EVP_MAX_MD_SIZE];
|
unsigned char* md_buf;
|
||||||
unsigned int md_len = EVP_MAX_MD_SIZE;
|
size_t md_len;
|
||||||
const EVP_MD *digester;
|
|
||||||
|
|
||||||
/* Should only be called when in stub mode */
|
/* Should only be called when in stub mode */
|
||||||
assert(req->query);
|
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); /* Error */
|
||||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||||
|
|
||||||
switch (upstream->tsig_alg) {
|
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);
|
||||||
#ifdef HAVE_EVP_MD5
|
if (!md_buf)
|
||||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
return req->response - req->query;
|
||||||
#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);
|
|
||||||
|
|
||||||
gldns_buffer_rewind(&gbuf);
|
gldns_buffer_rewind(&gbuf);
|
||||||
gldns_buffer_write(&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); /* Error */
|
||||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||||
|
|
||||||
|
free(md_buf);
|
||||||
|
|
||||||
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
||||||
return req->response - req->query;
|
return req->response - req->query;
|
||||||
|
|
||||||
|
@ -506,14 +485,10 @@ _getdns_network_validate_tsig(getdns_network_req *req)
|
||||||
const uint8_t *response_mac;
|
const uint8_t *response_mac;
|
||||||
uint16_t response_mac_len;
|
uint16_t response_mac_len;
|
||||||
uint8_t other_len;
|
uint8_t other_len;
|
||||||
uint8_t result_mac[EVP_MAX_MD_SIZE];
|
unsigned char *result_mac;
|
||||||
unsigned int result_mac_len = EVP_MAX_MD_SIZE;
|
size_t result_mac_len;
|
||||||
uint16_t original_id;
|
uint16_t original_id;
|
||||||
const EVP_MD *digester;
|
_getdns_tls_hmac *hmac;
|
||||||
HMAC_CTX *ctx;
|
|
||||||
#ifndef HAVE_HMAC_CTX_NEW
|
|
||||||
HMAC_CTX ctx_space;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
|
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
|
||||||
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
|
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_read_uint16(req->response + 10) - 1);
|
||||||
gldns_write_uint16(req->response, original_id);
|
gldns_write_uint16(req->response, original_id);
|
||||||
|
|
||||||
switch (req->upstream->tsig_alg) {
|
hmac = _getdns_tls_hmac_new(req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
|
||||||
#ifdef HAVE_EVP_MD5
|
if (!hmac)
|
||||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
return;
|
||||||
#endif
|
|
||||||
#ifdef HAVE_EVP_SHA1
|
_getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
|
||||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
_getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
|
||||||
#endif
|
_getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
|
||||||
#ifdef HAVE_EVP_SHA224
|
result_mac = _getdns_tls_hmac_end(hmac, &result_mac_len);
|
||||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
if (!result_mac)
|
||||||
#endif
|
return;
|
||||||
#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);
|
|
||||||
|
|
||||||
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
|
||||||
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
|
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)
|
memcmp(result_mac, response_mac, result_mac_len) == 0)
|
||||||
req->tsig_status = GETDNS_DNSSEC_SECURE;
|
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, gldns_read_uint16(req->query));
|
||||||
gldns_write_uint16(req->response + 10,
|
gldns_write_uint16(req->response + 10,
|
||||||
gldns_read_uint16(req->response + 10) + 1);
|
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);
|
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 */
|
#endif /* _GETDNS_TLS_H */
|
||||||
|
|
Loading…
Reference in New Issue