Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
WIP: IKEv2: Add ECDSA support via RFC 7427 Digital Signatures
Signed-off-by: Paul Wouters <pwouters@redhat.com>
  • Loading branch information
sahanaprasad07 authored and letoams committed Sep 10, 2018
1 parent d3e9708 commit 12f2f1a
Show file tree
Hide file tree
Showing 21 changed files with 1,146 additions and 68 deletions.
3 changes: 2 additions & 1 deletion include/asn1.h
Expand Up @@ -78,4 +78,5 @@ extern size_t asn1_length(chunk_t *blob);
extern void code_asn1_length(size_t length, chunk_t *code);
extern bool is_printablestring(chunk_t str);
extern bool is_asn1(chunk_t blob);

extern size_t asn1_length_signature(chunk_t *blob , chunk_t *sig_val);
extern bool is_asn1_der_encoded_signature(chunk_t blob, chunk_t *sig_val);
21 changes: 21 additions & 0 deletions include/ietf_constants.h
Expand Up @@ -1549,6 +1549,7 @@ enum ppk_id_type {
enum pubkey_alg {
PUBKEY_ALG_DSA = 1,
PUBKEY_ALG_RSA = 2,
PUBKEY_ALG_ECDSA = 3,
};

/*
Expand Down Expand Up @@ -1794,6 +1795,26 @@ enum notify_payload_hash_algorithms {
#define LEN_RSA_PSS_SHA2_BLOB {ASN1_SHA2_RSA_PSS_SIZE}
#define RSA_SHA1_SIGNED_OCTETS 16

/* ECDSA */
#define ASN1_SHA1_ECDSA_SIZE 11
#define ASN1_SHA2_ECDSA_SIZE 12

#define ECDSA_SHA1_BLOB \
{0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01}

#define ECDSA_SHA256_BLOB \
{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02}

#define ECDSA_SHA384_BLOB \
{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03}

#define ECDSA_SHA512_BLOB \
{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04}

#define LEN_ECDSA_SHA1_BLOB {ASN1_SHA1_ECDSA_SIZE}

#define LEN_ECDSA_SHA2_BLOB {ASN1_SHA2_ECDSA_SIZE}

/* Limits on size of RSA moduli.
* The upper bound matches that of DNSSEC (see RFC 2537).
* The lower bound must be more than 11 octets for certain
Expand Down
4 changes: 4 additions & 0 deletions include/ike_alg_hash.h
Expand Up @@ -36,3 +36,7 @@ extern const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_512;
extern const struct asn1_hash_blob asn1_rsa_pss_sha2_256;
extern const struct asn1_hash_blob asn1_rsa_pss_sha2_384;
extern const struct asn1_hash_blob asn1_rsa_pss_sha2_512;

extern const struct asn1_hash_blob asn1_ecdsa_sha2_256;
extern const struct asn1_hash_blob asn1_ecdsa_sha2_384;
extern const struct asn1_hash_blob asn1_ecdsa_sha2_512;
8 changes: 6 additions & 2 deletions include/pluto_constants.h
Expand Up @@ -7,7 +7,7 @@
* Copyright (C) 2013 David McCullough <ucdevel@gmail.com>
* Copyright (C) 2013 Matt Rogers <mrogers@redhat.com>
* Copyright (C) 2016-2017, Andrew Cagney
* Copyright (C) 2017 Sahana Prasad <sahana.prasad07@gmail.com>
* Copyright (C) 2017-2018 Sahana Prasad <sahana.prasad07@gmail.com>
* Copyright (C) 2017 Vukasin Karadzic <vukasin.karadzic@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -86,7 +86,8 @@ enum keyword_authby {
AUTH_NEVER = 1,
AUTH_PSK = 2,
AUTH_RSASIG = 3,
AUTH_NULL = 4,
AUTH_ECDSA = 4,
AUTH_NULL = 5,
};

enum keyword_xauthby {
Expand Down Expand Up @@ -929,6 +930,7 @@ enum sa_policy_bits {
*/
POLICY_PSK_IX = 0,
POLICY_RSASIG_IX = 1,
POLICY_ECDSA_IX = 2,
POLICY_AUTH_NEVER_IX,
POLICY_AUTH_NULL_IX,

Expand Down Expand Up @@ -1019,6 +1021,7 @@ enum sa_policy_bits {

#define POLICY_PSK LELEM(POLICY_PSK_IX)
#define POLICY_RSASIG LELEM(POLICY_RSASIG_IX)
#define POLICY_ECDSA LELEM(POLICY_ECDSA_IX)
#define POLICY_AUTH_NEVER LELEM(POLICY_AUTH_NEVER_IX)
#define POLICY_AUTH_NULL LELEM(POLICY_AUTH_NULL_IX)
#define POLICY_ENCRYPT LELEM(POLICY_ENCRYPT_IX) /* must be first of IPSEC policies */
Expand Down Expand Up @@ -1132,6 +1135,7 @@ enum PrivateKeyKind {
PKK_RSA,
PKK_XAUTH,
PKK_PPK,
PKK_ECDSA, /* should not be needed */
PKK_NULL,
};

Expand Down
23 changes: 23 additions & 0 deletions include/secrets.h
Expand Up @@ -81,7 +81,24 @@ struct RSA_private_key {
struct RSA_public_key pub;
};

struct ECDSA_public_key {
char keyid[KEYID_BUF];
unsigned int k;
chunk_t ecParams;
chunk_t pub; /* publicValue */
ckaid_t ckaid;
};

struct ECDSA_private_key {
struct ECDSA_public_key pub;
chunk_t ecParams;
chunk_t pub_val; /* publicValue */
chunk_t privateValue;
chunk_t version;
};

extern void free_RSA_public_content(struct RSA_public_key *rsa);
extern void free_ECDSA_public_content(struct ECDSA_public_key *ecdsa);

err_t rsa_pubkey_to_rfc_resource_record(chunk_t exponent, chunk_t modulus, chunk_t *rr);
err_t rfc_resource_record_to_rsa_pubkey(chunk_t rr, chunk_t *exponent, chunk_t *modulus);
Expand All @@ -91,8 +108,10 @@ err_t base64_to_rsa_pubkey(const char *rr, chunk_t *exponent, chunk_t *modulus);

err_t pack_RSA_public_key(const struct RSA_public_key *rsa, chunk_t *pubkey);
err_t unpack_RSA_public_key(struct RSA_public_key *rsa, const chunk_t *pubkey);
err_t unpack_ECDSA_public_key(struct ECDSA_public_key *ecdsa, const chunk_t *pubkey); /* ASKK */

void DBG_log_RSA_public_key(const struct RSA_public_key *rsa);
void DBG_log_ECDSA_public_key(const struct ECDSA_public_key *ecdsa);

struct private_key_stuff {
enum PrivateKeyKind kind;
Expand All @@ -113,6 +132,7 @@ struct private_key_stuff {
union {
chunk_t preshared_secret;
struct RSA_private_key RSA_private_key;
struct ECDSA_private_key ECDSA_private_key;
/* struct smartcard *smartcard; */
} u;

Expand Down Expand Up @@ -148,6 +168,7 @@ struct pubkey {
enum pubkey_alg alg;
union {
struct RSA_public_key rsa;
struct ECDSA_public_key ecdsa;
} u;
};

Expand Down Expand Up @@ -207,7 +228,9 @@ extern struct secret *lsw_get_ppk_by_id(struct secret *secrets, chunk_t ppk_id);
extern void lock_certs_and_keys(const char *who);
extern void unlock_certs_and_keys(const char *who);
extern err_t lsw_add_rsa_secret(struct secret **secrets, CERTCertificate *cert);
extern err_t lsw_add_ecdsa_secret(struct secret **secrets, CERTCertificate *cert);
extern struct pubkey *allocate_RSA_public_key_nss(CERTCertificate *cert);
extern struct pubkey *allocate_ECDSA_public_key_nss(CERTCertificate *cert);

/* these do not clone */
chunk_t same_secitem_as_chunk(SECItem si);
Expand Down
3 changes: 3 additions & 0 deletions include/x509.h
Expand Up @@ -97,9 +97,12 @@ extern SECItem same_chunk_as_dercert_secitem(chunk_t chunk);
extern chunk_t get_dercert_from_nss_cert(CERTCertificate *cert);
extern generalName_t *gndp_from_nss_cert(CERTCertificate *cert);
extern bool cert_key_is_rsa(CERTCertificate *cert);
extern bool cert_key_is_ecdsa(CERTCertificate *cert);
extern void select_nss_cert_id(CERTCertificate *cert, struct id *end_id);
extern void add_rsa_pubkey_from_cert(const struct id *keyid,
CERTCertificate *cert);
extern void add_ecdsa_pubkey_from_cert(const struct id *keyid,
CERTCertificate *cert);
extern bool trusted_ca_nss(chunk_t a, chunk_t b, int *pathlen);
extern CERTCertList *get_all_certificates(void);

Expand Down
3 changes: 2 additions & 1 deletion programs/pluto/Makefile
Expand Up @@ -9,6 +9,7 @@
# Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
# Copyright (C) 2015-2017 Andrew Cagney
# Copyright (C) 2016-2017 Paul Wouters <pwouters@redhat.com>
# Copyright (C) 2018 Sahana Prasad <sahana.prasad07@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
Expand Down Expand Up @@ -210,7 +211,7 @@ OBJS += ikev2_ipseckey.o
endif
OBJS += ikev1.o ikev1_main.o ikev1_quick.o ikev1_dpd.o ikev1_spdb_struct.o ikev1_msgid.o
OBJS += ikev2.o ikev2_parent.o ikev2_child.o ikev2_spdb_struct.o
OBJS += ikev2_rsa.o ikev2_psk.o ikev2_ppk.o ikev2_crypto.o
OBJS += ikev2_ecdsa.o ikev2_rsa.o ikev2_psk.o ikev2_ppk.o ikev2_crypto.o
OBJS += crypt_symkey.o crypt_prf.o ikev1_prf.o ikev2_prf.o
OBJS += crypt_hash.o
OBJS += kernel.o
Expand Down
25 changes: 25 additions & 0 deletions programs/pluto/connections.c
Expand Up @@ -843,6 +843,7 @@ static void load_end_nss_certificate(const char *which, CERTCertificate *cert,
SECKEY_DestroyPublicKey(pk);
return;
}
/* TODO FORCE MINIMUM SIZE ECDSA KEY */
SECKEY_DestroyPublicKey(pk);
}
#endif /* FIPS_CHECK */
Expand All @@ -860,7 +861,10 @@ static void load_end_nss_certificate(const char *which, CERTCertificate *cert,

DBG(DBG_X509, DBG_log("loaded %s certificate \'%s\'", which, name));

/* check for type instead of do both? */
add_rsa_pubkey_from_cert(&d_end->id, cert);
add_ecdsa_pubkey_from_cert(&d_end->id, cert);

d_end->cert.ty = CERT_X509_SIGNATURE;
d_end->cert.u.nss_cert = cert;

Expand Down Expand Up @@ -1405,6 +1409,12 @@ void add_connection(const struct whack_message *wm)
conflict = TRUE;
}
break;
case AUTH_ECDSA:
if (auth_pol != POLICY_ECDSA && auth_pol != LEMPTY) {
loglog(RC_FATAL, "leftauthby=ecdsa but authby= is not ecdsa");
conflict = TRUE;
}
break;
case AUTH_NULL:
if (auth_pol != POLICY_AUTH_NULL && auth_pol != LEMPTY) {
loglog(RC_FATAL, "leftauthby=null but authby= is not null");
Expand Down Expand Up @@ -1816,6 +1826,8 @@ void add_connection(const struct whack_message *wm)
if (wm->left.authby == AUTH_UNSET && wm->right.authby == AUTH_UNSET) {
if (c->policy & POLICY_RSASIG)
c->spd.this.authby = c->spd.that.authby = AUTH_RSASIG;
else if (c->policy & POLICY_ECDSA)
c->spd.this.authby = c->spd.that.authby = AUTH_ECDSA;
else if (c->policy & POLICY_PSK)
c->spd.this.authby = c->spd.that.authby = AUTH_PSK;
else if (c->policy & POLICY_AUTH_NULL)
Expand All @@ -1828,6 +1840,9 @@ void add_connection(const struct whack_message *wm)
case AUTH_RSASIG:
c->policy |= POLICY_RSASIG;
break;
case AUTH_ECDSA:
c->policy |= POLICY_ECDSA;
break;
case AUTH_PSK:
c->policy |= POLICY_PSK;
break;
Expand Down Expand Up @@ -3162,6 +3177,16 @@ struct connection *refine_host_connection(const struct state *st,
return c;
}
break;
#if 0
case AUTH_ECDSA:
my_ECDSA_pri = get_RSA_private_key(c);
if (my_ECDSA_pri == NULL) {
loglog(RC_LOG_SERIOUS, "cannot find ECDSA key");*/
/* cannot determine my ECDSA private key, so not switching */
return c;
}
break;*/
#endif
default:
/* don't die on bad_case(auth); */

Expand Down
2 changes: 1 addition & 1 deletion programs/pluto/ikev1_main.c
Expand Up @@ -310,7 +310,7 @@ size_t RSA_sign_hash(const struct connection *c,
passert(RSA_MIN_OCTETS <= sz &&
4 + hash_len < sz &&
sz <= RSA_MAX_OCTETS);
shr = sign_hash(k, hash_val, hash_len, sig_val, sz, 0 /* for ikev2 only */);
shr = sign_hash_RSA(k, hash_val, hash_len, sig_val, sz, 0 /* for ikev2 only */);
passert(shr == 0 || (int)sz == shr);
return shr;
}
Expand Down
4 changes: 4 additions & 0 deletions programs/pluto/ikev2.c
Expand Up @@ -2136,6 +2136,10 @@ bool ikev2_decode_peer_id_and_certs(struct msg_digest *md)
authby = AUTH_RSASIG;
break;
}
if (c->policy & POLICY_ECDSA) {
authby = AUTH_ECDSA;
break;
}
/* FALL THROUGH */
case IKEv2_AUTH_NONE:
default:
Expand Down
15 changes: 15 additions & 0 deletions programs/pluto/ikev2.h
Expand Up @@ -5,6 +5,7 @@
* Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
* Copyright (C) 2018 Paul Wouters <pwouters@redhat.com>
* Copyright (C) 2017 Andrew Cagney
* Copyright (C) 2018 Sahana Prasad <sahana.prasad07@gmail.com>
*/

typedef stf_status crypto_transition_fn(struct state *st, struct msg_digest *md,
Expand Down Expand Up @@ -144,6 +145,14 @@ extern bool ikev2_calculate_rsa_hash(struct state *st,
chunk_t *no_ppk_auth,
enum notify_payload_hash_algorithms hash_algo);

extern bool ikev2_calculate_ecdsa_hash(struct state *st,
enum original_role role,
unsigned char *idhash,
pb_stream *a_pbs,
bool calc_no_ppk_auth,
chunk_t *no_ppk_auth,
enum notify_payload_hash_algorithms hash_algo);

extern bool ikev2_create_psk_auth(enum keyword_authby authby,
const struct state *st,
const unsigned char *idhash,
Expand All @@ -156,6 +165,12 @@ extern stf_status ikev2_verify_rsa_hash(struct state *st,
pb_stream *sig_pbs,
enum notify_payload_hash_algorithms hash_algo);

extern stf_status ikev2_verify_ecdsa_hash(struct state *st,
enum original_role role,
const unsigned char *idhash,
pb_stream *sig_pbs,
enum notify_payload_hash_algorithms hash_algo);

extern stf_status ikev2_verify_psk_auth(enum keyword_authby authby,
const struct state *st,
const unsigned char *idhash,
Expand Down

0 comments on commit 12f2f1a

Please sign in to comment.