Return to mgf1_xof.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / mgf1 |
1.1 misho 1: /* 2: * Copyright (C) 2013-2016 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 "mgf1_xof.h" 17: 18: #include "crypto/hashers/hasher.h" 19: #include "utils/debug.h" 20: 21: typedef struct private_mgf1_xof_t private_mgf1_xof_t; 22: 23: /** 24: * Private data of an mgf1_xof_t object. 25: */ 26: struct private_mgf1_xof_t { 27: 28: /** 29: * Public mgf1_xof_t interface. 30: */ 31: mgf1_xof_t public; 32: 33: /** 34: * XOF type of the MGF1 Mask Generation Function 35: */ 36: ext_out_function_t type; 37: 38: /** 39: * Hasher the MGF1 Mask Generation Function is based on 40: */ 41: hasher_t *hasher; 42: 43: /** 44: * Is the seed hashed before using it as a seed for MGF1 ? 45: */ 46: bool hash_seed; 47: 48: /** 49: * Counter 50: */ 51: uint32_t counter; 52: 53: /** 54: * Set if counter has reached 2^32 55: */ 56: bool overflow; 57: 58: /** 59: * Current state to be hashed 60: */ 61: chunk_t state; 62: 63: /** 64: * Position of the 4 octet counter string 65: */ 66: uint8_t *ctr_str; 67: 68: /** 69: * Latest hash block 70: */ 71: uint8_t buf[HASH_SIZE_SHA512]; 72: 73: /** 74: * Index pointing to the current position in the hash block 75: */ 76: size_t buf_index; 77: 78: }; 79: 80: METHOD(xof_t, get_type, ext_out_function_t, 81: private_mgf1_xof_t *this) 82: { 83: return this->type; 84: } 85: 86: static bool get_next_block(private_mgf1_xof_t *this, uint8_t *buffer) 87: { 88: /* detect overflow, set counter string and increment counter */ 89: if (this->overflow) 90: { 91: DBG1(DBG_LIB, "MGF1 overflow occurred"); 92: return FALSE; 93: } 94: htoun32(this->ctr_str, this->counter++); 95: if (this->counter == 0) 96: { 97: this->overflow = TRUE; 98: } 99: 100: /* get the next block from the hash function */ 101: if (!this->hasher->get_hash(this->hasher, this->state, buffer)) 102: { 103: return FALSE; 104: } 105: 106: return TRUE; 107: } 108: 109: METHOD(xof_t, get_bytes, bool, 110: private_mgf1_xof_t *this, size_t out_len, uint8_t *buffer) 111: { 112: size_t index = 0, blocks, len, hash_size; 113: 114: hash_size = this->hasher->get_hash_size(this->hasher); 115: 116: /* empty the current hash block buffer first */ 117: len = min(out_len, hash_size - this->buf_index); 118: if (len) 119: { 120: memcpy(buffer, this->buf + this->buf_index, len); 121: index += len; 122: this->buf_index += len; 123: } 124: 125: /* copy whole hash blocks directly to output buffer */ 126: blocks = (out_len - index) / hash_size; 127: while (blocks--) 128: { 129: if (!get_next_block(this, buffer + index)) 130: { 131: return FALSE; 132: } 133: index += hash_size; 134: } 135: 136: /* get another hash block if some more output bytes are needed */ 137: len = out_len - index; 138: if (len) 139: { 140: if (!get_next_block(this, this->buf)) 141: { 142: return FALSE; 143: } 144: memcpy(buffer + index, this->buf, len); 145: this->buf_index = len; 146: } 147: 148: return TRUE; 149: } 150: 151: METHOD(xof_t, allocate_bytes, bool, 152: private_mgf1_xof_t *this, size_t out_len, chunk_t *chunk) 153: { 154: *chunk = chunk_alloc(out_len); 155: 156: if (!get_bytes(this, out_len, chunk->ptr)) 157: { 158: chunk_free(chunk); 159: return FALSE; 160: } 161: 162: return TRUE; 163: } 164: 165: METHOD(xof_t, get_block_size, size_t, 166: private_mgf1_xof_t *this) 167: { 168: return this->hasher->get_hash_size(this->hasher); 169: } 170: 171: METHOD(xof_t, get_seed_size, size_t, 172: private_mgf1_xof_t *this) 173: { 174: return this->hasher->get_hash_size(this->hasher); 175: } 176: 177: METHOD(xof_t, set_seed, bool, 178: private_mgf1_xof_t *this, chunk_t seed) 179: { 180: size_t hash_size, state_len; 181: 182: if (seed.len == 0) 183: { 184: DBG1(DBG_LIB, "empty seed for MGF1"); 185: return FALSE; 186: } 187: 188: /* determine state size and allocate space accordingly */ 189: hash_size = this->hasher->get_hash_size(this->hasher); 190: state_len = (this->hash_seed ? hash_size : seed.len) + 4; 191: chunk_clear(&this->state); 192: this->state = chunk_alloc(state_len); 193: 194: /* hash block buffer is empty */ 195: this->buf_index = hash_size; 196: 197: /* reset counter */ 198: this->counter = 0; 199: 200: /* determine position of the 4 octet counter string */ 201: this->ctr_str = this->state.ptr + state_len - 4; 202: 203: if (this->hash_seed) 204: { 205: if (!this->hasher->get_hash(this->hasher, seed, this->state.ptr)) 206: { 207: DBG1(DBG_LIB, "failed to hash seed for MGF1"); 208: return FALSE; 209: } 210: } 211: else 212: { 213: memcpy(this->state.ptr, seed.ptr, seed.len); 214: } 215: 216: return TRUE; 217: } 218: 219: METHOD(xof_t, destroy, void, 220: private_mgf1_xof_t *this) 221: { 222: this->hasher->destroy(this->hasher); 223: chunk_clear(&this->state); 224: free(this); 225: } 226: 227: METHOD(mgf1_t, set_hash_seed, void, 228: private_mgf1_xof_t *this, bool yes) 229: { 230: this->hash_seed = yes; 231: } 232: 233: /* 234: * Described in header. 235: */ 236: mgf1_xof_t *mgf1_xof_create(ext_out_function_t algorithm) 237: { 238: private_mgf1_xof_t *this; 239: hash_algorithm_t hash_alg; 240: hasher_t *hasher; 241: 242: switch (algorithm) 243: { 244: case XOF_MGF1_SHA1: 245: hash_alg = HASH_SHA1; 246: break; 247: case XOF_MGF1_SHA224: 248: hash_alg = HASH_SHA224; 249: break; 250: case XOF_MGF1_SHA256: 251: hash_alg = HASH_SHA256; 252: break; 253: case XOF_MGF1_SHA384: 254: hash_alg = HASH_SHA384; 255: break; 256: case XOF_MGF1_SHA512: 257: hash_alg = HASH_SHA512; 258: break; 259: default: 260: return NULL; 261: } 262: 263: hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); 264: if (!hasher) 265: { 266: DBG1(DBG_LIB, "failed to create %N hasher for MGF1", 267: hash_algorithm_names, hash_alg); 268: return NULL; 269: } 270: 271: INIT(this, 272: .public = { 273: .mgf1_interface = { 274: .xof_interface = { 275: .get_type = _get_type, 276: .get_bytes = _get_bytes, 277: .allocate_bytes = _allocate_bytes, 278: .get_block_size = _get_block_size, 279: .get_seed_size = _get_seed_size, 280: .set_seed = _set_seed, 281: .destroy = _destroy, 282: }, 283: .set_hash_seed = _set_hash_seed, 284: }, 285: }, 286: .type = algorithm, 287: .hasher = hasher, 288: ); 289: 290: return &this->public; 291: }