[Openvpn-devel] Fix connection cookie not including address and fix endianness in test

Message ID 20221206133647.954724-1-arne@rfc2549.org
State Accepted
Headers show
Series [Openvpn-devel] Fix connection cookie not including address and fix endianness in test | expand

Commit Message

Arne Schwabe Dec. 6, 2022, 1:36 p.m. UTC
We accidentially checked the adress family size instead of the address
family.

For  unit test checks we need to consider endianess to ensure the hmac
for the adress is always the same. The real code does not care about
endian since it only needs it to be same on the same architecture.

Converting the session to endianess is strictly speaking unecessary
for the actual function of the function but is almost no overhead
and makes the unit testing more robust.

Reported by David trying to the package on Red Hat/s390x and painfully
debugged by setting up a s390x qemu machine that takes 40s just to
run ./configure.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
---
 src/openvpn/ssl_pkt.c               |  4 ++--
 tests/unit_tests/openvpn/test_pkt.c | 12 +++++++-----
 2 files changed, 9 insertions(+), 7 deletions(-)

Comments

Gert Doering Dec. 6, 2022, 3:54 p.m. UTC | #1
Acked-by: Gert Doering <gert@greenie.muc.de>

Stared-at-code, ran unit tests beforehand on FreeBSD/amd64 and
AIX/PowerPC, verified that it *failed* on PowerPC.  Ran unit tests
again with the patch, and both FreeBSD/amd64 and AIX/PowerPC succeeded
now, so endianness is taken into account now.

I have not server-tested this, as it "should not" make a difference,
and Arne did test this on s390.  The full server tests will run
tonight, though.

As agreed on IRC, I've removed the comment from test_pkt.c that
says "we do not use htons..." because now we do :-)

Your patch has been applied to the master and release/2.6 branch.

commit 67bef0357280040b83f2185c91c4f830ba542d6b (master)
commit 3e63dc9b184b17674dfea3cea7eb55ce15779fb2 (release/2.6)
Author: Arne Schwabe
Date:   Tue Dec 6 14:36:47 2022 +0100

     Fix connection cookie not including address and fix endianness in test

     Signed-off-by: Arne Schwabe <arne@rfc2549.org>
     Acked-by: Gert Doering <gert@greenie.muc.de>
     Message-Id: <20221206133647.954724-1-arne@rfc2549.org>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25619.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering
Gert Doering Dec. 6, 2022, 4:19 p.m. UTC | #2
Hi,

On Tue, Dec 06, 2022 at 04:54:38PM +0100, Gert Doering wrote:
> I have not server-tested this, as it "should not" make a difference,
> and Arne did test this on s390.  The full server tests will run
> tonight, though.

I *should* have, as that would have caught the fact that this patch
breaks pkt_testdriver on Linux, no matter if OpenSSL or mbedTLS

[ RUN      ] test_calc_session_id_hmac_static
[  ERROR   ] --- difference at offset 0 0xffffff84 0xffffff8b
difference at offset 1 0x73 0xffffffeb
difference at offset 2 0x52 0x3d
difference at offset 3 0x2b 0x20
difference at offset 4 0x5b 0x14
difference at offset 5 0xffffffa9 0x53
difference at offset 6 0x2a 0xffffffbe
difference at offset 7 0x70 0x0a
8 bytes of 0x7ffe60967bd0 and 0x7ffe60967bc8 differ
[   LINE   ] --- test_pkt.c:492: error: Failure!
[  FAILED  ] test_calc_session_id_hmac_static
...
[==========] 9 test(s) run.
[  PASSED  ] 8 test(s).
[  FAILED  ] 1 test(s), listed below:
[  FAILED  ] test_calc_session_id_hmac_static

 1 FAILED TEST(S)
FAIL: pkt_testdriver

this is not specific to OpenSSL (1.1.1*) or mbedTLS, but seems to
be "a Linux thing", so I assume it's something related to sockaddr
(as this patch fixes the switch/case to actually look at the IPv4 addr)

gert
Arne Schwabe Dec. 6, 2022, 11:26 p.m. UTC | #3
Am 06.12.22 um 17:19 schrieb Gert Doering:
> Hi,
> 
> On Tue, Dec 06, 2022 at 04:54:38PM +0100, Gert Doering wrote:
>> I have not server-tested this, as it "should not" make a difference,
>> and Arne did test this on s390.  The full server tests will run
>> tonight, though.
> 
> I *should* have, as that would have caught the fact that this patch
> breaks pkt_testdriver on Linux, no matter if OpenSSL or mbedTLS
> 
> [ RUN      ] test_calc_session_id_hmac_static
> [  ERROR   ] --- difference at offset 0 0xffffff84 0xffffff8b
> difference at offset 1 0x73 0xffffffeb
> difference at offset 2 0x52 0x3d
> difference at offset 3 0x2b 0x20
> difference at offset 4 0x5b 0x14
> difference at offset 5 0xffffffa9 0x53
> difference at offset 6 0x2a 0xffffffbe
> difference at offset 7 0x70 0x0a
> 8 bytes of 0x7ffe60967bd0 and 0x7ffe60967bc8 differ
> [   LINE   ] --- test_pkt.c:492: error: Failure!
> [  FAILED  ] test_calc_session_id_hmac_static
> ...
> [==========] 9 test(s) run.
> [  PASSED  ] 8 test(s).
> [  FAILED  ] 1 test(s), listed below:
> [  FAILED  ] test_calc_session_id_hmac_static
> 
>   1 FAILED TEST(S)
> FAIL: pkt_testdriver
> 
> this is not specific to OpenSSL (1.1.1*) or mbedTLS, but seems to
> be "a Linux thing", so I assume it's something related to sockaddr
> (as this patch fixes the switch/case to actually look at the IPv4 addr)

