Extended PRF+ by a non-counting variant as used by IKEv1

This commit is contained in:
Martin Willi
2012-03-20 17:30:48 +01:00
parent f5c0096086
commit d4f6686c69
3 changed files with 50 additions and 65 deletions
+3 -3
View File
@@ -316,7 +316,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
this->prf->set_key(this->prf, fixed_nonce); this->prf->set_key(this->prf, fixed_nonce);
this->prf->allocate_bytes(this->prf, secret, &skeyseed); this->prf->allocate_bytes(this->prf, secret, &skeyseed);
this->prf->set_key(this->prf, skeyseed); this->prf->set_key(this->prf, skeyseed);
prf_plus = prf_plus_create(this->prf, prf_plus_seed); prf_plus = prf_plus_create(this->prf, TRUE, prf_plus_seed);
} }
else else
{ {
@@ -336,7 +336,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
rekey_prf->set_key(rekey_prf, rekey_skd); rekey_prf->set_key(rekey_prf, rekey_skd);
rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed); rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed);
rekey_prf->set_key(rekey_prf, skeyseed); rekey_prf->set_key(rekey_prf, skeyseed);
prf_plus = prf_plus_create(rekey_prf, prf_plus_seed); prf_plus = prf_plus_create(rekey_prf, TRUE, prf_plus_seed);
} }
DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
@@ -503,7 +503,7 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
} }
this->prf->set_key(this->prf, this->skd); this->prf->set_key(this->prf, this->skd);
prf_plus = prf_plus_create(this->prf, seed); prf_plus = prf_plus_create(this->prf, TRUE, seed);
prf_plus->allocate_bytes(prf_plus, enc_size, encr_i); prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
prf_plus->allocate_bytes(prf_plus, int_size, integ_i); prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
+42 -45
View File
@@ -25,6 +25,7 @@ typedef struct private_prf_plus_t private_prf_plus_t;
* *
*/ */
struct private_prf_plus_t { struct private_prf_plus_t {
/** /**
* Public interface of prf_plus_t. * Public interface of prf_plus_t.
*/ */
@@ -48,42 +49,43 @@ struct private_prf_plus_t {
/** /**
* Already given out bytes in current buffer. * Already given out bytes in current buffer.
*/ */
size_t given_out; size_t used;
/** /**
* Octet which will be appended to the seed. * Octet which will be appended to the seed, 0 if not used
*/ */
u_int8_t appending_octet; u_int8_t counter;
}; };
METHOD(prf_plus_t, get_bytes, void, METHOD(prf_plus_t, get_bytes, void,
private_prf_plus_t *this, size_t length, u_int8_t *buffer) private_prf_plus_t *this, size_t length, u_int8_t *buffer)
{ {
chunk_t appending_chunk; size_t round, written = 0;
size_t bytes_in_round;
size_t total_bytes_written = 0;
appending_chunk.ptr = &(this->appending_octet);
appending_chunk.len = 1;
while (length > 0) while (length > 0)
{ /* still more to do... */ {
if (this->buffer.len == this->given_out) if (this->buffer.len == this->used)
{ /* no bytes left in buffer, get next*/ { /* buffer used, get next round */
this->prf->get_bytes(this->prf, this->buffer, NULL); this->prf->get_bytes(this->prf, this->buffer, NULL);
this->prf->get_bytes(this->prf, this->seed, NULL); if (this->counter)
this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); {
this->given_out = 0; this->prf->get_bytes(this->prf, this->seed, NULL);
this->appending_octet++; this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
this->buffer.ptr);
}
else
{
this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
}
this->counter++;
this->used = 0;
} }
/* how many bytes can we write in this round ? */ round = min(length, this->buffer.len - this->used);
bytes_in_round = min(length, this->buffer.len - this->given_out); memcpy(buffer + written, this->buffer.ptr + this->used, round);
/* copy bytes from buffer with offset */
memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round);
length -= bytes_in_round; length -= round;
this->given_out += bytes_in_round; this->used += round;
total_bytes_written += bytes_in_round; written += round;
} }
} }
@@ -92,8 +94,7 @@ METHOD(prf_plus_t, allocate_bytes, void,
{ {
if (length) if (length)
{ {
chunk->ptr = malloc(length); *chunk = chunk_alloc(length);
chunk->len = length;
get_bytes(this, length, chunk->ptr); get_bytes(this, length, chunk->ptr);
} }
else else
@@ -113,10 +114,9 @@ METHOD(prf_plus_t, destroy, void,
/* /*
* Description in header. * 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; private_prf_plus_t *this;
chunk_t appending_chunk;
INIT(this, INIT(this,
.public = { .public = {
@@ -125,25 +125,22 @@ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
.destroy = _destroy, .destroy = _destroy,
}, },
.prf = prf, .prf = prf,
.buffer = chunk_alloc(prf->get_block_size(prf)),
.seed = chunk_clone(seed),
); );
/* allocate buffer for prf output */ if (counter)
this->buffer.len = prf->get_block_size(prf); {
this->buffer.ptr = malloc(this->buffer.len); this->counter = 0x01;
this->prf->get_bytes(this->prf, this->seed, NULL);
this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
this->buffer.ptr);
this->counter++;
}
else
{
this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
}
this->appending_octet = 0x01; return &this->public;
/* 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++;
return &(this->public);
} }
+5 -17
View File
@@ -27,19 +27,13 @@ typedef struct prf_plus_t prf_plus_t;
#include <crypto/prfs/prf.h> #include <crypto/prfs/prf.h>
/** /**
* Implementation of the prf+ function described in IKEv2 RFC. * Implementation of the prf+ function used in IKEv1/IKEv2 keymat extension.
*
* This class implements the prf+ algorithm. Internally it uses a pseudo random
* function, which implements the prf_t interface.
* See IKEv2 RFC 2.13.
*/ */
struct prf_plus_t { struct prf_plus_t {
/** /**
* Get pseudo random bytes. * Get pseudo random bytes.
* *
* Get the next few bytes of the prf+ output. Space
* must be allocated by the caller.
*
* @param length number of bytes to get * @param length number of bytes to get
* @param buffer pointer where the generated bytes will be written * @param buffer pointer where the generated bytes will be written
*/ */
@@ -48,9 +42,6 @@ struct prf_plus_t {
/** /**
* Allocate pseudo random bytes. * Allocate pseudo random bytes.
* *
* Get the next few bytes of the prf+ output. This function
* will allocate the required space.
*
* @param length number of bytes to get * @param length number of bytes to get
* @param chunk chunk which will hold generated bytes * @param chunk chunk which will hold generated bytes
*/ */
@@ -65,14 +56,11 @@ struct prf_plus_t {
/** /**
* Creates a new prf_plus_t object. * Creates a new prf_plus_t object.
* *
* Seed will be cloned. prf will * @param prf prf object to use, must be destroyd after prf+.
* not be cloned, must be destroyed outside after * @param counter use an appending counter byte (for IKEv2 variant)
* prf_plus_t usage.
*
* @param prf prf object to use
* @param seed input seed for prf * @param seed input seed for prf
* @return prf_plus_t object * @return prf_plus_t object
*/ */
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);
#endif /** PRF_PLUS_H_ @}*/ #endif /** PRF_PLUS_H_ @}*/