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: { 269: DBG1(DBG_LIB, "%N not sufficient for security strength of % bits", 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: }