Yeah. macOS has:

struct sockaddr_in {
	__uint8_t       sin_len;
	sa_family_t     sin_family;
	in_port_t       sin_port;
	struct  in_addr sin_addr;
	char            sin_zero[8];
};

with sa_family_t also uint8_t

and Linux has stupidly complex definition that boils down to:

struct sockaddr_in
   {
     uint16_t sin_family;
     in_port_t sin_port;
     struct in_addr sin_addr
     char sin_zero[8];
   };

So Linux basically has a 16 bit uint16 instead of two uint8_t. Because 
s390x is big endian, this happens to be same as on all BSDs with first 
byte being 0 and second byte being the family.

I will send a fix that fixes the fix *grumbels*

Arne

Patch

diff --git a/src/openvpn/ssl_pkt.c b/src/openvpn/ssl_pkt.c
index 7891e10ee..46bca21d8 100644
--- a/src/openvpn/ssl_pkt.c
+++ b/src/openvpn/ssl_pkt.c
@@ -495,7 +495,7 @@  calculate_session_id_hmac(struct session_id client_sid,
     /* Get the valid time quantisation for our hmac,
      * we divide time by handwindow/2 and allow the previous
      * and future session time if specified by offset */
-    uint32_t session_id_time = now/((handwindow+1)/2) + offset;
+    uint32_t session_id_time = ntohl(now/((handwindow+1)/2) + offset);
 
     hmac_ctx_reset(hmac);
     /* We do not care about endian here since it does not need to be
@@ -504,7 +504,7 @@  calculate_session_id_hmac(struct session_id client_sid,
                     sizeof(session_id_time));
 
     /* add client IP and port */
-    switch (af_addr_size(from->addr.sa.sa_family))
+    switch (from->addr.sa.sa_family)
     {
         case AF_INET:
             hmac_ctx_update(hmac, (const uint8_t *) &from->addr.in4, sizeof(struct sockaddr_in));
diff --git a/tests/unit_tests/openvpn/test_pkt.c b/tests/unit_tests/openvpn/test_pkt.c
index 2d771e301..1af46b7fb 100644
--- a/tests/unit_tests/openvpn/test_pkt.c
+++ b/tests/unit_tests/openvpn/test_pkt.c
@@ -435,6 +435,8 @@  test_verify_hmac_none(void **ut_state)
     hmac_ctx_t *hmac = session_id_hmac_init();
 
     struct link_socket_actual from = { 0 };
+    from.dest.addr.sa.sa_family = AF_INET;
+
     struct tls_auth_standalone tas = { 0 };
     struct tls_pre_decrypt_state state = { 0 };
 
@@ -463,7 +465,7 @@  init_static_hmac(void)
     ASSERT(md_valid("SHA256"));
     hmac_ctx_t *hmac_ctx = hmac_ctx_new();
 
-    uint8_t key[SHA256_DIGEST_LENGTH] = {1, 2, 3};
+    uint8_t key[SHA256_DIGEST_LENGTH] = {1, 2, 3, 0};
 
     hmac_ctx_init(hmac_ctx, key, "SHA256");
     return hmac_ctx;
@@ -475,14 +477,14 @@  test_calc_session_id_hmac_static(void **ut_state)
     hmac_ctx_t *hmac = init_static_hmac();
     static const int handwindow = 100;
 
-    struct openvpn_sockaddr addr = {0 };
+    struct openvpn_sockaddr addr = { 0 };
 
     /* we do not use htons functions here since the hmac calculate function
      * also does not care about the endianness of the data but just assumes
      * the endianness doesn't change between calls */
     addr.addr.in4.sin_family = AF_INET;
-    addr.addr.in4.sin_addr.s_addr = 0xff000ff;
-    addr.addr.in4.sin_port = 1194;
+    addr.addr.in4.sin_addr.s_addr = ntohl(0xff000ff);
+    addr.addr.in4.sin_port = ntohs(1195);
 
 
     struct session_id client_id = { {0, 1, 2, 3, 4, 5, 6, 7}};
@@ -490,7 +492,7 @@  test_calc_session_id_hmac_static(void **ut_state)
     now = 1005;
     struct session_id server_id = calculate_session_id_hmac(client_id, &addr, hmac, handwindow, 0);
 
-    struct session_id expected_server_id = { {0xba,  0x83, 0xa9, 0x00, 0x72, 0xbd, 0x93, 0xba }};
+    struct session_id expected_server_id = { {0x84, 0x73, 0x52, 0x2b, 0x5b, 0xa9, 0x2a, 0x70 }};
     assert_memory_equal(expected_server_id.id, server_id.id, SID_SIZE);
 
     struct session_id server_id_m1 = calculate_session_id_hmac(client_id, &addr, hmac, handwindow, -1);