}
/** 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)
}
/** 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;
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 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
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)) {
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];
}
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;
}
}
}
/** 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;
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;
}
#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);
*/
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.