Frank Denis пре 6 година
родитељ
комит
1669168fe5
3 измењених фајлова са 126 додато и 0 уклоњено
  1. 16 0
      hydrogen.h
  2. 79 0
      impl/kx.h
  3. 31 0
      tests/tests.c

+ 16 - 0
hydrogen.h

@@ -243,6 +243,22 @@ int hydro_kx_xx_4(hydro_kx_state *state, hydro_kx_session_keypair *kp,
                   const uint8_t packet3[hydro_kx_XX_PACKET3BYTES],
                   const uint8_t psk[hydro_kx_PSKBYTES]);
 
+/* NOISE_NK */
+
+#define hydro_kx_NK_PACKET1BYTES (32 + 16)
+#define hydro_kx_NK_PACKET2BYTES (32 + 16)
+
+int hydro_kx_nk_1(hydro_kx_state *state, uint8_t packet1[hydro_kx_NK_PACKET1BYTES],
+                  const uint8_t psk[hydro_kx_PSKBYTES],
+                  const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES]);
+
+int hydro_kx_nk_2(hydro_kx_session_keypair *kp, uint8_t packet2[hydro_kx_NK_PACKET2BYTES],
+                  const uint8_t packet1[hydro_kx_NK_PACKET1BYTES],
+                  const uint8_t psk[hydro_kx_PSKBYTES], const hydro_kx_keypair *static_kp);
+
+int hydro_kx_nk_3(hydro_kx_state *state, hydro_kx_session_keypair *kp,
+                  const uint8_t packet2[hydro_kx_NK_PACKET2BYTES]);
+
 /* ---------------- */
 
 #define hydro_pwhash_CONTEXTBYTES 8

+ 79 - 0
impl/kx.h

@@ -454,3 +454,82 @@ hydro_kx_xx_4(hydro_kx_state *state, hydro_kx_session_keypair *kp,
 
     return 0;
 }
+
+/* NOISE_NK */
+
+int
+hydro_kx_nk_1(hydro_kx_state *state, uint8_t packet1[hydro_kx_NK_PACKET1BYTES],
+              const uint8_t psk[hydro_kx_PSKBYTES],
+              const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES])
+{
+    uint8_t *packet1_eph_pk = &packet1[0];
+    uint8_t *packet1_mac    = &packet1[hydro_kx_PUBLICKEYBYTES];
+
+    if (psk == NULL) {
+        psk = zero;
+    }
+    hydro_kx_init_state(state, "Noise_NKpsk0_hydro1");
+    hydro_hash_update(&state->h_st, peer_static_pk, hydro_x25519_PUBLICKEYBYTES);
+
+    hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
+    hydro_kx_eph_keygen(state, &state->eph_kp);
+    if (hydro_kx_dh(state, state->eph_kp.sk, peer_static_pk) != 0) {
+        return -1;
+    }
+    hydro_kx_aead_encrypt(state, packet1_mac, NULL, 0);
+    memcpy(packet1_eph_pk, state->eph_kp.pk, sizeof state->eph_kp.pk);
+
+    return 0;
+}
+
+int
+hydro_kx_nk_2(hydro_kx_session_keypair *kp, uint8_t packet2[hydro_kx_NK_PACKET2BYTES],
+              const uint8_t packet1[hydro_kx_NK_PACKET1BYTES], const uint8_t psk[hydro_kx_PSKBYTES],
+              const hydro_kx_keypair *static_kp)
+{
+    hydro_kx_state state;
+    const uint8_t *peer_eph_pk    = &packet1[0];
+    const uint8_t *packet1_mac    = &packet1[hydro_kx_PUBLICKEYBYTES];
+    uint8_t *      packet2_eph_pk = &packet2[0];
+    uint8_t *      packet2_mac    = &packet2[hydro_kx_PUBLICKEYBYTES];
+
+    if (psk == NULL) {
+        psk = zero;
+    }
+    hydro_kx_init_state(&state, "Noise_NKpsk0_hydro1");
+    hydro_hash_update(&state.h_st, static_kp->pk, hydro_kx_PUBLICKEYBYTES);
+
+    hydro_hash_update(&state.h_st, psk, hydro_kx_PSKBYTES);
+    hydro_hash_update(&state.h_st, peer_eph_pk, hydro_x25519_PUBLICKEYBYTES);
+    if (hydro_kx_dh(&state, static_kp->sk, peer_eph_pk) != 0 ||
+        hydro_kx_aead_decrypt(&state, NULL, packet1_mac, hydro_kx_AEAD_MACBYTES) != 0) {
+        return -1;
+    }
+
+    hydro_kx_eph_keygen(&state, &state.eph_kp);
+    if (hydro_kx_dh(&state, state.eph_kp.sk, peer_eph_pk) != 0) {
+        return -1;
+    }
+    hydro_kx_aead_encrypt(&state, packet2_mac, NULL, 0);
+    hydro_kx_final(&state, kp->tx, kp->rx);
+    memcpy(packet2_eph_pk, state.eph_kp.pk, sizeof state.eph_kp.pk);
+
+    return 0;
+}
+
+int
+hydro_kx_nk_3(hydro_kx_state *state, hydro_kx_session_keypair *kp,
+              const uint8_t packet2[hydro_kx_NK_PACKET2BYTES])
+{
+    const uint8_t *peer_eph_pk = &packet2[0];
+    const uint8_t *packet2_mac = &packet2[hydro_kx_PUBLICKEYBYTES];
+
+    hydro_hash_update(&state->h_st, peer_eph_pk, hydro_x25519_PUBLICKEYBYTES);
+    if (hydro_kx_dh(state, state->eph_kp.sk, peer_eph_pk) != 0 ||
+        hydro_kx_aead_decrypt(state, NULL, packet2_mac, hydro_kx_AEAD_MACBYTES) != 0) {
+        return -1;
+    }
+    hydro_kx_final(state, kp->rx, kp->tx);
+
+    return 0;
+}

