Coverage Report

Created: 2025-11-03 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/src/kex-dh.c
Line
Count
Source
1
#include "includes.h"
2
#include "algo.h"
3
#include "buffer.h"
4
#include "session.h"
5
#include "bignum.h"
6
#include "dbrandom.h"
7
#include "crypto_desc.h"
8
#include "dh_groups.h"
9
#include "kex.h"
10
11
#if DROPBEAR_NORMAL_DH
12
static void load_dh_p(mp_int * dh_p)
13
20.6k
{
14
20.6k
    bytes_to_mp(dh_p, ses.newkeys->algo_kex->dh_p_bytes, 
15
20.6k
        ses.newkeys->algo_kex->dh_p_len);
16
20.6k
}
17
18
/* Initialises and generate one side of the diffie-hellman key exchange values.
19
 * See the transport rfc 4253 section 8 for details */
20
/* dh_pub and dh_priv MUST be already initialised */
21
10.2k
struct kex_dh_param *gen_kexdh_param() {
22
10.2k
    struct kex_dh_param *param = NULL;
23
24
10.2k
    DEF_MP_INT(dh_p);
25
10.2k
    DEF_MP_INT(dh_q);
26
10.2k
    DEF_MP_INT(dh_g);
27
28
10.2k
    TRACE(("enter gen_kexdh_vals"))
29
30
10.2k
    param = m_malloc(sizeof(*param));
31
10.2k
    m_mp_init_multi(&param->pub, &param->priv, &dh_g, &dh_p, &dh_q, NULL);
32
33
    /* read the prime and generator*/
34
10.2k
    load_dh_p(&dh_p);
35
    
36
10.2k
    mp_set_ul(&dh_g, DH_G_VAL);
37
38
    /* calculate q = (p-1)/2 */
39
    /* dh_priv is just a temp var here */
40
10.2k
    if (mp_sub_d(&dh_p, 1, &param->priv) != MP_OKAY) { 
41
0
        dropbear_exit("Diffie-Hellman error");
42
0
    }
43
10.2k
    if (mp_div_2(&param->priv, &dh_q) != MP_OKAY) {
44
0
        dropbear_exit("Diffie-Hellman error");
45
0
    }
46
47
    /* Generate a private portion 0 < dh_priv < dh_q */
48
10.2k
    gen_random_mpint(&dh_q, &param->priv);
49
50
    /* f = g^y mod p */
51
10.2k
    if (mp_exptmod(&dh_g, &param->priv, &dh_p, &param->pub) != MP_OKAY) {
52
0
        dropbear_exit("Diffie-Hellman error");
53
0
    }
54
10.2k
    mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL);
55
10.2k
    return param;
56
10.2k
}
57
58
void free_kexdh_param(struct kex_dh_param *param)
59
9.85k
{
60
9.85k
    mp_clear_multi(&param->pub, &param->priv, NULL);
61
9.85k
    m_free(param);
62
9.85k
}
63
64
/* This function is fairly common between client/server, with some substitution
65
 * of dh_e/dh_f etc. Hence these arguments:
66
 * dh_pub_us is 'e' for the client, 'f' for the server. dh_pub_them is 
67
 * vice-versa. dh_priv is the x/y value corresponding to dh_pub_us */
68
void kexdh_comb_key(struct kex_dh_param *param, mp_int *dh_pub_them,
69
10.4k
        sign_key *hostkey) {
70
71
10.4k
    DEF_MP_INT(dh_p);
72
10.4k
    DEF_MP_INT(dh_p_min1);
73
10.4k
    mp_int *dh_e = NULL, *dh_f = NULL;
74
75
10.4k
    m_mp_init_multi(&dh_p, &dh_p_min1, NULL);
76
10.4k
    load_dh_p(&dh_p);
77
78
10.4k
    if (mp_sub_d(&dh_p, 1, &dh_p_min1) != MP_OKAY) { 
79
0
        dropbear_exit("Diffie-Hellman error");
80
0
    }
81
82
    /* Check that dh_pub_them (dh_e or dh_f) is in the range [2, p-2] */
83
10.4k
    if (mp_cmp(dh_pub_them, &dh_p_min1) != MP_LT 
84
10.4k
            || mp_cmp_d(dh_pub_them, 1) != MP_GT) {
85
103
        dropbear_exit("Diffie-Hellman error");
86
103
    }
87
    
88
    /* K = e^y mod p = f^x mod p */
89
10.3k
    m_mp_alloc_init_multi(&ses.dh_K, NULL);
90
10.3k
    if (mp_exptmod(dh_pub_them, &param->priv, &dh_p, ses.dh_K) != MP_OKAY) {
91
0
        dropbear_exit("Diffie-Hellman error");
92
0
    }
93
94
    /* clear no longer needed vars */
95
10.3k
    mp_clear_multi(&dh_p, &dh_p_min1, NULL);
96
97
    /* From here on, the code needs to work with the _same_ vars on each side,
98
     * not vice-versaing for client/server */
99
10.3k
    if (IS_DROPBEAR_CLIENT) {
100
1.47k
        dh_e = &param->pub;
101
1.47k
        dh_f = dh_pub_them;
102
8.89k
    } else {
103
8.89k
        dh_e = dh_pub_them;
104
8.89k
        dh_f = &param->pub;
105
8.89k
    } 
106
107
    /* Create the remainder of the hash buffer, to generate the exchange hash */
108
    /* K_S, the host key */
109
10.3k
    buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
110
    /* e, exchange value sent by the client */
111
10.3k
    buf_putmpint(ses.kexhashbuf, dh_e);
112
    /* f, exchange value sent by the server */
113
10.3k
    buf_putmpint(ses.kexhashbuf, dh_f);
114
    /* K, the shared secret */
115
10.3k
    buf_putmpint(ses.kexhashbuf, ses.dh_K);
116
117
    /* calculate the hash H to sign */
118
10.3k
    finish_kexhashbuf();
119
10.3k
}
120
#endif