Skip to content

Commit 8feb588

Browse files
committed
Added random number generators.
1 parent 1a6e6ab commit 8feb588

File tree

7 files changed

+602
-1
lines changed

7 files changed

+602
-1
lines changed

src/Makefile.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ toolname = seedtool
2828
.PHONY: all
2929
all: $(toolname)
3030

31-
OBJS = seedtool.o utils.o generators.o params.o input.o output.o
31+
OBJS = seedtool.o utils.o generators.o params.o input.o output.o random.o randombytes.o hkdf.o
3232

3333
LDFLAGS = -lbc-crypto-base -lbc-shamir -lbc-slip39 -lbc-bip39 -largp
3434

@@ -40,6 +40,9 @@ input.o: input.h params.h
4040
output.o: output.h params.h utils.h
4141
params.o: params.h utils.h input.h output.h
4242
generators.o: generators.h utils.h
43+
random.o: random.h randombytes.h hkdf.h
44+
randombytes.o: randombytes.h
45+
hkdf.o: hkdf.h
4346

4447
bindir = $(DESTDIR)/$(prefix)/bin
4548

src/hkdf.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Permission is hereby granted, free of charge, to any person obtaining a copy
2+
// of this software and associated documentation files (the "Software"), to deal
3+
// in the Software without restriction, including without limitation the rights
4+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5+
// copies of the Software, and to permit persons to whom the Software is
6+
// furnished to do so, subject to the following conditions:
7+
8+
// The above copyright notice and this permission notice shall be included in
9+
// all copies or substantial portions of the Software.
10+
11+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17+
// THE SOFTWARE.
18+
19+
#include "hkdf.h"
20+
21+
#include <bc-crypto-base/bc-crypto-base.h>
22+
23+
#include <assert.h>
24+
#include <string.h>
25+
26+
void hkdf_sha256(uint8_t *okm, size_t okm_size,
27+
const uint8_t *s, size_t ssize,
28+
const uint8_t *k, size_t ksize,
29+
const uint8_t *info, size_t isize)
30+
{
31+
uint8_t prk[SHA256_DIGEST_LENGTH];
32+
uint8_t t[SHA256_DIGEST_LENGTH];
33+
HMAC_SHA256_CTX ctx;
34+
unsigned char c;
35+
36+
assert(okm_size < 255 * sizeof(t));
37+
38+
/* RFC 5869:
39+
*
40+
* 2.2. Step 1: Extract
41+
*
42+
* HKDF-Extract(salt, IKM) -> PRK
43+
*
44+
* Options:
45+
* Hash a hash function; HashLen denotes the length of the
46+
* hash function output in octets
47+
*
48+
* Inputs:
49+
* salt optional salt value (a non-secret random value);
50+
* if not provided, it is set to a string of HashLen zeros.
51+
* IKM input keying material
52+
*
53+
* Output:
54+
* PRK a pseudorandom key (of HashLen octets)
55+
*
56+
* The output PRK is calculated as follows:
57+
*
58+
* PRK = HMAC-Hash(salt, IKM)
59+
*/
60+
if(s == NULL || ssize == 0) {
61+
uint8_t a[SHA256_DIGEST_LENGTH];
62+
memset(a, 0, SHA256_DIGEST_LENGTH);
63+
hmac_sha256(a, SHA256_DIGEST_LENGTH, k, ksize, prk);
64+
} else {
65+
hmac_sha256(s, ssize, k, ksize, prk);
66+
}
67+
68+
/*
69+
* 2.3. Step 2: Expand
70+
*
71+
* HKDF-Expand(PRK, info, L) -> OKM
72+
*
73+
* Options:
74+
* Hash a hash function; HashLen denotes the length of the
75+
* hash function output in octets
76+
*
77+
* Inputs:
78+
* PRK a pseudorandom key of at least HashLen octets
79+
* (usually, the output from the extract step)
80+
* info optional context and application specific information
81+
* (can be a zero-length string)
82+
* L length of output keying material in octets
83+
* (<= 255*HashLen)
84+
*
85+
* Output:
86+
* OKM output keying material (of L octets)
87+
*
88+
* The output OKM is calculated as follows:
89+
*
90+
* N = ceil(L/HashLen)
91+
* T = T(1) | T(2) | T(3) | ... | T(N)
92+
* OKM = first L octets of T
93+
*
94+
* where:
95+
* T(0) = empty string (zero length)
96+
* T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
97+
* T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
98+
* T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
99+
* ...
100+
*
101+
* (where the constant concatenated to the end of each T(n) is a
102+
* single octet.)
103+
*/
104+
c = 1;
105+
hmac_sha256_Init(&ctx, prk, sizeof(prk));
106+
hmac_sha256_Update(&ctx, info, isize);
107+
hmac_sha256_Update(&ctx, &c, 1);
108+
hmac_sha256_Final(&ctx, t);
109+
110+
while (okm_size > sizeof(t)) {
111+
memcpy(okm, &t, sizeof(t));
112+
okm = okm + sizeof(t);
113+
okm_size -= sizeof(t);
114+
115+
c++;
116+
hmac_sha256_Init(&ctx, prk, sizeof(prk));
117+
hmac_sha256_Update(&ctx, t, sizeof(t));
118+
hmac_sha256_Update(&ctx, info, isize);
119+
hmac_sha256_Update(&ctx, &c, 1);
120+
hmac_sha256_Final(&ctx, t);
121+
}
122+
memcpy(okm, &t, okm_size);
123+
}

