zonemd, digest code calls, secalgo openssl sha384 and sha512.

This commit is contained in:
W.C.A. Wijngaards 2020-10-09 11:19:31 +02:00
parent d7e4525829
commit eb4932a463
3 changed files with 207 additions and 27 deletions

View File

@ -6983,19 +6983,79 @@ static int zonemd_scheme_supported(int scheme)
}
/** initialize hash for hashing with zonemd hash algo */
static void* zonemd_digest_init(int hashalgo)
static struct secalgo_hash* zonemd_digest_init(int hashalgo, char** reason)
{
struct secalgo_hash *h;
if(hashalgo == 1) {
/* sha384 */
//return secalgo_digest_start_sha384();
h = secalgo_hash_create_sha384();
if(!h)
*reason = "digest sha384 could not be created";
return h;
} else if(hashalgo == 2) {
/* sha512 */
//return secalgo_digest_start_sha512();
h = secalgo_hash_create_sha512();
if(!h)
*reason = "digest sha512 could not be created";
return h;
}
/* unknown hash algo */
*reason = "unsupported algorithm";
return NULL;
}
/** update the hash for zonemd */
static int zonemd_digest_update(int hashalgo, struct secalgo_hash* h,
uint8_t* data, size_t len, char** reason)
{
if(hashalgo == 1) {
if(!secalgo_hash_update(h, data, len)) {
*reason = "digest sha384 failed";
return 0;
}
return 1;
} else if(hashalgo == 2) {
if(!secalgo_hash_update(h, data, len)) {
*reason = "digest sha512 failed";
return 0;
}
return 1;
}
/* unknown hash algo */
*reason = "unsupported algorithm";
return 0;
}
/** finish the hash for zonemd */
static int zonemd_digest_finish(int hashalgo, struct secalgo_hash* h,
uint8_t* result, size_t hashlen, size_t* resultlen, char** reason)
{
if(hashalgo == 1) {
if(hashlen < 384/8) {
*reason = "digest buffer too small for sha384";
return 0;
}
if(!secalgo_hash_final(h, result, hashlen, resultlen)) {
*reason = "digest sha384 finish failed";
return 0;
}
return 1;
} else if(hashalgo == 2) {
if(hashlen < 512/8) {
*reason = "digest buffer too small for sha512";
return 0;
}
if(!secalgo_hash_final(h, result, hashlen, resultlen)) {
*reason = "digest sha512 finish failed";
return 0;
}
return 1;
}
/* unknown algo */
*reason = "unsupported algorithm";
return 0;
}
/** add rrsets from node to the list */
static size_t authdata_rrsets_to_list(struct auth_rrset** array,
size_t arraysize, struct auth_rrset* first)
@ -7043,9 +7103,10 @@ static void addrrsigtype_if_needed(struct auth_rrset** array,
}
/** collate the RRs in an RRset using the simple scheme */
static int zonemd_simple_rrset(struct auth_zone* z, void* hash,
struct auth_data* node, struct auth_rrset* rrset,
struct regional* region, struct sldns_buffer* buf, char** reason)
static int zonemd_simple_rrset(struct auth_zone* z, int hashalgo,
struct secalgo_hash* h, struct auth_data* node,
struct auth_rrset* rrset, struct regional* region,
struct sldns_buffer* buf, char** reason)
{
/* canonicalize */
struct ub_packed_rrset_key key;
@ -7063,6 +7124,10 @@ static int zonemd_simple_rrset(struct auth_zone* z, void* hash,
regional_free_all(region);
/* hash */
if(!zonemd_digest_update(hashalgo, h, sldns_buffer_begin(buf),
sldns_buffer_limit(buf), reason)) {
return 0;
}
return 1;
}
@ -7168,10 +7233,10 @@ static void add_rrset_into_data(struct packed_rrset_data* data,
}
/** collate the RRSIGs using the simple scheme */
static int zonemd_simple_rrsig(struct auth_zone* z, void* hash,
struct auth_data* node, struct auth_rrset* rrset,
struct auth_rrset** rrlist, size_t rrnum, struct regional* region,
struct sldns_buffer* buf, char** reason)
static int zonemd_simple_rrsig(struct auth_zone* z, int hashalgo,
struct secalgo_hash* h, struct auth_data* node,
struct auth_rrset* rrset, struct auth_rrset** rrlist, size_t rrnum,
struct regional* region, struct sldns_buffer* buf, char** reason)
{
/* the rrset pointer can be NULL, this means it is type RRSIG and
* there is no ordinary type RRSIG there. The RRSIGs are stored
@ -7194,7 +7259,7 @@ static int zonemd_simple_rrsig(struct auth_zone* z, void* hash,
key.entry.data = &data;
key.rk.dname = node->name;
key.rk.dname_len = node->namelen;
key.rk.type = htons(rrset->type);
key.rk.type = htons(LDNS_RR_TYPE_RRSIG);
key.rk.rrset_class = htons(z->dclass);
data.count = zonemd_simple_count_rrsig(rrset, rrlist, rrnum, z, node);
if(!zonemd_simple_rrsig_allocs(region, &data, data.count)) {
@ -7216,13 +7281,17 @@ static int zonemd_simple_rrsig(struct auth_zone* z, void* hash,
regional_free_all(region);
/* hash */
if(!zonemd_digest_update(hashalgo, h, sldns_buffer_begin(buf),
sldns_buffer_limit(buf), reason)) {
return 0;
}
return 1;
}
/** collate a domain's rrsets using the simple scheme */
static int zonemd_simple_domain(struct auth_zone* z, void* hash,
struct auth_data* node, struct regional* region,
struct sldns_buffer* buf, char** reason)
static int zonemd_simple_domain(struct auth_zone* z, int hashalgo,
struct secalgo_hash* h, struct auth_data* node,
struct regional* region, struct sldns_buffer* buf, char** reason)
{
const size_t rrlistsize = 65536;
struct auth_rrset* rrlist[rrlistsize];
@ -7243,11 +7312,11 @@ static int zonemd_simple_domain(struct auth_zone* z, void* hash,
}
if(rrlist[i] == NULL || rrlist[i]->type ==
LDNS_RR_TYPE_RRSIG) {
if(!zonemd_simple_rrsig(z, hash, node, rrlist[i],
rrlist, rrnum, region, buf, reason))
if(!zonemd_simple_rrsig(z, hashalgo, h, node,
rrlist[i], rrlist, rrnum, region, buf, reason))
return 0;
} else if(!zonemd_simple_rrset(z, hash, node, rrlist[i],
region, buf, reason)) {
} else if(!zonemd_simple_rrset(z, hashalgo, h, node,
rrlist[i], region, buf, reason)) {
return 0;
}
}
@ -7255,14 +7324,16 @@ static int zonemd_simple_domain(struct auth_zone* z, void* hash,
}
/** collate the zone using the simple scheme */
static int zonemd_simple_collate(struct auth_zone* z, void* hash,
struct regional* region, struct sldns_buffer* buf, char** reason)
static int zonemd_simple_collate(struct auth_zone* z, int hashalgo,
struct secalgo_hash* h, struct regional* region,
struct sldns_buffer* buf, char** reason)
{
/* our tree is sorted in canonical order, so we can just loop over
* the tree */
struct auth_data* n;
RBTREE_FOR(n, struct auth_data*, &z->data) {
if(!zonemd_simple_domain(z, hash, n, region, buf, reason))
if(!zonemd_simple_domain(z, hashalgo, h, n, region, buf,
reason))
return 0;
}
return 1;
@ -7272,23 +7343,26 @@ int auth_zone_generate_zonemd_hash(struct auth_zone* z, int scheme,
int hashalgo, uint8_t* hash, size_t hashlen, size_t* resultlen,
struct regional* region, struct sldns_buffer* buf, char** reason)
{
void* h = zonemd_digest_init(hashalgo);
struct secalgo_hash* h = zonemd_digest_init(hashalgo, reason);
if(!h) {
*reason = "digest init fail";
if(!*reason)
*reason = "digest init fail";
return 0;
}
if(scheme == 1) {
if(!zonemd_simple_collate(z, h, region, buf, reason)) {
if(!zonemd_simple_collate(z, hashalgo, h, region, buf, reason)) {
if(!*reason) *reason = "scheme simple collate fail";
secalgo_hash_delete(h);
return 0;
}
}
/*
if(!zonemd_digest_finish(hashalgo, hash, hashlen, resultlen)) {
if(!zonemd_digest_finish(hashalgo, h, hash, hashlen, resultlen,
reason)) {
secalgo_hash_delete(h);
*reason = "digest finish fail";
return 0;
}
*/
secalgo_hash_delete(h);
return 1;
}

View File

@ -141,6 +141,69 @@ secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
#endif
}
/** hash structure for keeping track of running hashes */
struct secalgo_hash {
/** the openssl message digest context */
EVP_MD_CTX* ctx;
};
/** create secalgo hash with hash type */
static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md)
{
struct secalgo_hash* h;
if(!md)
return NULL;
h = calloc(1, sizeof(*h));
if(!h)
return NULL;
h->ctx = EVP_MD_CTX_create();
if(!h->ctx) {
free(h);
return NULL;
}
if(!EVP_DigestInit_ex(h->ctx, md, NULL)) {
EVP_MD_CTX_destroy(h->ctx);
free(h);
return NULL;
}
return h;
}
struct secalgo_hash* secalgo_hash_create_sha384(void)
{
return secalgo_hash_create_md(EVP_sha384());
}
struct secalgo_hash* secalgo_hash_create_sha512(void)
{
return secalgo_hash_create_md(EVP_sha512());
}
int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
{
return EVP_DigestUpdate(hash->ctx, (unsigned char*)data,
(unsigned int)len);
}
int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
size_t maxlen, size_t* resultlen)
{
if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) {
*resultlen = 0;
log_err("secalgo_hash_final: hash buffer too small");
return 0;
}
*resultlen = EVP_MD_CTX_size(hash->ctx);
return EVP_DigestFinal_ex(hash->ctx, result, NULL);
}
void secalgo_hash_delete(struct secalgo_hash* hash)
{
if(!hash) return;
EVP_MD_CTX_destroy(hash->ctx);
free(hash);
}
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.

