all hashes, hmacs and prfs use libstrongswan
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 6 May 2009 18:05:06 +0000 (20:05 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 6 May 2009 18:05:22 +0000 (20:05 +0200)
src/pluto/ike_alg.c
src/pluto/ipsec_doi.c
src/pluto/modecfg.c
src/pluto/nat_traversal.c

index 2995e32..740bae8 100644 (file)
 #include <freeswan.h>
 #include <ipsec_policy.h>
 
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/prfs/prf.h>
+
 #include "constants.h"
 #include "defs.h"
 #include "crypto.h"
@@ -452,14 +456,16 @@ ike_hash_test(const struct hash_desc *desc)
                for (i = 0; desc->hash_testvectors[i].msg_digest != NULL; i++)
                {
                        u_char digest[MAX_DIGEST_LEN];
+                       chunk_t msg = { desc->hash_testvectors[i].msg,
+                                                       desc->hash_testvectors[i].msg_size };
+                       hash_algorithm_t hash_alg;
+                       hasher_t *hasher;
                        bool result;
 
-                       union hash_ctx ctx;
-
-                       desc->hash_init(&ctx);
-                       desc->hash_update(&ctx, desc->hash_testvectors[i].msg
-                                                                  ,desc->hash_testvectors[i].msg_size);
-                       desc->hash_final(digest, &ctx);
+                       hash_alg = oakley_to_hash_algorithm(desc->algo_id);
+                       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+                       hasher->get_hash(hasher, msg, digest);
+                       hasher->destroy(hasher);
                        result = memeq(digest, desc->hash_testvectors[i].msg_digest
                                                                  , desc->hash_digest_size);
                        DBG(DBG_CRYPT,
@@ -482,17 +488,21 @@ ike_hash_test(const struct hash_desc *desc)
                for (i = 0; desc->hmac_testvectors[i].hmac != NULL; i++)
                {
                        u_char digest[MAX_DIGEST_LEN];
+                       chunk_t key = { desc->hmac_testvectors[i].key,
+                                                       desc->hmac_testvectors[i].key_size };
+                       chunk_t msg = { desc->hmac_testvectors[i].msg,
+                                                       desc->hmac_testvectors[i].msg_size };
+                       pseudo_random_function_t prf_alg;
+                       prf_t *prf;
                        bool result;
 
-                       struct hmac_ctx ctx;
-
-                       hmac_init(&ctx, desc, desc->hmac_testvectors[i].key
-                                                               , desc->hmac_testvectors[i].key_size);
-                       hmac_update(&ctx, desc->hmac_testvectors[i].msg
-                                                        ,desc->hmac_testvectors[i].msg_size);
-                       hmac_final(digest, &ctx);
-                       result = memeq(digest, desc->hmac_testvectors[i].hmac
-                                                                 , desc->hash_digest_size);
+                       prf_alg = oakley_to_prf(desc->algo_id);
+                       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+                       prf->set_key(prf, key);
+                       prf->get_bytes(prf, msg, digest);
+                       prf->destroy(prf);
+                       result = memeq(digest, desc->hmac_testvectors[i].hmac,
+                                                                  desc->hash_digest_size);
                        DBG(DBG_CRYPT,
                                DBG_log("  hmac testvector %d: %s", i, result ? "ok":"failed")
                        )
index 11d4645..9d4b30c 100644 (file)
@@ -33,6 +33,7 @@
 #include <asn1/asn1.h>
 #include <crypto/hashers/hasher.h>
 #include <crypto/prfs/prf.h>
+#include <crypto/prf_plus.h>
 #include <crypto/rngs/rng.h>
 
 #include "constants.h"
@@ -397,16 +398,22 @@ static void send_notification(struct state *sndst, u_int16_t type,
        /* calculate hash value and patch into Hash Payload */
        if (encst)
        {
-               struct hmac_ctx ctx;
-               hmac_init_chunk(&ctx, encst->st_oakley.hasher, encst->st_skeyid_a);
-               hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
-               hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
-               hmac_final(r_hashval, &ctx);
+               chunk_t msgid_chunk = chunk_from_thing(msgid);
+               chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
+               pseudo_random_function_t prf_alg;
+               prf_t *prf;
+
+               prf_alg = oakley_to_prf(encst->st_oakley.hasher->algo_id);
+               prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+               prf->set_key(prf, encst->st_skeyid_a);
+               prf->get_bytes(prf, msgid_chunk, NULL);
+               prf->get_bytes(prf, msg_chunk, r_hashval);
 
                DBG(DBG_CRYPT,
                        DBG_log("HASH computed:");
-                       DBG_dump("", r_hashval, ctx.hmac_digest_size);
+                       DBG_dump("", r_hashval, prf->get_block_size(prf));
                )
+               prf->destroy(prf);
        }
 
        /* Encrypt message (preserve st_iv and st_new_iv) */
@@ -648,16 +655,23 @@ void send_delete(struct state *st)
 
        /* calculate hash value and patch into Hash Payload */
        {
-               struct hmac_ctx ctx;
-               hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);
-               hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
-               hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
-               hmac_final(r_hashval, &ctx);
+               chunk_t msgid_chunk = chunk_from_thing(msgid);
+               chunk_t msg_chunk = { r_hash_start, r_hdr_pbs.cur-r_hash_start };
+               pseudo_random_function_t prf_alg;
+               prf_t *prf;
+
+               prf_alg = oakley_to_prf(p1st->st_oakley.hasher->algo_id);
+               prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+               prf->set_key(prf, p1st->st_skeyid_a);
+               prf->get_bytes(prf, msgid_chunk, NULL);
+               prf->get_bytes(prf, msg_chunk, r_hashval);
 
                DBG(DBG_CRYPT,
                        DBG_log("HASH(1) computed:");
-                       DBG_dump("", r_hashval, ctx.hmac_digest_size);
+                       DBG_dump("", r_hashval, prf->get_block_size(prf));
                )
+
+               prf->destroy(prf);
        }
 
        /* Do a dance to avoid needing a new state object.
@@ -1172,8 +1186,8 @@ static bool skeyid_preshared(struct state *st)
                prf = lib->crypto->create_prf(lib->crypto, prf_alg);
                if (prf == NULL)
                {
-               loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
-                                                               pseudo_random_function_names, prf_alg);
+                       loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
+                                                                       pseudo_random_function_names, prf_alg);
                return FALSE;
                }
                free(st->st_skeyid.ptr);
@@ -1317,32 +1331,32 @@ static bool generate_skeyids_iv(struct state *st)
         * See RFC 2409 "IKE" Appendix B
         */
        {
-               /* const size_t keysize = st->st_oakley.encrypter->keydeflen/BITS_PER_BYTE; */
-               const size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE;
-               u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN];
-               u_char *k = st->st_skeyid_e.ptr;
+               size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE;
+
+               /* free any existing key */
+               free(st->st_enc_key.ptr);
 
                if (keysize > st->st_skeyid_e.len)
                {
-                       struct hmac_ctx ctx;
-                       size_t i = 0;
-
-                       hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_e);
-                       hmac_update(&ctx, "\0", 1);
-                       for (;;)
-                       {
-                               hmac_final(&keytemp[i], &ctx);
-                               i += ctx.hmac_digest_size;
-                               if (i >= keysize)
-                                       break;
-                               hmac_reinit(&ctx);
-                               hmac_update(&ctx, &keytemp[i - ctx.hmac_digest_size], ctx.hmac_digest_size);
-                       }
-                       k = keytemp;
+                       char seed_buf[] = { 0x00 };
+                       chunk_t seed = chunk_from_buf(seed_buf);
+                       pseudo_random_function_t prf_alg;
+                       prf_plus_t *prf_plus;
+                       prf_t *prf;
+
+                       prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+                       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+                       prf->set_key(prf, st->st_skeyid_e);
+                       prf_plus = prf_plus_create(prf, seed);
+                       prf_plus->allocate_bytes(prf_plus, keysize, &st->st_enc_key);
+                       prf_plus->destroy(prf_plus);
+                       prf->destroy(prf);
                }
-               free(st->st_enc_key.ptr);
-               st->st_enc_key = chunk_create(k, keysize);
-               st->st_enc_key = chunk_clone(st->st_enc_key);
+               else
+               {
+                       st->st_enc_key = chunk_create(st->st_skeyid_e.ptr, keysize);
+                       st->st_enc_key = chunk_clone(st->st_enc_key);
+               }                       
        }
 
        DBG(DBG_CRYPT,
@@ -1361,96 +1375,56 @@ static bool generate_skeyids_iv(struct state *st)
  * If the hashi argument is TRUE, generate HASH_I; if FALSE generate HASH_R.
  * If hashus argument is TRUE, we're generating a hash for our end.
  * See RFC2409 IKE 5.
- *
- * Generating the SIG_I and SIG_R for DSS is an odd perversion of this:
- * Most of the logic is the same, but SHA-1 is used in place of HMAC-whatever.
- * The extensive common logic is embodied in main_mode_hash_body().
- * See draft-ietf-ipsec-ike-01.txt 4.1 and 6.1.1.2
  */
-
-typedef void (*hash_update_t)(union hash_ctx *, const u_char *, size_t) ;
-
-static void main_mode_hash_body(struct state *st, bool hashi,
-                                                               const pb_stream *idpl, union hash_ctx *ctx,
-                       void (*hash_update_void)(void *, const u_char *input, size_t))
+ static size_t main_mode_hash(struct state *st, u_char *hash_val, bool hashi,
+                                                        const pb_stream *idpl)
 {
-#define HASH_UPDATE_T (union hash_ctx *, const u_char *input, unsigned int len)
-       hash_update_t hash_update=(hash_update_t)  hash_update_void;
-#if 0   /* if desperate to debug hashing */
-#   define hash_update(ctx, input, len) { \
-               DBG_dump("hash input", input, len); \
-               (hash_update)(ctx, input, len); \
-               }
-#endif
+       chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
+       chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE };
+       chunk_t sa_body = { st->st_p1isa.ptr + sizeof(struct isakmp_generic),
+                                               st->st_p1isa.len - sizeof(struct isakmp_generic) };
+       chunk_t id_body = { idpl->start + sizeof(struct isakmp_generic),
+                                               pbs_offset(idpl) - sizeof(struct isakmp_generic) };
+       pseudo_random_function_t prf_alg;
+       prf_t *prf;
+       size_t prf_block_size;
 
-#   define hash_update_chunk(ctx, ch) hash_update((ctx), (ch).ptr, (ch).len)
+       prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+       prf->set_key(prf, st->st_skeyid);
 
        if (hashi)
        {
-               hash_update_chunk(ctx, st->st_gi);
-               hash_update_chunk(ctx, st->st_gr);
-               hash_update(ctx, st->st_icookie, COOKIE_SIZE);
-               hash_update(ctx, st->st_rcookie, COOKIE_SIZE);
+               prf->get_bytes(prf, st->st_gi, NULL);
+               prf->get_bytes(prf, st->st_gr, NULL);
+               prf->get_bytes(prf, icookie, NULL);
+               prf->get_bytes(prf, rcookie, NULL);
        }
        else
        {
-               hash_update_chunk(ctx, st->st_gr);
-               hash_update_chunk(ctx, st->st_gi);
-               hash_update(ctx, st->st_rcookie, COOKIE_SIZE);
-               hash_update(ctx, st->st_icookie, COOKIE_SIZE);
+               prf->get_bytes(prf, st->st_gr, NULL);
+               prf->get_bytes(prf, st->st_gi, NULL);
+               prf->get_bytes(prf, rcookie, NULL);
+               prf->get_bytes(prf, icookie, NULL);
        }
 
-       DBG(DBG_CRYPT, DBG_log("hashing %lu bytes of SA"
-               , (unsigned long) (st->st_p1isa.len - sizeof(struct isakmp_generic))));
-
-       /* SA_b */
-       hash_update(ctx, st->st_p1isa.ptr + sizeof(struct isakmp_generic)
-               , st->st_p1isa.len - sizeof(struct isakmp_generic));
+       DBG(DBG_CRYPT,
+               DBG_log("hashing %u bytes of SA", sa_body.len)
+       )
+       prf->get_bytes(prf, sa_body, NULL);
 
        /* Hash identification payload, without generic payload header.
         * We used to reconstruct ID Payload for this purpose, but now
         * we use the bytes as they appear on the wire to avoid
         * "spelling problems".
         */
-       hash_update(ctx
-               , idpl->start + sizeof(struct isakmp_generic)
-               , pbs_offset(idpl) - sizeof(struct isakmp_generic));
-
-#   undef hash_update_chunk
-#   undef hash_update
-}
-
-static size_t   /* length of hash */
-main_mode_hash(struct state *st, u_char *hash_val, bool hashi,
-                          const pb_stream *idpl)
-{
-       struct hmac_ctx ctx;
+       prf->get_bytes(prf, id_body, hash_val);
+       prf_block_size = prf->get_block_size(prf);
+       prf->destroy(prf);
 
-       hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid);
-       main_mode_hash_body(st, hashi, idpl, &ctx.hash_ctx, ctx.h->hash_update);
-       hmac_final(hash_val, &ctx);
-       return ctx.hmac_digest_size;
+       return prf_block_size;
 }
 
