forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hashes/sha256: add sha256-chain computation and verification functions
* also added unittetst for it x[SQUASH ME] separated out all waypoints test and increased waypoints
- Loading branch information
BytesGalore
authored and
BytesGalore
committed
Feb 24, 2016
1 parent
dd15430
commit f0245bd
Showing
6 changed files
with
399 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/*- | ||
* Copyright 2005 Colin Percival | ||
* Copyright 2013 Christian Mehlis & René Kijewski | ||
* Copyright 2016 Martin Landsmann <[email protected]> | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
|
@@ -37,11 +38,13 @@ | |
* @author Colin Percival | ||
* @author Christian Mehlis | ||
* @author Rene Kijewski | ||
* @author Martin Landsmann | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <string.h> | ||
#include <assert.h> | ||
|
||
#include "hashes/sha256.h" | ||
#include "board.h" | ||
|
@@ -318,3 +321,140 @@ const unsigned char *hmac_sha256(const unsigned char *key, | |
|
||
return result; | ||
} | ||
|
||
/** | ||
* @brief helper to compute sha256 inplace for the given buffer | ||
* | ||
* @param[in, out] element the buffer to compute a sha256 and store it back to it | ||
* | ||
*/ | ||
static inline void sha256_inplace(unsigned char element[SHA256_DIGEST_LENGTH]) | ||
{ | ||
sha256_context_t ctx; | ||
sha256_init(&ctx); | ||
sha256_update(&ctx, element, SHA256_DIGEST_LENGTH); | ||
sha256_final(element, &ctx); | ||
} | ||
|
||
unsigned char *sha256_chain(const unsigned char *seed, size_t seed_length, | ||
size_t elements, unsigned char *tail_element) | ||
{ | ||
unsigned char tmp_element[SHA256_DIGEST_LENGTH]; | ||
|
||
/* assert if no sha256-chain can be created */ | ||
assert(elements >= 2); | ||
|
||
/* 1st iteration */ | ||
sha256(seed, seed_length, tmp_element); | ||
|
||
/* perform consecutive iterations minus the first one */ | ||
for (size_t i = 0; i < (elements - 1); ++i) { | ||
sha256_inplace(tmp_element); | ||
} | ||
|
||
/* store the result */ | ||
memcpy(tail_element, tmp_element, SHA256_DIGEST_LENGTH); | ||
|
||
return tail_element; | ||
} | ||
|
||
unsigned char *sha256_chain_with_waypoints(const unsigned char *seed, | ||
size_t seed_length, | ||
size_t elements, | ||
unsigned char *tail_element, | ||
sha256_chain_idx_elm_t *waypoints, | ||
size_t *waypoints_length) | ||
{ | ||
/* assert if no sha256-chain can be created */ | ||
assert(elements >= 2); | ||
|
||
/* assert to prevent division by 0 */ | ||
assert(*waypoints_length > 0); | ||
|
||
/* assert if no waypoints can be created */ | ||
assert(*waypoints_length > 1); | ||
|
||
/* if we have enough space we store the whole chain */ | ||
if (*waypoints_length >= elements) { | ||
/* 1st iteration */ | ||
sha256(seed, seed_length, waypoints[0].element); | ||
waypoints[0].index = 0; | ||
|
||
/* perform consecutive iterations starting at index 1*/ | ||
for (size_t i = 1; i < elements; ++i) { | ||
sha256_context_t ctx; | ||
sha256_init(&ctx); | ||
sha256_update(&ctx, waypoints[(i - 1)].element, SHA256_DIGEST_LENGTH); | ||
sha256_final(waypoints[i].element, &ctx); | ||
waypoints[i].index = i; | ||
} | ||
|
||
/* store the result */ | ||
memcpy(tail_element, waypoints[(elements - 1)].element, SHA256_DIGEST_LENGTH); | ||
*waypoints_length = (elements - 1); | ||
|
||
return tail_element; | ||
} | ||
else { | ||
unsigned char tmp_element[SHA256_DIGEST_LENGTH]; | ||
size_t waypoint_streak = (elements / *waypoints_length); | ||
|
||
/* 1st waypoint iteration */ | ||
sha256(seed, seed_length, tmp_element); | ||
for (size_t i = 1; i < waypoint_streak; ++i) { | ||
sha256_inplace(tmp_element); | ||
} | ||
memcpy(waypoints[0].element, tmp_element, SHA256_DIGEST_LENGTH); | ||
waypoints[0].index = (waypoint_streak - 1); | ||
|
||
/* index of the current computed element in the chain */ | ||
size_t index = (waypoint_streak - 1); | ||
|
||
/* consecutive waypoint iterations */ | ||
size_t j = 1; | ||
for (; j < *waypoints_length; ++j) { | ||
for (size_t i = 0; i < waypoint_streak; ++i) { | ||
sha256_inplace(tmp_element); | ||
index++; | ||
} | ||
memcpy(waypoints[j].element, tmp_element, SHA256_DIGEST_LENGTH); | ||
waypoints[j].index = index; | ||
} | ||
|
||
/* store/pass the last used index in the waypoint array */ | ||
*waypoints_length = (j - 1); | ||
|
||
/* remaining iterations down to elements */ | ||
for (size_t i = index; i < (elements - 1); ++i) { | ||
sha256_inplace(tmp_element); | ||
} | ||
|
||
/* store the result */ | ||
memcpy(tail_element, tmp_element, SHA256_DIGEST_LENGTH); | ||
|
||
return tail_element; | ||
} | ||
} | ||
|
||
int sha256_chain_verify_element(unsigned char *element, | ||
size_t element_index, | ||
unsigned char *tail_element, | ||
size_t chain_length) | ||
{ | ||
unsigned char tmp_element[SHA256_DIGEST_LENGTH]; | ||
|
||
int delta_count = (chain_length - element_index); | ||
|
||
/* assert if we have an index mismatch */ | ||
assert(delta_count >= 1); | ||
|
||
memcpy((void*)tmp_element, (void*)element, SHA256_DIGEST_LENGTH); | ||
|
||
/* perform all consecutive iterations down to tail_element */ | ||
for (int i = 0; i < (delta_count - 1); ++i) { | ||
sha256_inplace(tmp_element); | ||
} | ||
|
||
/* return if the computed element equals the tail_element */ | ||
return (memcmp(tmp_element, tail_element, SHA256_DIGEST_LENGTH) != 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/*- | ||
* Copyright 2005 Colin Percival | ||
* Copyright 2013 Christian Mehlis & René Kijewski | ||
* Copyright 2016 Martin Landsmann <[email protected]> | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
|
@@ -68,6 +69,16 @@ typedef struct { | |
unsigned char buf[64]; | ||
} sha256_context_t; | ||
|
||
/** | ||
* @brief sha256-chain indexed element | ||
*/ | ||
typedef struct { | ||
/** the position of this element in its chain */ | ||
size_t index; | ||
/** the element */ | ||
unsigned char element[SHA256_DIGEST_LENGTH]; | ||
} sha256_chain_idx_elm_t; | ||
|
||
/** | ||
* @brief SHA-256 initialization. Begins a SHA-256 operation. | ||
* | ||
|
@@ -124,6 +135,74 @@ const unsigned char *hmac_sha256(const unsigned char *key, | |
size_t message_length, | ||
unsigned char *result); | ||
|
||
/** | ||
* @brief function to produce a hash chain statring with a given seed element. | ||
* The chain is computed by taking the sha256 from the seed, | ||
* hash the resulting sha256 and continuing taking sha256 | ||
* from each result consecutively. | ||
* | ||
* @param[in] seed the seed of the sha256-chain, i.e. the first element | ||
* @param[in] seed_length the size of seed in bytes | ||
* @param[in] elements the number of chained elements, | ||
* i.e. the index of the last element is (elements-1) | ||
* @param[out] tail_element the final element of the sha256-chain | ||
* | ||
* @returns pointer to tail_element | ||
*/ | ||
unsigned char *sha256_chain(const unsigned char *seed, size_t seed_length, | ||
size_t elements, unsigned char *tail_element); | ||
|
||
/** | ||
* @brief function to produce a hash chain statring with a given seed element. | ||
* The chain is computed the same way as done with sha256_chain(). | ||
* Additionally intermediate elements are saved while computing the chain. | ||
* This slows down computation, but provides the caller with indexed | ||
* "waypoint"-elements. | ||
* They are supposed to shortcut computing verification elements, | ||
* this comes in handy when using long chains, | ||
* e.g. a chain with 2<sup>32</sup> elements. | ||
* | ||
* @param[in] seed the seed of the sha256-chain, i.e. the first element | ||
* @param[in] seed_length the size of seed in bytes | ||
* @param[in] elements the number of chained elements, | ||
* i.e. the index of the last element is (elements-1) | ||
* @param[out] tail_element the final element of the sha256-chain | ||
* @param[out] waypoints intermediate elements are stored there. | ||
* @param[in, out] waypoints_length the size of the waypoints array. | ||
* If the given size is equal or greater elements, the complete | ||
* chain will be stored. | ||
* Otherwise every n-th element is stored where: | ||
* n = floor(elements / waypoints_length); | ||
* floor is implicitly used since we perform unsigned integer division. | ||
* The last used waypoint index is stored in the variable after call. | ||
* That is (elements - 1) if the complete chain is stored, | ||
* and (*waypoints_length - 1) if we only store some waypoints. | ||
* | ||
* @returns pointer to tail_element | ||
*/ | ||
unsigned char *sha256_chain_with_waypoints(const unsigned char *seed, | ||
size_t seed_length, | ||
size_t elements, | ||
unsigned char *tail_element, | ||
sha256_chain_idx_elm_t *waypoints, | ||
size_t *waypoints_length); | ||
|
||
/** | ||
* @brief function to verify if a given chain element is part of the chain. | ||
* | ||
* @param[in] element the chain element to be verified | ||
* @param[in] element_index the position in the chain | ||
* @param[in] tail_element the last element of the sha256-chain | ||
* @param[in] chain_length the number of elements in the chain | ||
* | ||
* @returns 0 if element is verified to be part of the chain at element_index | ||
* 1 if the element cannot be verified as part of the chain | ||
*/ | ||
int sha256_chain_verify_element(unsigned char *element, | ||
size_t element_index, | ||
unsigned char *tail_element, | ||
size_t chain_length); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
Oops, something went wrong.