Reyk,
I've taken the liberty of patching ca.c, crypto.c, ikev2.h, parse.y,
iked.8 and iked.conf.5. I'm no expert on this, but this seems to work
for me. SAs and Flows are established, it hasn't crashed, and I'm
passing data.
Let me know what you think.
Thanks,
-Jason
diff -u sbin/iked.orig/ca.c sbin/iked/ca.c
--- sbin/iked.orig/ca.c Tue Mar 12 18:15:44 2013
+++ sbin/iked/ca.c Wed Mar 13 09:17:37 2013
@@ -346,6 +346,9 @@
case IKEV2_CERT_RSA_KEY:
ret = ca_validate_pubkey(env, &id, ptr, len);
break;
+ case IKEV2_CERT_EC_KEY:
+ ret = ca_validate_pubkey(env, &id, ptr, len);
+ break;
default:
log_debug("%s: unsupported cert type %d", __func__, type);
ret = -1;
@@ -754,6 +757,7 @@
int len;
u_int8_t *d;
RSA *rsa;
+ EC_KEY *eckey;
switch (key->type) {
case EVP_PKEY_RSA:
@@ -776,6 +780,26 @@
id->id_type = IKEV2_CERT_RSA_KEY;
break;
+ case EVP_PKEY_EC:
+ id->id_type = 0;
+ id->id_offset = 0;
+ ibuf_release(id->id_buf);
+
+ if ((eckey = EVP_PKEY_get1_EC_KEY(key)) == NULL)
+ return (-1);
+ if ((len = i2d_ECPrivateKey(eckey, NULL)) <= 0)
+ return (-1);
+ if ((id->id_buf = ibuf_new(NULL, len)) == NULL)
+ return (-1);
+
+ d = ibuf_data(id->id_buf);
+ if (i2d_ECPrivateKey(eckey, &d) != len) {
+ ibuf_release(id->id_buf);
+ return (-1);
+ }
+
+ id->id_type = IKEV2_CERT_EC_KEY;
+ break;
default:
log_debug("%s: unsupported key type %d", __func__, key->type);
return (-1);
@@ -819,6 +843,7 @@
{
BIO *rawcert = NULL;
RSA *rsa = NULL;
+ EC_KEY *eckey = NULL;
EVP_PKEY *peerkey = NULL, *localkey = NULL;
int ret = -1;
FILE *fp = NULL;
@@ -856,12 +881,16 @@
if ((rawcert = BIO_new_mem_buf(data, len)) == NULL)
goto done;
- if ((rsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL)
- goto sslerr;
+ if ((rsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL) {
+ if ((eckey = d2i_EC_PUBKEY_bio(rawcert, NULL )) == NULL)
+ goto sslerr;
+ }
if ((peerkey = EVP_PKEY_new()) == NULL)
goto sslerr;
- if (!EVP_PKEY_set1_RSA(peerkey, rsa))
- goto sslerr;
+ if (!EVP_PKEY_set1_RSA(peerkey, rsa)) {
+ if (!EVP_PKEY_set1_EC_KEY(peerkey, eckey))
+ goto sslerr;
+ }
}
lc_string(idstr);
@@ -892,6 +921,8 @@
EVP_PKEY_free(peerkey);
if (rsa != NULL)
RSA_free(rsa);
+ if (eckey != NULL)
+ EC_KEY_free(eckey);
if (rawcert != NULL)
BIO_free(rawcert);
diff -u sbin/iked.orig/crypto.c sbin/iked/crypto.c
--- sbin/iked.orig/crypto.c Tue Mar 12 18:15:44 2013
+++ sbin/iked/crypto.c Wed Mar 13 09:17:37 2013
@@ -542,6 +542,7 @@
BIO *rawcert = NULL;
X509 *cert = NULL;
RSA *rsa = NULL;
+ EC_KEY *eckey = NULL;
EVP_PKEY *pkey = NULL;
ibuf_release(dsa->dsa_keydata);
@@ -576,6 +577,25 @@
if ((pkey = EVP_PKEY_new()) == NULL)
goto sslerr;
if (!EVP_PKEY_set1_RSA(pkey, rsa))
+ goto sslerr;
+
+ dsa->dsa_cert = NULL;
+ dsa->dsa_key = pkey;
+ break;
+ case IKEV2_CERT_EC_KEY:
+ if (dsa->dsa_sign) {
+ if ((eckey = d2i_ECPrivateKey_bio(rawcert,
+ NULL)) == NULL)
+ goto sslerr;
+ } else {
+ if ((eckey = d2i_EC_PUBKEY_bio(rawcert,
+ NULL)) == NULL)
+ goto sslerr;
+ }
+
+ if ((pkey = EVP_PKEY_new()) == NULL)
+ goto sslerr;
+ if (!EVP_PKEY_set1_EC_KEY(pkey, eckey))
goto sslerr;
dsa->dsa_cert = NULL;
diff -u sbin/iked.orig/iked.8 sbin/iked/iked.8
--- sbin/iked.orig/iked.8 Tue Mar 12 18:15:45 2013
+++ sbin/iked/iked.8 Wed Mar 13 09:17:37 2013
@@ -46,7 +46,7 @@
.Xr isakmpd 8 .
.Pp
.Nm
-supports mutual authentication using RSA public keys and X.509
certificates.
+supports mutual authentication using RSA, or ECDSA, public keys and
X.509 certificates.
See the
.Sx FILES
section below and
diff -u sbin/iked.orig/iked.conf.5 sbin/iked/iked.conf.5
--- sbin/iked.orig/iked.conf.5 Tue Mar 12 18:15:45 2013
+++ sbin/iked/iked.conf.5 Wed Mar 13 09:17:37 2013
@@ -472,6 +472,10 @@
.It Ic rsa
Use RSA public key authentication.
This is the default mode if no option is specified.
+.It Ic ecdsa-256
+.It Ic ecdsa-384
+.It Ic ecdsa-512
+Use ECDSA public key authentication.
.El
.It Ic tag Ar string
Add a
diff -u sbin/iked.orig/ikev2.h sbin/iked/ikev2.h
--- sbin/iked.orig/ikev2.h Tue Mar 12 18:15:45 2013
+++ sbin/iked/ikev2.h Wed Mar 13 09:37:27 2013
@@ -374,6 +374,7 @@
#define IKEV2_CERT_HASHURL_X509 12 /* RFC4306 */
#define IKEV2_CERT_HASHURL_X509_BUNDLE 13 /* RFC4306 */
#define IKEV2_CERT_OCSP 14 /* RFC4806 */
+#define IKEV2_CERT_EC_KEY 201 /* UNKNOWN RFC */
extern struct iked_constmap ikev2_cert_map[];
diff -u sbin/iked.orig/parse.y sbin/iked/parse.y
--- sbin/iked.orig/parse.y Tue Mar 12 18:15:45 2013
+++ sbin/iked/parse.y Wed Mar 13 09:17:37 2013
@@ -365,6 +365,7 @@
%}
%token FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK PORT
+%token ECDSA_256 ECDSA_384 ECDSA_512
%token FILENAME AUTHXF PRFXF ENCXF ERROR IKEV2 IKESA CHILDSA
%token PASSIVE ACTIVE ANY TAG TAP PROTO LOCAL GROUP NAME CONFIG EAP USER
%token IKEV1 FLOW SA TCPMD5 TUNNEL TRANSPORT COUPLE DECOUPLE SET
@@ -791,6 +792,18 @@
$$.auth_method = IKEV2_AUTH_RSA_SIG;
$$.auth_length = 0;
}
+ | ECDSA_256 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_256;
+ $$.auth_length = 0;
+ }
+ | ECDSA_384 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_384;
+ $$.auth_length = 0;
+ }
+ | ECDSA_512 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_512;
+ $$.auth_length = 0;
+ }
| PSK keyspec {
memcpy(&$$, &$2, sizeof($$));
$$.auth_method = IKEV2_AUTH_SHARED_KEY_MIC;
@@ -1065,6 +1078,9 @@
{ "default", DEFAULT },
{ "dstid", DSTID },
{ "eap", EAP },
+ { "ecdsa-256", ECDSA_256 },
+ { "ecdsa-384", ECDSA_384 },
+ { "ecdsa-512", ECDSA_512 },
{ "enc", ENCXF },
{ "esp", ESP },
{ "file", FILENAME },
diff -u sbin/iked.orig/ca.c sbin/iked/ca.c
--- sbin/iked.orig/ca.c Tue Mar 12 18:15:44 2013
+++ sbin/iked/ca.c Wed Mar 13 09:17:37 2013
@@ -346,6 +346,9 @@
case IKEV2_CERT_RSA_KEY:
ret = ca_validate_pubkey(env, &id, ptr, len);
break;
+ case IKEV2_CERT_EC_KEY:
+ ret = ca_validate_pubkey(env, &id, ptr, len);
+ break;
default:
log_debug("%s: unsupported cert type %d", __func__, type);
ret = -1;
@@ -754,6 +757,7 @@
int len;
u_int8_t *d;
RSA *rsa;
+ EC_KEY *eckey;
switch (key->type) {
case EVP_PKEY_RSA:
@@ -776,6 +780,26 @@
id->id_type = IKEV2_CERT_RSA_KEY;
break;
+ case EVP_PKEY_EC:
+ id->id_type = 0;
+ id->id_offset = 0;
+ ibuf_release(id->id_buf);
+
+ if ((eckey = EVP_PKEY_get1_EC_KEY(key)) == NULL)
+ return (-1);
+ if ((len = i2d_ECPrivateKey(eckey, NULL)) <= 0)
+ return (-1);
+ if ((id->id_buf = ibuf_new(NULL, len)) == NULL)
+ return (-1);
+
+ d = ibuf_data(id->id_buf);
+ if (i2d_ECPrivateKey(eckey, &d) != len) {
+ ibuf_release(id->id_buf);
+ return (-1);
+ }
+
+ id->id_type = IKEV2_CERT_EC_KEY;
+ break;
default:
log_debug("%s: unsupported key type %d", __func__, key->type);
return (-1);
@@ -819,6 +843,7 @@
{
BIO *rawcert = NULL;
RSA *rsa = NULL;
+ EC_KEY *eckey = NULL;
EVP_PKEY *peerkey = NULL, *localkey = NULL;
int ret = -1;
FILE *fp = NULL;
@@ -856,12 +881,16 @@
if ((rawcert = BIO_new_mem_buf(data, len)) == NULL)
goto done;
- if ((rsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL)
- goto sslerr;
+ if ((rsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL) {
+ if ((eckey = d2i_EC_PUBKEY_bio(rawcert, NULL )) == NULL)
+ goto sslerr;
+ }
if ((peerkey = EVP_PKEY_new()) == NULL)
goto sslerr;
- if (!EVP_PKEY_set1_RSA(peerkey, rsa))
- goto sslerr;
+ if (!EVP_PKEY_set1_RSA(peerkey, rsa)) {
+ if (!EVP_PKEY_set1_EC_KEY(peerkey, eckey))
+ goto sslerr;
+ }
}
lc_string(idstr);
@@ -892,6 +921,8 @@
EVP_PKEY_free(peerkey);
if (rsa != NULL)
RSA_free(rsa);
+ if (eckey != NULL)
+ EC_KEY_free(eckey);
if (rawcert != NULL)
BIO_free(rawcert);
diff -u sbin/iked.orig/crypto.c sbin/iked/crypto.c
--- sbin/iked.orig/crypto.c Tue Mar 12 18:15:44 2013
+++ sbin/iked/crypto.c Wed Mar 13 09:17:37 2013
@@ -542,6 +542,7 @@
BIO *rawcert = NULL;
X509 *cert = NULL;
RSA *rsa = NULL;
+ EC_KEY *eckey = NULL;
EVP_PKEY *pkey = NULL;
ibuf_release(dsa->dsa_keydata);
@@ -576,6 +577,25 @@
if ((pkey = EVP_PKEY_new()) == NULL)
goto sslerr;
if (!EVP_PKEY_set1_RSA(pkey, rsa))
+ goto sslerr;
+
+ dsa->dsa_cert = NULL;
+ dsa->dsa_key = pkey;
+ break;
+ case IKEV2_CERT_EC_KEY:
+ if (dsa->dsa_sign) {
+ if ((eckey = d2i_ECPrivateKey_bio(rawcert,
+ NULL)) == NULL)
+ goto sslerr;
+ } else {
+ if ((eckey = d2i_EC_PUBKEY_bio(rawcert,
+ NULL)) == NULL)
+ goto sslerr;
+ }
+
+ if ((pkey = EVP_PKEY_new()) == NULL)
+ goto sslerr;
+ if (!EVP_PKEY_set1_EC_KEY(pkey, eckey))
goto sslerr;
dsa->dsa_cert = NULL;
diff -u sbin/iked.orig/iked.8 sbin/iked/iked.8
--- sbin/iked.orig/iked.8 Tue Mar 12 18:15:45 2013
+++ sbin/iked/iked.8 Wed Mar 13 09:17:37 2013
@@ -46,7 +46,7 @@
.Xr isakmpd 8 .
.Pp
.Nm
-supports mutual authentication using RSA public keys and X.509 certificates.
+supports mutual authentication using RSA, or ECDSA, public keys and X.509
certificates.
See the
.Sx FILES
section below and
diff -u sbin/iked.orig/iked.conf.5 sbin/iked/iked.conf.5
--- sbin/iked.orig/iked.conf.5 Tue Mar 12 18:15:45 2013
+++ sbin/iked/iked.conf.5 Wed Mar 13 09:17:37 2013
@@ -472,6 +472,10 @@
.It Ic rsa
Use RSA public key authentication.
This is the default mode if no option is specified.
+.It Ic ecdsa-256
+.It Ic ecdsa-384
+.It Ic ecdsa-512
+Use ECDSA public key authentication.
.El
.It Ic tag Ar string
Add a
diff -u sbin/iked.orig/ikev2.h sbin/iked/ikev2.h
--- sbin/iked.orig/ikev2.h Tue Mar 12 18:15:45 2013
+++ sbin/iked/ikev2.h Wed Mar 13 09:37:27 2013
@@ -374,6 +374,7 @@
#define IKEV2_CERT_HASHURL_X509 12 /* RFC4306 */
#define IKEV2_CERT_HASHURL_X509_BUNDLE 13 /* RFC4306 */
#define IKEV2_CERT_OCSP 14 /* RFC4806 */
+#define IKEV2_CERT_EC_KEY 201 /* UNKNOWN RFC */
extern struct iked_constmap ikev2_cert_map[];
diff -u sbin/iked.orig/parse.y sbin/iked/parse.y
--- sbin/iked.orig/parse.y Tue Mar 12 18:15:45 2013
+++ sbin/iked/parse.y Wed Mar 13 09:17:37 2013
@@ -365,6 +365,7 @@
%}
%token FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK PORT
+%token ECDSA_256 ECDSA_384 ECDSA_512
%token FILENAME AUTHXF PRFXF ENCXF ERROR IKEV2 IKESA CHILDSA
%token PASSIVE ACTIVE ANY TAG TAP PROTO LOCAL GROUP NAME CONFIG EAP USER
%token IKEV1 FLOW SA TCPMD5 TUNNEL TRANSPORT COUPLE DECOUPLE SET
@@ -791,6 +792,18 @@
$$.auth_method = IKEV2_AUTH_RSA_SIG;
$$.auth_length = 0;
}
+ | ECDSA_256 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_256;
+ $$.auth_length = 0;
+ }
+ | ECDSA_384 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_384;
+ $$.auth_length = 0;
+ }
+ | ECDSA_512 {
+ $$.auth_method = IKEV2_AUTH_ECDSA_512;
+ $$.auth_length = 0;
+ }
| PSK keyspec {
memcpy(&$$, &$2, sizeof($$));
$$.auth_method = IKEV2_AUTH_SHARED_KEY_MIC;
@@ -1065,6 +1078,9 @@
{ "default", DEFAULT },
{ "dstid", DSTID },
{ "eap", EAP },
+ { "ecdsa-256", ECDSA_256 },
+ { "ecdsa-384", ECDSA_384 },
+ { "ecdsa-512", ECDSA_512 },
{ "enc", ENCXF },
{ "esp", ESP },
{ "file", FILENAME },