-#if 0   /* only needed for DSS */
-static void
-main_mode_sha1(struct state *st
-, u_char *hash_val      /* resulting bytes */
-, size_t *hash_len      /* length of hash */
-, bool hashi    /* Initiator? */
-, const pb_stream *idpl)        /* ID payload, as PBS */
-{
-       union hash_ctx ctx;
-
-       SHA1Init(&ctx.ctx_sha1);
-       SHA1Update(&ctx.ctx_sha1, st->st_skeyid.ptr, st->st_skeyid.len);
-       *hash_len = SHA1_DIGEST_SIZE;
-       main_mode_hash_body(st, hashi, idpl, &ctx
-               , (void (*)(union hash_ctx *, const u_char *, unsigned int))&SHA1Update);
-       SHA1Final(hash_val, &ctx.ctx_sha1);
-}
-#endif
-
 /* Create an RSA signature of a hash.
  * Poorly specified in draft-ietf-ipsec-ike-01.txt 6.1.1.2.
  * Use PKCS#1 version 1.5 encryption of hash (called
@@ -1911,31 +1885,33 @@ encrypt_message(pb_stream *pbs, struct state *st)
  * Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2
  * (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25)
  */
-static size_t quick_mode_hash12(u_char *dest, const u_char *start,
-                                                               const u_char *roof, const struct state *st,
-                                                               const msgid_t *msgid, bool hash2)
+static size_t quick_mode_hash12(u_char *dest, u_char *start, u_char *roof,
+                                                               const struct state *st, const msgid_t *msgid,
+                                                               bool hash2)
 {
-       struct hmac_ctx ctx;
+       chunk_t msgid_chunk = chunk_from_thing(*msgid);
+       chunk_t msg_chunk = { start, roof - start };
+       pseudo_random_function_t prf_alg;
+       prf_t *prf;
+       size_t prf_block_size;
 
-#if 0   /* if desperate to debug hashing */
-#   define hmac_update(ctx, ptr, len) { \
-               DBG_dump("hash input", (ptr), (len)); \
-               (hmac_update)((ctx), (ptr), (len)); \
-       }
-       DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len);
-#endif
-       hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
-       hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t));
+       prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+       prf->set_key(prf, st->st_skeyid_a);
+       prf->get_bytes(prf, msgid_chunk, NULL);
        if (hash2)
