Coverage Report

Created: 2025-07-11 06:08

/src/dropbear/src/kex-dh.c
Line
Count
Source (jump to first uncovered line)
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
0
{
14
0
    bytes_to_mp(dh_p, ses.newkeys->algo_kex->dh_p_bytes, 
15
0
        ses.newkeys->algo_kex->dh_p_len);
16
0
}
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
0
struct kex_dh_param *gen_kexdh_param() {
22
0
    struct kex_dh_param *param = NULL;
23
24
0
    DEF_MP_INT(dh_p);
25
0
    DEF_MP_INT(dh_q);
26
0
    DEF_MP_INT(dh_g);
27
28
0
    TRACE(("enter gen_kexdh_vals"))
29
30
0
    param = m_malloc(sizeof(*param));
31
0
    m_mp_init_multi(&param->pub, &param->priv, &dh_g, &dh_p, &dh_q, NULL);
32
33
    /* read the prime and generator*/
34
0
    load_dh_p(&dh_p);
35
    
36
0
    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
0
    if (mp_sub_d(&dh_p, 1, &param->priv) != MP_OKAY) { 
41
0
        dropbear_exit("Diffie-Hellman error");
42
0
    }
43
0
    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
0
    gen_random_mpint(&dh_q, &param->priv);
49
50
    /* f = g^y mod p */
51
0
    if (mp_exptmod(&dh_g, &param->priv, &dh_p, &param->pub) != MP_OKAY) {
52
0
        dropbear_exit("Diffie-Hellman error");
53
0
    }
54
0
    mp_clear_multi(&dh_g, &dh_p, &dh_q, NULL);
55
0
    return param;
56
0
}
57
58
void free_kexdh_param(struct kex_dh_param *param)
59
0
{
60
0
    mp_clear_multi(&param->pub, &param->priv, NULL);
61
0
    m_free(param);
62
0
}
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
0
        sign_key *hostkey) {
70
71
0
    DEF_MP_INT(dh_p);
72
0
    DEF_MP_INT(dh_p_min1);
73
0
    mp_int *dh_e = NULL, *dh_f = NULL;
74
75
0
    m_mp_init_multi(&dh_p, &dh_p_min1, NULL);
76
0
    load_dh_p(&dh_p);
77
78
0
    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
0
    if (mp_cmp(dh_pub_them, &dh_p_min1) != MP_LT 
84
0
            || mp_cmp_d(dh_pub_them, 1) != MP_GT) {
85
0
        dropbear_exit("Diffie-Hellman error");
86
0
    }
87
    
88
    /* K = e^y mod p = f^x mod p */
89
0
    m_mp_alloc_init_multi(&ses.dh_K, NULL);
90
0
    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
0
    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
0
    if (IS_DROPBEAR_CLIENT) {
100
0
        dh_e = &param->pub;
101
0
        dh_f = dh_pub_them;
102
0
    } else {
103
0
        dh_e = dh_pub_them;
104
0
        dh_f = &param->pub;
105
0
    } 
106
107
    /* Create the remainder of the hash buffer, to generate the exchange hash */
108
    /* K_S, the host key */
109
0
    buf_put_pub_key(ses.kexhashbuf, hostkey, ses.newkeys->algo_hostkey);
110
    /* e, exchange value sent by the client */
111
0
    buf_putmpint(ses.kexhashbuf, dh_e);
112
    /* f, exchange value sent by the server */
113
0
    buf_putmpint(ses.kexhashbuf, dh_f);
114
    /* K, the shared secret */
115
0
    buf_putmpint(ses.kexhashbuf, ses.dh_K);
116
117
    /* calculate the hash H to sign */
118
0
    finish_kexhashbuf();
119
0
}
120
#endif