SKEYID derivation based on libstrongswan

This commit is contained in:
Andreas Steffen
2009-05-05 14:28:31 +02:00
parent e868a564d9
commit 6eb9bc9bb8
22 changed files with 365 additions and 362 deletions
+4
View File
@@ -951,15 +951,18 @@ if test x$des = xtrue; then
fi fi
if test x$sha1 = xtrue; then if test x$sha1 = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" sha1" libstrongswan_plugins=${libstrongswan_plugins}" sha1"
pluto_plugins=${pluto_plugins}" sha1"
fi fi
if test x$sha2 = xtrue; then if test x$sha2 = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" sha2" libstrongswan_plugins=${libstrongswan_plugins}" sha2"
pluto_plugins=${pluto_plugins}" sha2"
fi fi
if test x$md4 = xtrue; then if test x$md4 = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" md4" libstrongswan_plugins=${libstrongswan_plugins}" md4"
fi fi
if test x$md5 = xtrue; then if test x$md5 = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" md5" libstrongswan_plugins=${libstrongswan_plugins}" md5"
pluto_plugins=${pluto_plugins}" md5"
fi fi
if test x$fips_prf = xtrue; then if test x$fips_prf = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" fips-prf" libstrongswan_plugins=${libstrongswan_plugins}" fips-prf"
@@ -979,6 +982,7 @@ if test x$xcbc = xtrue; then
fi fi
if test x$hmac = xtrue; then if test x$hmac = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" hmac" libstrongswan_plugins=${libstrongswan_plugins}" hmac"
pluto_plugins=${pluto_plugins}" hmac"
fi fi
if test x$mysql = xtrue; then if test x$mysql = xtrue; then
libstrongswan_plugins=${libstrongswan_plugins}" mysql" libstrongswan_plugins=${libstrongswan_plugins}" mysql"
-2
View File
@@ -33,8 +33,6 @@
#include "defs.h" #include "defs.h"
#include "log.h" #include "log.h"
#include "whack.h" #include "whack.h"
#include "sha1.h"
#include "md5.h"
#include "crypto.h" #include "crypto.h"
#include "kernel_alg.h" #include "kernel_alg.h"
#include "ike_alg.h" #include "ike_alg.h"
+15 -14
View File
@@ -26,7 +26,6 @@
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "sha1.h"
#include "cookie.h" #include "cookie.h"
const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ 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. * First argument is true if we're to create an Initiator cookie.
* Length SHOULD be a multiple of sizeof(u_int32_t). * Length SHOULD be a multiple of sizeof(u_int32_t).
*/ */
void get_cookie(bool initiator, u_int8_t *cookie, int length, void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr)
const ip_address *addr)
{ {
u_char buffer[SHA1_DIGEST_SIZE]; hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
SHA1_CTX ctx; u_char buffer[HASH_SIZE_SHA1];
do { do {
if (initiator) if (initiator)
@@ -52,20 +50,23 @@ void get_cookie(bool initiator, u_int8_t *cookie, int length,
} }
else /* Responder cookie */ else /* Responder cookie */
{ {
/* This looks as good as any way */ chunk_t addr_chunk, secret_chunk, counter_chunk;
size_t addr_length; size_t addr_len;
static u_int32_t counter = 0; static u_int32_t counter = 0;
unsigned char addr_buff[ unsigned char addr_buf[
sizeof(union {struct in_addr A; struct in6_addr B;})]; sizeof(union {struct in_addr A; struct in6_addr B;})];
addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff)); addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf));
SHA1Init(&ctx); addr_chunk = chunk_create(addr_buf, addr_len);
SHA1Update(&ctx, addr_buff, addr_length); secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1);
SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day));
counter++; counter++;
SHA1Update(&ctx, (const void *) &counter, sizeof(counter)); counter_chunk = chunk_create((void *) &counter, sizeof(counter));
SHA1Final(buffer, &ctx); 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); memcpy(cookie, buffer, length);
} }
} while (is_zero_cookie(cookie)); /* probably never loops */ } while (is_zero_cookie(cookie)); /* probably never loops */
hasher->destroy(hasher);
} }
+2 -2
View File
@@ -16,7 +16,7 @@
extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
extern void get_cookie(bool initiator, u_int8_t *cookie, int length extern void get_cookie(bool initiator, u_int8_t *cookie, int length,
, const ip_address *addr); ip_address *addr);
#define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE) #define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE)
+18 -10
View File
@@ -28,6 +28,7 @@
#include <asn1/asn1.h> #include <asn1/asn1.h>
#include <asn1/asn1_parser.h> #include <asn1/asn1_parser.h>
#include <asn1/oid.h> #include <asn1/oid.h>
#include <crypto/hashers/hasher.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
@@ -39,7 +40,7 @@
#include "keys.h" #include "keys.h"
#include "whack.h" #include "whack.h"
#include "fetch.h" #include "fetch.h"
#include "sha1.h"
/* chained lists of X.509 crls */ /* 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) if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
{ {
char path[BUF_LEN]; char path[BUF_LEN], buf[BUF_LEN];
char buf[BUF_LEN]; char digest_buf[HASH_SIZE_SHA1];
char digest_buf[SHA1_DIGEST_SIZE]; chunk_t subjectKeyID = chunk_from_buf(digest_buf);
chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE }; bool has_keyID;
if (issuer_cert->subjectKeyID.ptr == NULL) if (issuer_cert->subjectKeyID.ptr == NULL)
compute_subjectKeyID(issuer_cert, subjectKeyID); {
has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID);
}
else else
{
subjectKeyID = issuer_cert->subjectKeyID; subjectKeyID = issuer_cert->subjectKeyID;
has_keyID = TRUE;
datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN); }
snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf); if (has_keyID)
chunk_write(crl->certificateList, path, "crl", 0022, TRUE); {
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? */ /* is the fetched crl valid? */
+51 -23
View File
@@ -28,9 +28,7 @@
#include "defs.h" #include "defs.h"
#include "state.h" #include "state.h"
#include "log.h" #include "log.h"
#include "md5.h" #include "crypto.h"
#include "sha1.h"
#include "crypto.h" /* requires sha1.h and md5.h */
#include "alg_info.h" #include "alg_info.h"
#include "ike_alg.h" #include "ike_alg.h"
@@ -451,8 +449,7 @@ static struct hash_desc crypto_hasher_sha1 =
hash_final: (void (*)(u_char *, void *)) SHA1Final hash_final: (void (*)(u_char *, void *)) SHA1Final
}; };
void void init_crypto(void)
init_crypto(void)
{ {
if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0 if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0
|| mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0 || mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0
@@ -471,8 +468,7 @@ init_crypto(void)
ike_alg_test(); ike_alg_test();
} }
void void free_crypto(void)
free_crypto(void)
{ {
mpz_clear(&groupgenerator); mpz_clear(&groupgenerator);
mpz_clear(&modp1024_modulus); mpz_clear(&modp1024_modulus);
@@ -503,8 +499,7 @@ const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE] = {
# undef BYTES # undef BYTES
}; };
const struct oakley_group_desc * const struct oakley_group_desc *lookup_group(u_int16_t group)
lookup_group(u_int16_t group)
{ {
int i; 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 /* encrypt or decrypt part of an IKE message using 3DES
* See RFC 2409 "IKE" Appendix B * See RFC 2409 "IKE" Appendix B
*/ */
static void static void do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key,
do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc) size_t key_size, u_int8_t *iv, bool enc)
{ {
des_key_schedule ks[3]; 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 */ /* hash and prf routines */
void void crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf,
crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st) size_t size, struct state *st)
{ {
passert(st->st_new_iv_len >= e->enc_blocksize); passert(st->st_new_iv_len >= e->enc_blocksize);
st->st_new_iv_len = e->enc_blocksize; /* truncate */ 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. * rfc2104.txt specifies how HMAC works.
*/ */
void void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h,
hmac_init(struct hmac_ctx *ctx, const u_char *key, size_t key_len)
const struct hash_desc *h,
const u_char *key, size_t key_len)
{ {
int k; int k;
@@ -610,22 +603,19 @@ hmac_init(struct hmac_ctx *ctx,
hmac_reinit(ctx); hmac_reinit(ctx);
} }
void void hmac_reinit(struct hmac_ctx *ctx)
hmac_reinit(struct hmac_ctx *ctx)
{ {
ctx->h->hash_init(&ctx->hash_ctx); ctx->h->hash_init(&ctx->hash_ctx);
ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size); ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size);
} }
void void hmac_update(struct hmac_ctx *ctx,
hmac_update(struct hmac_ctx *ctx,
const u_char *data, size_t data_len) const u_char *data, size_t data_len)
{ {
ctx->h->hash_update(&ctx->hash_ctx, data, data_len); ctx->h->hash_update(&ctx->hash_ctx, data, data_len);
} }
void void hmac_final(u_char *output, struct hmac_ctx *ctx)
hmac_final(u_char *output, struct hmac_ctx *ctx)
{ {
const struct hash_desc *h = ctx->h; 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_update(&ctx->hash_ctx, output, h->hash_digest_size);
h->hash_final(output, &ctx->hash_ctx); 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;
}
}
+9
View File
@@ -14,6 +14,11 @@
#include <gmp.h> /* GNU MP library */ #include <gmp.h> /* GNU MP library */
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include "md5.h"
#include "sha1.h"
#include "libsha2/sha2.h" #include "libsha2/sha2.h"
#include "ike_alg.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); \ (ch).ptr = malloc((ch).len); \
hmac_final((ch).ptr, (ctx)); \ 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 #endif
+1 -3
View File
@@ -130,9 +130,7 @@
#include "connections.h" #include "connections.h"
#include "state.h" #include "state.h"
#include "packet.h" #include "packet.h"
#include "md5.h" #include "crypto.h"
#include "sha1.h"
#include "crypto.h" /* requires sha1.h and md5.h */
#include "ike_alg.h" #include "ike_alg.h"
#include "log.h" #include "log.h"
#include "demux.h" /* needs packet.h */ #include "demux.h" /* needs packet.h */
-2
View File
@@ -23,8 +23,6 @@
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "sha1.h"
#include "md5.h"
#include "crypto.h" #include "crypto.h"
#include "state.h" #include "state.h"
+78 -49
View File
@@ -31,6 +31,8 @@
#include <library.h> #include <library.h>
#include <asn1/asn1.h> #include <asn1/asn1.h>
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <crypto/rngs/rng.h> #include <crypto/rngs/rng.h>
#include "constants.h" #include "constants.h"
@@ -59,10 +61,7 @@
#include "whack.h" #include "whack.h"
#include "fetch.h" #include "fetch.h"
#include "pkcs7.h" #include "pkcs7.h"
#include "crypto.h"
#include "sha1.h"
#include "md5.h"
#include "crypto.h" /* requires sha1.h and md5.h */
#include "vendor.h" #include "vendor.h"
#include "alg_info.h" #include "alg_info.h"
#include "ike_alg.h" #include "ike_alg.h"
@@ -1166,12 +1165,22 @@ static bool skeyid_preshared(struct state *st)
} }
else else
{ {
struct hmac_ctx ctx; pseudo_random_function_t prf_alg;
prf_t *prf;
hmac_init_chunk(&ctx, st->st_oakley.hasher, *pss); prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
hmac_update_chunk(&ctx, st->st_ni); prf = lib->crypto->create_prf(lib->crypto, prf_alg);
hmac_update_chunk(&ctx, st->st_nr); if (prf == NULL)
hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_preshared()", &ctx); {
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; return TRUE;
} }
} }
@@ -1179,21 +1188,24 @@ static bool skeyid_preshared(struct state *st)
static bool static bool
skeyid_digisig(struct state *st) skeyid_digisig(struct state *st)
{ {
struct hmac_ctx ctx;
chunk_t nir; 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, prf_alg = oakley_to_prf(st->st_oakley.hasher->algo_id);
* so we have to build a temporary concatentation. prf = lib->crypto->create_prf(lib->crypto, prf_alg);
*/ if (prf == NULL)
nir.len = st->st_ni.len + st->st_nr.len; {
nir.ptr = malloc(nir.len); loglog(RC_LOG_SERIOUS, "%N not available to compute skeyid",
memcpy(nir.ptr, st->st_ni.ptr, st->st_ni.len); pseudo_random_function_names, prf_alg);
memcpy(nir.ptr+st->st_ni.len, st->st_nr.ptr, st->st_nr.len); return FALSE;
hmac_init_chunk(&ctx, st->st_oakley.hasher, nir); }
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); free(nir.ptr);
hmac_update_chunk(&ctx, st->st_shared);
hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_digisig()", &ctx);
return TRUE; return TRUE;
} }
@@ -1209,14 +1221,18 @@ static bool generate_skeyids_iv(struct state *st)
case XAUTHInitPreShared: case XAUTHInitPreShared:
case XAUTHRespPreShared: case XAUTHRespPreShared:
if (!skeyid_preshared(st)) if (!skeyid_preshared(st))
{
return FALSE; return FALSE;
}
break; break;
case OAKLEY_RSA_SIG: case OAKLEY_RSA_SIG:
case XAUTHInitRSA: case XAUTHInitRSA:
case XAUTHRespRSA: case XAUTHRespRSA:
if (!skeyid_digisig(st)) if (!skeyid_digisig(st))
{
return FALSE; return FALSE;
}
break; break;
case OAKLEY_DSS_SIG: case OAKLEY_DSS_SIG:
@@ -1234,52 +1250,65 @@ static bool generate_skeyids_iv(struct state *st)
/* generate SKEYID_* from SKEYID */ /* 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 */ /* SKEYID_D */
hmac_update_chunk(&ctx, st->st_shared); free(st->st_skeyid_d.ptr);
hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); prf->allocate_bytes(prf, st->st_shared, NULL);
hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); prf->allocate_bytes(prf, icookie, NULL);
hmac_update(&ctx, "\0", 1); prf->allocate_bytes(prf, rcookie, NULL);
hmac_final_chunk(st->st_skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx); prf->allocate_bytes(prf, seed_skeyid_d, &st->st_skeyid_d);
/* SKEYID_A */ /* SKEYID_A */
hmac_reinit(&ctx); free(st->st_skeyid_a.ptr);
hmac_update_chunk(&ctx, st->st_skeyid_d); prf->allocate_bytes(prf, st->st_skeyid_d, NULL);
hmac_update_chunk(&ctx, st->st_shared); prf->allocate_bytes(prf, st->st_shared, NULL);
hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); prf->allocate_bytes(prf, icookie, NULL);
hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); prf->allocate_bytes(prf, rcookie, NULL);
hmac_update(&ctx, "\1", 1); prf->allocate_bytes(prf, seed_skeyid_a, &st->st_skeyid_a);
hmac_final_chunk(st->st_skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx);
/* SKEYID_E */ /* SKEYID_E */
hmac_reinit(&ctx); free(st->st_skeyid_e.ptr);
hmac_update_chunk(&ctx, st->st_skeyid_a); prf->allocate_bytes(prf, st->st_skeyid_a, NULL);
hmac_update_chunk(&ctx, st->st_shared); prf->allocate_bytes(prf, st->st_shared, NULL);
hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); prf->allocate_bytes(prf, icookie, NULL);
hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); prf->allocate_bytes(prf, rcookie, NULL);
hmac_update(&ctx, "\2", 1); prf->allocate_bytes(prf, seed_skeyid_e, &st->st_skeyid_e);
hmac_final_chunk(st->st_skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx);
prf->destroy(prf);
} }
/* generate IV */ /* generate IV */
{ {
union hash_ctx hash_ctx; hash_algorithm_t hash_alg;
const struct hash_desc *h = st->st_oakley.hasher; 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)); passert(st->st_new_iv_len <= sizeof(st->st_new_iv));
DBG(DBG_CRYPT, DBG(DBG_CRYPT,
DBG_dump_chunk("DH_i:", st->st_gi); DBG_dump_chunk("DH_i:", st->st_gi);
DBG_dump_chunk("DH_r:", st->st_gr); 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); hasher->get_hash(hasher, st->st_gi, NULL);
h->hash_update(&hash_ctx, st->st_gr.ptr, st->st_gr.len); hasher->get_hash(hasher, st->st_gr, st->st_new_iv);
h->hash_final(st->st_new_iv, &hash_ctx); hasher->destroy(hasher);
} }
/* Oakley Keying Material /* Oakley Keying Material
-2
View File
@@ -33,8 +33,6 @@
#include "timer.h" #include "timer.h"
#include "ipsec_doi.h" #include "ipsec_doi.h"
#include "log.h" #include "log.h"
#include "md5.h"
#include "sha1.h"
#include "crypto.h" #include "crypto.h"
#include "modecfg.h" #include "modecfg.h"
#include "whack.h" #include "whack.h"
-2
View File
@@ -40,8 +40,6 @@
#include "whack.h" #include "whack.h"
#include "timer.h" #include "timer.h"
#include "cookie.h" #include "cookie.h"
#include "sha1.h"
#include "md5.h"
#include "crypto.h" #include "crypto.h"
#include "vendor.h" #include "vendor.h"
#include "ike_alg.h" #include "ike_alg.h"
+97 -62
View File
@@ -25,21 +25,23 @@
#include <sys/types.h> #include <sys/types.h>
#include <freeswan.h> #include <freeswan.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
#define HEADER_DES_LOCL_H /* stupid trick to force prototype decl in <des.h> */ #define HEADER_DES_LOCL_H /* stupid trick to force prototype decl in <des.h> */
#include <libdes/des.h> #include <libdes/des.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "log.h" #include "log.h"
#include "md5.h"
#include "whack.h" #include "whack.h"
#include "pem.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 static bool present(const char* pattern, chunk_t* ch)
present(const char* pattern, chunk_t* ch)
{ {
u_int pattern_len = strlen(pattern); u_int pattern_len = strlen(pattern);
@@ -52,29 +54,33 @@ present(const char* pattern, chunk_t* ch)
return FALSE; return FALSE;
} }
/* /**
* compare string with chunk * Compare string with chunk
*/ */
static bool static bool match(const char *pattern, const chunk_t *ch)
match(const char *pattern, const chunk_t *ch)
{ {
return ch->len == strlen(pattern) && strneq(pattern, ch->ptr, ch->len); 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 static bool find_boundary(const char* tag, chunk_t *line)
find_boundary(const char* tag, chunk_t *line)
{ {
chunk_t name = chunk_empty; chunk_t name = chunk_empty;
if (!present("-----", line)) if (!present("-----", line))
{
return FALSE; return FALSE;
}
if (!present(tag, line)) if (!present(tag, line))
{
return FALSE; return FALSE;
}
if (*line->ptr != ' ') if (*line->ptr != ' ')
{
return FALSE; return FALSE;
}
line->ptr++; line->len--; line->ptr++; line->len--;
/* extract name */ /* extract name */
@@ -94,11 +100,10 @@ find_boundary(const char* tag, chunk_t *line)
return FALSE; return FALSE;
} }
/* /**
* eat whitespace * Eat whitespace
*/ */
static void static void eat_whitespace(chunk_t *src)
eat_whitespace(chunk_t *src)
{ {
while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) 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 static bool extract_token(chunk_t *token, char termination, chunk_t *src)
extract_token(chunk_t *token, char termination, chunk_t *src)
{ {
u_char *eot = memchr(src->ptr, termination, src->len); 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; *token = chunk_empty;
if (eot == NULL) /* termination symbol not found */ if (eot == NULL) /* termination symbol not found */
{
return FALSE; return FALSE;
}
/* extract token */ /* extract token */
token->ptr = src->ptr; token->ptr = src->ptr;
@@ -131,11 +137,10 @@ extract_token(chunk_t *token, char termination, chunk_t *src)
return TRUE; return TRUE;
} }
/* /**
* extracts a name: value pair from the PEM header * Extracts a name: value pair from the PEM header
*/ */
static bool static bool extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line)
extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line)
{ {
DBG(DBG_PARSING, DBG(DBG_PARSING,
DBG_log(" %.*s", (int)line->len, line->ptr); 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 */ /* extract name */
if (!extract_token(name,':', line)) if (!extract_token(name,':', line))
{
return FALSE; return FALSE;
}
eat_whitespace(line); eat_whitespace(line);
/* extract value */ /* extract value */
@@ -152,19 +158,21 @@ extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line)
return TRUE; return TRUE;
} }
/* /**
* fetches a new line terminated by \n or \r\n * Fetches a new line terminated by \n or \r\n
*/ */
static bool static bool fetchline(chunk_t *src, chunk_t *line)
fetchline(chunk_t *src, chunk_t *line)
{ {
if (src->len == 0) /* end of src reached */ if (src->len == 0) /* end of src reached */
{
return FALSE; return FALSE;
}
if (extract_token(line, '\n', src)) if (extract_token(line, '\n', src))
{ {
if (line->len > 0 && *(line->ptr + line->len -1) == '\r') if (line->len > 0 && *(line->ptr + line->len -1) == '\r')
{
line->len--; /* remove optional \r */ line->len--; /* remove optional \r */
}
} }
else /*last line ends without newline */ else /*last line ends without newline */
{ {
@@ -175,35 +183,39 @@ fetchline(chunk_t *src, chunk_t *line)
return TRUE; return TRUE;
} }
/* /**
* decrypts a DES-EDE-CBC encrypted data block * Decrypts a DES-EDE-CBC encrypted data block
*/ */
static bool static bool pem_decrypt_3des(chunk_t *blob, chunk_t *iv, char *passphrase)
pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase)
{ {
MD5_CTX context;
u_char digest[MD5_DIGEST_SIZE];
u_char des_iv[DES_CBC_BLOCK_SIZE]; u_char des_iv[DES_CBC_BLOCK_SIZE];
u_char key[24]; u_char key[24];
des_cblock *deskey = (des_cblock *)key; des_cblock *deskey = (des_cblock *)key;
des_key_schedule ks[3]; des_key_schedule ks[3];
u_char padding, *last_padding_pos, *first_padding_pos; 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 */ /* Convert passphrase to 3des key */
MD5Init(&context); hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
MD5Update(&context, passphrase, strlen(passphrase)); if (hasher == NULL)
MD5Update(&context, iv->ptr, iv->len); {
MD5Final(digest, &context); 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); hasher->get_hash(hasher, digest, NULL);
MD5Update(&context, digest, MD5_DIGEST_SIZE); hasher->get_hash(hasher, passphrase_chunk, NULL);
MD5Update(&context, passphrase, strlen(passphrase)); hasher->get_hash(hasher, *iv, digest.ptr);
MD5Update(&context, iv->ptr, iv->len); hasher->destroy(hasher);
MD5Final(digest, &context);
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[0], ks[0]);
(void) des_set_key(&deskey[1], ks[1]); (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) while (--last_padding_pos > first_padding_pos)
{ {
if (*last_padding_pos != padding) if (*last_padding_pos != padding)
{
return FALSE; return FALSE;
}
} }
/* remove padding */ /* remove padding */
@@ -232,21 +246,24 @@ pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase)
return TRUE; return TRUE;
} }
/* /**
* optionally prompts for a passphrase before decryption * Optionally prompts for a passphrase before decryption
* currently we support DES-EDE3-CBC, only * currently we support DES-EDE3-CBC, only
*/ */
static err_t static err_t pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass,
pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) const char* label)
{ {
DBG(DBG_CRYPT, DBG(DBG_CRYPT,
DBG_log(" decrypting file using 'DES-EDE3-CBC'"); DBG_log(" decrypting file using 'DES-EDE3-CBC'");
) )
if (iv->len != DES_CBC_BLOCK_SIZE) if (iv->len != DES_CBC_BLOCK_SIZE)
{
return "size of DES-EDE3-CBC IV is not 8 bytes"; return "size of DES-EDE3-CBC IV is not 8 bytes";
}
if (pass == NULL) if (pass == NULL)
{
return "no passphrase available"; return "no passphrase available";
}
/* do we prompt for the passphrase? */ /* do we prompt for the passphrase? */
if (pass->prompt && pass->fd != NULL_FD) 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; int n;
if (i > 0) 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); n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
if (n == -1) if (n == -1)
@@ -303,9 +321,13 @@ pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label)
else else
{ {
if (pem_decrypt_3des(blob, iv, pass->secret)) if (pem_decrypt_3des(blob, iv, pass->secret))
{
return NULL; return NULL;
}
else else
{
return "invalid passphrase"; 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 1421 Privacy Enhancement for Electronic Mail, February 1993
* RFC 934 Message Encapsulation, January 1985 * RFC 934 Message Encapsulation, January 1985
*/ */
err_t err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
{ {
typedef enum { typedef enum {
PEM_PRE = 0, 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 */ /* we are looking for a name: value pair */
if (!extract_parameter(&name, &value, &line)) if (!extract_parameter(&name, &value, &line))
{
continue; continue;
}
if (match("Proc-Type", &name) && *value.ptr == '4') if (match("Proc-Type", &name) && *value.ptr == '4')
encrypted = TRUE; {
encrypted = TRUE;
}
else if (match("DEK-Info", &name)) else if (match("DEK-Info", &name))
{ {
const char *ugh = NULL; const char *ugh = NULL;
@@ -392,18 +416,22 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
chunk_t dek; chunk_t dek;
if (!extract_token(&dek, ',', &value)) if (!extract_token(&dek, ',', &value))
{
dek = value; dek = value;
}
/* we support DES-EDE3-CBC encrypted files, only */ /* we support DES-EDE3-CBC encrypted files, only */
if (!match("DES-EDE3-CBC", &dek)) if (!match("DES-EDE3-CBC", &dek))
{
return "we support DES-EDE3-CBC encrypted files, only"; return "we support DES-EDE3-CBC encrypted files, only";
}
eat_whitespace(&value); eat_whitespace(&value);
ugh = ttodata(value.ptr, value.len, 16, ugh = ttodata(value.ptr, value.len, 16,
iv.ptr, MAX_DIGEST_LEN, &len); iv.ptr, MAX_DIGEST_LEN, &len);
if (ugh) if (ugh)
{
return "error in IV"; return "error in IV";
}
iv.len = len; iv.len = len;
} }
} }
@@ -415,7 +443,9 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
/* remove any trailing whitespace */ /* remove any trailing whitespace */
if (!extract_token(&data ,' ', &line)) if (!extract_token(&data ,' ', &line))
{
data = line; data = line;
}
/* check for PGP armor checksum */ /* check for PGP armor checksum */
if (*data.ptr == '=') if (*data.ptr == '=')
@@ -451,10 +481,15 @@ pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
blob->len = dst.len; blob->len = dst.len;
if (state != PEM_POST) if (state != PEM_POST)
{
return "file coded in unknown format, discarded"; return "file coded in unknown format, discarded";
}
if (encrypted) if (encrypted)
{
return pem_decrypt(blob, &iv, pass, label); return pem_decrypt(blob, &iv, pass, label);
}
else else
{
return NULL; return NULL;
}
} }
+15 -6
View File
@@ -19,6 +19,9 @@
#include <freeswan.h> #include <freeswan.h>
#include <ipsec_policy.h> #include <ipsec_policy.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "mp_defs.h" #include "mp_defs.h"
@@ -26,7 +29,6 @@
#include "id.h" #include "id.h"
#include "pgp.h" #include "pgp.h"
#include "certs.h" #include "certs.h"
#include "md5.h"
#include "whack.h" #include "whack.h"
#include "pkcs1.h" #include "pkcs1.h"
#include "keys.h" #include "keys.h"
@@ -246,12 +248,19 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
if (version == 3) if (version == 3)
{ {
hasher_t *hasher;
/* a V3 fingerprint is the MD5 hash of modulus and public exponent */ /* a V3 fingerprint is the MD5 hash of modulus and public exponent */
MD5_CTX context;
MD5Init(&context); hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
MD5Update(&context, cert->modulus.ptr, cert->modulus.len); if (hasher == NULL)
MD5Update(&context, cert->publicExponent.ptr, cert->publicExponent.len); {
MD5Final(cert->fingerprint, &context); 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 else
{ {
+17 -76
View File
@@ -26,15 +26,13 @@
#include <asn1/asn1_parser.h> #include <asn1/asn1_parser.h>
#include <asn1/oid.h> #include <asn1/oid.h>
#include <crypto/rngs/rng.h> #include <crypto/rngs/rng.h>
#include <crypto/hashers/hasher.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "mp_defs.h" #include "mp_defs.h"
#include "log.h" #include "log.h"
#include "pkcs1.h" #include "pkcs1.h"
#include "md2.h"
#include "md5.h"
#include "sha1.h"
const struct fld RSA_private_field[] = const struct fld RSA_private_field[] =
{ {
@@ -287,84 +285,27 @@ end:
/** /**
* Compute a digest over a binary blob * 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; digest->len = 0;
return FALSE; 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;
} }
/** /**
+1 -3
View File
@@ -66,9 +66,7 @@
#include "crl.h" #include "crl.h"
#include "fetch.h" #include "fetch.h"
#include "xauth.h" #include "xauth.h"
#include "sha1.h" #include "crypto.h"
#include "md5.h"
#include "crypto.h" /* requires sha1.h and md5.h */
#include "nat_traversal.h" #include "nat_traversal.h"
#include "virtual.h" #include "virtual.h"
#include "timer.h" #include "timer.h"
+1 -3
View File
@@ -34,9 +34,7 @@
#include "log.h" #include "log.h"
#include "spdb.h" #include "spdb.h"
#include "whack.h" #include "whack.h"
#include "sha1.h" #include "crypto.h"
#include "md5.h"
#include "crypto.h" /* requires sha1.h and md5.h */
#include "alg_info.h" #include "alg_info.h"
#include "kernel_alg.h" #include "kernel_alg.h"
#include "ike_alg.h" #include "ike_alg.h"
+1 -4
View File
@@ -41,10 +41,7 @@
#include "whack.h" #include "whack.h"
#include "demux.h" /* needs packet.h */ #include "demux.h" /* needs packet.h */
#include "ipsec_doi.h" /* needs demux.h and state.h */ #include "ipsec_doi.h" /* needs demux.h and state.h */
#include "crypto.h"
#include "sha1.h"
#include "md5.h"
#include "crypto.h" /* requires sha1.h and md5.h */
/* /*
* Global variables: had to go somewhere, might as well be this file. * Global variables: had to go somewhere, might as well be this file.
+37 -82
View File
@@ -18,10 +18,12 @@
#include <sys/queue.h> #include <sys/queue.h>
#include <freeswan.h> #include <freeswan.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
#include "log.h" #include "log.h"
#include "md5.h"
#include "connections.h" #include "connections.h"
#include "packet.h" #include "packet.h"
#include "demux.h" #include "demux.h"
@@ -90,27 +92,24 @@ struct vid_struct {
unsigned short flags; unsigned short flags;
const char *data; const char *data;
const char *descr; const char *descr;
char *vid; chunk_t vid;
u_int vid_len;
}; };
#define DEC_MD5_VID_D(id,str,descr) \ #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) \ #define DEC_MD5_VID(id,str) \
{ VID_##id, VID_MD5HASH, str, NULL, NULL, 0 }, { VID_##id, VID_MD5HASH, str, NULL, { NULL, 0 } },
#define DEC_FSWAN_VID(id,str,descr) \
{ VID_##id, VID_FSWAN_HASH, str, descr, NULL, 0 },
static struct vid_struct _vid_tab[] = { static struct vid_struct _vid_tab[] = {
/* Implementation names */ /* 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") DEC_MD5_VID(KAME_RACOON, "KAME/racoon")
{ VID_MS_NT5, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA, { 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, "SSH Sentinel")
DEC_MD5_VID(SSH_SENTINEL_1_1, "SSH Sentinel 1.1") 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 */ /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */
{ VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity", { VID_CISCO_UNITY, VID_KEEP, NULL, "Cisco-Unity",
"\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", { "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00", 16 } },
16 },
{ VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, { VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "Cisco VPN 3000 Series" ,
NULL, "Cisco VPN 3000 Series" , "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14}, { "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14 } },
{ VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH, { 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: * Timestep VID seen:
@@ -168,31 +166,25 @@ static struct vid_struct _vid_tab[] = {
* = 'TIMESTEP 1 SGW 1520 315 2.01E013' * = 'TIMESTEP 1 SGW 1520 315 2.01E013'
*/ */
{ VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP", { VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP",
NULL, NULL, 0 }, NULL, { NULL, 0 } },
/* /*
* Netscreen: * Netscreen:
* 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100) * 4865617274426561745f4e6f74696679386b0100 (HeartBeat_Notify + 386b0100)
*/ */
{ VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA, { VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA,
"HeartBeat_Notify", "HeartBeat Notify", NULL, 0 }, "HeartBeat_Notify", "HeartBeat Notify", { NULL, 0 } },
/* /*
* MacOS X * MacOS X
*/ */
{ VID_MACOSX, VID_STRING|VID_SUBSTRING_DUMPHEXA, "Mac OSX 10.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 */ /* NCP */
{ VID_NCP_SERVER, VID_KEEP | VID_SUBSTRING_MATCH, NULL, "NCP Server", { 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", { 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?) * Windows Vista (and Windows Server 2008?)
@@ -297,10 +289,10 @@ static struct vid_struct _vid_tab[] = {
/* misc */ /* misc */
{ VID_MISC_XAUTH, VID_KEEP, NULL, "XAUTH", { 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", { 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") DEC_MD5_VID(MISC_FRAGMENTATION, "FRAGMENTATION")
@@ -310,10 +302,10 @@ static struct vid_struct _vid_tab[] = {
* Cisco VPN 3000 * Cisco VPN 3000
*/ */
{ VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA, { 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) void init_vendorid(void)
{ {
hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
struct vid_struct *vid; struct vid_struct *vid;
MD5_CTX ctx;
int i;
for (vid = _vid_tab; vid->id; vid++) for (vid = _vid_tab; vid->id; vid++)
{ {
if (vid->flags & VID_STRING) if (vid->flags & VID_STRING)
{ {
/** VendorID is a string **/ /** VendorID is a string **/
vid->vid = strdup(vid->data); vid->vid = chunk_create((u_char *)vid->data, strlen(vid->data));
vid->vid_len = strlen(vid->data); vid->vid = chunk_clone(vid->vid);
} }
else if (vid->flags & VID_MD5HASH) 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 **/ /** VendorID is a string to hash with MD5 **/
char *vidm = malloc(MD5_DIGEST_SIZE); hasher->allocate_hash(hasher, vid_data, &vid->vid);
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;
}
} }
if (vid->descr == NULL) if (vid->descr == NULL)
@@ -386,6 +340,7 @@ void init_vendorid(void)
vid->descr = vid->data; vid->descr = vid->data;
} }
} }
hasher->destroy(hasher);
_vid_struct_init = 1; _vid_struct_init = 1;
} }
@@ -397,7 +352,7 @@ void free_vendorid(void)
{ {
if (vid->flags & (VID_STRING | VID_MD5HASH | VID_FSWAN_HASH)) 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)); memset(vid_dump, 0, sizeof(vid_dump));
snprintf(vid_dump, sizeof(vid_dump), "%s ", snprintf(vid_dump, sizeof(vid_dump), "%s ",
vid->descr ? vid->descr : ""); 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; j < len && i < sizeof(vid_dump) - 2;
i += 2, j++) 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++) 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); handle_known_vendorid(md, vid, len, pvid);
return; 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); handle_known_vendorid(md, vid, len, pvid);
return; return;
@@ -556,13 +511,13 @@ bool out_vendorid (u_int8_t np, pb_stream *outs, enum known_vendorid vid)
if (pvid->id != vid) if (pvid->id != vid)
return STF_INTERNAL_ERROR; /* not found */ return STF_INTERNAL_ERROR; /* not found */
if (!pvid->vid) if (!pvid->vid.ptr)
return STF_INTERNAL_ERROR; /* not initialized */ return STF_INTERNAL_ERROR; /* not initialized */
DBG(DBG_EMITTING, DBG(DBG_EMITTING,
DBG_log("out_vendorid(): sending [%s]", pvid->descr) DBG_log("out_vendorid(): sending [%s]", pvid->descr)
) )
return out_generic_raw(np, &isakmp_vendor_id_desc, outs, 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");
} }
+5 -6
View File
@@ -47,12 +47,11 @@ enum known_vendorid {
VID_TIMESTEP = 28, VID_TIMESTEP = 28,
VID_SAFENET = 29, VID_SAFENET = 29,
VID_MACOSX = 30, VID_MACOSX = 30,
VID_OPENSWAN2 = 31, VID_NCP_SERVER = 31,
VID_NCP_SERVER = 32, VID_NCP_CLIENT = 32,
VID_NCP_CLIENT = 33, VID_VISTA_AUTHIP = 33,
VID_VISTA_AUTHIP = 34, VID_VISTA_AUTHIP2 = 34,
VID_VISTA_AUTHIP2 = 35, VID_VISTA_AUTHIP3 = 35,
VID_VISTA_AUTHIP3 = 36,
VID_STRONGSWAN = 37, VID_STRONGSWAN = 37,
VID_STRONGSWAN_2_2_0 = 38, VID_STRONGSWAN_2_2_0 = 38,
+11 -9
View File
@@ -29,6 +29,7 @@
#include <asn1/asn1.h> #include <asn1/asn1.h>
#include <asn1/asn1_parser.h> #include <asn1/asn1_parser.h>
#include <asn1/oid.h> #include <asn1/oid.h>
#include <crypto/hashers/hasher.h>
#include "constants.h" #include "constants.h"
#include "defs.h" #include "defs.h"
@@ -44,7 +45,6 @@
#include "whack.h" #include "whack.h"
#include "fetch.h" #include "fetch.h"
#include "ocsp.h" #include "ocsp.h"
#include "sha1.h"
/** /**
* Chained lists of X.509 end certificates * 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 * Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280
* as the 160 bit SHA-1 hash of the public key * 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); if (hasher == NULL)
SHA1Update(&context {
, cert->subjectPublicKey.ptr plog(" no SHA-1 hasher available to compute subjectKeyID");
, cert->subjectPublicKey.len); return FALSE;
SHA1Final(subjectKeyID.ptr, &context); }
subjectKeyID.len = SHA1_DIGEST_SIZE; hasher->get_hash(hasher, cert->subjectPublicKey, subjectKeyID.ptr);
hasher->destroy(hasher);
return TRUE;
} }
/** /**
+1 -1
View File
@@ -108,7 +108,7 @@ extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn
, const char* null_dn); , const char* null_dn);
extern err_t atodn(char *src, chunk_t *dn); extern err_t atodn(char *src, chunk_t *dn);
extern void gntoid(struct id *id, const generalName_t *gn); 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 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 bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert);
extern time_t parse_time(chunk_t blob, int level0); extern time_t parse_time(chunk_t blob, int level0);