* Expand SKEYID_e according to Appendix B in RFC 2409.
* TODO-IKEv1: verify keys (e.g. for weak keys, see Appendix B)
*/
-static chunk_t expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf)
+static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
+ chunk_t *ka)
{
size_t block_size;
- chunk_t seed, ka;
+ chunk_t seed;
int i;
if (skeyid_e.len >= key_size)
{ /* no expansion required, reduce to key_size */
skeyid_e.len = key_size;
- return skeyid_e;
+ *ka = skeyid_e;
+ return TRUE;
}
block_size = prf->get_block_size(prf);
- ka = chunk_alloc((key_size / block_size + 1) * block_size);
- ka.len = key_size;
+ *ka = chunk_alloc((key_size / block_size + 1) * block_size);
+ ka->len = key_size;
/* Ka = K1 | K2 | ..., K1 = prf(SKEYID_e, 0), K2 = prf(SKEYID_e, K1) ... */
prf->set_key(prf, skeyid_e);
seed = octet_0;
for (i = 0; i < key_size; i += block_size)
{
- prf->get_bytes(prf, seed, ka.ptr + i);
- seed = chunk_create(ka.ptr + i, block_size);
+ if (!prf->get_bytes(prf, seed, ka->ptr + i))
+ {
+ chunk_clear(ka);
+ chunk_clear(&skeyid_e);
+ return FALSE;
+ }
+ seed = chunk_create(ka->ptr + i, block_size);
}
chunk_clear(&skeyid_e);
- return ka;
+ return TRUE;
}
/**
return NULL;
}
key_size = crypter->get_key_size(crypter);
- ka = expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf);
+ if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, &ka))
+ {
+ return NULL;
+ }
DBG4(DBG_IKE, "encryption key Ka %B", &ka);
crypter->set_key(crypter, ka);
chunk_clear(&ka);
str = chunk_alloca(this->prf->get_block_size(this->prf) * 3);
for (i = 0; i < 3; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 3 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 3 * i))
+ {
+ chunk_clear(mk);
+ return FALSE;
+ }
}
k_encr = chunk_create(str.ptr, KENCR_LEN);
str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
for (i = 0; i < 2; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 2 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 2 * i))
+ {
+ return FALSE;
+ }
}
k_encr = chunk_create(str.ptr, KENCR_LEN);
k_auth = chunk_create(str.ptr + KENCR_LEN, KAUTH_LEN);
str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
for (i = 0; i < 2; i++)
{
- this->prf->get_bytes(this->prf, chunk_empty, str.ptr + str.len / 2 * i);
+ if (!this->prf->get_bytes(this->prf, chunk_empty,
+ str.ptr + str.len / 2 * i))
+ {
+ return FALSE;
+ }
}
*msk = chunk_create(str.ptr, MSK_LEN);
DBG3(DBG_LIB, "MSK %B", msk);
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- prf->get_bytes(prf, buf, bytes);
- runs++;
+ if (prf->get_bytes(prf, buf, bytes))
+ {
+ runs++;
+ }
}
free(buf.ptr);
prf->destroy(prf);
{
prf->set_key(prf, key);
}
- prf->get_bytes(prf, seed, out.ptr);
+ if (!prf->get_bytes(prf, seed, out.ptr))
+ {
+ failed = TRUE;
+ }
if (!memeq(vector->out, out.ptr, out.len))
{
failed = TRUE;
prf->set_key(prf, key);
}
prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL);
- prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL);
- prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr);
+ if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL) ||
+ !prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
+ {
+ failed = TRUE;
+ }
if (!memeq(vector->out, out.ptr, out.len))
{
failed = TRUE;
{
if (this->buffer.len == this->used)
{ /* buffer used, get next round */
- this->prf->get_bytes(this->prf, this->buffer, NULL);
+ if (!this->prf->get_bytes(this->prf, this->buffer, NULL))
+ {
+ return FALSE;
+ }
if (this->counter)
{
- this->prf->get_bytes(this->prf, this->seed, NULL);
- this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
- this->buffer.ptr);
+ 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
{
- this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
+ if (!this->prf->get_bytes(this->prf, this->seed,
+ this->buffer.ptr))
+ {
+ return FALSE;
+ }
}
this->used = 0;
}
if (counter)
{
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);
+ 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
{
- this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
+ if (!this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr))
+ {
+ destroy(this);
+ return NULL;
+ }
}
return &this->public;
mac_t *mac;
};
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_prf_t *this, chunk_t seed, u_int8_t *buffer)
{
this->mac->get_mac(this->mac, seed, buffer);
+ return TRUE;
}
METHOD(prf_t, allocate_bytes, void,
* Generic interface for pseudo-random-functions.
*/
struct prf_t {
+
/**
* Generates pseudo random bytes and writes them in the buffer.
*
* @param seed a chunk containing the seed for the next bytes
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
+ __attribute__((warn_unused_result))
+ bool (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
/**
* Generates pseudo random bytes and allocate space for them.
return 0;
}
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_af_alg_prf_t *this, chunk_t seed, u_int8_t *buffer)
{
this->ops->hash(this->ops, seed, buffer, this->block_size);
+ return TRUE;
}
METHOD(prf_t, allocate_bytes, void,
/**
* G function, either SHA1 or DES
*/
- void (*g)(private_fips_prf_t *this, chunk_t c, u_int8_t res[]);
+ bool (*g)(private_fips_prf_t *this, chunk_t c, u_int8_t res[]);
};
/**
* 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
* 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
*/
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_fips_prf_t *this, chunk_t seed, u_int8_t w[])
{
int i;
}
/* 3.3 done already, mod q not used */
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
/**
* Implementation of the G() function based on SHA1
*/
-void g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[])
+static bool g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[])
{
u_int8_t buf[64];
/* use the keyed hasher, but use an empty key to use SHA1 IV */
this->keyed_prf->set_key(this->keyed_prf, chunk_empty);
- this->keyed_prf->get_bytes(this->keyed_prf, c, res);
+ if (!this->keyed_prf->get_bytes(this->keyed_prf, c, res))
+ {
+ return FALSE;
+ }
+ return TRUE;
}
METHOD(prf_t, destroy, void,
SHA_CTX ctx;
};
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
{
SHA1_Update(&this->ctx, seed.ptr, seed.len);
hash[3] = htonl(this->ctx.h3);
hash[4] = htonl(this->ctx.h4);
}
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
/**
* Prototype for key derivation functions.
*/
-typedef void (*kdf_t)(void *generator, chunk_t password, chunk_t salt,
+typedef bool (*kdf_t)(void *generator, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key);
/**
{
chunk_t decrypted;
- kdf(generator, shared->get_key(shared), salt, iterations, keymat);
+ if (!kdf(generator, shared->get_key(shared), salt, iterations, keymat))
+ {
+ continue;
+ }
crypter->set_key(crypter, key);
crypter->decrypt(crypter, blob, iv, &decrypted);
/**
* Function F of PBKDF2
*/
-static void pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
+static bool pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
u_int64_t iterations)
{
chunk_t u;
u_int64_t i;
u = chunk_alloca(prf->get_block_size(prf));
- prf->get_bytes(prf, seed, u.ptr);
+ if (!prf->get_bytes(prf, seed, u.ptr))
+ {
+ return FALSE;
+ }
memcpy(block.ptr, u.ptr, block.len);
for (i = 1; i < iterations; i++)
{
- prf->get_bytes(prf, u, u.ptr);
+ if (!prf->get_bytes(prf, u, u.ptr))
+ {
+ return FALSE;
+ }
memxor(block.ptr, u.ptr, block.len);
}
+ return TRUE;
}
/**
* PBKDF2 key derivation function
*/
-static void pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
+static bool pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key)
{
chunk_t keymat, block, seed;
{
*ni = htonl(i + 1);
block.ptr = keymat.ptr + (i * block.len);
- pbkdf2_f(block, prf, seed, iterations);
+ if (!pbkdf2_f(block, prf, seed, iterations))
+ {
+ return FALSE;
+ }
}
memcpy(key.ptr, keymat.ptr, key.len);
+
+ return TRUE;
}
/**
/**
* PBKDF1 key derivation function
*/
-static void pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt,
+static bool pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt,
u_int64_t iterations, chunk_t key)
{
chunk_t hash;
}
memcpy(key.ptr, hash.ptr, key.len);
+
+ return TRUE;
}
/**
*/
extern void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len);
-METHOD(prf_t, get_bytes, void,
+METHOD(prf_t, get_bytes, bool,
private_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
{
u_int32_t *hash = (u_int32_t*)bytes;
hash[2] = htonl(this->hasher->state[2]);
hash[3] = htonl(this->hasher->state[3]);
hash[4] = htonl(this->hasher->state[4]);
+
+ return TRUE;
}
METHOD(prf_t, get_block_size, size_t,
--- /dev/null
+timestamp for src/libstrongswan/config.h
while (TRUE)
{
- /* A(i) = HMAC_hash(secret, A(i-1)) */
- prf->get_bytes(prf, a, abuf);
a = chunk_from_thing(abuf);
- /* HMAC_hash(secret, A(i) + seed) */
- prf->get_bytes(prf, a, NULL);
- prf->get_bytes(prf, seed, buf);
+ /* A(i) = HMAC_hash(secret, A(i-1))
+ * HMAC_hash(secret, A(i) + seed) */
+ if (!prf->get_bytes(prf, a, abuf) ||
+ !prf->get_bytes(prf, a, NULL) ||
+ !prf->get_bytes(prf, seed, buf))
+ {
+ return FALSE;
+ }
if (bytes <= block_size)
{