Skip to content

Commit

Permalink
Added detailed documentation for all SSKR and SSS functions
Browse files Browse the repository at this point in the history
  • Loading branch information
aido committed Mar 3, 2024
1 parent 51d6dbf commit a8e9bba
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 195 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Change log

## [1.7.0] - 2024-03-02
## [1.7.0] - 2024-03-03
### Added
-
- Added detailed documentation for all SSKR and SSS functions

### Changed
- Changed Shamir interpolate function to use `cx_bn_gf2_n_mul()` syscalls
Expand Down
198 changes: 145 additions & 53 deletions src/sskr/sskr.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@

#define memzero(...) explicit_bzero(__VA_ARGS__)

/**
* @brief Validates the length of a secret for SSKR functions.
*
* @details This function checks if the length of a secret is within the acceptable
* range for use in SSKR. It enforces constraints on the secret length to
* ensure security and compatibility.
*
* @param[in] len Length of the secret in bytes.
*
* @return 0 on success, indicating a valid secret length, or a negative error code on failure:
* - SSKR_ERROR_SECRET_TOO_SHORT: if len is less than SSKR_MIN_STRENGTH_BYTES
* - SSKR_ERROR_SECRET_TOO_LONG: if len is greater than SSKR_MAX_STRENGTH_BYTES
* - SSKR_ERROR_SECRET_LENGTH_NOT_EVEN: if len is not even
*/
static int16_t sskr_check_secret_length(uint8_t len) {
if (len < SSKR_MIN_STRENGTH_BYTES) {
return SSKR_ERROR_SECRET_TOO_SHORT;
Expand All @@ -28,6 +42,21 @@ static int16_t sskr_check_secret_length(uint8_t len) {
return 0;
}

/**
* @brief Serializes an SSKR shard into a byte array.
*
* @details This function converts an `sskr_shard_t` structure into a byte array suitable for
* storage or transmission. It packs the shard's metadata (identifier, group/member
* information) and value into a single buffer.
*
* @param[in] shard Pointer to the `sskr_shard_t` structure to be serialized.
* @param[out] destination Pointer to the buffer where the serialized data will be written.
* @param[in] destination_len Length of the `destination` buffer in bytes.
*
* @return Length of the serialized shard data on success, or a negative error code:
* - SSKR_ERROR_INSUFFICIENT_SPACE: if `destination_len` is not enough to hold the
* serialized data.
*/
static int16_t sskr_serialize_shard(const sskr_shard_t *shard,
uint8_t *destination,
uint16_t destination_len) {
Expand Down Expand Up @@ -68,6 +97,25 @@ static int16_t sskr_serialize_shard(const sskr_shard_t *shard,
return shard->value_len + SSKR_METADATA_LENGTH_BYTES;
}

/**
* @brief Deserializes an SSKR shard from a byte array.
*
* @details This function reconstructs an `sskr_shard_t` structure from a serialized
* byte array created using `sskr_serialize_shard`. It validates the metadata
* and extracts the shard's identifier, group/member information, and value.
*
* @param[in] source Pointer to the serialized shard data.
* @param[in] source_len Length of the `source` array in bytes.
* @param[out] shard Pointer to an `sskr_shard_t` structure to be populated.
*
* @return Length of the shard value on success, or a negative error code:
* - SSKR_ERROR_NOT_ENOUGH_SERIALIZED_BYTES: if `source_len` is too short.
* - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if group threshold exceeds group count.
* - SSKR_ERROR_INVALID_RESERVED_BITS: if reserved bits are not zero.
* - SSKR_ERROR_SECRET_TOO_SHORT, SSKR_ERROR_SECRET_TOO_LONG,
* SSKR_ERROR_SECRET_LENGTH_NOT_EVEN (via `sskr_check_secret_length`)
* if the extracted value length is invalid.
*/
static int16_t sskr_deserialize_shard(const uint8_t *source,
uint16_t source_len,
sskr_shard_t *shard) {
Expand Down Expand Up @@ -102,6 +150,25 @@ static int16_t sskr_deserialize_shard(const uint8_t *source,
return shard->value_len;
}

/**
* @brief Calculates the total number of shards generated for a given SSKR configuration.
*
* @details This function determines the total shard count based on the group threshold,
* group descriptors, and their respective member counts. It validates the
* group configuration and enforces constraints to ensure logical consistency.
*
* @param[in] group_threshold Minimum number of groups required for secret reconstruction.
* @param[in] groups Pointer to an array of `sskr_group_descriptor_t` structures.
* @param[in] groups_len Number of groups in the `groups` array.
*
* @return Total number of shards on success, or a negative error code:
* - SSKR_ERROR_INVALID_GROUP_LENGTH: if `groups_len` is less than 1.
* - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if `group_threshold` exceeds `groups_len`.
* - SSKR_ERROR_INVALID_GROUP_COUNT: if any group has a count less than 1.
* - SSKR_ERROR_INVALID_MEMBER_THRESHOLD: if any group's threshold exceeds its count.
* - SSKR_ERROR_INVALID_SINGLETON_MEMBER: if any group with threshold 1 has a count greater
* than 1.
*/
int16_t sskr_count_shards(uint8_t group_threshold,
const sskr_group_descriptor_t *groups,
uint8_t groups_len) {
Expand Down Expand Up @@ -131,17 +198,39 @@ int16_t sskr_count_shards(uint8_t group_threshold,
return shard_count;
}

//////////////////////////////////////////////////
// generate shards
//
static int16_t sskr_generate_shards(uint8_t group_threshold,
const sskr_group_descriptor_t *groups,
uint8_t groups_len,
const uint8_t *master_secret,
uint16_t master_secret_len,
sskr_shard_t *shards,
uint16_t shards_size,
unsigned char *(*random_generator)(uint8_t *, size_t)) {
/**
* @brief Internal function to generate SSKR shards from a master secret.
*
* @details This function performs the core logic of generating a set of shards
* from a given master secret, using a specific group configuration and a
* random number generator. It's an internal function, not intended for direct
* use by external applications.
*
* @param[in] group_threshold Minimum number of groups required for secret reconstruction.
* @param[in] groups Pointer to an array of `sskr_group_descriptor_t` structures.
* @param[in] groups_len Number of groups in the `groups` array.
* @param[in] master_secret Pointer to the master secret to be split.
* @param[in] master_secret_len Length of the master secret in bytes.
* @param[out] shards Pointer to an array of `sskr_shard_t` structures to store
* the generated shards.
* @param[in] shards_size Size of the `shards` array in bytes.
* @param[in] random_generator Pointer to a function that generates random bytes.
*
* @return Number of shards generated on success, or a negative error code:
* - SSKR_ERROR_INVALID_SECRET_LENGTH: if master secret length is invalid.
* - SSKR_ERROR_INSUFFICIENT_SPACE: if `shards_size` is insufficient.
* - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if `group_threshold` exceeds `groups_len`.
* - Other error codes from `sss_split_secret`.
*/
static int16_t sskr_generate_shards_internal(uint8_t group_threshold,
const sskr_group_descriptor_t *groups,
uint8_t groups_len,
const uint8_t *master_secret,
uint16_t master_secret_len,
sskr_shard_t *shards,
uint16_t shards_size,
unsigned char *(*random_generator)(uint8_t *,
size_t)) {
int16_t err = sskr_check_secret_length(master_secret_len);
if (err) {
return err;
Expand Down Expand Up @@ -216,18 +305,15 @@ static int16_t sskr_generate_shards(uint8_t group_threshold,
return shards_count;
}

//////////////////////////////////////////////////
// generate mnemonics
//
int16_t sskr_generate(uint8_t group_threshold,
const sskr_group_descriptor_t *groups,
uint8_t groups_len,
const uint8_t *master_secret,
uint16_t master_secret_len,
uint8_t *shard_len,
uint8_t *output,
uint16_t buffer_size,
unsigned char *(*random_generator)(uint8_t *, size_t)) {
int16_t sskr_generate_shards(uint8_t group_threshold,
const sskr_group_descriptor_t *groups,
uint8_t groups_len,
const uint8_t *master_secret,
uint16_t master_secret_len,
uint8_t *shard_len,
uint8_t *output,
uint16_t buffer_size,
unsigned char *(*random_generator)(uint8_t *, size_t)) {
int16_t err = sskr_check_secret_length(master_secret_len);
if (err) {
return err;
Expand All @@ -252,14 +338,14 @@ int16_t sskr_generate(uint8_t group_threshold,
sskr_shard_t shards[SSS_MAX_SHARE_COUNT * SSKR_MAX_GROUP_COUNT];

// generate shards
total_shards = sskr_generate_shards(group_threshold,
groups,
groups_len,
master_secret,
master_secret_len,
shards,
(uint16_t) total_shards,
random_generator);
total_shards = sskr_generate_shards_internal(group_threshold,
groups,
groups_len,
master_secret,
master_secret_len,
shards,
(uint16_t) total_shards,
random_generator);

if (total_shards < 0) {
error = total_shards;
Expand Down Expand Up @@ -296,19 +382,29 @@ typedef struct sskr_group_struct {
uint8_t count;
uint8_t member_index[SSS_MAX_SHARE_COUNT];
const uint8_t *value[SSS_MAX_SHARE_COUNT];
} sskr_group;
} sskr_group_t;

/**
* This version of combine shards potentially modifies the shard structures
* in place, so it is for internal use only, however it provides the implementation
* for both combine_shards and sskr_combine.
* @brief Internal function to combine shards for secret reconstruction.
*
* @details This function implements the core logic for combining SSKR shards to
* recover the original secret. It potentially modifies shard structures in
* place, making it unsuitable for direct public use. It's the underlying
* implementation for and `sskr_combine_shards`.
*
* @param[in,out] shards Pointer to an array of `sskr_shard_t` structures to be combined.
* @param[in] shards_count Number of shards in the `shards` array.
* @param[out] buffer Pointer to a buffer for working space and storing the reconstructed
* secret.
* @param[in] buffer_len Length of the `buffer` array in bytes.
*
* @return Length of the reconstructed secret on success, or a negative error code.
* Specific error codes are implementation-dependent, consult implementation details.
*/
static int16_t sskr_combine_shards_internal(
sskr_shard_t *shards, // array of shard structures
uint8_t shards_count, // number of shards in array
uint8_t *buffer, // working space, and place to return secret
uint16_t buffer_len // total amount of working space
) {
static int16_t sskr_combine_shards_internal(sskr_shard_t *shards,
uint8_t shards_count,
uint8_t *buffer,
uint16_t buffer_len) {
int16_t error = 0;
uint16_t identifier = 0;
uint8_t group_threshold = 0;
Expand All @@ -319,7 +415,7 @@ static int16_t sskr_combine_shards_internal(
}

uint8_t next_group = 0;
sskr_group groups[SSKR_MAX_GROUP_COUNT];
sskr_group_t groups[SSKR_MAX_GROUP_COUNT];
uint8_t secret_len = 0;

for (uint8_t i = 0; i < shards_count; ++i) {
Expand Down Expand Up @@ -359,7 +455,7 @@ static int16_t sskr_combine_shards_internal(
}

if (!group_found) {
sskr_group *g = &groups[next_group];
sskr_group_t *g = &groups[next_group];
g->group_index = shard->group_index;
g->member_threshold = shard->member_threshold;
g->count = 1;
Expand Down Expand Up @@ -387,7 +483,7 @@ static int16_t sskr_combine_shards_internal(
uint8_t *group_share = group_shares;

for (uint8_t i = 0; !error && i < (uint8_t) next_group; ++i) {
sskr_group *g = &groups[i];
sskr_group_t *g = &groups[i];

gx[i] = g->group_index;
if (g->count < g->member_threshold) {
Expand Down Expand Up @@ -437,15 +533,11 @@ static int16_t sskr_combine_shards_internal(
return secret_len;
}

/////////////////////////////////////////////////
// sskr_combine

int16_t sskr_combine(const uint8_t **input_shards, // array of pointers to 10-bit words
uint8_t shard_len, // number of bytes in each serialized shard
uint8_t shards_count, // total number of shards
uint8_t *buffer, // working space, and place to return secret
uint16_t buffer_len // total amount of working space
) {
int16_t sskr_combine_shards(const uint8_t **input_shards,
uint8_t shard_len,
uint8_t shards_count,
uint8_t *buffer,
uint16_t buffer_len) {
int16_t result = 0;

if (shards_count == 0) {
Expand Down
Loading

0 comments on commit a8e9bba

Please sign in to comment.