pluto supports ECDSA authentication
This commit is contained in:
parent
eca36f44de
commit
11e6d28533
|
@ -25,13 +25,13 @@ ENUM(key_type_names, KEY_RSA, KEY_DSA,
|
|||
|
||||
ENUM(signature_scheme_names, SIGN_UNKNOWN, SIGN_ECDSA_521,
|
||||
"UNKNOWN",
|
||||
"DEFAULT",
|
||||
"RSA_EMSA_PKCS1_NULL",
|
||||
"RSA_EMSA_PKCS1_MD5",
|
||||
"RSA_EMSA_PKCS1_SHA1",
|
||||
"RSA_EMSA_PKCS1_SHA256",
|
||||
"RSA_EMSA_PKCS1_SHA384",
|
||||
"RSA_EMSA_PKCS1_SHA512",
|
||||
"ECDSA_WITH_NULL",
|
||||
"ECDSA_WITH_SHA1",
|
||||
"ECDSA-256",
|
||||
"ECDSA-384",
|
||||
|
|
|
@ -60,8 +60,6 @@ extern enum_name_t *key_type_names;
|
|||
enum signature_scheme_t {
|
||||
/** Unknown signature scheme */
|
||||
SIGN_UNKNOWN,
|
||||
/** Default scheme of the underlying crypto system */
|
||||
SIGN_DEFAULT,
|
||||
/** EMSA-PKCS1_v1.5 signature over digest without digestInfo */
|
||||
SIGN_RSA_EMSA_PKCS1_NULL,
|
||||
/** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and MD5 */
|
||||
|
@ -74,6 +72,8 @@ enum signature_scheme_t {
|
|||
SIGN_RSA_EMSA_PKCS1_SHA384,
|
||||
/** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-512 */
|
||||
SIGN_RSA_EMSA_PKCS1_SHA512,
|
||||
/** ECDSA over precomputed digest */
|
||||
SIGN_ECDSA_WITH_NULL,
|
||||
/** ECDSA with SHA-1 */
|
||||
SIGN_ECDSA_WITH_SHA1,
|
||||
/** ECDSA on the P-256 curve with SHA-256 as in RFC 4754 */
|
||||
|
|
|
@ -269,7 +269,7 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme,
|
|||
char buf[2048];
|
||||
chunk_t blob = chunk_from_buf(buf);
|
||||
|
||||
if (scheme != SIGN_DEFAULT && scheme != SIGN_RSA_EMSA_PKCS1_SHA1)
|
||||
if (scheme != SIGN_RSA_EMSA_PKCS1_SHA1)
|
||||
{
|
||||
DBG1("signature scheme %N not supported by ssh-agent",
|
||||
signature_scheme_names, scheme);
|
||||
|
|
|
@ -144,8 +144,6 @@ static bool sign(private_gcrypt_rsa_private_key_t *this, signature_scheme_t sche
|
|||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_DEFAULT:
|
||||
/* default is EMSA-PKCS1 using SHA1 */
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
return sign_pkcs1(this, HASH_SHA1, "sha1", data, sig);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA256:
|
||||
|
|
|
@ -138,8 +138,6 @@ static bool verify(private_gcrypt_rsa_public_key_t *this,
|
|||
return verify_pkcs1(this, HASH_SHA384, "sha384", data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA512:
|
||||
return verify_pkcs1(this, HASH_SHA512, "sha512", data, signature);
|
||||
case SIGN_DEFAULT:
|
||||
/* parsing hash OID currently not supported by gcrypt, fall */
|
||||
default:
|
||||
DBG1("signature scheme %N not supported in RSA",
|
||||
signature_scheme_names, scheme);
|
||||
|
|
|
@ -292,7 +292,6 @@ static bool sign(private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
|
|||
{
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return build_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
|
||||
case SIGN_DEFAULT:
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
return build_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA256:
|
||||
|
|
|
@ -299,7 +299,6 @@ static bool verify(private_gmp_rsa_public_key_t *this, signature_scheme_t scheme
|
|||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_DEFAULT:
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return verify_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_MD5:
|
||||
|
|
|
@ -128,36 +128,18 @@ static bool sig2chunk(const EC_GROUP *group, ECDSA_SIG *sig, chunk_t *chunk)
|
|||
* Build the signature
|
||||
*/
|
||||
static bool build_signature(private_openssl_ec_private_key_t *this,
|
||||
int hash_type, chunk_t data, chunk_t *signature)
|
||||
chunk_t hash, chunk_t *signature)
|
||||
{
|
||||
chunk_t hash = chunk_empty;
|
||||
ECDSA_SIG *sig;
|
||||
bool ret = FALSE;
|
||||
|
||||
if (!openssl_hash_chunk(hash_type, data, &hash))
|
||||
ECDSA_SIG *sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
|
||||
bool success;
|
||||
|
||||
if (!sig)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
|
||||
if (!sig)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!sig2chunk(EC_KEY_get0_group(this->ec), sig, signature))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
error:
|
||||
chunk_free(&hash);
|
||||
if (sig)
|
||||
{
|
||||
ECDSA_SIG_free(sig);
|
||||
}
|
||||
return ret;
|
||||
success = sig2chunk(EC_KEY_get0_group(this->ec), sig, signature);
|
||||
ECDSA_SIG_free(sig);
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,36 +156,51 @@ static key_type_t get_type(private_openssl_ec_private_key_t *this)
|
|||
static bool sign(private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
|
||||
chunk_t data, chunk_t *signature)
|
||||
{
|
||||
EC_GROUP *req_group;
|
||||
const EC_GROUP *my_group;
|
||||
int hash, curve;
|
||||
|
||||
if (!lookup_scheme(scheme, &hash, &curve))
|
||||
bool success;
|
||||
|
||||
if (scheme == SIGN_ECDSA_WITH_NULL)
|
||||
{
|
||||
DBG1("signature scheme %N not supported in EC",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
success = build_signature(this, data, signature);
|
||||
}
|
||||
|
||||
req_group = EC_GROUP_new_by_curve_name(curve);
|
||||
if (!req_group)
|
||||
else
|
||||
{
|
||||
DBG1("signature scheme %N not supported in EC (required curve not supported)",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
EC_GROUP *req_group;
|
||||
const EC_GROUP *my_group;
|
||||
chunk_t hash = chunk_empty;
|
||||
int hash_type, curve;
|
||||
|
||||
if (!lookup_scheme(scheme, &hash_type, &curve))
|
||||
{
|
||||
DBG1("signature scheme %N not supported in EC",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
my_group = EC_KEY_get0_group(this->ec);
|
||||
if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
|
||||
{
|
||||
DBG1("signature scheme %N not supported by private key",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
req_group = EC_GROUP_new_by_curve_name(curve);
|
||||
if (!req_group)
|
||||
{
|
||||
DBG1("signature scheme %N not supported in EC (required curve not supported)",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EC_GROUP_free(req_group);
|
||||
|
||||
return build_signature(this, hash, data, signature);
|
||||
my_group = EC_KEY_get0_group(this->ec);
|
||||
if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
|
||||
{
|
||||
DBG1("signature scheme %N not supported by private key",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
EC_GROUP_free(req_group);
|
||||
|
||||
if (!openssl_hash_chunk(hash_type, data, &hash))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
success = build_signature(this, hash, signature);
|
||||
chunk_free(&hash);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -73,9 +73,16 @@ static bool verify_signature(private_openssl_ec_public_key_t *this,
|
|||
ECDSA_SIG *sig;
|
||||
bool valid = FALSE;
|
||||
|
||||
if (!openssl_hash_chunk(hash_type, data, &hash))
|
||||
if (hash_type == NID_undef)
|
||||
{
|
||||
return FALSE;
|
||||
hash = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!openssl_hash_chunk(hash_type, data, &hash))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
sig = ECDSA_SIG_new();
|
||||
|
@ -88,7 +95,6 @@ static bool verify_signature(private_openssl_ec_public_key_t *this,
|
|||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1);
|
||||
|
||||
error:
|
||||
|
@ -96,7 +102,10 @@ error:
|
|||
{
|
||||
ECDSA_SIG_free(sig);
|
||||
}
|
||||
chunk_free(&hash);
|
||||
if (hash_type != NID_undef)
|
||||
{
|
||||
chunk_free(&hash);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
@ -158,6 +167,8 @@ static bool verify(private_openssl_ec_public_key_t *this, signature_scheme_t sch
|
|||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_ECDSA_WITH_NULL:
|
||||
return verify_signature(this, NID_undef, data, signature);
|
||||
case SIGN_ECDSA_WITH_SHA1:
|
||||
return verify_default_signature(this, data, signature);
|
||||
case SIGN_ECDSA_256:
|
||||
|
|
|
@ -162,7 +162,6 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch
|
|||
{
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return build_emsa_pkcs1_signature(this, NID_undef, data, signature);
|
||||
case SIGN_DEFAULT:
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
return build_emsa_pkcs1_signature(this, NID_sha1, data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA256:
|
||||
|
|
|
@ -139,7 +139,6 @@ static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t sc
|
|||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_DEFAULT:
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
|
|
|
@ -997,7 +997,7 @@ add_connection(const whack_message_t *wm)
|
|||
if (c->alg_info_esp)
|
||||
alg_info_snprint(buf, sizeof(buf)
|
||||
,(struct alg_info *)c->alg_info_esp);
|
||||
DBG_log("esp string values: %s", buf);
|
||||
DBG_log("esp proposal: %s", buf);
|
||||
)
|
||||
if (c->alg_info_esp)
|
||||
{
|
||||
|
@ -1024,7 +1024,7 @@ add_connection(const whack_message_t *wm)
|
|||
if (c->alg_info_ike)
|
||||
alg_info_snprint(buf, sizeof(buf)
|
||||
, (struct alg_info *)c->alg_info_ike);
|
||||
DBG_log("ike string values: %s", buf);
|
||||
DBG_log("ike proposal: %s", buf);
|
||||
)
|
||||
if (c->alg_info_ike)
|
||||
{
|
||||
|
@ -3301,19 +3301,25 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
|||
* we just used it to decode the current message!
|
||||
*/
|
||||
if (psk == NULL)
|
||||
{
|
||||
return NULL; /* cannot determine PSK! */
|
||||
}
|
||||
break;
|
||||
case XAUTHInitPreShared:
|
||||
case XAUTHRespPreShared:
|
||||
auth_policy = POLICY_XAUTH_PSK;
|
||||
psk = get_preshared_secret(c);
|
||||
if (psk == NULL)
|
||||
{
|
||||
return NULL; /* cannot determine PSK! */
|
||||
}
|
||||
break;
|
||||
case OAKLEY_RSA_SIG:
|
||||
auth_policy = POLICY_RSASIG;
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
auth_policy = POLICY_PUBKEY;
|
||||
break;
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
auth_policy = POLICY_XAUTH_RSASIG;
|
||||
break;
|
||||
|
@ -3397,6 +3403,9 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
|||
break;
|
||||
|
||||
case OAKLEY_RSA_SIG:
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
/*
|
||||
|
|
|
@ -472,7 +472,7 @@ ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
|
|||
|
||||
const char *const sa_policy_bit_names[] = {
|
||||
"PSK",
|
||||
"RSASIG",
|
||||
"PUBKEY",
|
||||
"ENCRYPT",
|
||||
"AUTHENTICATE",
|
||||
"COMPRESS",
|
||||
|
@ -495,7 +495,6 @@ const char *const sa_policy_bit_names[] = {
|
|||
"DONTREAUTH",
|
||||
"BEET",
|
||||
"MOBIKE",
|
||||
"ECDSA",
|
||||
"PROXY",
|
||||
NULL
|
||||
};
|
||||
|
@ -849,13 +848,17 @@ enum_names oakley_hash_names =
|
|||
/* Oakley Authentication Method attribute */
|
||||
|
||||
static const char *const oakley_auth_name1[] = {
|
||||
"OAKLEY_PRESHARED_KEY",
|
||||
"OAKLEY_DSS_SIG",
|
||||
"OAKLEY_RSA_SIG",
|
||||
"OAKLEY_RSA_ENC",
|
||||
"OAKLEY_RSA_ENC_REV",
|
||||
"OAKLEY_ELGAMAL_ENC",
|
||||
"OAKLEY_ELGAMAL_ENC_REV",
|
||||
"PRESHARED_KEY",
|
||||
"DSS_SIG",
|
||||
"RSA_SIG",
|
||||
"RSA_ENC",
|
||||
"RSA_ENC_REV",
|
||||
"ELGAMAL_ENC",
|
||||
"ELGAMAL_ENC_REV",
|
||||
"ECDSA_SIG",
|
||||
"ECDSA_256_SIG",
|
||||
"ECDSA_384_SIG",
|
||||
"ECDSA_512_SIG",
|
||||
};
|
||||
|
||||
static const char *const oakley_auth_name2[] = {
|
||||
|
@ -879,7 +882,7 @@ static const char *const oakley_auth_name3[] = {
|
|||
};
|
||||
|
||||
static enum_names oakley_auth_names1 =
|
||||
{ OAKLEY_PRESHARED_KEY, OAKLEY_ELGAMAL_ENC_REV
|
||||
{ OAKLEY_PRESHARED_KEY, OAKLEY_ECDSA_512
|
||||
, oakley_auth_name1, NULL };
|
||||
|
||||
static enum_names oakley_auth_names2 =
|
||||
|
@ -1079,8 +1082,7 @@ aftoinfo(int af)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
subnetisnone(const ip_subnet *sn)
|
||||
bool subnetisnone(const ip_subnet *sn)
|
||||
{
|
||||
ip_address base;
|
||||
|
||||
|
@ -1174,8 +1176,7 @@ const char *const natt_type_bitnames[] = {
|
|||
|
||||
/* look up enum names in an enum_names */
|
||||
|
||||
const char *
|
||||
enum_name(enum_names *ed, unsigned long val)
|
||||
const char* enum_name(enum_names *ed, unsigned long val)
|
||||
{
|
||||
enum_names *p;
|
||||
|
||||
|
@ -1237,8 +1238,7 @@ enum_search(enum_names *ed, const char *str)
|
|||
* Result may be in STATIC buffer!
|
||||
* Note: prettypolicy depends on internal details.
|
||||
*/
|
||||
const char *
|
||||
bitnamesof(const char *const table[], lset_t val)
|
||||
const char* bitnamesof(const char *const table[], lset_t val)
|
||||
{
|
||||
char *p = bitnamesbuf;
|
||||
lset_t bit;
|
||||
|
@ -1285,8 +1285,7 @@ bitnamesof(const char *const table[], lset_t val)
|
|||
/* print a policy: like bitnamesof, but it also does the non-bitfields.
|
||||
* Suppress the shunt and fail fields if 0.
|
||||
*/
|
||||
const char *
|
||||
prettypolicy(lset_t policy)
|
||||
const char* prettypolicy(lset_t policy)
|
||||
{
|
||||
const char *bn = bitnamesof(sa_policy_bit_names
|
||||
, policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK));
|
||||
|
@ -1319,8 +1318,7 @@ prettypolicy(lset_t policy)
|
|||
|
||||
/* test a set by seeing if all bits have names */
|
||||
|
||||
bool
|
||||
testset(const char *const table[], lset_t val)
|
||||
bool testset(const char *const table[], lset_t val)
|
||||
{
|
||||
lset_t bit;
|
||||
const char *const *tp;
|
||||
|
@ -1353,8 +1351,7 @@ const char *sparse_name(sparse_names sd, unsigned long val)
|
|||
/* find or construct a string to describe an sparse value
|
||||
* Result may be in STATIC buffer!
|
||||
*/
|
||||
const char *
|
||||
sparse_val_show(sparse_names sd, unsigned long val)
|
||||
const char* sparse_val_show(sparse_names sd, unsigned long val)
|
||||
{
|
||||
const char *p = sparse_name(sd, val);
|
||||
|
||||
|
|
|
@ -724,10 +724,10 @@ extern const char *prettypolicy(lset_t policy);
|
|||
|
||||
/* ISAKMP auth techniques (none means never negotiate) */
|
||||
#define POLICY_PSK LELEM(0)
|
||||
#define POLICY_RSASIG LELEM(1)
|
||||
#define POLICY_PUBKEY LELEM(1)
|
||||
|
||||
#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */
|
||||
#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_RSASIG | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
|
||||
#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_PUBKEY | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
|
||||
#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */
|
||||
|
||||
/* Quick Mode (IPSEC) attributes */
|
||||
|
@ -776,8 +776,7 @@ extern const char *prettypolicy(lset_t policy);
|
|||
#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
|
||||
#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
|
||||
#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
|
||||
#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */
|
||||
#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */
|
||||
#define POLICY_PROXY LELEM(25) /* proxy transport mode (MIPv6) */
|
||||
|
||||
/* Any IPsec policy? If not, a connection description
|
||||
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
|
||||
|
@ -979,8 +978,12 @@ extern enum_names oakley_auth_names;
|
|||
#define OAKLEY_RSA_ENC_REV 5
|
||||
#define OAKLEY_ELGAMAL_ENC 6
|
||||
#define OAKLEY_ELGAMAL_ENC_REV 7
|
||||
#define OAKLEY_ECDSA_SIG 8
|
||||
#define OAKLEY_ECDSA_256 9
|
||||
#define OAKLEY_ECDSA_384 10
|
||||
#define OAKLEY_ECDSA_512 11
|
||||
|
||||
#define OAKLEY_AUTH_ROOF 8 /* roof on auth values THAT WE SUPPORT */
|
||||
#define OAKLEY_AUTH_ROOF 12 /* roof on auth values THAT WE SUPPORT */
|
||||
|
||||
#define HybridInitRSA 64221
|
||||
#define HybridRespRSA 64222
|
||||
|
|
|
@ -188,7 +188,9 @@ struct state_microcode {
|
|||
*/
|
||||
#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1)
|
||||
#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY)
|
||||
#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG))
|
||||
#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG) | \
|
||||
LELEM(OAKLEY_ECDSA_SIG) | LELEM(OAKLEY_ECDSA_256) | \
|
||||
LELEM(OAKLEY_ECDSA_384) | LELEM(OAKLEY_ECDSA_512))
|
||||
#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC))
|
||||
#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV))
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
#include "constants.h"
|
||||
#include "defs.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include "state.h"
|
||||
#include "packet.h"
|
||||
#include "keys.h"
|
||||
#include "log.h"
|
||||
#include "whack.h"
|
||||
#include "spdb.h"
|
||||
|
@ -141,8 +141,9 @@ const struct dh_desc *ike_alg_pfsgroup(struct connection *c, lset_t policy)
|
|||
/**
|
||||
* Create an OAKLEY proposal based on alg_info and policy
|
||||
*/
|
||||
struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
||||
struct db_context *ike_alg_db_new(struct connection *c, lset_t policy)
|
||||
{
|
||||
struct alg_info_ike *ai = c->alg_info_ike;
|
||||
struct db_context *db_ctx = NULL;
|
||||
struct ike_info *ike_info;
|
||||
struct encrypt_desc *enc_desc;
|
||||
|
@ -189,14 +190,47 @@ struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
|||
}
|
||||
enc_desc = ike_alg_get_crypter(ealg);
|
||||
|
||||
if (policy & POLICY_RSASIG)
|
||||
if (policy & POLICY_PUBKEY)
|
||||
{
|
||||
int auth_method = 0;
|
||||
private_key_t *key = get_private_key(c);
|
||||
|
||||
if (key == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (key->get_type(key))
|
||||
{
|
||||
case KEY_RSA:
|
||||
auth_method = OAKLEY_RSA_SIG;
|
||||
break;
|
||||
case KEY_ECDSA:
|
||||
switch (key->get_keysize(key))
|
||||
{
|
||||
case 32:
|
||||
auth_method = OAKLEY_ECDSA_256;
|
||||
break;
|
||||
case 48:
|
||||
auth_method = OAKLEY_ECDSA_384;
|
||||
break;
|
||||
case 66:
|
||||
auth_method = OAKLEY_ECDSA_512;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
db_trans_add(db_ctx, KEY_IKE);
|
||||
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
|
||||
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
|
||||
if (eklen)
|
||||
{
|
||||
db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
|
||||
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
|
||||
}
|
||||
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, auth_method);
|
||||
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
|
||||
}
|
||||
|
||||
|
@ -206,7 +240,9 @@ struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
|||
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
|
||||
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
|
||||
if (eklen)
|
||||
{
|
||||
db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
|
||||
}
|
||||
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
|
||||
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
|
||||
}
|
||||
|
@ -217,7 +253,9 @@ struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
|||
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
|
||||
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
|
||||
if (eklen)
|
||||
{
|
||||
db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
|
||||
}
|
||||
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
|
||||
, is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
|
||||
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
|
||||
|
@ -229,7 +267,9 @@ struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
|||
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
|
||||
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
|
||||
if (eklen)
|
||||
{
|
||||
db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
|
||||
}
|
||||
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
|
||||
, is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
|
||||
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
|
||||
|
|
|
@ -62,7 +62,7 @@ extern struct hash_desc *ike_alg_get_hasher(u_int alg);
|
|||
extern struct encrypt_desc *ike_alg_get_crypter(u_int alg);
|
||||
extern struct dh_desc *ike_alg_get_dh_group(u_int alg);
|
||||
extern const struct dh_desc* ike_alg_pfsgroup(struct connection *c, lset_t policy);
|
||||
extern struct db_context * ike_alg_db_new(struct alg_info_ike *ai, lset_t policy);
|
||||
extern struct db_context * ike_alg_db_new(struct connection *c, lset_t policy);
|
||||
extern void ike_alg_list(void);
|
||||
extern void ike_alg_show_connection(struct connection *c, const char *instance);
|
||||
extern bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group
|
||||
|
|
|
@ -1208,6 +1208,9 @@ static bool generate_skeyids_iv(struct state *st)
|
|||
break;
|
||||
|
||||
case OAKLEY_RSA_SIG:
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
if (!skeyid_digisig(st))
|
||||
|
@ -1354,7 +1357,7 @@ static bool generate_skeyids_iv(struct state *st)
|
|||
* If hashus argument is TRUE, we're generating a hash for our end.
|
||||
* See RFC2409 IKE 5.
|
||||
*/
|
||||
static size_t main_mode_hash(struct state *st, u_char *hash_val, bool hashi,
|
||||
static void main_mode_hash(struct state *st, chunk_t *hash, bool hashi,
|
||||
const pb_stream *idpl)
|
||||
{
|
||||
chunk_t icookie = { st->st_icookie, COOKIE_SIZE };
|
||||
|
@ -1365,9 +1368,21 @@ static bool generate_skeyids_iv(struct state *st)
|
|||
pbs_offset(idpl) - sizeof(struct isakmp_generic) };
|
||||
pseudo_random_function_t prf_alg;
|
||||
prf_t *prf;
|
||||
size_t prf_block_size;
|
||||
|
||||
prf_alg = oakley_to_prf(st->st_oakley.hash);
|
||||
switch (st->st_oakley.auth)
|
||||
{
|
||||
case OAKLEY_ECDSA_256:
|
||||
prf_alg = PRF_HMAC_SHA2_256;
|
||||
break;
|
||||
case OAKLEY_ECDSA_384:
|
||||
prf_alg = PRF_HMAC_SHA2_384;
|
||||
break;
|
||||
case OAKLEY_ECDSA_512:
|
||||
prf_alg = PRF_HMAC_SHA2_512;
|
||||
break;
|
||||
default:
|
||||
prf_alg = oakley_to_prf(st->st_oakley.hash);
|
||||
}
|
||||
prf = lib->crypto->create_prf(lib->crypto, prf_alg);
|
||||
prf->set_key(prf, st->st_skeyid);
|
||||
|
||||
|
@ -1396,11 +1411,9 @@ static bool generate_skeyids_iv(struct state *st)
|
|||
* we use the bytes as they appear on the wire to avoid
|
||||
* "spelling problems".
|
||||
*/
|
||||
prf->get_bytes(prf, id_body, hash_val);
|
||||
prf_block_size = prf->get_block_size(prf);
|
||||
prf->get_bytes(prf, id_body, hash->ptr);
|
||||
hash->len = prf->get_block_size(prf);
|
||||
prf->destroy(prf);
|
||||
|
||||
return prf_block_size;
|
||||
}
|
||||
|
||||
/* Create a public key signature of a hash.
|
||||
|
@ -1408,30 +1421,27 @@ static bool generate_skeyids_iv(struct state *st)
|
|||
* Use PKCS#1 version 1.5 encryption of hash (called
|
||||
* RSAES-PKCS1-V1_5) in PKCS#2.
|
||||
*/
|
||||
static size_t sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS],
|
||||
u_char *hash_val, size_t hash_len)
|
||||
static size_t sign_hash(signature_scheme_t scheme, struct connection *c,
|
||||
u_char sig_val[RSA_MAX_OCTETS], chunk_t hash)
|
||||
{
|
||||
size_t sz = 0;
|
||||
smartcard_t *sc = c->spd.this.sc;
|
||||
|
||||
if (sc == NULL) /* no smartcard */
|
||||
{
|
||||
chunk_t hash, sig;
|
||||
chunk_t sig;
|
||||
private_key_t *private = get_private_key(c);
|
||||
|
||||
if (private == NULL)
|
||||
{
|
||||
return 0; /* failure: no key to use */
|
||||
}
|
||||
sz = private->get_keysize(private);
|
||||
passert(RSA_MIN_OCTETS <= sz && 4 + hash_len < sz && sz <= RSA_MAX_OCTETS);
|
||||
hash = chunk_create(hash_val, hash_len);
|
||||
sig = chunk_create(sig_val, sz);
|
||||
if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_NULL, hash, &sig))
|
||||
if (!private->sign(private, scheme, hash, &sig))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(sig_val, sig.ptr, sz);
|
||||
memcpy(sig_val, sig.ptr, sig.len);
|
||||
sz = sig.len;
|
||||
free(sig.ptr);
|
||||
}
|
||||
else if (sc->valid) /* if valid pin then sign hash on the smartcard */
|
||||
|
@ -1457,7 +1467,7 @@ static size_t sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS],
|
|||
DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
|
||||
, (int)sc->slot, sc->id)
|
||||
)
|
||||
sz = scx_sign_hash(sc, hash_val, hash_len, sig_val, sz) ? sz : 0;
|
||||
sz = scx_sign_hash(sc, hash.ptr, hash.len, sig_val, sz) ? sz : 0;
|
||||
if (!pkcs11_keep_state)
|
||||
scx_release_context(sc);
|
||||
unlock_certs_and_keys("sign_hash");
|
||||
|
@ -1485,14 +1495,18 @@ struct tac_state {
|
|||
static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
|
||||
{
|
||||
public_key_t *pub_key = kr->public_key;
|
||||
identification_t *keyid = pub_key->get_id(pub_key, ID_PUBKEY_SHA1);
|
||||
identification_t *keyid = pub_key->get_id(pub_key, ID_PUBKEY_INFO_SHA1);
|
||||
signature_scheme_t scheme;
|
||||
|
||||
scheme = (s->st->st_oakley.auth == OAKLEY_RSA_SIG) ?
|
||||
SIGN_RSA_EMSA_PKCS1_NULL : SIGN_ECDSA_WITH_NULL;
|
||||
s->tried_cnt++;
|
||||
|
||||
if (pub_key->verify(pub_key, SIGN_RSA_EMSA_PKCS1_NULL, s->hash, s->sig))
|
||||
if (pub_key->verify(pub_key, scheme, s->hash, s->sig))
|
||||
{
|
||||
DBG(DBG_CRYPT | DBG_CONTROL,
|
||||
DBG_log("signature check passed with keyid %Y", keyid)
|
||||
DBG_log("%s check passed with keyid %Y",
|
||||
enum_show(&oakley_auth_names, s->st->st_oakley.auth), keyid)
|
||||
)
|
||||
unreference_key(&s->st->st_peer_pubkey);
|
||||
s->st->st_peer_pubkey = reference_key(kr);
|
||||
|
@ -1501,25 +1515,26 @@ static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
|
|||
else
|
||||
{
|
||||
DBG(DBG_CRYPT,
|
||||
DBG_log("signature check failed with keyid %Y", keyid)
|
||||
DBG_log("%s check failed with keyid %Y",
|
||||
enum_show(&oakley_auth_names, s->st->st_oakley.auth), keyid)
|
||||
)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static stf_status RSA_check_signature(const struct id* peer, struct state *st,
|
||||
u_char hash_val[MAX_DIGEST_LEN],
|
||||
size_t hash_len, const pb_stream *sig_pbs,
|
||||
static stf_status check_signature(key_type_t key_type, const struct id* peer,
|
||||
struct state *st, chunk_t hash,
|
||||
const pb_stream *sig_pbs,
|
||||
#ifdef USE_KEYRR
|
||||
const pubkey_list_t *keys_from_dns,
|
||||
const pubkey_list_t *keys_from_dns,
|
||||
#endif /* USE_KEYRR */
|
||||
const struct gw_info *gateways_from_dns)
|
||||
const struct gw_info *gateways_from_dns)
|
||||
{
|
||||
const struct connection *c = st->st_connection;
|
||||
struct tac_state s;
|
||||
|
||||
s.st = st;
|
||||
s.hash = chunk_create(hash_val, hash_len);
|
||||
s.hash = hash;
|
||||
s.sig = chunk_create(sig_pbs->cur, pbs_left(sig_pbs));
|
||||
s.tried_cnt = 0;
|
||||
|
||||
|
@ -1550,7 +1565,7 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
|
|||
pubkey_t *key = p->key;
|
||||
key_type_t type = key->public_key->get_type(key->public_key);
|
||||
|
||||
if (type == KEY_RSA && same_id(peer, &key->id))
|
||||
if (type == key_type && same_id(peer, &key->id))
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
|
@ -2775,6 +2790,23 @@ static void compute_keymats(struct state *st)
|
|||
compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp);
|
||||
}
|
||||
|
||||
static bool uses_pubkey_auth(int auth)
|
||||
{
|
||||
switch (auth)
|
||||
{
|
||||
case OAKLEY_RSA_SIG:
|
||||
case OAKLEY_ECDSA_SIG:
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* State Transition Functions.
|
||||
*
|
||||
* The definition of state_microcode_table in demux.c is a good
|
||||
|
@ -3170,11 +3202,9 @@ stf_status main_inI2_outR2(struct msg_digest *md)
|
|||
struct state *const st = md->st;
|
||||
pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
|
||||
|
||||
/* send CR if auth is RSA and no preloaded RSA public key exists*/
|
||||
bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
|
||||
|| st->st_oakley.auth == XAUTHInitRSA
|
||||
|| st->st_oakley.auth == XAUTHRespRSA;
|
||||
bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st);
|
||||
/* send CR if auth is RSA or ECDSA and no preloaded public key exists*/
|
||||
bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
|
||||
bool send_cr = !no_cr_send && pubkey_auth && !has_preloaded_public_key(st);
|
||||
|
||||
u_int8_t np = ISAKMP_NEXT_NONE;
|
||||
|
||||
|
@ -3314,12 +3344,9 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
|
||||
cert_t mycert = st->st_connection->spd.this.cert;
|
||||
bool requested, send_cert, send_cr;
|
||||
bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
|
||||
|
||||
bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
|
||||
|| st->st_oakley.auth == XAUTHInitRSA
|
||||
|| st->st_oakley.auth == XAUTHRespRSA;
|
||||
|
||||
int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||
int auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||
|
||||
/* KE in */
|
||||
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
|
||||
|
@ -3342,7 +3369,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
*/
|
||||
requested = cert_policy == CERT_SEND_IF_ASKED
|
||||
&& st->st_connection->got_certrequest;
|
||||
send_cert = RSA_auth && mycert.type != CERT_NONE
|
||||
send_cert = pubkey_auth && mycert.type != CERT_NONE
|
||||
&& (cert_policy == CERT_ALWAYS_SEND || requested);
|
||||
|
||||
/* send certificate request if we don't have a preloaded RSA public key */
|
||||
|
@ -3385,7 +3412,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
}
|
||||
|
||||
/* CERT out */
|
||||
if (RSA_auth)
|
||||
if (pubkey_auth)
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
|
||||
|
@ -3429,23 +3456,30 @@ stf_status main_inR2_outI3(struct msg_digest *md)
|
|||
|
||||
/* HASH_I or SIG_I out */
|
||||
{
|
||||
u_char hash_val[MAX_DIGEST_LEN];
|
||||
size_t hash_len = main_mode_hash(st, hash_val, TRUE, &id_pbs);
|
||||
u_char hash_buf[MAX_DIGEST_LEN];
|
||||
chunk_t hash = chunk_from_buf(hash_buf);
|
||||
|
||||
main_mode_hash(st, &hash, TRUE, &id_pbs);
|
||||
|
||||
if (auth_payload == ISAKMP_NEXT_HASH)
|
||||
{
|
||||
/* HASH_I out */
|
||||
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
|
||||
, hash_val, hash_len, "HASH_I"))
|
||||
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
|
||||
hash.ptr, hash.len, "HASH_I"))
|
||||
{
|
||||
return STF_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SIG_I out */
|
||||
u_char sig_val[RSA_MAX_OCTETS];
|
||||
size_t sig_len = sign_hash(st->st_connection, sig_val, hash_val,
|
||||
hash_len);
|
||||
signature_scheme_t scheme;
|
||||
size_t sig_len;
|
||||
|
||||
scheme = (st->st_oakley.auth == OAKLEY_RSA_SIG) ?
|
||||
SIGN_RSA_EMSA_PKCS1_NULL : SIGN_ECDSA_WITH_NULL;
|
||||
sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
|
||||
if (sig_len == 0)
|
||||
{
|
||||
loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
|
||||
|
@ -3514,9 +3548,9 @@ main_id_and_auth(struct msg_digest *md
|
|||
, const struct key_continuation *kc /* current state, can be NULL */
|
||||
)
|
||||
{
|
||||
u_char hash_buf[MAX_DIGEST_LEN];
|
||||
chunk_t hash = chunk_from_buf(hash_buf);
|
||||
struct state *st = md->st;
|
||||
u_char hash_val[MAX_DIGEST_LEN];
|
||||
size_t hash_len;
|
||||
struct id peer;
|
||||
stf_status r = STF_OK;
|
||||
|
||||
|
@ -3533,7 +3567,7 @@ main_id_and_auth(struct msg_digest *md
|
|||
u_int8_t *old_cur = idpl->cur;
|
||||
|
||||
idpl->cur = idpl->roof;
|
||||
hash_len = main_mode_hash(st, hash_val, !initiator, idpl);
|
||||
main_mode_hash(st, &hash, !initiator, idpl);
|
||||
idpl->cur = old_cur;
|
||||
}
|
||||
|
||||
|
@ -3545,8 +3579,8 @@ main_id_and_auth(struct msg_digest *md
|
|||
{
|
||||
pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
|
||||
|
||||
if (pbs_left(hash_pbs) != hash_len
|
||||
|| memcmp(hash_pbs->cur, hash_val, hash_len) != 0)
|
||||
if (pbs_left(hash_pbs) != hash.len
|
||||
|| memcmp(hash_pbs->cur, hash.ptr, hash.len) != 0)
|
||||
{
|
||||
DBG_cond_dump(DBG_CRYPT, "received HASH:"
|
||||
, hash_pbs->cur, pbs_left(hash_pbs));
|
||||
|
@ -3560,14 +3594,14 @@ main_id_and_auth(struct msg_digest *md
|
|||
case OAKLEY_RSA_SIG:
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
r = RSA_check_signature(&peer, st, hash_val, hash_len
|
||||
, &md->chain[ISAKMP_NEXT_SIG]->pbs
|
||||
r = check_signature(KEY_RSA, &peer, st, hash,
|
||||
&md->chain[ISAKMP_NEXT_SIG]->pbs,
|
||||
#ifdef USE_KEYRR
|
||||
, kc == NULL? NULL : kc->ac.keys_from_dns
|
||||
kc == NULL? NULL : kc->ac.keys_from_dns,
|
||||
#endif /* USE_KEYRR */
|
||||
, kc == NULL? NULL : kc->ac.gateways_from_dns
|
||||
kc == NULL? NULL : kc->ac.gateways_from_dns
|
||||
);
|
||||
|
||||
|
||||
if (r == STF_SUSPEND)
|
||||
{
|
||||
/* initiate/resume asynchronous DNS lookup for key */
|
||||
|
@ -3622,6 +3656,17 @@ main_id_and_auth(struct msg_digest *md
|
|||
}
|
||||
break;
|
||||
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
r = check_signature(KEY_ECDSA, &peer, st, hash,
|
||||
&md->chain[ISAKMP_NEXT_SIG]->pbs,
|
||||
#ifdef USE_KEYRR
|
||||
NULL,
|
||||
#endif /* USE_KEYRR */
|
||||
NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
bad_case(st->st_oakley.auth);
|
||||
}
|
||||
|
@ -3732,9 +3777,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
|
||||
certpolicy_t cert_policy;
|
||||
cert_t mycert;
|
||||
bool RSA_auth;
|
||||
bool send_cert;
|
||||
bool requested;
|
||||
bool pubkey_auth, send_cert, requested;
|
||||
|
||||
/* ID and HASH_I or SIG_I in
|
||||
* Note: this may switch the connection being used!
|
||||
|
@ -3748,19 +3791,16 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
return r;
|
||||
}
|
||||
|
||||
/* send certificate if auth is RSA, we have one and we want
|
||||
* or are requested to send it
|
||||
/* send certificate if pubkey authentication is used, we have one
|
||||
* and we want or are requested to send it
|
||||
*/
|
||||
cert_policy = st->st_connection->spd.this.sendcert;
|
||||
mycert = st->st_connection->spd.this.cert;
|
||||
requested = cert_policy == CERT_SEND_IF_ASKED
|
||||
&& st->st_connection->got_certrequest;
|
||||
RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
|
||||
|| st->st_oakley.auth == XAUTHInitRSA
|
||||
|| st->st_oakley.auth == XAUTHRespRSA;
|
||||
send_cert = RSA_auth
|
||||
&& mycert.type != CERT_NONE
|
||||
&& (cert_policy == CERT_ALWAYS_SEND || requested);
|
||||
pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
|
||||
send_cert = pubkey_auth && mycert.type != CERT_NONE &&
|
||||
(cert_policy == CERT_ALWAYS_SEND || requested);
|
||||
|
||||
/*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
|
||||
/* proccess_packet() would automatically generate the HDR*
|
||||
|
@ -3776,7 +3816,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
*/
|
||||
echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
|
||||
|
||||
auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||
auth_payload = pubkey_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||
|
||||
/* IDir out */
|
||||
{
|
||||
|
@ -3795,7 +3835,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
}
|
||||
|
||||
/* CERT out */
|
||||
if (RSA_auth)
|
||||
if (pubkey_auth)
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
|
||||
|
@ -3831,23 +3871,30 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||
|
||||
/* HASH_R or SIG_R out */
|
||||
{
|
||||
u_char hash_val[MAX_DIGEST_LEN];
|
||||
size_t hash_len = main_mode_hash(st, hash_val, FALSE, &r_id_pbs);
|
||||
u_char hash_buf[MAX_DIGEST_LEN];
|
||||
chunk_t hash = chunk_from_buf(hash_buf);
|
||||
|
||||
main_mode_hash(st, &hash, FALSE, &r_id_pbs);
|
||||
|
||||
if (auth_payload == ISAKMP_NEXT_HASH)
|
||||
{
|
||||
/* HASH_R out */
|
||||
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
|
||||
, hash_val, hash_len, "HASH_R"))
|
||||
if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody,
|
||||
hash.ptr, hash.len, "HASH_R"))
|
||||
{
|
||||
return STF_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SIG_R out */
|
||||
u_char sig_val[RSA_MAX_OCTETS];
|
||||
size_t sig_len = sign_hash(st->st_connection, sig_val, hash_val,
|
||||
hash_len);
|
||||
signature_scheme_t scheme;
|
||||
size_t sig_len;
|
||||
|
||||
scheme = (st->st_oakley.auth == OAKLEY_RSA_SIG) ?
|
||||
SIGN_RSA_EMSA_PKCS1_NULL : SIGN_ECDSA_WITH_NULL;
|
||||
sig_len = sign_hash(scheme, st->st_connection, sig_val, hash);
|
||||
if (sig_len == 0)
|
||||
{
|
||||
loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
|
||||
|
|
|
@ -660,20 +660,14 @@ struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
|
|||
{
|
||||
const struct esp_info *esp_info;
|
||||
struct esp_info tmp_esp_info;
|
||||
struct db_context *ctx_new=NULL;
|
||||
struct db_trans *t;
|
||||
struct db_context *ctx_new = NULL;
|
||||
struct db_prop *prop;
|
||||
u_int trans_cnt;
|
||||
int tn = 0;
|
||||
u_int trans_cnt = esp_ealg_num * esp_aalg_num;
|
||||
|
||||
if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */
|
||||
{
|
||||
return NULL;
|
||||
|
||||
trans_cnt = esp_ealg_num * esp_aalg_num;
|
||||
DBG(DBG_EMITTING,
|
||||
DBG_log("kernel_alg_db_prop_new() initial trans_cnt=%d"
|
||||
, trans_cnt)
|
||||
)
|
||||
}
|
||||
|
||||
/* pass aprox. number of transforms and attributes */
|
||||
ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2);
|
||||
|
@ -716,26 +710,7 @@ struct db_context* kernel_alg_db_new(struct alg_info_esp *alg_info,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
prop = db_prop_get(ctx_new);
|
||||
|
||||
DBG(DBG_CONTROL|DBG_EMITTING,
|
||||
DBG_log("kernel_alg_db_prop_new() "
|
||||
"will return p_new->protoid=%d, p_new->trans_cnt=%d"
|
||||
, prop->protoid, prop->trans_cnt)
|
||||
)
|
||||
|
||||
for (t = prop->trans, tn = 0; tn < prop->trans_cnt; tn++)
|
||||
{
|
||||
DBG(DBG_CONTROL|DBG_EMITTING,
|
||||
DBG_log("kernel_alg_db_prop_new() "
|
||||
" trans[%d]: transid=%d, attr_cnt=%d, "
|
||||
"attrs[0].type=%d, attrs[0].val=%d"
|
||||
, tn
|
||||
, t[tn].transid, t[tn].attr_cnt
|
||||
, t[tn].attrs[0].type, t[tn].attrs[0].val)
|
||||
)
|
||||
}
|
||||
return ctx_new;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,8 +258,8 @@ const chunk_t* get_preshared_secret(const struct connection *c)
|
|||
return s == NULL? NULL : &s->u.preshared_secret;
|
||||
}
|
||||
|
||||
/* check the existence of an RSA private key matching an RSA public
|
||||
* key contained in an X.509 or OpenPGP certificate
|
||||
/* check the existence of a private key matching a public key contained
|
||||
* in an X.509 or OpenPGP certificate
|
||||
*/
|
||||
bool has_private_key(cert_t cert)
|
||||
{
|
||||
|
@ -280,7 +280,7 @@ bool has_private_key(cert_t cert)
|
|||
}
|
||||
|
||||
/*
|
||||
* get the matching RSA private key belonging to a given X.509 certificate
|
||||
* get the matching private key belonging to a given X.509 certificate
|
||||
*/
|
||||
private_key_t* get_x509_private_key(const x509cert_t *cert)
|
||||
{
|
||||
|
@ -297,7 +297,7 @@ private_key_t* get_x509_private_key(const x509cert_t *cert)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* find the appropriate RSA private key (see get_secret).
|
||||
/* find the appropriate private key (see get_secret).
|
||||
* Failure is indicated by a NULL pointer.
|
||||
*/
|
||||
private_key_t* get_private_key(const struct connection *c)
|
||||
|
|
|
@ -321,7 +321,7 @@ out_sa(pb_stream *outs
|
|||
|
||||
alg_info_snprint(buf, sizeof (buf),
|
||||
(struct alg_info *)st->st_connection->alg_info_esp);
|
||||
DBG_log(buf);
|
||||
DBG_log("esp proposal: %s", buf);
|
||||
}
|
||||
)
|
||||
db_ctx = kernel_alg_db_new(st->st_connection->alg_info_esp, st->st_policy);
|
||||
|
@ -345,10 +345,10 @@ out_sa(pb_stream *outs
|
|||
|
||||
alg_info_snprint(buf, sizeof (buf),
|
||||
(struct alg_info *)st->st_connection->alg_info_ike);
|
||||
DBG_log(buf);
|
||||
DBG_log("ike proposal: %s", buf);
|
||||
}
|
||||
)
|
||||
db_ctx = ike_alg_db_new(st->st_connection->alg_info_ike, st->st_policy);
|
||||
db_ctx = ike_alg_db_new(st->st_connection, st->st_policy);
|
||||
p = db_prop_get(db_ctx);
|
||||
|
||||
if (!p || p->trans_cnt == 0)
|
||||
|
@ -794,7 +794,10 @@ parse_isakmp_policy(pb_stream *proposal_pbs
|
|||
*policy |= POLICY_PSK;
|
||||
break;
|
||||
case OAKLEY_RSA_SIG:
|
||||
*policy |= POLICY_RSASIG;
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
*policy |= POLICY_PUBKEY;
|
||||
break;
|
||||
case XAUTHInitPreShared:
|
||||
*policy |= POLICY_XAUTH_SERVER;
|
||||
|
@ -978,7 +981,7 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
|
|||
case OAKLEY_PRESHARED_KEY:
|
||||
if ((iap & POLICY_PSK) == LEMPTY)
|
||||
{
|
||||
ugh = "policy does not allow OAKLEY_PRESHARED_KEY authentication";
|
||||
ugh = "policy does not allow pre-shared key authentication";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1009,14 +1012,16 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
|
|||
}
|
||||
break;
|
||||
case OAKLEY_RSA_SIG:
|
||||
/* Accept if policy specifies RSASIG or is default */
|
||||
if ((iap & POLICY_RSASIG) == LEMPTY)
|
||||
case OAKLEY_ECDSA_256:
|
||||
case OAKLEY_ECDSA_384:
|
||||
case OAKLEY_ECDSA_512:
|
||||
if ((iap & POLICY_PUBKEY) == LEMPTY)
|
||||
{
|
||||
ugh = "policy does not allow OAKLEY_RSA_SIG authentication";
|
||||
ugh = "policy does not allow public key authentication";
|
||||
}
|
||||
else
|
||||
{
|
||||
ta.auth = OAKLEY_RSA_SIG;
|
||||
ta.auth = val;
|
||||
}
|
||||
break;
|
||||
case XAUTHInitRSA:
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
/* strings containing a colon are interpreted as an IPv6 address */
|
||||
#define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
|
||||
|
||||
static const char ike_defaults[] = "aes128-sha-modp2048";
|
||||
static const char esp_defaults[] = "aes128-sha1, 3des-md5";
|
||||
static const char ike_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
|
||||
static const char esp_defaults[] = "aes128-sha1,3des-sha1";
|
||||
|
||||
static const char firewall_defaults[] = "ipsec _updown iptables";
|
||||
|
||||
|
@ -70,7 +70,7 @@ static void default_values(starter_config_t *cfg)
|
|||
cfg->conn_default.seen = LEMPTY;
|
||||
cfg->conn_default.startup = STARTUP_NO;
|
||||
cfg->conn_default.state = STATE_IGNORE;
|
||||
cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_RSASIG |
|
||||
cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_PUBKEY |
|
||||
POLICY_PFS | POLICY_MOBIKE;
|
||||
|
||||
cfg->conn_default.ike = clone_str(ike_defaults);
|
||||
|
@ -555,18 +555,16 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
|
|||
/* also handles the cases secret|rsasig and rsasig|secret */
|
||||
for (;;)
|
||||
{
|
||||
if (streq(value, "rsa") || streq(value, "rsasig"))
|
||||
if (streq(value, "rsa") || streq(value, "rsasig") ||
|
||||
streq(value, "ecdsa") || streq(value, "ecdsasig") ||
|
||||
streq(value, "pubkey"))
|
||||
{
|
||||
conn->policy |= POLICY_RSASIG | POLICY_ENCRYPT;
|
||||
conn->policy |= POLICY_PUBKEY | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "secret") || streq(value, "psk"))
|
||||
{
|
||||
conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "ecdsa") || streq(value, "ecdsasig"))
|
||||
{
|
||||
conn->policy |= POLICY_ECDSASIG | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "xauthrsasig"))
|
||||
{
|
||||
conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
|
||||
|
|
|
@ -239,7 +239,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
|
|||
msg.add_conn.name = push_string(&msg, connection_name(conn));
|
||||
|
||||
/* PUBKEY is preferred to PSK and EAP */
|
||||
if (conn->policy & POLICY_RSASIG || conn->policy & POLICY_ECDSASIG)
|
||||
if (conn->policy & POLICY_PUBKEY)
|
||||
{
|
||||
msg.add_conn.auth_method = AUTH_PUBKEY;
|
||||
}
|
||||
|
|
|
@ -323,7 +323,7 @@ starter_whack_add_conn(starter_conn_t *conn)
|
|||
|
||||
r = send_whack_msg(&msg);
|
||||
|
||||
if (r == 0 && (conn->policy & POLICY_RSASIG))
|
||||
if (r == 0 && (conn->policy & POLICY_PUBKEY))
|
||||
{
|
||||
r += starter_whack_add_pubkey (conn, &conn->left, "left");
|
||||
r += starter_whack_add_pubkey (conn, &conn->right, "right");
|
||||
|
|
|
@ -1634,8 +1634,8 @@ int main(int argc, char **argv)
|
|||
|
||||
if (msg.policy & POLICY_OPPO)
|
||||
{
|
||||
if ((msg.policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG)
|
||||
diag("only RSASIG is supported for opportunism");
|
||||
if ((msg.policy & (POLICY_PSK | POLICY_PUBKEY)) != POLICY_PUBKEY)
|
||||
diag("only PUBKEY is supported for opportunism");
|
||||
if ((msg.policy & POLICY_PFS) == 0)
|
||||
diag("PFS required for opportunism");
|
||||
if ((msg.policy & POLICY_ENCRYPT) == 0)
|
||||
|
|
Loading…
Reference in New Issue