psk-authenticator: Add support for authentication with PPK
authorTobias Brunner <tobias@strongswan.org>
Thu, 26 Jul 2018 14:25:02 +0000 (16:25 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 10 Sep 2018 16:03:03 +0000 (18:03 +0200)
src/libcharon/sa/ikev2/authenticators/psk_authenticator.c

index 99219ec..76571e7 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2018 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * HSR Hochschule fuer Technik Rapperswil
@@ -51,6 +52,16 @@ struct private_psk_authenticator_t {
         * Reserved bytes of ID payload
         */
        char reserved[3];
+
+       /**
+        * PPK to use
+        */
+       chunk_t ppk;
+
+       /**
+        * Add a NO_PPK_AUTH notify
+        */
+       bool no_ppk_auth;
 };
 
 METHOD(authenticator_t, build, status_t,
@@ -68,19 +79,19 @@ METHOD(authenticator_t, build, status_t,
        DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
                 my_id, auth_method_names, AUTH_PSK);
        key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id, other_id);
-       if (key == NULL)
+       if (!key)
        {
                DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
                return NOT_FOUND;
        }
        if (!keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, this->nonce,
-                                                        key->get_key(key), chunk_empty, my_id,
+                                                        key->get_key(key), this->ppk, my_id,
                                                         this->reserved, &auth_data))
        {
                key->destroy(key);
                return FAILED;
        }
-       key->destroy(key);
+
        DBG2(DBG_IKE, "successfully created shared key MAC");
        auth_payload = auth_payload_create();
        auth_payload->set_auth_method(auth_payload, AUTH_PSK);
@@ -88,6 +99,21 @@ METHOD(authenticator_t, build, status_t,
        chunk_free(&auth_data);
        message->add_payload(message, (payload_t*)auth_payload);
 
+       if (this->no_ppk_auth)
+       {
+               if (!keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, this->nonce,
+                                                        key->get_key(key), chunk_empty, my_id,
+                                                        this->reserved, &auth_data))
+               {
+                       DBG1(DBG_IKE, "failed adding NO_PPK_AUTH notify");
+                       key->destroy(key);
+                       return SUCCESS;
+               }
+               DBG2(DBG_IKE, "successfully created shared key MAC without PPK");
+               message->add_notify(message, FALSE, NO_PPK_AUTH, auth_data);
+               chunk_free(&auth_data);
+       }
+       key->destroy(key);
        return SUCCESS;
 }
 
@@ -97,6 +123,7 @@ METHOD(authenticator_t, process, status_t,
        chunk_t auth_data, recv_auth_data;
        identification_t *my_id, *other_id;
        auth_payload_t *auth_payload;
+       notify_payload_t *notify;
        auth_cfg_t *auth;
        shared_key_t *key;
        enumerator_t *enumerator;
@@ -109,8 +136,20 @@ METHOD(authenticator_t, process, status_t,
        {
                return FAILED;
        }
-       keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
        recv_auth_data = auth_payload->get_data(auth_payload);
+
+       if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
+               !this->ppk.ptr)
+       {       /* look for a NO_PPK_AUTH notify if we have no PPK */
+               notify = message->get_notify(message, NO_PPK_AUTH);
+               if (notify)
+               {
+                       DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
+                       recv_auth_data = notify->get_notification_data(notify);
+               }
+       }
+
+       keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
        my_id = this->ike_sa->get_my_id(this->ike_sa);
        other_id = this->ike_sa->get_other_id(this->ike_sa);
        enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
@@ -120,7 +159,7 @@ METHOD(authenticator_t, process, status_t,
                keys_found++;
 
                if (!keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init, this->nonce,
-                                                                key->get_key(key), chunk_empty, other_id,
+                                                                key->get_key(key), this->ppk, other_id,
                                                                 this->reserved, &auth_data))
                {
                        continue;
@@ -152,6 +191,13 @@ METHOD(authenticator_t, process, status_t,
        return SUCCESS;
 }
 
+METHOD(authenticator_t, use_ppk, void,
+       private_psk_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
+{
+       this->ppk = ppk;
+       this->no_ppk_auth = no_ppk_auth;
+}
+
 METHOD(authenticator_t, destroy, void,
        private_psk_authenticator_t *this)
 {
@@ -172,6 +218,7 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
                        .authenticator = {
                                .build = _build,
                                .process = (void*)return_failed,
+                               .use_ppk = _use_ppk,
                                .is_mutual = (void*)return_false,
                                .destroy = _destroy,
                        },
@@ -199,6 +246,7 @@ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
                        .authenticator = {
                                .build = (void*)return_failed,
                                .process = _process,
+                               .use_ppk = _use_ppk,
                                .is_mutual = (void*)return_false,
                                .destroy = _destroy,
                        },