src/hkdf.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef CCAN_CRYPTO_HKDF_SHA256_H
2+
#define CCAN_CRYPTO_HKDF_SHA256_H
3+
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
11+
// The above copyright notice and this permission notice shall be included in
12+
// all copies or substantial portions of the Software.
13+
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
// THE SOFTWARE.
21+
22+
#include <stdlib.h>
23+
24+
/**
25+
* hkdf_sha256 - generate a derived key
26+
* @okm: where to output the key
27+
* @okm_size: the number of bytes pointed to by @okm (must be less than 255*32)
28+
* @s: salt
29+
* @ssize: the number of bytes pointed to by @s
30+
* @k: pointer to input key
31+
* @ksize: the number of bytes pointed to by @k
32+
* @info: pointer to info
33+
* @isize: the number of bytes pointed to by @info
34+
*/
35+
void hkdf_sha256(uint8_t *okm, size_t okm_size,
36+
const uint8_t *s, size_t ssize,
37+
const uint8_t *k, size_t ksize,
38+
const uint8_t *info, size_t isize);
39+
#endif /* CCAN_CRYPTO_HKDF_SHA256_H */

src/random.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// random.c
3+
//
4+
// Copyright © 2020 by Blockchain Commons, LLC
5+
// Licensed under the "BSD-2-Clause Plus Patent License"
6+
//
7+
8+
#include <assert.h>
9+
#include <string.h>
10+
11+
#include <bc-crypto-base/bc-crypto-base.h>
12+
13+
#include "random.h"
14+
#include "randombytes.h"
15+
#include "hkdf.h"
16+
17+
void crypto_random(uint8_t* buf, size_t n) {
18+
assert(randombytes(buf, n) == 0);
19+
}
20+
21+
static uint8_t deterministic_seed[SHA256_DIGEST_LENGTH];
22+
static uint64_t deterministic_salt = 0;
23+
24+
void seed_deterministic_string(const char* string) {
25+
uint8_t digest[SHA256_DIGEST_LENGTH];
26+
sha256_Raw((uint8_t*)string, strlen(string), deterministic_seed);
27+
deterministic_salt = 0;
28+
}
29+
30+
void deterministic_random(uint8_t* buf, size_t n) {
31+
deterministic_salt += 1;
32+
hkdf_sha256(buf, n,
33+
(uint8_t*)&deterministic_salt, sizeof(deterministic_salt),
34+
deterministic_seed, SHA256_DIGEST_LENGTH,
35+
NULL, 0);
36+
}

src/random.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// random.h
3+
//
4+
// Copyright © 2020 by Blockchain Commons, LLC
5+
// Licensed under the "BSD-2-Clause Plus Patent License"
6+
//
7+
8+
#ifndef RANDOM_H
9+
#define RANDOM_H
10+
11+
#include <stdint.h>
12+
#include <stdlib.h>
13+
14+
// Generates a buffer of random bytes using the OS's cryptographically strong random number generator.
15+
void crypto_random(uint8_t* buf, size_t n);
16+
17+
// Seeds the cryptographically strong deterministic random number generator with the SHA256 digest of the string.
18+
void seed_deterministic_string(const char* string);
19+
20+
// Generates a buffer of random bytes using the cryptographically strong deterministic random number generator.
21+
void deterministic_random(uint8_t* buf, size_t n);
22+
23+
#endif /* RANDOM_H */

0 commit comments

Comments
 (0)