View File

@ -43,6 +43,7 @@
#ifndef VALIDATOR_VAL_SECALGO_H
#define VALIDATOR_VAL_SECALGO_H
struct sldns_buffer;
struct secalgo_hash;
/** Return size of nsec3 hash algorithm, 0 if not supported */
size_t nsec3_hash_algo_size_supported(int id);
@ -67,6 +68,48 @@ int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
*/
void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
/**
* Start a hash of type sha384. Allocates structure, then inits it,
* so that a series of updates can be performed, before the final result.
* @return hash structure. NULL on malloc failure or no support.
*/
struct secalgo_hash* secalgo_hash_create_sha384(void);
/**
* Start a hash of type sha512. Allocates structure, then inits it,
* so that a series of updates can be performed, before the final result.
* @return hash structure. NULL on malloc failure or no support.
*/
struct secalgo_hash* secalgo_hash_create_sha512(void);
/**
* Update a hash with more information to add to it.
* @param hash: the hash that is updated.
* @param data: data to add.
* @param len: length of data.
* @return false on failure.
*/
int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len);
/**
* Get the final result of the hash.
* @param hash: the hash that has had updates to it.
* @param result: where to store the result.
* @param maxlen: length of the result buffer, eg. size of the allocation.
* If not large enough the routine fails.
* @param resultlen: the length of the result, returned to the caller.
* How much of maxlen is used.
* @return false on failure.
*/
int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
size_t maxlen, size_t* resultlen);
/**
* Delete the hash structure.
* @param hash: the hash to delete.
*/
void secalgo_hash_delete(struct secalgo_hash* hash);
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.