Return to drbg_hmac.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / drbg |
1.1 misho 1: /*
2: * Copyright (C) 2016-2019 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "drbg_hmac.h"
17:
18: #define MAX_DRBG_REQUESTS 0xfffffffe /* 2^32 - 2 */
19: #define MAX_DRBG_BYTES 0x00010000 /* 2^19 bits = 2^16 bytes */
20:
21: typedef struct private_drbg_hmac_t private_drbg_hmac_t;
22:
23: /**
24: * Private data of an drbg_prf_t object.
25: */
26: struct private_drbg_hmac_t {
27:
28: /**
29: * Public drbg_prf_t interface.
30: */
31: drbg_hmac_t public;
32:
33: /**
34: * DRBG type.
35: */
36: drbg_type_t type;
37:
38: /**
39: * Security strength in bits.
40: */
41: uint32_t strength;
42:
43: /**
44: * Number of requests for pseudorandom bits
45: */
46: size_t reseed_counter;
47:
48: /**
49: * Maximum number of requests for pseudorandom bits
50: */
51: size_t max_requests;
52:
53: /**
54: * True entropy source
55: */
56: rng_t *entropy;
57:
58: /**
59: * HMAC PRF used by the DRBG
60: */
61: prf_t *prf;
62:
63: /**
64: * Internal state of HMAC: key
65: */
66: chunk_t key;
67:
68: /**
69: * Internal state of HMAC: value
70: */
71: chunk_t value;
72:
73: /**
74: * reference count
75: */
76: refcount_t ref;
77:
78: };
79:
80: METHOD(drbg_t, get_type, drbg_type_t,
81: private_drbg_hmac_t *this)
82: {
83: return this->type;
84: }
85:
86: METHOD(drbg_t, get_strength, uint32_t,
87: private_drbg_hmac_t *this)
88: {
89: return this->strength;
90: }
91:
92: /**
93: * Update the internal state of the HMAC_DRBG
94: */
95: static bool update(private_drbg_hmac_t *this, chunk_t data)
96: {
97: chunk_t ch_00 = chunk_from_chars(0x00);
98: chunk_t ch_01 = chunk_from_chars(0x01);
99:
100: if (!this->prf->set_key(this->prf, this->key) ||
101: !this->prf->get_bytes(this->prf, this->value, NULL) ||
102: !this->prf->get_bytes(this->prf, ch_00, NULL) ||
103: !this->prf->get_bytes(this->prf, data, this->key.ptr) ||
104: !this->prf->set_key(this->prf, this->key) ||
105: !this->prf->get_bytes(this->prf, this->value, this->value.ptr))
106: {
107: return FALSE;
108: }
109:
110: if (data.len > 0)
111: {
112: if (!this->prf->set_key(this->prf, this->key) ||
113: !this->prf->get_bytes(this->prf, this->value, NULL) ||
114: !this->prf->get_bytes(this->prf, ch_01, NULL) ||
115: !this->prf->get_bytes(this->prf, data, this->key.ptr) ||
116: !this->prf->set_key(this->prf, this->key) ||
117: !this->prf->get_bytes(this->prf, this->value, this->value.ptr))
118: {
119: return FALSE;
120: }
121: }
122: DBG4(DBG_LIB, "HMAC_DRBG K: %B", &this->key);
123: DBG4(DBG_LIB, "HMAC_DRBG V: %B", &this->value);
124:
125: return TRUE;
126: }
127:
128: METHOD(drbg_t, reseed, bool,
129: private_drbg_hmac_t *this)
130: {
131: chunk_t seed;
132: bool success;
133:
134: seed = chunk_alloc(this->strength / BITS_PER_BYTE);
135: DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len);
136:
137: if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr))
138: {
139: chunk_free(&seed);
140: return FALSE;
141: }
142: DBG4(DBG_LIB, "reseed: %B", &seed);
143:
144: success = update(this, seed);
145: chunk_clear(&seed);
146:
147: if (!success)
148: {
149: return FALSE;
150: }
151: this->reseed_counter = 1;
152:
153: return TRUE;
154: }
155:
156: METHOD(drbg_t, generate, bool,
157: private_drbg_hmac_t *this, uint32_t len, uint8_t *out)
158: {
159: size_t delta;
160: chunk_t output;
161:
162: if (len > MAX_DRBG_BYTES)
163: {
164: DBG1(DBG_LIB, "DRBG cannot generate more than %d bytes", MAX_DRBG_BYTES);
165: return FALSE;
166: }
167:
168: if (this->reseed_counter > this->max_requests)
169: {
170: if (!reseed(this))
171: {
172: return FALSE;
173: }
174: }
175:
176: DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len);
177: if (!out || len == 0)
178: {
179: return FALSE;
180: }
181: output = chunk_create(out, len);
182:
183: while (len)
184: {
185: if (!this->prf->get_bytes(this->prf, this->value, this->value.ptr))
186: {
187: return FALSE;
188: }
189: delta = min(len, this->value.len);
190: memcpy(out, this->value.ptr, delta);
191: len -= delta;
192: out += delta;
193: }
194: DBG4(DBG_LIB, "HMAC_DRBG Out: %B", &output);
195:
196: if (!update(this, chunk_empty))
197: {
198: return FALSE;
199: }
200: this->reseed_counter++;
201:
202: return TRUE;
203: }
204:
205: METHOD(drbg_t, get_ref, drbg_t*,
206: private_drbg_hmac_t *this)
207: {
208: ref_get(&this->ref);
209: return &this->public.interface;
210: }
211:
212: METHOD(drbg_t, destroy, void,
213: private_drbg_hmac_t *this)
214: {
215: if (ref_put(&this->ref))
216: {
217: DESTROY_IF(this->entropy);
218: this->prf->destroy(this->prf);
219: chunk_clear(&this->key);
220: chunk_clear(&this->value);
221: free(this);
222: }
223: }
224:
225: /**
226: * See header
227: */
228: drbg_hmac_t *drbg_hmac_create(drbg_type_t type, uint32_t strength,
229: rng_t *entropy, chunk_t personalization_str)
230: {
231: private_drbg_hmac_t *this;
232: pseudo_random_function_t prf_type = PRF_UNDEFINED;
233: size_t out_len, entropy_len;
234: uint32_t max_requests;
235: chunk_t seed;
236: prf_t * prf;
237: bool success;
238:
239: switch (type)
240: {
241: case DRBG_HMAC_SHA1:
242: prf_type = PRF_HMAC_SHA1;
243: break;
244: case DRBG_HMAC_SHA256:
245: prf_type = PRF_HMAC_SHA2_256;
246: break;
247: case DRBG_HMAC_SHA384:
248: prf_type = PRF_HMAC_SHA2_384;
249: break;
250: case DRBG_HMAC_SHA512:
251: prf_type = PRF_HMAC_SHA2_512;
252: break;
253: default:
254: DBG1(DBG_LIB, "%N not supported", drbg_type_names, type);
255: return NULL;
256: }
257:
258: prf = lib->crypto->create_prf(lib->crypto, prf_type);
259: if (!prf)
260: {
261: DBG1(DBG_LIB, "creation of %N for DRBG failed",
262: pseudo_random_function_names, prf_type);
263: return NULL;
264: }
265: out_len = prf->get_key_size(prf);
266:
267: if (strength > out_len * BITS_PER_BYTE)
268: {
1.1.1.2 ! misho 269: DBG1(DBG_LIB, "%N not sufficient for security strength of %u bits",
1.1 misho 270: pseudo_random_function_names, prf_type, strength);
271: prf->destroy(prf);
272: return NULL;
273: }
274:
275: max_requests = lib->settings->get_int(lib->settings,
276: "%s.plugins.drbg.max_drbg_requests",
277: MAX_DRBG_REQUESTS, lib->ns);
278:
279: INIT(this,
280: .public = {
281: .interface = {
282: .get_type = _get_type,
283: .get_strength = _get_strength,
284: .reseed = _reseed,
285: .generate = _generate,
286: .get_ref = _get_ref,
287: .destroy = _destroy,
288: },
289: },
290: .type = type,
291: .strength = strength,
292: .prf = prf,
293: .key = chunk_alloc(out_len),
294: .value = chunk_alloc(out_len),
295: .max_requests = max_requests,
296: .reseed_counter = 1,
297: .ref = 1,
298: );
299:
300: memset(this->key.ptr, 0x00, out_len);
301: memset(this->value.ptr, 0x01, out_len);
302:
303: entropy_len = (strength + strength/2) / BITS_PER_BYTE;
304: seed = chunk_alloc(entropy_len + personalization_str.len);
305: DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", entropy_len);
306:
307: if (!entropy->get_bytes(entropy, entropy_len, seed.ptr))
308: {
309: chunk_free(&seed);
310: destroy(this);
311: return NULL;
312: }
313: memcpy(seed.ptr + entropy_len,
314: personalization_str.ptr, personalization_str.len);
315: DBG4(DBG_LIB, "seed: %B", &seed);
316:
317: success = update(this, seed);
318: chunk_clear(&seed);
319:
320: if (!success)
321: {
322: destroy(this);
323: return NULL;
324: }
325:
326: /* ownership of entropy source is transferred to DRBG */
327: this->entropy = entropy;
328:
329: return &this->public;
330: }