]> git.ozlabs.org Git - ccan/blob - ccan/crypto/shachain/shachain.h
ccan/structeq: make it safe when there's padding.
[ccan] / ccan / crypto / shachain / shachain.h
1 /* MIT (BSD) license - see LICENSE file for details */
2 #ifndef CCAN_CRYPTO_SHACHAIN_H
3 #define CCAN_CRYPTO_SHACHAIN_H
4 #include "config.h"
5 #include <ccan/crypto/sha256/sha256.h>
6 #include <stdbool.h>
7 #include <stdint.h>
8
9 #ifndef SHACHAIN_BITS
10 #define SHACHAIN_BITS (sizeof(uint64_t) * 8)
11 #endif
12
13 /**
14  * shachain_from_seed - Generate an unpredictable SHA from a seed value.
15  * @seed: (secret) seed value to use
16  * @index: index of value to generate (0 == seed)
17  * @hash: value generated
18  *
19  * There will be no way to derive the result from that generated for
20  * any *greater* index.
21  *
22  * Example:
23  * #include <time.h>
24  *
25  * static void next_hash(struct sha256 *hash)
26  * {
27  *      static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
28  *      static struct sha256 seed;
29  *
30  *      // First time, initialize seed.
31  *      if (index == 0xFFFFFFFFFFFFFFFFULL) {
32  *              // DO NOT DO THIS!  Very predictable!
33  *              time_t now = time(NULL);
34  *              memcpy(&seed, &now, sizeof(now));
35  *      }
36  *
37  *      shachain_from_seed(&seed, index--, hash);
38  * }
39  */
40 void shachain_from_seed(const struct sha256 *seed, uint64_t index,
41                         struct sha256 *hash);
42
43 /**
44  * shachain - structure for recording/deriving decrementing chain members
45  * @min_index: minimum index value successfully shachain_add_hash()ed.
46  * @num_valid: number of known[] array valid.  If non-zero, @min_index valid.
47  * @known: known values to allow us to derive those >= @min_index.
48  *
49  * This is sufficient storage to derive any shachain hash value previously
50  * added.
51  */
52 struct shachain {
53         uint64_t min_index;
54         unsigned int num_valid;
55         struct {
56                 uint64_t index;
57                 struct sha256 hash;
58         } known[SHACHAIN_BITS + 1];
59 };
60
61 /**
62  * shachain_init - initialize an shachain
63  * @chain: the chain to initialize
64  *
65  * Alternately, ensure that it's all zero.
66  */
67 void shachain_init(struct shachain *chain);
68
69 /**
70  * shachain_next_index - what's the next index I can add to the shachain?
71  * @chain: the chain
72  *
73  * This returns 0xFFFFFFFFFFFFFFFF (for a freshly
74  * initialized chain), or one less than the previously successfully
75  * added value.
76  */
77 uint64_t shachain_next_index(const struct shachain *chain);
78
79 /**
80  * shachain_add_hash - record the hash for the next index.
81  * @chain: the chain to add to
82  * @index: the index of the hash
83  * @hash: the hash value.
84  *
85  * You can only add shachain_next_index(@chain).
86  *
87  * This can fail (return false without altering @chain) if the hash
88  * for this index isn't consistent with previous hashes (ie. wasn't
89  * generated from the same seed), though it can't always detect that.
90  * If the hash is inconsistent yet undetected, a future addition will
91  * fail.
92  *
93  * Example:
94  * static void next_hash(const struct sha256 *hash)
95  * {
96  *      static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
97  *      static struct shachain chain;
98  *
99  *      if (!shachain_add_hash(&chain, index--, hash))
100  *              errx(1, "Corrupted hash value?");
101  * }
102  */
103 bool shachain_add_hash(struct shachain *chain,
104                        uint64_t index, const struct sha256 *hash);
105
106 /**
107  * shachain_get_hash - get the hash for a given index.
108  * @chain: the chain query
109  * @index: the index of the hash to get
110  * @hash: the hash value.
111  *
112  * This will return true and set @hash to that given in the successful
113  * shachain_get_hash() call for that index.  If there was no
114  * successful shachain_get_hash() for that index, it will return
115  * false.
116  *
117  * Example:
118  * #include <ccan/structeq/structeq.h>
119  * // Defines sha256_eq
120  * STRUCTEQ_DEF(sha256, 0, u);
121  *
122  * static void next_hash(const struct sha256 *hash)
123  * {
124  *      static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
125  *      static struct shachain chain;
126  *
127  *      if (!shachain_add_hash(&chain, index--, hash))
128  *              errx(1, "Corrupted hash value?");
129  *      else {
130  *              struct sha256 check;
131  *              assert(shachain_get_hash(&chain, index+1, &check));
132  *              assert(sha256_eq(&check, hash));
133  *      }
134  * }
135  */
136 bool shachain_get_hash(const struct shachain *chain,
137                        uint64_t index, struct sha256 *hash);
138 #endif /* CCAN_CRYPTO_SHACHAIN_H */