From 6eb9bc9bb86ae6499fd600dbe8555de454baa2a8 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Tue, 5 May 2009 14:28:02 +0200 Subject: [PATCH] SKEYID derivation based on libstrongswan --- configure.in | 4 + src/pluto/alg_info.c | 2 - src/pluto/cookie.c | 29 +++---- src/pluto/cookie.h | 4 +- src/pluto/crl.c | 30 ++++--- src/pluto/crypto.c | 74 ++++++++++++------ src/pluto/crypto.h | 9 +++ src/pluto/demux.c | 4 +- src/pluto/ike_alg.c | 2 - src/pluto/ipsec_doi.c | 127 ++++++++++++++++++------------ src/pluto/modecfg.c | 2 - src/pluto/nat_traversal.c | 2 - src/pluto/pem.c | 159 +++++++++++++++++++++++--------------- src/pluto/pgp.c | 21 +++-- src/pluto/pkcs1.c | 93 ++++------------------ src/pluto/plutomain.c | 4 +- src/pluto/spdb.c | 4 +- src/pluto/state.c | 5 +- src/pluto/vendor.c | 119 +++++++++------------------- src/pluto/vendor.h | 11 ++- src/pluto/x509.c | 20 ++--- src/pluto/x509.h | 2 +- 22 files changed, 365 insertions(+), 362 deletions(-) diff --git a/configure.in b/configure.in index 47a7b8ed6..f9d7fb8be 100644 --- a/configure.in +++ b/configure.in @@ -951,15 +951,18 @@ if test x$des = xtrue; then fi if test x$sha1 = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" sha1" + pluto_plugins=${pluto_plugins}" sha1" fi if test x$sha2 = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" sha2" + pluto_plugins=${pluto_plugins}" sha2" fi if test x$md4 = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" md4" fi if test x$md5 = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" md5" + pluto_plugins=${pluto_plugins}" md5" fi if test x$fips_prf = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" fips-prf" @@ -979,6 +982,7 @@ if test x$xcbc = xtrue; then fi if test x$hmac = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" hmac" + pluto_plugins=${pluto_plugins}" hmac" fi if test x$mysql = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" mysql" diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c index a81d6414c..bd0c73f2b 100644 --- a/src/pluto/alg_info.c +++ b/src/pluto/alg_info.c @@ -33,8 +33,6 @@ #include "defs.h" #include "log.h" #include "whack.h" -#include "sha1.h" -#include "md5.h" #include "crypto.h" #include "kernel_alg.h" #include "ike_alg.h" diff --git a/src/pluto/cookie.c b/src/pluto/cookie.c index 7caa19ba9..39fe74787 100644 --- a/src/pluto/cookie.c +++ b/src/pluto/cookie.c @@ -26,7 +26,6 @@ #include "constants.h" #include "defs.h" -#include "sha1.h" #include "cookie.h" const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ @@ -35,11 +34,10 @@ const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ * First argument is true if we're to create an Initiator cookie. * Length SHOULD be a multiple of sizeof(u_int32_t). */ -void get_cookie(bool initiator, u_int8_t *cookie, int length, - const ip_address *addr) +void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr) { - u_char buffer[SHA1_DIGEST_SIZE]; - SHA1_CTX ctx; + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + u_char buffer[HASH_SIZE_SHA1]; do { if (initiator) @@ -52,20 +50,23 @@ void get_cookie(bool initiator, u_int8_t *cookie, int length, } else /* Responder cookie */ { - /* This looks as good as any way */ - size_t addr_length; + chunk_t addr_chunk, secret_chunk, counter_chunk; + size_t addr_len; static u_int32_t counter = 0; - unsigned char addr_buff[ + unsigned char addr_buf[ sizeof(union {struct in_addr A; struct in6_addr B;})]; - addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff)); - SHA1Init(&ctx); - SHA1Update(&ctx, addr_buff, addr_length); - SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day)); + addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf)); + addr_chunk = chunk_create(addr_buf, addr_len); + secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1); counter++; - SHA1Update(&ctx, (const void *) &counter, sizeof(counter)); - SHA1Final(buffer, &ctx); + counter_chunk = chunk_create((void *) &counter, sizeof(counter)); + hasher->get_hash(hasher, addr_chunk, NULL); + hasher->get_hash(hasher, secret_chunk, NULL); + hasher->get_hash(hasher, counter_chunk, buffer); memcpy(cookie, buffer, length); } } while (is_zero_cookie(cookie)); /* probably never loops */ + + hasher->destroy(hasher); } diff --git a/src/pluto/cookie.h b/src/pluto/cookie.h index 7a1b8fdb9..809d66491 100644 --- a/src/pluto/cookie.h +++ b/src/pluto/cookie.h @@ -16,7 +16,7 @@ extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ -extern void get_cookie(bool initiator, u_int8_t *cookie, int length - , const ip_address *addr); +extern void get_cookie(bool initiator, u_int8_t *cookie, int length, + ip_address *addr); #define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE) diff --git a/src/pluto/crl.c b/src/pluto/crl.c index 321e98adc..b8cdb435b 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "constants.h" #include "defs.h" @@ -39,7 +40,7 @@ #include "keys.h" #include "whack.h" #include "fetch.h" -#include "sha1.h" + /* chained lists of X.509 crls */ @@ -292,19 +293,26 @@ bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) */ if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0) { - char path[BUF_LEN]; - char buf[BUF_LEN]; - char digest_buf[SHA1_DIGEST_SIZE]; - chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE }; - + char path[BUF_LEN], buf[BUF_LEN]; + char digest_buf[HASH_SIZE_SHA1]; + chunk_t subjectKeyID = chunk_from_buf(digest_buf); + bool has_keyID; + if (issuer_cert->subjectKeyID.ptr == NULL) - compute_subjectKeyID(issuer_cert, subjectKeyID); + { + has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID); + } else + { subjectKeyID = issuer_cert->subjectKeyID; - - datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN); - snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf); - chunk_write(crl->certificateList, path, "crl", 0022, TRUE); + has_keyID = TRUE; + } + if (has_keyID) + { + datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN); + snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf); + chunk_write(crl->certificateList, path, "crl", 0022, TRUE); + } } /* is the fetched crl valid? */ diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c index 8f9e2accc..6a885b885 100644 --- a/src/pluto/crypto.c +++ b/src/pluto/crypto.c @@ -28,9 +28,7 @@ #include "defs.h" #include "state.h" #include "log.h" -#include "md5.h" -#include "sha1.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" #include "alg_info.h" #include "ike_alg.h" @@ -451,8 +449,7 @@ static struct hash_desc crypto_hasher_sha1 = hash_final: (void (*)(u_char *, void *)) SHA1Final }; -void -init_crypto(void) +void init_crypto(void) { if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0 || mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0 @@ -471,8 +468,7 @@ init_crypto(void) ike_alg_test(); } -void -free_crypto(void) +void free_crypto(void) { mpz_clear(&groupgenerator); mpz_clear(&modp1024_modulus); @@ -503,8 +499,7 @@ const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE] = { # undef BYTES }; -const struct oakley_group_desc * -lookup_group(u_int16_t group) +const struct oakley_group_desc *lookup_group(u_int16_t group) { int i; @@ -541,8 +536,8 @@ do_des(bool enc, void *buf, size_t buf_len, struct state *st) /* encrypt or decrypt part of an IKE message using 3DES * See RFC 2409 "IKE" Appendix B */ -static void -do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc) +static void do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, + size_t key_size, u_int8_t *iv, bool enc) { des_key_schedule ks[3]; @@ -557,8 +552,8 @@ do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t } /* hash and prf routines */ -void -crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st) +void crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, + size_t size, struct state *st) { passert(st->st_new_iv_len >= e->enc_blocksize); st->st_new_iv_len = e->enc_blocksize; /* truncate */ @@ -574,10 +569,8 @@ crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t * rfc2104.txt specifies how HMAC works. */ -void -hmac_init(struct hmac_ctx *ctx, - const struct hash_desc *h, - const u_char *key, size_t key_len) +void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h, + const u_char *key, size_t key_len) { int k; @@ -610,22 +603,19 @@ hmac_init(struct hmac_ctx *ctx, hmac_reinit(ctx); } -void -hmac_reinit(struct hmac_ctx *ctx) +void hmac_reinit(struct hmac_ctx *ctx) { ctx->h->hash_init(&ctx->hash_ctx); ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size); } -void -hmac_update(struct hmac_ctx *ctx, +void hmac_update(struct hmac_ctx *ctx, const u_char *data, size_t data_len) { ctx->h->hash_update(&ctx->hash_ctx, data, data_len); } -void -hmac_final(u_char *output, struct hmac_ctx *ctx) +void hmac_final(u_char *output, struct hmac_ctx *ctx) { const struct hash_desc *h = ctx->h; @@ -636,3 +626,41 @@ hmac_final(u_char *output, struct hmac_ctx *ctx) h->hash_update(&ctx->hash_ctx, output, h->hash_digest_size); h->hash_final(output, &ctx->hash_ctx); } + +hash_algorithm_t oakley_to_hash_algorithm(int alg) +{ + switch (alg) + { + case OAKLEY_MD5: + return HASH_MD5; + case OAKLEY_SHA: + return HASH_SHA1; + case OAKLEY_SHA2_256: + return HASH_SHA256; + case OAKLEY_SHA2_384: + return HASH_SHA384; + case OAKLEY_SHA2_512: + return HASH_SHA512; + default: + return HASH_UNKNOWN; + } +} + +pseudo_random_function_t oakley_to_prf(int alg) +{ + switch (alg) + { + case OAKLEY_MD5: + return PRF_HMAC_MD5; + case OAKLEY_SHA: + return PRF_HMAC_SHA1; + case OAKLEY_SHA2_256: + return PRF_HMAC_SHA2_256; + case OAKLEY_SHA2_384: + return PRF_HMAC_SHA2_384; + case OAKLEY_SHA2_512: + return PRF_HMAC_SHA2_512; + default: + return PRF_UNDEFINED; + } +} diff --git a/src/pluto/crypto.h b/src/pluto/crypto.h index be33cf870..72df70ef6 100644 --- a/src/pluto/crypto.h +++ b/src/pluto/crypto.h @@ -14,6 +14,11 @@ #include /* GNU MP library */ +#include +#include + +#include "md5.h" +#include "sha1.h" #include "libsha2/sha2.h" #include "ike_alg.h" @@ -104,4 +109,8 @@ extern void hmac_final(u_char *output, struct hmac_ctx *ctx); (ch).ptr = malloc((ch).len); \ hmac_final((ch).ptr, (ctx)); \ } + +extern hash_algorithm_t oakley_to_hash_algorithm(int alg); +extern pseudo_random_function_t oakley_to_prf(int alg); + #endif diff --git a/src/pluto/demux.c b/src/pluto/demux.c index 25c722f82..fef9b98cc 100644 --- a/src/pluto/demux.c +++ b/src/pluto/demux.c @@ -130,9 +130,7 @@ #include "connections.h" #include "state.h" #include "packet.h" -#include "md5.h" -#include "sha1.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" #include "ike_alg.h" #include "log.h" #include "demux.h" /* needs packet.h */ diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c index e48c011ce..2995e32fb 100644 --- a/src/pluto/ike_alg.c +++ b/src/pluto/ike_alg.c @@ -23,8 +23,6 @@ #include "constants.h" #include "defs.h" -#include "sha1.h" -#include "md5.h" #include "crypto.h" #include "state.h" diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index a9a06cb4f..11d4645cf 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include "constants.h" @@ -59,10 +61,7 @@ #include "whack.h" #include "fetch.h" #include "pkcs7.h" - -#include "sha1.h" -#include "md5.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" #include "vendor.h" #include "alg_info.h" #include "ike_alg.h" @@ -1166,12 +1165,22 @@ static bool skeyid_preshared(struct state *st) } else { - struct hmac_ctx ctx; + pseudo_random_function_t prf_alg; + prf_t *prf; - hmac_init_chunk(&ctx, st->st_oakley.hasher, *pss); - hmac_update_chunk(&ctx, st->st_ni); - hmac_update_chunk(&ctx, st->st_nr); - hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_preshared()", &ctx); + prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id); + 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); + return FALSE; + } + free(st->st_skeyid.ptr); + prf->set_key(prf, *pss); + prf->allocate_bytes(prf, st->st_ni, NULL); + prf->allocate_bytes(prf, st->st_nr, &st->st_skeyid); + prf->destroy(prf); return TRUE; } } @@ -1179,21 +1188,24 @@ static bool skeyid_preshared(struct state *st) static bool skeyid_digisig(struct state *st) { - struct hmac_ctx ctx; chunk_t nir; + pseudo_random_function_t prf_alg; + prf_t *prf; - /* We need to hmac_init with the concatenation of Ni_b and Nr_b, - * so we have to build a temporary concatentation. - */ - nir.len = st->st_ni.len + st->st_nr.len; - nir.ptr = malloc(nir.len); - memcpy(nir.ptr, st->st_ni.ptr, st->st_ni.len); - memcpy(nir.ptr+st->st_ni.len, st->st_nr.ptr, st->st_nr.len); - hmac_init_chunk(&ctx, st->st_oakley.hasher, nir); + prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id); + 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); + return FALSE; + } + free(st->st_skeyid.ptr); + nir = chunk_cat("cc", st->st_ni, st->st_nr); + prf->set_key(prf, nir); + prf->allocate_bytes(prf, st->st_shared, &st->st_skeyid); + prf->destroy(prf); free(nir.ptr); - - hmac_update_chunk(&ctx, st->st_shared); - hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_digisig()", &ctx); return TRUE; } @@ -1209,14 +1221,18 @@ static bool generate_skeyids_iv(struct state *st) case XAUTHInitPreShared: case XAUTHRespPreShared: if (!skeyid_preshared(st)) + { return FALSE; + } break; case OAKLEY_RSA_SIG: case XAUTHInitRSA: case XAUTHRespRSA: if (!skeyid_digisig(st)) + { return FALSE; + } break; case OAKLEY_DSS_SIG: @@ -1234,52 +1250,65 @@ static bool generate_skeyids_iv(struct state *st) /* generate SKEYID_* from SKEYID */ { - struct hmac_ctx ctx; + char buf_skeyid_d[] = { 0x00 }; + char buf_skeyid_a[] = { 0x01 }; + char buf_skeyid_e[] = { 0x02 }; + chunk_t seed_skeyid_d = chunk_from_buf(buf_skeyid_d); + chunk_t seed_skeyid_a = chunk_from_buf(buf_skeyid_a); + chunk_t seed_skeyid_e = chunk_from_buf(buf_skeyid_e); + chunk_t icookie = { st->st_icookie, COOKIE_SIZE }; + chunk_t rcookie = { st->st_rcookie, COOKIE_SIZE }; + pseudo_random_function_t prf_alg; + prf_t *prf; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid); + 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); /* SKEYID_D */ - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\0", 1); - hmac_final_chunk(st->st_skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx); + free(st->st_skeyid_d.ptr); + prf->allocate_bytes(prf, st->st_shared, NULL); + prf->allocate_bytes(prf, icookie, NULL); + prf->allocate_bytes(prf, rcookie, NULL); + prf->allocate_bytes(prf, seed_skeyid_d, &st->st_skeyid_d); /* SKEYID_A */ - hmac_reinit(&ctx); - hmac_update_chunk(&ctx, st->st_skeyid_d); - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\1", 1); - hmac_final_chunk(st->st_skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx); + free(st->st_skeyid_a.ptr); + prf->allocate_bytes(prf, st->st_skeyid_d, NULL); + prf->allocate_bytes(prf, st->st_shared, NULL); + prf->allocate_bytes(prf, icookie, NULL); + prf->allocate_bytes(prf, rcookie, NULL); + prf->allocate_bytes(prf, seed_skeyid_a, &st->st_skeyid_a); /* SKEYID_E */ - hmac_reinit(&ctx); - hmac_update_chunk(&ctx, st->st_skeyid_a); - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\2", 1); - hmac_final_chunk(st->st_skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx); + free(st->st_skeyid_e.ptr); + prf->allocate_bytes(prf, st->st_skeyid_a, NULL); + prf->allocate_bytes(prf, st->st_shared, NULL); + prf->allocate_bytes(prf, icookie, NULL); + prf->allocate_bytes(prf, rcookie, NULL); + prf->allocate_bytes(prf, seed_skeyid_e, &st->st_skeyid_e); + + prf->destroy(prf); } /* generate IV */ { - union hash_ctx hash_ctx; - const struct hash_desc *h = st->st_oakley.hasher; + hash_algorithm_t hash_alg; + hasher_t *hasher; - st->st_new_iv_len = h->hash_digest_size; + 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 = hasher->get_hash_size(hasher); passert(st->st_new_iv_len <= sizeof(st->st_new_iv)); DBG(DBG_CRYPT, DBG_dump_chunk("DH_i:", st->st_gi); DBG_dump_chunk("DH_r:", st->st_gr); ); - h->hash_init(&hash_ctx); - h->hash_update(&hash_ctx, st->st_gi.ptr, st->st_gi.len); - h->hash_update(&hash_ctx, st->st_gr.ptr, st->st_gr.len); - h->hash_final(st->st_new_iv, &hash_ctx); + + hasher->get_hash(hasher, st->st_gi, NULL); + hasher->get_hash(hasher, st->st_gr, st->st_new_iv); + hasher->destroy(hasher); } /* Oakley Keying Material diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 8a50f50a3..71c86859f 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -33,8 +33,6 @@ #include "timer.h" #include "ipsec_doi.h" #include "log.h" -#include "md5.h" -#include "sha1.h" #include "crypto.h" #include "modecfg.h" #include "whack.h" diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c index 0f16cf06d..24d70e505 100644 --- a/src/pluto/nat_traversal.c +++ b/src/pluto/nat_traversal.c @@ -40,8 +40,6 @@ #include "whack.h" #include "timer.h" #include "cookie.h" -#include "sha1.h" -#include "md5.h" #include "crypto.h" #include "vendor.h" #include "ike_alg.h" diff --git a/src/pluto/pem.c b/src/pluto/pem.c index 99dda539d..98287c215 100644 --- a/src/pluto/pem.c +++ b/src/pluto/pem.c @@ -25,21 +25,23 @@ #include #include + +#include +#include + #define HEADER_DES_LOCL_H /* stupid trick to force prototype decl in */ #include #include "constants.h" #include "defs.h" #include "log.h" -#include "md5.h" #include "whack.h" #include "pem.h" -/* - * check the presence of a pattern in a character string +/** + * Check the presence of a pattern in a character string */ -static bool -present(const char* pattern, chunk_t* ch) +static bool present(const char* pattern, chunk_t* ch) { u_int pattern_len = strlen(pattern); @@ -52,29 +54,33 @@ present(const char* pattern, chunk_t* ch) return FALSE; } -/* - * compare string with chunk +/** + * Compare string with chunk */ -static bool -match(const char *pattern, const chunk_t *ch) +static bool match(const char *pattern, const chunk_t *ch) { return ch->len == strlen(pattern) && strneq(pattern, ch->ptr, ch->len); } -/* - * find a boundary of the form -----tag name----- +/** + * Find a boundary of the form -----tag name----- */ -static bool -find_boundary(const char* tag, chunk_t *line) +static bool find_boundary(const char* tag, chunk_t *line) { chunk_t name = chunk_empty; if (!present("-----", line)) + { return FALSE; + } if (!present(tag, line)) + { return FALSE; + } if (*line->ptr != ' ') + { return FALSE; + } line->ptr++; line->len--; /* extract name */ @@ -94,11 +100,10 @@ find_boundary(const char* tag, chunk_t *line) return FALSE; } -/* - * eat whitespace +/** + * Eat whitespace */ -static void -eat_whitespace(chunk_t *src) +static void eat_whitespace(chunk_t *src) { while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) { @@ -106,11 +111,10 @@ eat_whitespace(chunk_t *src) } } -/* - * extracts a token ending with a given termination symbol +/** + * Extracts a token ending with a given termination symbol */ -static bool -extract_token(chunk_t *token, char termination, chunk_t *src) +static bool extract_token(chunk_t *token, char termination, chunk_t *src) { u_char *eot = memchr(src->ptr, termination, src->len); @@ -118,7 +122,9 @@ extract_token(chunk_t *token, char termination, chunk_t *src) *token = chunk_empty; if (eot == NULL) /* termination symbol not found */ + { return FALSE; + } /* extract token */ token->ptr = src->ptr; @@ -131,11 +137,10 @@ extract_token(chunk_t *token, char termination, chunk_t *src) return TRUE; } -/* - * extracts a name: value pair from the PEM header +/** + * Extracts a name: value pair from the PEM header */ -static bool -extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) +static bool extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) { DBG(DBG_PARSING, DBG_log(" %.*s", (int)line->len, line->ptr); @@ -143,8 +148,9 @@ extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) /* extract name */ if (!extract_token(name,':', line)) + { return FALSE; - + } eat_whitespace(line); /* extract value */ @@ -152,19 +158,21 @@ extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) return TRUE; } -/* - * fetches a new line terminated by \n or \r\n +/** + * Fetches a new line terminated by \n or \r\n */ -static bool -fetchline(chunk_t *src, chunk_t *line) +static bool fetchline(chunk_t *src, chunk_t *line) { if (src->len == 0) /* end of src reached */ + { return FALSE; - + } if (extract_token(line, '\n', src)) { if (line->len > 0 && *(line->ptr + line->len -1) == '\r') + { line->len--; /* remove optional \r */ + } } else /*last line ends without newline */ { @@ -175,35 +183,39 @@ fetchline(chunk_t *src, chunk_t *line) return TRUE; } -/* - * decrypts a DES-EDE-CBC encrypted data block +/** + * Decrypts a DES-EDE-CBC encrypted data block */ -static bool -pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase) +static bool pem_decrypt_3des(chunk_t *blob, chunk_t *iv, char *passphrase) { - MD5_CTX context; - u_char digest[MD5_DIGEST_SIZE]; u_char des_iv[DES_CBC_BLOCK_SIZE]; u_char key[24]; des_cblock *deskey = (des_cblock *)key; des_key_schedule ks[3]; u_char padding, *last_padding_pos, *first_padding_pos; + hasher_t *hasher; + chunk_t digest; + chunk_t passphrase_chunk = { passphrase, strlen(passphrase) }; /* Convert passphrase to 3des key */ - MD5Init(&context); - MD5Update(&context, passphrase, strlen(passphrase)); - MD5Update(&context, iv->ptr, iv->len); - MD5Final(digest, &context); + hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); + if (hasher == NULL) + { + plog(" passphrase could not be hashed, no MD5 hasher available"); + return FALSE; + } + hasher->allocate_hash(hasher, passphrase_chunk, NULL); + hasher->allocate_hash(hasher, *iv, &digest); - memcpy(key, digest, MD5_DIGEST_SIZE); + memcpy(key, digest.ptr, digest.len); - MD5Init(&context); - MD5Update(&context, digest, MD5_DIGEST_SIZE); - MD5Update(&context, passphrase, strlen(passphrase)); - MD5Update(&context, iv->ptr, iv->len); - MD5Final(digest, &context); + hasher->get_hash(hasher, digest, NULL); + hasher->get_hash(hasher, passphrase_chunk, NULL); + hasher->get_hash(hasher, *iv, digest.ptr); + hasher->destroy(hasher); - memcpy(key + MD5_DIGEST_SIZE, digest, 24 - MD5_DIGEST_SIZE); + memcpy(key + digest.len, digest.ptr, 24 - digest.len); + free(digest.ptr); (void) des_set_key(&deskey[0], ks[0]); (void) des_set_key(&deskey[1], ks[1]); @@ -224,7 +236,9 @@ pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase) while (--last_padding_pos > first_padding_pos) { if (*last_padding_pos != padding) + { return FALSE; + } } /* remove padding */ @@ -232,21 +246,24 @@ pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase) return TRUE; } -/* - * optionally prompts for a passphrase before decryption +/** + * Optionally prompts for a passphrase before decryption * currently we support DES-EDE3-CBC, only */ -static err_t -pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) +static err_t pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, + const char* label) { DBG(DBG_CRYPT, DBG_log(" decrypting file using 'DES-EDE3-CBC'"); ) if (iv->len != DES_CBC_BLOCK_SIZE) + { return "size of DES-EDE3-CBC IV is not 8 bytes"; - + } if (pass == NULL) + { return "no passphrase available"; + } /* do we prompt for the passphrase? */ if (pass->prompt && pass->fd != NULL_FD) @@ -262,8 +279,9 @@ pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) int n; if (i > 0) - whack_log(RC_ENTERSECRET, "invalid passphrase, please try again"); - + { + whack_log(RC_ENTERSECRET, "invalid passphrase, please try again"); + } n = read(pass->fd, pass->secret, PROMPT_PASS_LEN); if (n == -1) @@ -303,9 +321,13 @@ pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) else { if (pem_decrypt_3des(blob, iv, pass->secret)) + { return NULL; + } else + { return "invalid passphrase"; + } } } @@ -314,8 +336,7 @@ pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993 * RFC 934 Message Encapsulation, January 1985 */ -err_t -pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) +err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) { typedef enum { PEM_PRE = 0, @@ -381,10 +402,13 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) /* we are looking for a name: value pair */ if (!extract_parameter(&name, &value, &line)) + { continue; - + } if (match("Proc-Type", &name) && *value.ptr == '4') - encrypted = TRUE; + { + encrypted = TRUE; + } else if (match("DEK-Info", &name)) { const char *ugh = NULL; @@ -392,18 +416,22 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) chunk_t dek; if (!extract_token(&dek, ',', &value)) + { dek = value; + } /* we support DES-EDE3-CBC encrypted files, only */ if (!match("DES-EDE3-CBC", &dek)) + { return "we support DES-EDE3-CBC encrypted files, only"; - + } eat_whitespace(&value); ugh = ttodata(value.ptr, value.len, 16, iv.ptr, MAX_DIGEST_LEN, &len); if (ugh) + { return "error in IV"; - + } iv.len = len; } } @@ -415,7 +443,9 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) /* remove any trailing whitespace */ if (!extract_token(&data ,' ', &line)) + { data = line; + } /* check for PGP armor checksum */ if (*data.ptr == '=') @@ -451,10 +481,15 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) blob->len = dst.len; if (state != PEM_POST) + { return "file coded in unknown format, discarded"; - + } if (encrypted) + { return pem_decrypt(blob, &iv, pass, label); + } else + { return NULL; + } } diff --git a/src/pluto/pgp.c b/src/pluto/pgp.c index 514e39adb..999a771a4 100644 --- a/src/pluto/pgp.c +++ b/src/pluto/pgp.c @@ -19,6 +19,9 @@ #include #include +#include +#include + #include "constants.h" #include "defs.h" #include "mp_defs.h" @@ -26,7 +29,6 @@ #include "id.h" #include "pgp.h" #include "certs.h" -#include "md5.h" #include "whack.h" #include "pkcs1.h" #include "keys.h" @@ -246,12 +248,19 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert) if (version == 3) { + hasher_t *hasher; + /* a V3 fingerprint is the MD5 hash of modulus and public exponent */ - MD5_CTX context; - MD5Init(&context); - MD5Update(&context, cert->modulus.ptr, cert->modulus.len); - MD5Update(&context, cert->publicExponent.ptr, cert->publicExponent.len); - MD5Final(cert->fingerprint, &context); + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); + if (hasher == NULL) + { + plog(" computation of V3 key ID failed, no MD5 hasher is available"); + return FALSE; + } + hasher->get_hash(hasher, cert->modulus, NULL); + hasher->get_hash(hasher, cert->publicExponent, cert->fingerprint); + hasher->destroy(hasher); } else { diff --git a/src/pluto/pkcs1.c b/src/pluto/pkcs1.c index ba1c9e4d2..6f2ab2268 100644 --- a/src/pluto/pkcs1.c +++ b/src/pluto/pkcs1.c @@ -26,15 +26,13 @@ #include #include #include +#include #include "constants.h" #include "defs.h" #include "mp_defs.h" #include "log.h" #include "pkcs1.h" -#include "md2.h" -#include "md5.h" -#include "sha1.h" const struct fld RSA_private_field[] = { @@ -287,84 +285,27 @@ end: /** * Compute a digest over a binary blob */ -bool compute_digest(chunk_t tbs, int alg, chunk_t *digest) +bool compute_digest(chunk_t tbs, int oid, chunk_t *digest) { - switch (alg) + hasher_t *hasher; + hash_algorithm_t alg = hasher_algorithm_from_oid(oid); + + if (alg == HASH_UNKNOWN) { - case OID_MD2: - case OID_MD2_WITH_RSA: - { - MD2_CTX context; - - MD2Init(&context); - MD2Update(&context, tbs.ptr, tbs.len); - MD2Final(digest->ptr, &context); - digest->len = MD2_DIGEST_SIZE; - return TRUE; - } - case OID_MD5: - case OID_MD5_WITH_RSA: - { - MD5_CTX context; - - MD5Init(&context); - MD5Update(&context, tbs.ptr, tbs.len); - MD5Final(digest->ptr, &context); - digest->len = MD5_DIGEST_SIZE; - return TRUE; - } - case OID_SHA1: - case OID_SHA1_WITH_RSA: - case OID_SHA1_WITH_RSA_OIW: - { - SHA1_CTX context; - - SHA1Init(&context); - SHA1Update(&context, tbs.ptr, tbs.len); - SHA1Final(digest->ptr, &context); - digest->len = SHA1_DIGEST_SIZE; - return TRUE; - } - case OID_SHA256: - case OID_SHA256_WITH_RSA: - { - sha256_context context; - - sha256_init(&context); - sha256_write(&context, tbs.ptr, tbs.len); - sha256_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_256_DIGEST_SIZE); - digest->len = SHA2_256_DIGEST_SIZE; - return TRUE; - } - case OID_SHA384: - case OID_SHA384_WITH_RSA: - { - sha512_context context; - - sha384_init(&context); - sha512_write(&context, tbs.ptr, tbs.len); - sha512_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_384_DIGEST_SIZE); - digest->len = SHA2_384_DIGEST_SIZE; - return TRUE; - } - case OID_SHA512: - case OID_SHA512_WITH_RSA: - { - sha512_context context; - - sha512_init(&context); - sha512_write(&context, tbs.ptr, tbs.len); - sha512_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_512_DIGEST_SIZE); - digest->len = SHA2_512_DIGEST_SIZE; - return TRUE; - } - default: digest->len = 0; return FALSE; } + + hasher = lib->crypto->create_hasher(lib->crypto, alg); + if (hasher == NULL) + { + digest->len = 0; + return FALSE; + } + digest->len = hasher->get_hash_size(hasher); + hasher->get_hash(hasher, tbs, digest->ptr); + hasher->destroy(hasher); + return TRUE; } /** diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index d19a75c42..618c09b07 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -66,9 +66,7 @@ #include "crl.h" #include "fetch.h" #include "xauth.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" #include "nat_traversal.h" #include "virtual.h" #include "timer.h" diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c index 3b75c1dbc..6bcc3f117 100644 --- a/src/pluto/spdb.c +++ b/src/pluto/spdb.c @@ -34,9 +34,7 @@ #include "log.h" #include "spdb.h" #include "whack.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" #include "alg_info.h" #include "kernel_alg.h" #include "ike_alg.h" diff --git a/src/pluto/state.c b/src/pluto/state.c index 937418104..b19b2cae5 100644 --- a/src/pluto/state.c +++ b/src/pluto/state.c @@ -41,10 +41,7 @@ #include "whack.h" #include "demux.h" /* needs packet.h */ #include "ipsec_doi.h" /* needs demux.h and state.h */ - -#include "sha1.h" -#include "md5.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" /* * Global variables: had to go somewhere, might as well be this file. diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c index facc953e5..0fcf18666 100644 --- a/src/pluto/vendor.c +++ b/src/pluto/vendor.c @@ -18,10 +18,12 @@ #include #include +#include +#include + #include "constants.h" #include "defs.h" #include "log.h" -#include "md5.h" #include "connections.h" #include "packet.h" #include "demux.h" @@ -90,27 +92,24 @@ struct vid_struct { unsigned short flags; const char *data; const char *descr; - char *vid; - u_int vid_len; + chunk_t vid; }; #define DEC_MD5_VID_D(id,str,descr) \ - { VID_##id, VID_MD5HASH, str, descr, NULL, 0 }, + { VID_##id, VID_MD5HASH, str, descr, { NULL, 0 } }, #define DEC_MD5_VID(id,str) \ - { VID_##id, VID_MD5HASH, str, NULL, NULL, 0 }, -#define DEC_FSWAN_VID(id,str,descr) \ - { VID_##id, VID_FSWAN_HASH, str, descr, NULL, 0 }, + { VID_##id, VID_MD5HASH, str, NULL, { NULL, 0 } }, static struct vid_struct _vid_tab[] = { /* Implementation names */ - { VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP", NULL, 0 }, + { VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP", { NULL, 0 } }, DEC_MD5_VID(KAME_RACOON, "KAME/racoon") { VID_MS_NT5, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA, - "MS NT5 ISAKMPOAKLEY", NULL, NULL, 0 }, + "MS NT5 ISAKMPOAKLEY", NULL, { NULL, 0 } }, DEC_MD5_VID(SSH_SENTINEL, "SSH Sentinel") DEC_MD5_VID(SSH_SENTINEL_1_1, "SSH Sentinel 1.1") @@ -153,14 +152,13 @@ static struct vid_struct _vid_tab[] = { /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */ { VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity", - "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", - 16 }, + { "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", 16 } }, - { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, - NULL, "Cisco VPN 3000 Series" , "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14}, + { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "Cisco VPN 3000 Series" , + { "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14 } }, { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH, - NULL, "Cisco IOS Device", "\x3e\x98\x40\x48", 4}, + NULL, "Cisco IOS Device", { "\x3e\x98\x40\x48", 4 } }, /* * Timestep VID seen: @@ -168,31 +166,25 @@ static struct vid_struct _vid_tab[] = { * = 'TIMESTEP 1 SGW 1520 315 2.01E013' */ { VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP", - NULL, NULL, 0 }, + NULL, { NULL, 0 } }, /* * Netscreen: * 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100) */ { VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA, - "HeartBeat_Notify", "HeartBeat Notify", NULL, 0 }, - + "HeartBeat_Notify", "HeartBeat Notify", { NULL, 0 } }, /* * MacOS X */ { VID_MACOSX, VID_STRING|VID_SUBSTRING_DUMPHEXA, "Mac OSX 10.x", - "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62", NULL, 0}, + "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62", { NULL, 0 } }, - /* - * Openswan - */ - DEC_FSWAN_VID(OPENSWAN2, "Openswan 2.2.0", "Openswan 2.2.0") - /* NCP */ { VID_NCP_SERVER, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Server", - "\xc6\xf5\x7a\xc3\x98\xf4\x93\x20\x81\x45\xb7\x58", 12}, + { "\xc6\xf5\x7a\xc3\x98\xf4\x93\x20\x81\x45\xb7\x58", 12 } }, { VID_NCP_CLIENT, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Client", - "\xeb\x4c\x1b\x78\x8a\xfd\x4a\x9c\xb7\x73\x0a\x68", 12}, + { "\xeb\x4c\x1b\x78\x8a\xfd\x4a\x9c\xb7\x73\x0a\x68", 12 } }, /* * Windows Vista (and Windows Server 2008?) @@ -297,10 +289,10 @@ static struct vid_struct _vid_tab[] = { /* misc */ { VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH", - "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 }, + { "\x09\x00\x26\x89\xdf\xd6\xb7\x12", 8 } }, { VID_MISC_DPD, VID_KEEP, NULL, "Dead Peer Detection", - "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00", 16 }, + { "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00", 16 } }, DEC_MD5_VID(MISC_FRAGMENTATION, "FRAGMENTATION") @@ -310,10 +302,10 @@ static struct vid_struct _vid_tab[] = { * Cisco VPN 3000 */ { VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA, - "FRAGMENTATION", NULL, NULL, 0 }, + "FRAGMENTATION", NULL, { NULL, 0 } }, /* -- */ - { 0, 0, NULL, NULL, NULL, 0 } + { 0, 0, NULL, NULL, { NULL, 0 } } }; @@ -323,61 +315,23 @@ static int _vid_struct_init = 0; void init_vendorid(void) { + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); struct vid_struct *vid; - MD5_CTX ctx; - int i; for (vid = _vid_tab; vid->id; vid++) { if (vid->flags & VID_STRING) { /** VendorID is a string **/ - vid->vid = strdup(vid->data); - vid->vid_len = strlen(vid->data); + vid->vid = chunk_create((u_char *)vid->data, strlen(vid->data)); + vid->vid = chunk_clone(vid->vid); } else if (vid->flags & VID_MD5HASH) { + chunk_t vid_data = { (u_char *)vid->data, strlen(vid->data) }; + /** VendorID is a string to hash with MD5 **/ - char *vidm = malloc(MD5_DIGEST_SIZE); - - vid->vid = vidm; - if (vidm) - { - MD5Init(&ctx); - MD5Update(&ctx, (const u_char *)vid->data, strlen(vid->data)); - MD5Final(vidm, &ctx); - vid->vid_len = MD5_DIGEST_SIZE; - } - } - else if (vid->flags & VID_FSWAN_HASH) - { - /** FreeS/WAN 2.00+ specific hash **/ -#define FSWAN_VID_SIZE 12 - unsigned char hash[MD5_DIGEST_SIZE]; - char *vidm = malloc(FSWAN_VID_SIZE); - - vid->vid = vidm; - if (vidm) - { - MD5Init(&ctx); - MD5Update(&ctx, (const u_char *)vid->data, strlen(vid->data)); - MD5Final(hash, &ctx); - vidm[0] = 'O'; - vidm[1] = 'E'; -#if FSWAN_VID_SIZE - 2 <= MD5_DIGEST_SIZE - memcpy(vidm + 2, hash, FSWAN_VID_SIZE - 2); -#else - memcpy(vidm + 2, hash, MD5_DIGEST_SIZE); - memset(vidm + 2 + MD5_DIGEST_SIZE, '\0', - FSWAN_VID_SIZE - 2 - MD5_DIGEST_SIZE); -#endif - for (i = 2; i < FSWAN_VID_SIZE; i++) - { - vidm[i] &= 0x7f; - vidm[i] |= 0x40; - } - vid->vid_len = FSWAN_VID_SIZE; - } + hasher->allocate_hash(hasher, vid_data, &vid->vid); } if (vid->descr == NULL) @@ -386,6 +340,7 @@ void init_vendorid(void) vid->descr = vid->data; } } + hasher->destroy(hasher); _vid_struct_init = 1; } @@ -397,7 +352,7 @@ void free_vendorid(void) { if (vid->flags & (VID_STRING | VID_MD5HASH | VID_FSWAN_HASH)) { - free(vid->vid); + free(vid->vid.ptr); } } } @@ -462,7 +417,7 @@ static void handle_known_vendorid (struct msg_digest *md, const char *vidstr, memset(vid_dump, 0, sizeof(vid_dump)); snprintf(vid_dump, sizeof(vid_dump), "%s ", vid->descr ? vid->descr : ""); - for (i = strlen(vid_dump), j = vid->vid_len; + for (i = strlen(vid_dump), j = vid->vid.len; j < len && i < sizeof(vid_dump) - 2; i += 2, j++) { @@ -502,19 +457,19 @@ void handle_vendorid (struct msg_digest *md, const char *vid, size_t len) */ for (pvid = _vid_tab; pvid->id; pvid++) { - if (pvid->vid && vid && pvid->vid_len && len) + if (pvid->vid.ptr && vid && pvid->vid.len && len) { - if (pvid->vid_len == len) + if (pvid->vid.len == len) { - if (memeq(pvid->vid, vid, len)) + if (memeq(pvid->vid.ptr, vid, len)) { handle_known_vendorid(md, vid, len, pvid); return; } } - else if ((pvid->vid_len < len) && (pvid->flags & VID_SUBSTRING)) + else if ((pvid->vid.len < len) && (pvid->flags & VID_SUBSTRING)) { - if (memeq(pvid->vid, vid, pvid->vid_len)) + if (memeq(pvid->vid.ptr, vid, pvid->vid.len)) { handle_known_vendorid(md, vid, len, pvid); return; @@ -556,13 +511,13 @@ bool out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid) if (pvid->id != vid) return STF_INTERNAL_ERROR; /* not found */ - if (!pvid->vid) + if (!pvid->vid.ptr) return STF_INTERNAL_ERROR; /* not initialized */ DBG(DBG_EMITTING, DBG_log("out_vendorid(): sending [%s]", pvid->descr) ) return out_generic_raw(np, &isakmp_vendor_id_desc, outs, - pvid->vid, pvid->vid_len, "V_ID"); + pvid->vid.ptr, pvid->vid.len, "V_ID"); } diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h index 6304c5e0f..9ea5b7a11 100644 --- a/src/pluto/vendor.h +++ b/src/pluto/vendor.h @@ -47,12 +47,11 @@ enum known_vendorid { VID_TIMESTEP = 28, VID_SAFENET = 29, VID_MACOSX = 30, - VID_OPENSWAN2 = 31, - VID_NCP_SERVER = 32, - VID_NCP_CLIENT = 33, - VID_VISTA_AUTHIP = 34, - VID_VISTA_AUTHIP2 = 35, - VID_VISTA_AUTHIP3 = 36, + VID_NCP_SERVER = 31, + VID_NCP_CLIENT = 32, + VID_VISTA_AUTHIP = 33, + VID_VISTA_AUTHIP2 = 34, + VID_VISTA_AUTHIP3 = 35, VID_STRONGSWAN = 37, VID_STRONGSWAN_2_2_0 = 38, diff --git a/src/pluto/x509.c b/src/pluto/x509.c index 284011626..18e26abb6 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "constants.h" #include "defs.h" @@ -44,7 +45,6 @@ #include "whack.h" #include "fetch.h" #include "ocsp.h" -#include "sha1.h" /** * Chained lists of X.509 end certificates @@ -1488,16 +1488,18 @@ void gntoid(struct id *id, const generalName_t *gn) * Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280 * as the 160 bit SHA-1 hash of the public key */ -void compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID) +bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID) { - SHA1_CTX context; + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - SHA1Init(&context); - SHA1Update(&context - , cert->subjectPublicKey.ptr - , cert->subjectPublicKey.len); - SHA1Final(subjectKeyID.ptr, &context); - subjectKeyID.len = SHA1_DIGEST_SIZE; + if (hasher == NULL) + { + plog(" no SHA-1 hasher available to compute subjectKeyID"); + return FALSE; + } + hasher->get_hash(hasher, cert->subjectPublicKey, subjectKeyID.ptr); + hasher->destroy(hasher); + return TRUE; } /** diff --git a/src/pluto/x509.h b/src/pluto/x509.h index 7a46c5c7b..ec3203d74 100644 --- a/src/pluto/x509.h +++ b/src/pluto/x509.h @@ -108,7 +108,7 @@ extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn , const char* null_dn); extern err_t atodn(char *src, chunk_t *dn); extern void gntoid(struct id *id, const generalName_t *gn); -extern void compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID); +extern bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID); extern void select_x509cert_id(x509cert_t *cert, struct id *end_id); extern bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert); extern time_t parse_time(chunk_t blob, int level0);