diff options
Diffstat (limited to 'src/libstrongswan/crypto/prf_plus.c')
-rw-r--r-- | src/libstrongswan/crypto/prf_plus.c | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c index 8e815e608..94be1d5bf 100644 --- a/src/libstrongswan/crypto/prf_plus.c +++ b/src/libstrongswan/crypto/prf_plus.c @@ -25,6 +25,7 @@ typedef struct private_prf_plus_t private_prf_plus_t; * */ struct private_prf_plus_t { + /** * Public interface of prf_plus_t. */ @@ -41,65 +42,74 @@ struct private_prf_plus_t { chunk_t seed; /** - * Buffer to store current PRF result. + * Octet which will be appended to the seed, 0 if not used */ - chunk_t buffer; + u_int8_t counter; /** * Already given out bytes in current buffer. */ - size_t given_out; + size_t used; /** - * Octet which will be appended to the seed. + * Buffer to store current PRF result. */ - u_int8_t appending_octet; + chunk_t buffer; }; -METHOD(prf_plus_t, get_bytes, void, +METHOD(prf_plus_t, get_bytes, bool, private_prf_plus_t *this, size_t length, u_int8_t *buffer) { - chunk_t appending_chunk; - size_t bytes_in_round; - size_t total_bytes_written = 0; - - appending_chunk.ptr = &(this->appending_octet); - appending_chunk.len = 1; + size_t round, written = 0; while (length > 0) - { /* still more to do... */ - if (this->buffer.len == this->given_out) - { /* no bytes left in buffer, get next*/ - this->prf->get_bytes(this->prf, this->buffer, NULL); - this->prf->get_bytes(this->prf, this->seed, NULL); - this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); - this->given_out = 0; - this->appending_octet++; + { + if (this->buffer.len == this->used) + { /* buffer used, get next round */ + if (!this->prf->get_bytes(this->prf, this->buffer, NULL)) + { + return FALSE; + } + if (this->counter) + { + if (!this->prf->get_bytes(this->prf, this->seed, NULL) || + !this->prf->get_bytes(this->prf, + chunk_from_thing(this->counter), this->buffer.ptr)) + { + return FALSE; + } + this->counter++; + } + else + { + if (!this->prf->get_bytes(this->prf, this->seed, + this->buffer.ptr)) + { + return FALSE; + } + } + this->used = 0; } - /* how many bytes can we write in this round ? */ - bytes_in_round = min(length, this->buffer.len - this->given_out); - /* copy bytes from buffer with offset */ - memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round); - - length -= bytes_in_round; - this->given_out += bytes_in_round; - total_bytes_written += bytes_in_round; + round = min(length, this->buffer.len - this->used); + memcpy(buffer + written, this->buffer.ptr + this->used, round); + + length -= round; + this->used += round; + written += round; } + return TRUE; } -METHOD(prf_plus_t, allocate_bytes, void, +METHOD(prf_plus_t, allocate_bytes, bool, private_prf_plus_t *this, size_t length, chunk_t *chunk) { if (length) { - chunk->ptr = malloc(length); - chunk->len = length; - get_bytes(this, length, chunk->ptr); - } - else - { - *chunk = chunk_empty; + *chunk = chunk_alloc(length); + return get_bytes(this, length, chunk->ptr); } + *chunk = chunk_empty; + return TRUE; } METHOD(prf_plus_t, destroy, void, @@ -113,10 +123,9 @@ METHOD(prf_plus_t, destroy, void, /* * Description in header. */ -prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed) +prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed) { private_prf_plus_t *this; - chunk_t appending_chunk; INIT(this, .public = { @@ -125,25 +134,30 @@ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed) .destroy = _destroy, }, .prf = prf, + .seed = chunk_clone(seed), + .buffer = chunk_alloc(prf->get_block_size(prf)), ); - /* allocate buffer for prf output */ - this->buffer.len = prf->get_block_size(prf); - this->buffer.ptr = malloc(this->buffer.len); - - this->appending_octet = 0x01; - - /* clone seed */ - this->seed.ptr = clalloc(seed.ptr, seed.len); - this->seed.len = seed.len; - - /* do the first run */ - appending_chunk.ptr = &(this->appending_octet); - appending_chunk.len = 1; - this->prf->get_bytes(this->prf, this->seed, NULL); - this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); - this->given_out = 0; - this->appending_octet++; + if (counter) + { + this->counter = 0x01; + if (!this->prf->get_bytes(this->prf, this->seed, NULL) || + !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter), + this->buffer.ptr)) + { + destroy(this); + return NULL; + } + this->counter++; + } + else + { + if (!this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr)) + { + destroy(this); + return NULL; + } + } - return &(this->public); + return &this->public; } |