-               hmac_update_chunk(&ctx, st->st_ni);     /* include Ni_b in the hash */
-       hmac_update(&ctx, start, roof-start);
-       hmac_final(dest, &ctx);
+       {
+               prf->get_bytes(prf, st->st_ni, NULL); /* include Ni_b in the hash */
+       }     
+       prf->get_bytes(prf, msg_chunk, dest);
+       prf_block_size = prf->get_block_size(prf);
+       prf->destroy(prf);
 
        DBG(DBG_CRYPT,
                DBG_log("HASH(%d) computed:", hash2 + 1);
-               DBG_dump("", dest, ctx.hmac_digest_size));
-       return ctx.hmac_digest_size;
-#   undef hmac_update
+               DBG_dump("", dest, prf_block_size)
+       )
+       return prf_block_size;
 }
 
 /* Compute HASH(3) in Quick Mode (part of Quick I2 message).
@@ -1946,16 +1922,25 @@ static size_t quick_mode_hash12(u_char *dest, const u_char *start,
  */
 static size_t quick_mode_hash3(u_char *dest, struct state *st)
 {
-       struct hmac_ctx ctx;
-
-       hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
-       hmac_update(&ctx, "\0", 1);
-       hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid));
-       hmac_update_chunk(&ctx, st->st_ni);
-       hmac_update_chunk(&ctx, st->st_nr);
-       hmac_final(dest, &ctx);
-       DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_size);
-       return ctx.hmac_digest_size;
+       char seed_buf[] = { 0x00 };
+       chunk_t seed_chunk = chunk_from_buf(seed_buf);
+       chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
+       pseudo_random_function_t prf_alg;
+       prf_t *prf;
+       size_t prf_block_size;
+       
+       prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+       prf->set_key(prf, st->st_skeyid_a);
+       prf->get_bytes(prf, seed_chunk, NULL );
+       prf->get_bytes(prf, msgid_chunk, NULL);
+       prf->get_bytes(prf, st->st_ni, NULL);
+       prf->get_bytes(prf, st->st_nr, dest);
+       prf_block_size = prf->get_block_size(prf);
+       prf->destroy(prf);
+
+       DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, prf_block_size);
+       return prf_block_size;
 }
 
 /* Compute Phase 2 IV.
@@ -1963,23 +1948,26 @@ static size_t quick_mode_hash3(u_char *dest, struct state *st)
  */
 void init_phase2_iv(struct state *st, const msgid_t *msgid)
 {
-       const struct hash_desc *h = st->st_oakley.hasher;
-       union hash_ctx ctx;
+       chunk_t iv_chunk = { st->st_ph1_iv, st->st_ph1_iv_len };
+       chunk_t msgid_chunk = chunk_from_thing(*msgid);
+       hash_algorithm_t hash_alg;
+       hasher_t *hasher;
 
-       DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:"
-               , st->st_ph1_iv, st->st_ph1_iv_len);
+       hash_alg = oakley_to_hash_algorithm(st->st_oakley.hasher->algo_id);
+       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
 