+ 31 - 0
tests/tests.c

@@ -366,6 +366,36 @@ test_kx_xx(void)
     assert(hydro_equal(server_peer_pk, client_static_kp.pk, hydro_kx_PUBLICKEYBYTES));
 }
 
+static void
+test_kx_nk(void)
+{
+    hydro_kx_state           st_client;
+    hydro_kx_keypair         server_static_kp;
+    uint8_t                  psk[hydro_kx_PSKBYTES];
+    uint8_t                  packet1[hydro_kx_NK_PACKET1BYTES];
+    uint8_t                  packet2[hydro_kx_NK_PACKET2BYTES];
+    hydro_kx_session_keypair kp_client;
+    hydro_kx_session_keypair kp_server;
+
+    hydro_kx_keygen(&server_static_kp);
+
+    hydro_kx_nk_1(&st_client, packet1, NULL, server_static_kp.pk);
+    hydro_kx_nk_2(&kp_server, packet2, packet1, NULL, &server_static_kp);
+    hydro_kx_nk_3(&st_client, &kp_client, packet2);
+
+    assert(hydro_equal(kp_client.tx, kp_server.rx, hydro_kx_SESSIONKEYBYTES));
+    assert(hydro_equal(kp_client.rx, kp_server.tx, hydro_kx_SESSIONKEYBYTES));
+
+    hydro_random_buf(psk, sizeof psk);
+
+    hydro_kx_nk_1(&st_client, packet1, psk, server_static_kp.pk);
+    hydro_kx_nk_2(&kp_server, packet2, packet1, psk, &server_static_kp);
+    hydro_kx_nk_3(&st_client, &kp_client, packet2);
+
+    assert(hydro_equal(kp_client.tx, kp_server.rx, hydro_kx_SESSIONKEYBYTES));
+    assert(hydro_equal(kp_client.rx, kp_server.tx, hydro_kx_SESSIONKEYBYTES));
+}
+
 static void
 test_pwhash(void)
 {
@@ -437,6 +467,7 @@ main(void)
     test_kx_n();
     test_kx_kk();
     test_kx_xx();
+    test_kx_nk();
     test_pwhash();
     test_randombytes();
     test_secretbox();