From bc4748832395a5db4b71cb38d37f75de0d6e9416 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 6 Jul 2012 10:14:29 +0200 Subject: [PATCH] Add a return value to prf_t.get_bytes() --- src/libcharon/sa/ikev1/keymat_v1.c | 28 ++++++++++----- src/libsimaka/simaka_crypto.c | 19 ++++++++-- src/libstrongswan/crypto/crypto_tester.c | 18 +++++++--- src/libstrongswan/crypto/prf_plus.c | 36 ++++++++++++++----- src/libstrongswan/crypto/prfs/mac_prf.c | 3 +- src/libstrongswan/crypto/prfs/prf.h | 5 ++- src/libstrongswan/plugins/af_alg/af_alg_prf.c | 3 +- src/libstrongswan/plugins/fips_prf/fips_prf.c | 14 +++++--- .../plugins/openssl/openssl_sha1_prf.c | 4 ++- .../plugins/pkcs8/pkcs8_builder.c | 33 ++++++++++++----- src/libstrongswan/plugins/sha1/sha1_prf.c | 4 ++- src/libstrongswan/stamp-h1 | 1 + src/libtls/tls_prf.c | 13 ++++--- 13 files changed, 133 insertions(+), 48 deletions(-) create mode 100644 src/libstrongswan/stamp-h1 diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c index 77f0a5651..2b22b14f8 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.c +++ b/src/libcharon/sa/ikev1/keymat_v1.c @@ -222,31 +222,38 @@ METHOD(aead_t, aead_destroy, void, * 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; } /** @@ -276,7 +283,10 @@ static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e) 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); diff --git a/src/libsimaka/simaka_crypto.c b/src/libsimaka/simaka_crypto.c index 0a92cb342..532655e3b 100644 --- a/src/libsimaka/simaka_crypto.c +++ b/src/libsimaka/simaka_crypto.c @@ -133,7 +133,12 @@ METHOD(simaka_crypto_t, derive_keys_full, bool, 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); @@ -166,7 +171,11 @@ METHOD(simaka_crypto_t, derive_keys_reauth, bool, 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); @@ -202,7 +211,11 @@ METHOD(simaka_crypto_t, derive_keys_reauth_msk, bool, 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); diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c index b97855325..469059371 100644 --- a/src/libstrongswan/crypto/crypto_tester.c +++ b/src/libstrongswan/crypto/crypto_tester.c @@ -797,8 +797,10 @@ static u_int bench_prf(private_crypto_tester_t *this, 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); @@ -860,7 +862,10 @@ METHOD(crypto_tester_t, test_prf, bool, { 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; @@ -874,8 +879,11 @@ METHOD(crypto_tester_t, test_prf, bool, 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; diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c index 2e7f87d1f..94be1d5bf 100644 --- a/src/libstrongswan/crypto/prf_plus.c +++ b/src/libstrongswan/crypto/prf_plus.c @@ -66,17 +66,27 @@ METHOD(prf_plus_t, get_bytes, bool, { 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; } @@ -131,14 +141,22 @@ prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed) 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; diff --git a/src/libstrongswan/crypto/prfs/mac_prf.c b/src/libstrongswan/crypto/prfs/mac_prf.c index 6215a4bec..489797fb7 100644 --- a/src/libstrongswan/crypto/prfs/mac_prf.c +++ b/src/libstrongswan/crypto/prfs/mac_prf.c @@ -35,10 +35,11 @@ struct private_prf_t { 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, diff --git a/src/libstrongswan/crypto/prfs/prf.h b/src/libstrongswan/crypto/prfs/prf.h index ad15205d3..8b98b41aa 100644 --- a/src/libstrongswan/crypto/prfs/prf.h +++ b/src/libstrongswan/crypto/prfs/prf.h @@ -71,13 +71,16 @@ extern enum_name_t *pseudo_random_function_names; * 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. diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.c b/src/libstrongswan/plugins/af_alg/af_alg_prf.c index a7912291f..5b12adfc2 100644 --- a/src/libstrongswan/plugins/af_alg/af_alg_prf.c +++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.c @@ -105,10 +105,11 @@ static size_t lookup_alg(pseudo_random_function_t algo, char **name, bool *xcbc) 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, diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c index c0666367a..ae5ed98f2 100644 --- a/src/libstrongswan/plugins/fips_prf/fips_prf.c +++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c @@ -48,7 +48,7 @@ struct private_fips_prf_t { /** * 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[]); }; /** @@ -106,7 +106,7 @@ static void chunk_mod(size_t length, chunk_t chunk, u_int8_t buffer[]) * 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; @@ -138,6 +138,8 @@ METHOD(prf_t, get_bytes, void, } /* 3.3 done already, mod q not used */ + + return TRUE; } METHOD(prf_t, get_block_size, size_t, @@ -168,7 +170,7 @@ METHOD(prf_t, set_key, void, /** * 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]; @@ -188,7 +190,11 @@ void g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[]) /* 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, diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 20f2fa984..03b7fa08b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -35,7 +35,7 @@ struct private_openssl_sha1_prf_t { 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); @@ -50,6 +50,8 @@ METHOD(prf_t, get_bytes, void, hash[3] = htonl(this->ctx.h3); hash[4] = htonl(this->ctx.h4); } + + return TRUE; } METHOD(prf_t, get_block_size, size_t, diff --git a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c index d34a185f0..e9ea92369 100644 --- a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c +++ b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c @@ -126,7 +126,7 @@ static bool verify_padding(chunk_t *blob) /** * 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); /** @@ -164,7 +164,10 @@ static private_key_t *decrypt_private_key(chunk_t blob, { 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); @@ -188,27 +191,34 @@ static private_key_t *decrypt_private_key(chunk_t blob, /** * 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; @@ -228,10 +238,15 @@ static void pbkdf2(prf_t *prf, chunk_t password, chunk_t salt, { *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; } /** @@ -266,7 +281,7 @@ static private_key_t *decrypt_private_key_pbes2(chunk_t blob, /** * 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; @@ -282,6 +297,8 @@ static void pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt, } memcpy(key.ptr, hash.ptr, key.len); + + return TRUE; } /** diff --git a/src/libstrongswan/plugins/sha1/sha1_prf.c b/src/libstrongswan/plugins/sha1/sha1_prf.c index 11f588c9d..f3e44ed65 100644 --- a/src/libstrongswan/plugins/sha1/sha1_prf.c +++ b/src/libstrongswan/plugins/sha1/sha1_prf.c @@ -59,7 +59,7 @@ struct private_sha1_prf_t { */ 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; @@ -71,6 +71,8 @@ METHOD(prf_t, get_bytes, void, 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, diff --git a/src/libstrongswan/stamp-h1 b/src/libstrongswan/stamp-h1 new file mode 100644 index 000000000..f88780108 --- /dev/null +++ b/src/libstrongswan/stamp-h1 @@ -0,0 +1 @@ +timestamp for src/libstrongswan/config.h diff --git a/src/libtls/tls_prf.c b/src/libtls/tls_prf.c index 09f693448..bc0a8c178 100644 --- a/src/libtls/tls_prf.c +++ b/src/libtls/tls_prf.c @@ -56,12 +56,15 @@ static bool p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size, 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) {