-       st->st_new_iv_len = h->hash_digest_size;
-       passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+       DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:",
+                                 st->st_ph1_iv, st->st_ph1_iv_len);
 
-       h->hash_init(&ctx);
-       h->hash_update(&ctx, st->st_ph1_iv, st->st_ph1_iv_len);
-       passert(*msgid != 0);
-       h->hash_update(&ctx, (const u_char *)msgid, sizeof(*msgid));
-       h->hash_final(st->st_new_iv, &ctx);
+       st->st_new_iv_len = hasher->get_hash_size(hasher);
+       passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
+               
+       hasher->get_hash(hasher, iv_chunk, NULL);
+       hasher->get_hash(hasher, msgid_chunk, st->st_new_iv);
+       hasher->destroy(hasher);
 
-       DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:"
-               , st->st_new_iv, st->st_new_iv_len);
+       DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:",
+                                 st->st_new_iv, st->st_new_iv_len);
 }
 
 /* Initiate quick mode.
@@ -2872,62 +2860,68 @@ static void compute_proto_keymat(struct state *st, u_int8_t protoid,
 
        pi->keymat_len = needed_len;
 
-       /* Allocate space for the keying material.
-        * Although only needed_len bytes are desired, we
-        * must round up to a multiple of ctx.hmac_digest_size
+       /* Allocate space for the keying material. Although only needed_len bytes
+        * are desired, we must round up to a multiple of hash_size
         * so that our buffer isn't overrun.
         */
        {
-               struct hmac_ctx ctx_me, ctx_peer;
-               size_t needed_space;    /* space needed for keying material (rounded up) */
-               size_t i;
+               size_t needed_space; /* space needed for keying material (rounded up) */
+               size_t i, prf_block_size;
+               chunk_t protoid_chunk = chunk_from_thing(protoid);
+               chunk_t spi_our =  chunk_from_thing(pi->our_spi);
+               chunk_t spi_peer = chunk_from_thing(pi->attrs.spi);
+               pseudo_random_function_t prf_alg;
+               prf_t *prf_our, *prf_peer;
 
-               hmac_init_chunk(&ctx_me, st->st_oakley.hasher, st->st_skeyid_d);
-               ctx_peer = ctx_me;      /* duplicate initial conditions */
+               prf_alg  = oakley_to_prf(st->st_oakley.hasher->algo_id);
+               prf_our  = lib->crypto->create_prf(lib->crypto, prf_alg);
+               prf_peer = lib->crypto->create_prf(lib->crypto, prf_alg);
+               prf_our->set_key(prf_our, st->st_skeyid_d);
+               prf_peer->set_key(prf_peer, st->st_skeyid_d);
+               prf_block_size = prf_our->get_block_size(prf_our);
 
-               needed_space = needed_len + pad_up(needed_len, ctx_me.hmac_digest_size);
+               needed_space = needed_len + pad_up(needed_len, prf_block_size);
                replace(pi->our_keymat, malloc(needed_space));
                replace(pi->peer_keymat, malloc(needed_space));
 
                for (i = 0;; )
                {
+                       char *keymat_i_our  = pi->our_keymat + i;
+                       char *keymat_i_peer = pi->peer_keymat + i;
+                       chunk_t keymat_our  = { keymat_i_our,  prf_block_size };
+                       chunk_t keymat_peer = { keymat_i_peer, prf_block_size };
+                       
                        if (st->st_shared.ptr != NULL)
                        {
                                /* PFS: include the g^xy */
-                               hmac_update_chunk(&ctx_me, st->st_shared);
-                               hmac_update_chunk(&ctx_peer, st->st_shared);
+                               prf_our->get_bytes(prf_our,   st->st_shared, NULL);
+                               prf_peer->get_bytes(prf_peer, st->st_shared, NULL);
                        }
-                       hmac_update(&ctx_me, &protoid, sizeof(protoid));
-                       hmac_update(&ctx_peer, &protoid, sizeof(protoid));
+                       prf_our->get_bytes(prf_our,   protoid_chunk, NULL);
+                       prf_peer->get_bytes(prf_peer, protoid_chunk, NULL);
 
-                       hmac_update(&ctx_me, (u_char *)&pi->our_spi, sizeof(pi->our_spi));
-                       hmac_update(&ctx_peer, (u_char *)&pi->attrs.spi, sizeof(pi->attrs.spi));
+                       prf_our->get_bytes(prf_our,   spi_our,  NULL);
+                       prf_peer->get_bytes(prf_peer, spi_peer, NULL);
 
-                       hmac_update_chunk(&ctx_me, st->st_ni);
-                       hmac_update_chunk(&ctx_peer, st->st_ni);
+                       prf_our->get_bytes(prf_our,   st->st_ni, NULL);
+                       prf_peer->get_bytes(prf_peer, st->st_ni, NULL);
 
-                       hmac_update_chunk(&ctx_me, st->st_nr);
-                       hmac_update_chunk(&ctx_peer, st->st_nr);
+                       prf_our->get_bytes(prf_our,   st->st_nr, keymat_i_our);
+                       prf_peer->get_bytes(prf_peer, st->st_nr, keymat_i_peer);
 
-                       hmac_final(pi->our_keymat + i, &ctx_me);
-                       hmac_final(pi->peer_keymat + i, &ctx_peer);
-
-                       i += ctx_me.hmac_digest_size;
+                       i += prf_block_size;
                        if (i >= needed_space)
+                       {
                                break;
+                       }
 
                        /* more keying material needed: prepare to go around again */
-
-                       hmac_reinit(&ctx_me);
-                       hmac_reinit(&ctx_peer);
-
-                       hmac_update(&ctx_me, pi->our_keymat + i - ctx_me.hmac_digest_size
-                               , ctx_me.hmac_digest_size);
-                       hmac_update(&ctx_peer, pi->peer_keymat + i - ctx_peer.hmac_digest_size
-                               , ctx_peer.hmac_digest_size);
+                       prf_our->get_bytes(prf_our,   keymat_our,  NULL);
+                       prf_peer->get_bytes(prf_peer, keymat_peer, NULL);
                }
+               prf_our->destroy(prf_our);
+               prf_peer->destroy(prf_peer);
        }
