1*4d3fc8b0SEd Maste /* $OpenBSD: test_proposal.c,v 1.2 2023/03/06 12:15:47 dtucker Exp $ */
2f374ba41SEd Maste /*
3f374ba41SEd Maste * Regress test KEX
4f374ba41SEd Maste *
5f374ba41SEd Maste * Placed in the public domain
6f374ba41SEd Maste */
7f374ba41SEd Maste
8f374ba41SEd Maste #include "includes.h"
9f374ba41SEd Maste
10f374ba41SEd Maste #include <sys/types.h>
11f374ba41SEd Maste #include <signal.h>
12f374ba41SEd Maste #include <stdio.h>
13f374ba41SEd Maste #ifdef HAVE_STDINT_H
14f374ba41SEd Maste #include <stdint.h>
15f374ba41SEd Maste #endif
16f374ba41SEd Maste #include <stdlib.h>
17f374ba41SEd Maste #include <string.h>
18f374ba41SEd Maste
19f374ba41SEd Maste #include "../test_helper/test_helper.h"
20f374ba41SEd Maste
21*4d3fc8b0SEd Maste #include "cipher.h"
22f374ba41SEd Maste #include "compat.h"
23f374ba41SEd Maste #include "ssherr.h"
24f374ba41SEd Maste #include "sshbuf.h"
25f374ba41SEd Maste #include "kex.h"
26*4d3fc8b0SEd Maste #include "myproposal.h"
27f374ba41SEd Maste #include "packet.h"
28f374ba41SEd Maste #include "xmalloc.h"
29f374ba41SEd Maste
30*4d3fc8b0SEd Maste void kex_proposal_tests(void);
31*4d3fc8b0SEd Maste void kex_proposal_populate_tests(void);
32f374ba41SEd Maste
33f374ba41SEd Maste #define CURVE25519 "curve25519-sha256@libssh.org"
34f374ba41SEd Maste #define DHGEX1 "diffie-hellman-group-exchange-sha1"
35f374ba41SEd Maste #define DHGEX256 "diffie-hellman-group-exchange-sha256"
36f374ba41SEd Maste #define KEXALGOS CURVE25519","DHGEX256","DHGEX1
37f374ba41SEd Maste void
kex_proposal_tests(void)38*4d3fc8b0SEd Maste kex_proposal_tests(void)
39f374ba41SEd Maste {
40f374ba41SEd Maste size_t i;
41f374ba41SEd Maste struct ssh ssh;
42f374ba41SEd Maste char *result, *out, *in;
43f374ba41SEd Maste struct {
44f374ba41SEd Maste char *in; /* TODO: make this const */
45f374ba41SEd Maste char *out;
46f374ba41SEd Maste int compat;
47f374ba41SEd Maste } tests[] = {
48f374ba41SEd Maste { KEXALGOS, KEXALGOS, 0},
49f374ba41SEd Maste { KEXALGOS, DHGEX256","DHGEX1, SSH_BUG_CURVE25519PAD },
50f374ba41SEd Maste { KEXALGOS, CURVE25519, SSH_OLD_DHGEX },
51f374ba41SEd Maste { "a,"KEXALGOS, "a", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX },
52f374ba41SEd Maste /* TODO: enable once compat_kex_proposal doesn't fatal() */
53f374ba41SEd Maste /* { KEXALGOS, "", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, */
54f374ba41SEd Maste };
55f374ba41SEd Maste
56f374ba41SEd Maste TEST_START("compat_kex_proposal");
57f374ba41SEd Maste for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
58f374ba41SEd Maste ssh.compat = tests[i].compat;
59f374ba41SEd Maste /* match entire string */
60f374ba41SEd Maste result = compat_kex_proposal(&ssh, tests[i].in);
61f374ba41SEd Maste ASSERT_STRING_EQ(result, tests[i].out);
62f374ba41SEd Maste free(result);
63f374ba41SEd Maste /* match at end */
64f374ba41SEd Maste in = kex_names_cat("a", tests[i].in);
65f374ba41SEd Maste out = kex_names_cat("a", tests[i].out);
66f374ba41SEd Maste result = compat_kex_proposal(&ssh, in);
67f374ba41SEd Maste ASSERT_STRING_EQ(result, out);
68f374ba41SEd Maste free(result); free(in); free(out);
69f374ba41SEd Maste /* match at start */
70f374ba41SEd Maste in = kex_names_cat(tests[i].in, "a");
71f374ba41SEd Maste out = kex_names_cat(tests[i].out, "a");
72f374ba41SEd Maste result = compat_kex_proposal(&ssh, in);
73f374ba41SEd Maste ASSERT_STRING_EQ(result, out);
74f374ba41SEd Maste free(result); free(in); free(out);
75f374ba41SEd Maste /* match in middle */
76f374ba41SEd Maste xasprintf(&in, "a,%s,b", tests[i].in);
77f374ba41SEd Maste if (*(tests[i].out) == '\0')
78f374ba41SEd Maste out = xstrdup("a,b");
79f374ba41SEd Maste else
80f374ba41SEd Maste xasprintf(&out, "a,%s,b", tests[i].out);
81f374ba41SEd Maste result = compat_kex_proposal(&ssh, in);
82f374ba41SEd Maste ASSERT_STRING_EQ(result, out);
83f374ba41SEd Maste free(result); free(in); free(out);
84f374ba41SEd Maste }
85f374ba41SEd Maste TEST_DONE();
86f374ba41SEd Maste }
87*4d3fc8b0SEd Maste
88*4d3fc8b0SEd Maste void
kex_proposal_populate_tests(void)89*4d3fc8b0SEd Maste kex_proposal_populate_tests(void)
90*4d3fc8b0SEd Maste {
91*4d3fc8b0SEd Maste char *prop[PROPOSAL_MAX], *kexalgs, *ciphers, *macs, *hkalgs;
92*4d3fc8b0SEd Maste const char *comp = compression_alg_list(0);
93*4d3fc8b0SEd Maste int i;
94*4d3fc8b0SEd Maste struct ssh ssh;
95*4d3fc8b0SEd Maste struct kex kex;
96*4d3fc8b0SEd Maste
97*4d3fc8b0SEd Maste kexalgs = kex_alg_list(',');
98*4d3fc8b0SEd Maste ciphers = cipher_alg_list(',', 0);
99*4d3fc8b0SEd Maste macs = mac_alg_list(',');
100*4d3fc8b0SEd Maste hkalgs = kex_alg_list(',');
101*4d3fc8b0SEd Maste
102*4d3fc8b0SEd Maste ssh.kex = &kex;
103*4d3fc8b0SEd Maste TEST_START("compat_kex_proposal_populate");
104*4d3fc8b0SEd Maste for (i = 0; i <= 1; i++) {
105*4d3fc8b0SEd Maste kex.server = i;
106*4d3fc8b0SEd Maste for (ssh.compat = 0; ssh.compat < 0x40000000; ) {
107*4d3fc8b0SEd Maste kex_proposal_populate_entries(&ssh, prop, NULL, NULL,
108*4d3fc8b0SEd Maste NULL, NULL, NULL);
109*4d3fc8b0SEd Maste kex_proposal_free_entries(prop);
110*4d3fc8b0SEd Maste kex_proposal_populate_entries(&ssh, prop, kexalgs,
111*4d3fc8b0SEd Maste ciphers, macs, hkalgs, comp);
112*4d3fc8b0SEd Maste kex_proposal_free_entries(prop);
113*4d3fc8b0SEd Maste if (ssh.compat == 0)
114*4d3fc8b0SEd Maste ssh.compat = 1;
115*4d3fc8b0SEd Maste else
116*4d3fc8b0SEd Maste ssh.compat <<= 1;
117*4d3fc8b0SEd Maste }
118*4d3fc8b0SEd Maste }
119*4d3fc8b0SEd Maste
120*4d3fc8b0SEd Maste free(kexalgs);
121*4d3fc8b0SEd Maste free(ciphers);
122*4d3fc8b0SEd Maste free(macs);
123*4d3fc8b0SEd Maste free(hkalgs);
124*4d3fc8b0SEd Maste }
125