Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_crypto/src/c/rng.c

5.3 KiB, 1 run

created by r1870400018:220, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//
2// rng.c
3//
4// Created by Bassham, Lawrence E (Fed) on 8/29/17.
5// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6//
7
8#include <string.h>
9#include "rng.h"
10#include <openssl/conf.h>
11#include <openssl/evp.h>
12#include <openssl/err.h>
13
14AES256_CTR_DRBG_struct DRBG_ctx;
15
16void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer);
17
18/*
19 seedexpander_init()
20 ctx - stores the current state of an instance of the seed expander
21 seed - a 32 byte random value
22 diversifier - an 8 byte diversifier
23 maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
24 */
25int
26seedexpander_init(AES_XOF_struct *ctx,
27 unsigned char *seed,
28 unsigned char *diversifier,
29 unsigned long maxlen)
30{
31 if ( maxlen >= 0x100000000 )
32 return RNG_BAD_MAXLEN;
33
34 ctx->length_remaining = maxlen;
35
36 memcpy(ctx->key, seed, 32);
37
38 memcpy(ctx->ctr, diversifier, 8);
39 ctx->ctr[11] = maxlen % 256;
40 maxlen >>= 8;
41 ctx->ctr[10] = maxlen % 256;
42 maxlen >>= 8;
43 ctx->ctr[9] = maxlen % 256;
44 maxlen >>= 8;
45 ctx->ctr[8] = maxlen % 256;
46 memset(ctx->ctr+12, 0x00, 4);
47
48 ctx->buffer_pos = 16;
49 memset(ctx->buffer, 0x00, 16);
50
51 return RNG_SUCCESS;
52}
53
54/*
55 seedexpander()
56 ctx - stores the current state of an instance of the seed expander
57 x - returns the XOF data
58 xlen - number of bytes to return
59 */
60int
61seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen)
62{
63 unsigned long offset;
64
65 if ( x == NULL )
66 return RNG_BAD_OUTBUF;
67 if ( xlen >= ctx->length_remaining )
68 return RNG_BAD_REQ_LEN;
69
70 ctx->length_remaining -= xlen;
71
72 offset = 0;
73 while ( xlen > 0 ) {
74 if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need
75 memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen);
76 ctx->buffer_pos += xlen;
77
78 return RNG_SUCCESS;
79 }
80
81 // take what's in the buffer
82 memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos);
83 xlen -= 16-ctx->buffer_pos;
84 offset += 16-ctx->buffer_pos;
85
86 AES256_ECB(ctx->key, ctx->ctr, ctx->buffer);
87 ctx->buffer_pos = 0;
88
89 //increment the counter
90 for (int i=15; i>=12; i--) {
91 if ( ctx->ctr[i] == 0xff )
92 ctx->ctr[i] = 0x00;
93 else {
94 ctx->ctr[i]++;
95 break;
96 }
97 }
98
99 }
100
101 return RNG_SUCCESS;
102}
103
104
105void handleErrors(void)
106{
107 ERR_print_errors_fp(stderr);
108 abort();
109}
110
111// Use whatever AES implementation you have. This uses AES from openSSL library
112// key - 256-bit AES key
113// ctr - a 128-bit plaintext value
114// buffer - a 128-bit ciphertext value
115void
116AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer)
117{
118 EVP_CIPHER_CTX *ctx;
119
120 int len;
121
122 int ciphertext_len;
123
124 /* Create and initialise the context */
125 if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
126
127 if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
128 handleErrors();
129
130 if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16))
131 handleErrors();
132 ciphertext_len = len;
133
134 /* Clean up */
135 EVP_CIPHER_CTX_free(ctx);
136}
137
138void
139randombytes_init(unsigned char *entropy_input,
140 unsigned char *personalization_string,
141 int security_strength)
142{
143 unsigned char seed_material[48];
144
145 memcpy(seed_material, entropy_input, 48);
146 if (personalization_string)
147 for (int i=0; i<48; i++)
148 seed_material[i] ^= personalization_string[i];
149 memset(DRBG_ctx.Key, 0x00, 32);
150 memset(DRBG_ctx.V, 0x00, 16);
151 AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
152 DRBG_ctx.reseed_counter = 1;
153}
154
155int
156randombytes(unsigned char *x, unsigned long long xlen)
157{
158 unsigned char block[16];
159 int i = 0;
160
161 while ( xlen > 0 ) {
162 //increment V
163 for (int j=15; j>=0; j--) {
164 if ( DRBG_ctx.V[j] == 0xff )
165 DRBG_ctx.V[j] = 0x00;
166 else {
167 DRBG_ctx.V[j]++;
168 break;
169 }
170 }
171 AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
172 if ( xlen > 15 ) {
173 memcpy(x+i, block, 16);
174 i += 16;
175 xlen -= 16;
176 }
177 else {
178 memcpy(x+i, block, xlen);
179 xlen = 0;
180 }
181 }
182 AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
183 DRBG_ctx.reseed_counter++;
184
185 return RNG_SUCCESS;
186}
187
188void
189AES256_CTR_DRBG_Update(unsigned char *provided_data,
190 unsigned char *Key,
191 unsigned char *V)
192{
193 unsigned char temp[48];
194
195 for (int i=0; i<3; i++) {
196 //increment V
197 for (int j=15; j>=0; j--) {
198 if ( V[j] == 0xff )
199 V[j] = 0x00;
200 else {
201 V[j]++;
202 break;
203 }
204 }
205
206 AES256_ECB(Key, V, temp+16*i);
207 }
208 if ( provided_data != NULL )
209 for (int i=0; i<48; i++)
210 temp[i] ^= provided_data[i];
211 memcpy(Key, temp, 32);
212 memcpy(V, temp+32, 16);
213}
214
215
216
217
218
219
220
221
222