-
        DBG(DBG_CRYPT,
                DBG_dump("KEYMAT computed:\n", pi->our_keymat, pi->keymat_len);
                DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat, pi->keymat_len));
@@ -2963,8 +2957,7 @@ static void compute_keymats(struct state *st)
 /* Handle a Main Mode Oakley first packet (responder side).
  * HDR;SA --> HDR;SA
  */
-stf_status
-main_inI1_outR1(struct msg_digest *md)
+stf_status main_inI1_outR1(struct msg_digest *md)
 {
        struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
        struct state *st;
@@ -5268,15 +5261,22 @@ static stf_status send_isakmp_notification(struct state *st, u_int16_t type,
                        
        {
                /* finish computing HASH */     
-               struct hmac_ctx ctx;
-               hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
-               hmac_update(&ctx, (const u_char *) &msgid, sizeof(msgid_t));
-               hmac_update(&ctx, r_hash_start, rbody.cur-r_hash_start);
-               hmac_final(r_hashval, &ctx);  
+               chunk_t msgid_chunk = chunk_from_thing(msgid);
+               chunk_t msg_chunk = { r_hash_start, rbody.cur-r_hash_start };
+               pseudo_random_function_t prf_alg;
+               prf_t *prf;
+
+               prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+               prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+               prf->set_key(prf, st->st_skeyid_a);
+               prf->get_bytes(prf, msgid_chunk, NULL);
+               prf->get_bytes(prf, msg_chunk, r_hashval);
 
                DBG(DBG_CRYPT,
-                               DBG_log("HASH computed:");
-                               DBG_dump("", r_hashval, ctx.hmac_digest_size));
+                       DBG_log("HASH computed:");
+                       DBG_dump("", r_hashval, prf->get_block_size(prf));
+               )
+               prf->destroy(prf);
        }
 
        /* Encrypt message (preserve st_iv and st_new_iv) */
index 71c8685..b38b9d4 100644 (file)
@@ -24,7 +24,9 @@
 #include <string.h>
 
 #include <freeswan.h>
+
 #include <library.h>
+#include <crypto/prfs/prf.h>
 
 #include "constants.h"
 #include "defs.h"
@@ -241,22 +243,28 @@ set_internal_addr(struct connection *c, internal_addr_t *ia)
 /*
  * Compute HASH of Mode Config.
  */
-static size_t
-modecfg_hash(u_char *dest, const u_char *start, const u_char *roof
-                       , const struct state *st)
+static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
+                                                  const struct state *st)
 {
-       struct hmac_ctx ctx;
-
-       hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
-       hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid));
-       hmac_update(&ctx, start, roof-start);
-       hmac_final(dest, &ctx);
+       chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
+       chunk_t msg_chunk = { start, roof - start };
+       size_t prf_block_size;
+       pseudo_random_function_t prf_alg;
+       prf_t *prf;
+
+       prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
+       prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+       prf->set_key(prf, st->st_skeyid_a);
+       prf->get_bytes(prf, msgid_chunk, NULL);
+       prf->get_bytes(prf, msg_chunk, dest);
+       prf_block_size = prf->get_block_size(prf);
+       prf->destroy(prf);
 
        DBG(DBG_CRYPT,
                DBG_log("ModeCfg HASH computed:");
-               DBG_dump("", dest, ctx.hmac_digest_size)
+               DBG_dump("", dest, prf_block_size)
        ) 
