1515
1616#define memzero (...) explicit_bzero(__VA_ARGS__)
1717
18+ /**
19+ * @brief Validates the length of a secret for SSKR functions.
20+ *
21+ * @details This function checks if the length of a secret is within the acceptable
22+ * range for use in SSKR. It enforces constraints on the secret length to
23+ * ensure security and compatibility.
24+ *
25+ * @param[in] len Length of the secret in bytes.
26+ *
27+ * @return 0 on success, indicating a valid secret length, or a negative error code on failure:
28+ * - SSKR_ERROR_SECRET_TOO_SHORT: if len is less than SSKR_MIN_STRENGTH_BYTES
29+ * - SSKR_ERROR_SECRET_TOO_LONG: if len is greater than SSKR_MAX_STRENGTH_BYTES
30+ * - SSKR_ERROR_SECRET_LENGTH_NOT_EVEN: if len is not even
31+ */
1832static int16_t sskr_check_secret_length (uint8_t len ) {
1933 if (len < SSKR_MIN_STRENGTH_BYTES ) {
2034 return SSKR_ERROR_SECRET_TOO_SHORT ;
@@ -28,6 +42,21 @@ static int16_t sskr_check_secret_length(uint8_t len) {
2842 return 0 ;
2943}
3044
45+ /**
46+ * @brief Serializes an SSKR shard into a byte array.
47+ *
48+ * @details This function converts an `sskr_shard_t` structure into a byte array suitable for
49+ * storage or transmission. It packs the shard's metadata (identifier, group/member
50+ * information) and value into a single buffer.
51+ *
52+ * @param[in] shard Pointer to the `sskr_shard_t` structure to be serialized.
53+ * @param[out] destination Pointer to the buffer where the serialized data will be written.
54+ * @param[in] destination_len Length of the `destination` buffer in bytes.
55+ *
56+ * @return Length of the serialized shard data on success, or a negative error code:
57+ * - SSKR_ERROR_INSUFFICIENT_SPACE: if `destination_len` is not enough to hold the
58+ * serialized data.
59+ */
3160static int16_t sskr_serialize_shard (const sskr_shard_t * shard ,
3261 uint8_t * destination ,
3362 uint16_t destination_len ) {
@@ -68,6 +97,25 @@ static int16_t sskr_serialize_shard(const sskr_shard_t *shard,
6897 return shard -> value_len + SSKR_METADATA_LENGTH_BYTES ;
6998}
7099
100+ /**
101+ * @brief Deserializes an SSKR shard from a byte array.
102+ *
103+ * @details This function reconstructs an `sskr_shard_t` structure from a serialized
104+ * byte array created using `sskr_serialize_shard`. It validates the metadata
105+ * and extracts the shard's identifier, group/member information, and value.
106+ *
107+ * @param[in] source Pointer to the serialized shard data.
108+ * @param[in] source_len Length of the `source` array in bytes.
109+ * @param[out] shard Pointer to an `sskr_shard_t` structure to be populated.
110+ *
111+ * @return Length of the shard value on success, or a negative error code:
112+ * - SSKR_ERROR_NOT_ENOUGH_SERIALIZED_BYTES: if `source_len` is too short.
113+ * - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if group threshold exceeds group count.
114+ * - SSKR_ERROR_INVALID_RESERVED_BITS: if reserved bits are not zero.
115+ * - SSKR_ERROR_SECRET_TOO_SHORT, SSKR_ERROR_SECRET_TOO_LONG,
116+ * SSKR_ERROR_SECRET_LENGTH_NOT_EVEN (via `sskr_check_secret_length`)
117+ * if the extracted value length is invalid.
118+ */
71119static int16_t sskr_deserialize_shard (const uint8_t * source ,
72120 uint16_t source_len ,
73121 sskr_shard_t * shard ) {
@@ -102,6 +150,25 @@ static int16_t sskr_deserialize_shard(const uint8_t *source,
102150 return shard -> value_len ;
103151}
104152
153+ /**
154+ * @brief Calculates the total number of shards generated for a given SSKR configuration.
155+ *
156+ * @details This function determines the total shard count based on the group threshold,
157+ * group descriptors, and their respective member counts. It validates the
158+ * group configuration and enforces constraints to ensure logical consistency.
159+ *
160+ * @param[in] group_threshold Minimum number of groups required for secret reconstruction.
161+ * @param[in] groups Pointer to an array of `sskr_group_descriptor_t` structures.
162+ * @param[in] groups_len Number of groups in the `groups` array.
163+ *
164+ * @return Total number of shards on success, or a negative error code:
165+ * - SSKR_ERROR_INVALID_GROUP_LENGTH: if `groups_len` is less than 1.
166+ * - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if `group_threshold` exceeds `groups_len`.
167+ * - SSKR_ERROR_INVALID_GROUP_COUNT: if any group has a count less than 1.
168+ * - SSKR_ERROR_INVALID_MEMBER_THRESHOLD: if any group's threshold exceeds its count.
169+ * - SSKR_ERROR_INVALID_SINGLETON_MEMBER: if any group with threshold 1 has a count greater
170+ * than 1.
171+ */
105172int16_t sskr_count_shards (uint8_t group_threshold ,
106173 const sskr_group_descriptor_t * groups ,
107174 uint8_t groups_len ) {
@@ -131,17 +198,39 @@ int16_t sskr_count_shards(uint8_t group_threshold,
131198 return shard_count ;
132199}
133200
134- //////////////////////////////////////////////////
135- // generate shards
136- //
137- static int16_t sskr_generate_shards (uint8_t group_threshold ,
138- const sskr_group_descriptor_t * groups ,
139- uint8_t groups_len ,
140- const uint8_t * master_secret ,
141- uint16_t master_secret_len ,
142- sskr_shard_t * shards ,
143- uint16_t shards_size ,
144- unsigned char * (* random_generator )(uint8_t * , size_t )) {
201+ /**
202+ * @brief Internal function to generate SSKR shards from a master secret.
203+ *
204+ * @details This function performs the core logic of generating a set of shards
205+ * from a given master secret, using a specific group configuration and a
206+ * random number generator. It's an internal function, not intended for direct
207+ * use by external applications.
208+ *
209+ * @param[in] group_threshold Minimum number of groups required for secret reconstruction.
210+ * @param[in] groups Pointer to an array of `sskr_group_descriptor_t` structures.
211+ * @param[in] groups_len Number of groups in the `groups` array.
212+ * @param[in] master_secret Pointer to the master secret to be split.
213+ * @param[in] master_secret_len Length of the master secret in bytes.
214+ * @param[out] shards Pointer to an array of `sskr_shard_t` structures to store
215+ * the generated shards.
216+ * @param[in] shards_size Size of the `shards` array in bytes.
217+ * @param[in] random_generator Pointer to a function that generates random bytes.
218+ *
219+ * @return Number of shards generated on success, or a negative error code:
220+ * - SSKR_ERROR_INVALID_SECRET_LENGTH: if master secret length is invalid.
221+ * - SSKR_ERROR_INSUFFICIENT_SPACE: if `shards_size` is insufficient.
222+ * - SSKR_ERROR_INVALID_GROUP_THRESHOLD: if `group_threshold` exceeds `groups_len`.
223+ * - Other error codes from `sss_split_secret`.
224+ */
225+ static int16_t sskr_generate_shards_internal (uint8_t group_threshold ,
226+ const sskr_group_descriptor_t * groups ,
227+ uint8_t groups_len ,
228+ const uint8_t * master_secret ,
229+ uint16_t master_secret_len ,
230+ sskr_shard_t * shards ,
231+ uint16_t shards_size ,
232+ unsigned char * (* random_generator )(uint8_t * ,
233+ size_t )) {
145234 int16_t err = sskr_check_secret_length (master_secret_len );
146235 if (err ) {
147236 return err ;
@@ -216,18 +305,15 @@ static int16_t sskr_generate_shards(uint8_t group_threshold,
216305 return shards_count ;
217306}
218307
219- //////////////////////////////////////////////////
220- // generate mnemonics
221- //
222- int16_t sskr_generate (uint8_t group_threshold ,
223- const sskr_group_descriptor_t * groups ,
224- uint8_t groups_len ,
225- const uint8_t * master_secret ,
226- uint16_t master_secret_len ,
227- uint8_t * shard_len ,
228- uint8_t * output ,
229- uint16_t buffer_size ,
230- unsigned char * (* random_generator )(uint8_t * , size_t )) {
308+ int16_t sskr_generate_shards (uint8_t group_threshold ,
309+ const sskr_group_descriptor_t * groups ,
310+ uint8_t groups_len ,
311+ const uint8_t * master_secret ,
312+ uint16_t master_secret_len ,
313+ uint8_t * shard_len ,
314+ uint8_t * output ,
315+ uint16_t buffer_size ,
316+ unsigned char * (* random_generator )(uint8_t * , size_t )) {
231317 int16_t err = sskr_check_secret_length (master_secret_len );
232318 if (err ) {
233319 return err ;
@@ -252,14 +338,14 @@ int16_t sskr_generate(uint8_t group_threshold,
252338 sskr_shard_t shards [SSS_MAX_SHARE_COUNT * SSKR_MAX_GROUP_COUNT ];
253339
254340 // generate shards
255- total_shards = sskr_generate_shards (group_threshold ,
256- groups ,
257- groups_len ,
258- master_secret ,
259- master_secret_len ,
260- shards ,
261- (uint16_t ) total_shards ,
262- random_generator );
341+ total_shards = sskr_generate_shards_internal (group_threshold ,
342+ groups ,
343+ groups_len ,
344+ master_secret ,
345+ master_secret_len ,
346+ shards ,
347+ (uint16_t ) total_shards ,
348+ random_generator );
263349
264350 if (total_shards < 0 ) {
265351 error = total_shards ;
@@ -296,19 +382,29 @@ typedef struct sskr_group_struct {
296382 uint8_t count ;
297383 uint8_t member_index [SSS_MAX_SHARE_COUNT ];
298384 const uint8_t * value [SSS_MAX_SHARE_COUNT ];
299- } sskr_group ;
385+ } sskr_group_t ;
300386
301387/**
302- * This version of combine shards potentially modifies the shard structures
303- * in place, so it is for internal use only, however it provides the implementation
304- * for both combine_shards and sskr_combine.
388+ * @brief Internal function to combine shards for secret reconstruction.
389+ *
390+ * @details This function implements the core logic for combining SSKR shards to
391+ * recover the original secret. It potentially modifies shard structures in
392+ * place, making it unsuitable for direct public use. It's the underlying
393+ * implementation for and `sskr_combine_shards`.
394+ *
395+ * @param[in,out] shards Pointer to an array of `sskr_shard_t` structures to be combined.
396+ * @param[in] shards_count Number of shards in the `shards` array.
397+ * @param[out] buffer Pointer to a buffer for working space and storing the reconstructed
398+ * secret.
399+ * @param[in] buffer_len Length of the `buffer` array in bytes.
400+ *
401+ * @return Length of the reconstructed secret on success, or a negative error code.
402+ * Specific error codes are implementation-dependent, consult implementation details.
305403 */
306- static int16_t sskr_combine_shards_internal (
307- sskr_shard_t * shards , // array of shard structures
308- uint8_t shards_count , // number of shards in array
309- uint8_t * buffer , // working space, and place to return secret
310- uint16_t buffer_len // total amount of working space
311- ) {
404+ static int16_t sskr_combine_shards_internal (sskr_shard_t * shards ,
405+ uint8_t shards_count ,
406+ uint8_t * buffer ,
407+ uint16_t buffer_len ) {
312408 int16_t error = 0 ;
313409 uint16_t identifier = 0 ;
314410 uint8_t group_threshold = 0 ;
@@ -319,7 +415,7 @@ static int16_t sskr_combine_shards_internal(
319415 }
320416
321417 uint8_t next_group = 0 ;
322- sskr_group groups [SSKR_MAX_GROUP_COUNT ];
418+ sskr_group_t groups [SSKR_MAX_GROUP_COUNT ];
323419 uint8_t secret_len = 0 ;
324420
325421 for (uint8_t i = 0 ; i < shards_count ; ++ i ) {
@@ -359,7 +455,7 @@ static int16_t sskr_combine_shards_internal(
359455 }
360456
361457 if (!group_found ) {
362- sskr_group * g = & groups [next_group ];
458+ sskr_group_t * g = & groups [next_group ];
363459 g -> group_index = shard -> group_index ;
364460 g -> member_threshold = shard -> member_threshold ;
365461 g -> count = 1 ;
@@ -387,7 +483,7 @@ static int16_t sskr_combine_shards_internal(
387483 uint8_t * group_share = group_shares ;
388484
389485 for (uint8_t i = 0 ; !error && i < (uint8_t ) next_group ; ++ i ) {
390- sskr_group * g = & groups [i ];
486+ sskr_group_t * g = & groups [i ];
391487
392488 gx [i ] = g -> group_index ;
393489 if (g -> count < g -> member_threshold ) {
@@ -437,15 +533,11 @@ static int16_t sskr_combine_shards_internal(
437533 return secret_len ;
438534}
439535
440- /////////////////////////////////////////////////
441- // sskr_combine
442-
443- int16_t sskr_combine (const uint8_t * * input_shards , // array of pointers to 10-bit words
444- uint8_t shard_len , // number of bytes in each serialized shard
445- uint8_t shards_count , // total number of shards
446- uint8_t * buffer , // working space, and place to return secret
447- uint16_t buffer_len // total amount of working space
448- ) {
536+ int16_t sskr_combine_shards (const uint8_t * * input_shards ,
537+ uint8_t shard_len ,
538+ uint8_t shards_count ,
539+ uint8_t * buffer ,
540+ uint16_t buffer_len ) {
449541 int16_t result = 0 ;
450542
451543 if (shards_count == 0 ) {
0 commit comments