/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(¶m->pub, ¶m->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, ¶m->priv) != MP_OKAY) { |
41 | 0 | dropbear_exit("Diffie-Hellman error"); |
42 | 0 | } |
43 | 0 | if (mp_div_2(¶m->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, ¶m->priv); |
49 | | |
50 | | /* f = g^y mod p */ |
51 | 0 | if (mp_exptmod(&dh_g, ¶m->priv, &dh_p, ¶m->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(¶m->pub, ¶m->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, ¶m->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 = ¶m->pub; |
101 | 0 | dh_f = dh_pub_them; |
102 | 0 | } else { |
103 | 0 | dh_e = dh_pub_them; |
104 | 0 | dh_f = ¶m->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 |