-       return ctx.hmac_digest_size;
+       return prf_block_size;
 }
 
 
index 24d70e5..a9501ec 100644 (file)
@@ -28,6 +28,9 @@
 #include <pfkeyv2.h>
 #include <pfkey.h>
 
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
@@ -102,16 +105,18 @@ static void disable_nat_traversal (int type)
                        nat_traversal_enabled = FALSE;
 }
 
-static void _natd_hash(const struct hash_desc *hasher, char *hash,
+static void _natd_hash(const struct hash_desc *oakley_hasher, char *hash,
                u_int8_t *icookie, u_int8_t *rcookie,
                const ip_address *ip, u_int16_t port)
 {
-       union hash_ctx ctx;
-
        if (is_zero_cookie(icookie))
+       {
                DBG_log("_natd_hash: Warning, icookie is zero !!");
+       }
        if (is_zero_cookie(rcookie))
+       {
                DBG_log("_natd_hash: Warning, rcookie is zero !!");
+       }
 
        /**
         * draft-ietf-ipsec-nat-t-ike-01.txt
@@ -120,36 +125,41 @@ static void _natd_hash(const struct hash_desc *hasher, char *hash,
         *
         * All values in network order
         */
-       hasher->hash_init(&ctx);
-       hasher->hash_update(&ctx, icookie, COOKIE_SIZE);
-       hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);
-       switch (addrtypeof(ip)) {
-       case AF_INET:
-               hasher->hash_update(&ctx, (const u_char *)&ip->u.v4.sin_addr.s_addr
-                               , sizeof(ip->u.v4.sin_addr.s_addr));
-               break;
-       case AF_INET6:
-               hasher->hash_update(&ctx, (const u_char *)&ip->u.v6.sin6_addr.s6_addr
-                               , sizeof(ip->u.v6.sin6_addr.s6_addr));
-               break;
-       }
-       hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));
-       hasher->hash_final(hash, &ctx);
-#ifdef NAT_D_DEBUG
-       DBG(DBG_NATT,
-               DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len);
-               DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE);
-               DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE);
-               switch (addrtypeof(ip)) {
-               case AF_INET:
-                       DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr
-                               , sizeof(ip->u.v4.sin_addr.s_addr));
-                       break;
+       {
+               chunk_t icookie_chunk = { icookie, COOKIE_SIZE };
+               chunk_t rcookie_chunk = { rcookie, COOKIE_SIZE };
+               chunk_t port_chunk = chunk_from_thing(port);
+               chunk_t addr_chunk;
+               hash_algorithm_t hash_alg;
+               hasher_t *hasher;
+               size_t hash_size;
+
+               hash_alg = oakley_to_hash_algorithm(oakley_hasher->algo_id);
+               hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+               hasher->get_hash(hasher, icookie_chunk, NULL);
+               hasher->get_hash(hasher, rcookie_chunk, NULL);
+               switch (addrtypeof(ip))
+               {
+                       case AF_INET:
+                               addr_chunk = chunk_from_thing(ip->u.v4.sin_addr.s_addr);
+                               break;
+                       case AF_INET6:
+                               addr_chunk = chunk_from_thing(ip->u.v6.sin6_addr.s6_addr);
                }
-               DBG_log("_natd_hash: port=%d", port);
-               DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);
-       );
+               hasher->get_hash(hasher, addr_chunk, NULL);
+               hasher->get_hash(hasher, port_chunk, hash);
+               hash_size = hasher->get_hash_size(hasher);
+               hasher->destroy(hasher);
+#ifdef NAT_D_DEBUG
+               DBG(DBG_NATT,
+                       DBG_dump_chunk("_natd_hash: icookie=", icookie_chunk);
+                       DBG_dump_chunk("_natd_hash: rcookie=", rcookie_chunk);
+                       DBG_dump_chunk("_natd_hash: ip=", addr_chunk);
+                       DBG_log("_natd_hash: port=%d", port);
+                       DBG_dump("_natd_hash: hash=", hash, hash_size);
+               )
 #endif
+       }
 }
 
 /* Add NAT-Traversal VIDs (supported ones)