Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * dh.c - Diffie-Helman algorithm code against SSH 2 |
3 | | * |
4 | | * This file is part of the SSH Library |
5 | | * |
6 | | * Copyright (c) 2003-2018 by Aris Adamantiadis |
7 | | * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org> |
8 | | * Copyright (c) 2012 by Dmitriy Kuznetsov <dk@yandex.ru> |
9 | | * |
10 | | * The SSH Library is free software; you can redistribute it and/or modify |
11 | | * it under the terms of the GNU Lesser General Public License as published by |
12 | | * the Free Software Foundation; either version 2.1 of the License, or (at your |
13 | | * option) any later version. |
14 | | * |
15 | | * The SSH Library is distributed in the hope that it will be useful, but |
16 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
17 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
18 | | * License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public License |
21 | | * along with the SSH Library; see the file COPYING. If not, write to |
22 | | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
23 | | * MA 02111-1307, USA. |
24 | | */ |
25 | | |
26 | | #include "config.h" |
27 | | |
28 | | #include <stdio.h> |
29 | | |
30 | | #include "libssh/priv.h" |
31 | | #include "libssh/crypto.h" |
32 | | #include "libssh/buffer.h" |
33 | | #include "libssh/session.h" |
34 | | #include "libssh/misc.h" |
35 | | #include "libssh/dh.h" |
36 | | #include "libssh/ssh2.h" |
37 | | #include "libssh/pki.h" |
38 | | #include "libssh/bignum.h" |
39 | | |
40 | | static unsigned char p_group1_value[] = { |
41 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
42 | | 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
43 | | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
44 | | 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
45 | | 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
46 | | 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, |
47 | | 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, |
48 | | 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, |
49 | | 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
50 | | 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, |
51 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
52 | | #define P_GROUP1_LEN 128 /* Size in bytes of the p number */ |
53 | | |
54 | | static unsigned char p_group14_value[] = { |
55 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
56 | | 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
57 | | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
58 | | 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
59 | | 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
60 | | 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, |
61 | | 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, |
62 | | 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, |
63 | | 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
64 | | 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, |
65 | | 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, |
66 | | 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, |
67 | | 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, |
68 | | 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, |
69 | | 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, |
70 | | 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, |
71 | | 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, |
72 | | 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, |
73 | | 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, |
74 | | 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, |
75 | | 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, |
76 | | 0xFF, 0xFF, 0xFF, 0xFF}; |
77 | | |
78 | | #define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */ |
79 | | |
80 | | static unsigned char p_group16_value[] = { |
81 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
82 | | 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
83 | | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
84 | | 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
85 | | 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
86 | | 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, |
87 | | 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, |
88 | | 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, |
89 | | 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
90 | | 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, |
91 | | 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, |
92 | | 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, |
93 | | 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, |
94 | | 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, |
95 | | 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, |
96 | | 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, |
97 | | 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, |
98 | | 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, |
99 | | 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, |
100 | | 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, |
101 | | 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, |
102 | | 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, |
103 | | 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, |
104 | | 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, |
105 | | 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, |
106 | | 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, |
107 | | 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, |
108 | | 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, |
109 | | 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, |
110 | | 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, |
111 | | 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, |
112 | | 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, |
113 | | 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, |
114 | | 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, |
115 | | 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, |
116 | | 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, |
117 | | 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, |
118 | | 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, |
119 | | 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, |
120 | | 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, |
121 | | 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, |
122 | | 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, |
123 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
124 | | |
125 | | #define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */ |
126 | | |
127 | | static unsigned char p_group18_value[] = { |
128 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
129 | | 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
130 | | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
131 | | 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
132 | | 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
133 | | 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, |
134 | | 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, |
135 | | 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, |
136 | | 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
137 | | 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, |
138 | | 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, |
139 | | 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, |
140 | | 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, |
141 | | 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, |
142 | | 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, |
143 | | 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, |
144 | | 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, |
145 | | 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, |
146 | | 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, |
147 | | 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, |
148 | | 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, |
149 | | 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, |
150 | | 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, |
151 | | 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, |
152 | | 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, |
153 | | 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, |
154 | | 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, |
155 | | 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, |
156 | | 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, |
157 | | 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, |
158 | | 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, |
159 | | 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, |
160 | | 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, |
161 | | 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, |
162 | | 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, |
163 | | 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, |
164 | | 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, |
165 | | 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, |
166 | | 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, |
167 | | 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, |
168 | | 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, |
169 | | 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, |
170 | | 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, |
171 | | 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, |
172 | | 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, |
173 | | 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, |
174 | | 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, |
175 | | 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, |
176 | | 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, |
177 | | 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, |
178 | | 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, |
179 | | 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, |
180 | | 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, |
181 | | 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, |
182 | | 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, |
183 | | 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, |
184 | | 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, |
185 | | 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, |
186 | | 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, |
187 | | 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, |
188 | | 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, |
189 | | 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, |
190 | | 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, |
191 | | 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, |
192 | | 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, |
193 | | 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, |
194 | | 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, |
195 | | 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, |
196 | | 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, |
197 | | 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, |
198 | | 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, |
199 | | 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, |
200 | | 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, |
201 | | 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, |
202 | | 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, |
203 | | 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, |
204 | | 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, |
205 | | 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, |
206 | | 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, |
207 | | 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, |
208 | | 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, |
209 | | 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, |
210 | | 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, |
211 | | 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, |
212 | | 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, |
213 | | 0xFF, 0xFF, 0xFF, 0xFF}; |
214 | | |
215 | | #define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */ |
216 | | |
217 | | bignum ssh_dh_generator; |
218 | | bignum ssh_dh_group1; |
219 | | bignum ssh_dh_group14; |
220 | | bignum ssh_dh_group16; |
221 | | bignum ssh_dh_group18; |
222 | | static int dh_crypto_initialized; |
223 | | |
224 | | /** |
225 | | * @internal |
226 | | * @brief Initialize global constants used in DH key agreement |
227 | | * @return SSH_OK on success, SSH_ERROR otherwise. |
228 | | */ |
229 | | int ssh_dh_init(void) |
230 | 2 | { |
231 | 2 | unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */ |
232 | 2 | int rc; |
233 | 2 | if (dh_crypto_initialized) { |
234 | 0 | return SSH_OK; |
235 | 0 | } |
236 | 2 | dh_crypto_initialized = 1; |
237 | | |
238 | 2 | ssh_dh_generator = bignum_new(); |
239 | 2 | if (ssh_dh_generator == NULL) { |
240 | 0 | goto error; |
241 | 0 | } |
242 | 2 | rc = bignum_set_word(ssh_dh_generator, g_int); |
243 | 2 | if (rc != 1) { |
244 | 0 | goto error; |
245 | 0 | } |
246 | | |
247 | 2 | bignum_bin2bn(p_group1_value, P_GROUP1_LEN, &ssh_dh_group1); |
248 | 2 | if (ssh_dh_group1 == NULL) { |
249 | 0 | goto error; |
250 | 0 | } |
251 | 2 | bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &ssh_dh_group14); |
252 | 2 | if (ssh_dh_group14 == NULL) { |
253 | 0 | goto error; |
254 | 0 | } |
255 | 2 | bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &ssh_dh_group16); |
256 | 2 | if (ssh_dh_group16 == NULL) { |
257 | 0 | goto error; |
258 | 0 | } |
259 | 2 | bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &ssh_dh_group18); |
260 | 2 | if (ssh_dh_group18 == NULL) { |
261 | 0 | goto error; |
262 | 0 | } |
263 | | |
264 | 2 | return 0; |
265 | 0 | error: |
266 | 0 | ssh_dh_finalize(); |
267 | 0 | return SSH_ERROR; |
268 | 2 | } |
269 | | |
270 | | /** |
271 | | * @internal |
272 | | * @brief Finalize and free global constants used in DH key agreement |
273 | | */ |
274 | | void ssh_dh_finalize(void) |
275 | 0 | { |
276 | 0 | if (!dh_crypto_initialized) { |
277 | 0 | return; |
278 | 0 | } |
279 | | |
280 | 0 | bignum_safe_free(ssh_dh_generator); |
281 | 0 | bignum_safe_free(ssh_dh_group1); |
282 | 0 | bignum_safe_free(ssh_dh_group14); |
283 | 0 | bignum_safe_free(ssh_dh_group16); |
284 | 0 | bignum_safe_free(ssh_dh_group18); |
285 | |
|
286 | 0 | dh_crypto_initialized = 0; |
287 | 0 | } |
288 | | |
289 | | int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob) |
290 | 0 | { |
291 | 0 | return ssh_pki_import_pubkey_blob(pubkey_blob, |
292 | 0 | &session->next_crypto->server_pubkey); |
293 | |
|
294 | 0 | } |
295 | | |
296 | | static SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply); |
297 | | |
298 | | static ssh_packet_callback dh_client_callbacks[]= { |
299 | | ssh_packet_client_dh_reply |
300 | | }; |
301 | | |
302 | | static struct ssh_packet_callbacks_struct ssh_dh_client_callbacks = { |
303 | | .start = SSH2_MSG_KEXDH_REPLY, |
304 | | .n_callbacks = 1, |
305 | | .callbacks = dh_client_callbacks, |
306 | | .user = NULL |
307 | | }; |
308 | | |
309 | | /** @internal |
310 | | * @brief Starts diffie-hellman-group1 key exchange |
311 | | */ |
312 | 0 | int ssh_client_dh_init(ssh_session session){ |
313 | 0 | struct ssh_crypto_struct *crypto = session->next_crypto; |
314 | 0 | #if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L |
315 | 0 | const_bignum pubkey; |
316 | | #else |
317 | | bignum pubkey = NULL; |
318 | | #endif /* OPENSSL_VERSION_NUMBER */ |
319 | 0 | int rc; |
320 | |
|
321 | 0 | rc = ssh_dh_init_common(crypto); |
322 | 0 | if (rc == SSH_ERROR) { |
323 | 0 | goto error; |
324 | 0 | } |
325 | | |
326 | 0 | rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR); |
327 | 0 | if (rc == SSH_ERROR){ |
328 | 0 | goto error; |
329 | 0 | } |
330 | 0 | rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR, |
331 | 0 | NULL, &pubkey); |
332 | 0 | if (rc != SSH_OK) { |
333 | 0 | goto error; |
334 | 0 | } |
335 | 0 | rc = ssh_buffer_pack(session->out_buffer, "bB", SSH2_MSG_KEXDH_INIT, pubkey); |
336 | 0 | if (rc != SSH_OK) { |
337 | 0 | goto error; |
338 | 0 | } |
339 | | #if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L |
340 | | bignum_safe_free(pubkey); |
341 | | #endif |
342 | | |
343 | | /* register the packet callbacks */ |
344 | 0 | ssh_packet_set_callbacks(session, &ssh_dh_client_callbacks); |
345 | 0 | session->dh_handshake_state = DH_STATE_INIT_SENT; |
346 | |
|
347 | 0 | rc = ssh_packet_send(session); |
348 | 0 | return rc; |
349 | 0 | error: |
350 | | #if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L |
351 | | bignum_safe_free(pubkey); |
352 | | #endif |
353 | 0 | ssh_dh_cleanup(crypto); |
354 | 0 | return SSH_ERROR; |
355 | 0 | } |
356 | | |
357 | 0 | SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ |
358 | 0 | struct ssh_crypto_struct *crypto=session->next_crypto; |
359 | 0 | ssh_string pubkey_blob = NULL; |
360 | 0 | bignum server_pubkey; |
361 | 0 | int rc; |
362 | |
|
363 | 0 | (void)type; |
364 | 0 | (void)user; |
365 | |
|
366 | 0 | ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); |
367 | |
|
368 | 0 | rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, |
369 | 0 | &crypto->dh_server_signature); |
370 | 0 | if (rc == SSH_ERROR) { |
371 | 0 | goto error; |
372 | 0 | } |
373 | 0 | rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, |
374 | 0 | NULL, server_pubkey); |
375 | 0 | if (rc != SSH_OK) { |
376 | 0 | SSH_STRING_FREE(pubkey_blob); |
377 | 0 | bignum_safe_free(server_pubkey); |
378 | 0 | goto error; |
379 | 0 | } |
380 | 0 | rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); |
381 | 0 | SSH_STRING_FREE(pubkey_blob); |
382 | 0 | if (rc != 0) { |
383 | 0 | goto error; |
384 | 0 | } |
385 | | |
386 | 0 | rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx, |
387 | 0 | DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR, |
388 | 0 | &session->next_crypto->shared_secret); |
389 | 0 | ssh_dh_debug_crypto(session->next_crypto); |
390 | 0 | if (rc == SSH_ERROR){ |
391 | 0 | ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); |
392 | 0 | goto error; |
393 | 0 | } |
394 | | |
395 | | /* Send the MSG_NEWKEYS */ |
396 | 0 | if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { |
397 | 0 | goto error; |
398 | 0 | } |
399 | | |
400 | 0 | rc=ssh_packet_send(session); |
401 | 0 | if (rc == SSH_ERROR) { |
402 | 0 | goto error; |
403 | 0 | } |
404 | | |
405 | 0 | SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); |
406 | 0 | session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; |
407 | 0 | return SSH_PACKET_USED; |
408 | 0 | error: |
409 | 0 | ssh_dh_cleanup(session->next_crypto); |
410 | 0 | session->session_state=SSH_SESSION_STATE_ERROR; |
411 | 0 | return SSH_PACKET_USED; |
412 | 0 | } |
413 | | |
414 | | #ifdef WITH_SERVER |
415 | | |
416 | | static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init); |
417 | | |
418 | | static ssh_packet_callback dh_server_callbacks[] = { |
419 | | ssh_packet_server_dh_init, |
420 | | }; |
421 | | |
422 | | static struct ssh_packet_callbacks_struct ssh_dh_server_callbacks = { |
423 | | .start = SSH2_MSG_KEXDH_INIT, |
424 | | .n_callbacks = 1, |
425 | | .callbacks = dh_server_callbacks, |
426 | | .user = NULL |
427 | | }; |
428 | | |
429 | | /** @internal |
430 | | * @brief sets up the diffie-hellman-groupx kex callbacks |
431 | | */ |
432 | 0 | void ssh_server_dh_init(ssh_session session){ |
433 | | /* register the packet callbacks */ |
434 | 0 | ssh_packet_set_callbacks(session, &ssh_dh_server_callbacks); |
435 | |
|
436 | 0 | ssh_dh_init_common(session->next_crypto); |
437 | 0 | } |
438 | | |
439 | | /** @internal |
440 | | * @brief processes a SSH_MSG_KEXDH_INIT or SSH_MSG_KEX_DH_GEX_INIT packet and sends |
441 | | * the appropriate SSH_MSG_KEXDH_REPLY or SSH_MSG_KEX_DH_GEX_REPLY |
442 | | */ |
443 | | int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet) |
444 | 0 | { |
445 | 0 | struct ssh_crypto_struct *crypto = session->next_crypto; |
446 | 0 | ssh_key privkey = NULL; |
447 | 0 | enum ssh_digest_e digest = SSH_DIGEST_AUTO; |
448 | 0 | ssh_string sig_blob = NULL; |
449 | 0 | ssh_string pubkey_blob = NULL; |
450 | 0 | bignum client_pubkey; |
451 | 0 | #if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L |
452 | 0 | const_bignum server_pubkey; |
453 | | #else |
454 | | bignum server_pubkey = NULL; |
455 | | #endif /* OPENSSL_VERSION_NUMBER */ |
456 | 0 | int packet_type; |
457 | 0 | int rc; |
458 | |
|
459 | 0 | rc = ssh_buffer_unpack(packet, "B", &client_pubkey); |
460 | 0 | if (rc == SSH_ERROR) { |
461 | 0 | ssh_set_error(session, SSH_FATAL, "No e number in client request"); |
462 | 0 | goto error; |
463 | 0 | } |
464 | | |
465 | 0 | rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR, |
466 | 0 | NULL, client_pubkey); |
467 | 0 | if (rc != SSH_OK) { |
468 | 0 | bignum_safe_free(client_pubkey); |
469 | 0 | goto error; |
470 | 0 | } |
471 | | |
472 | 0 | rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR); |
473 | 0 | if (rc == SSH_ERROR) { |
474 | 0 | goto error; |
475 | 0 | } |
476 | | |
477 | 0 | rc = ssh_get_key_params(session, &privkey, &digest); |
478 | 0 | if (rc != SSH_OK) { |
479 | 0 | goto error; |
480 | 0 | } |
481 | 0 | rc = ssh_dh_compute_shared_secret(crypto->dh_ctx, |
482 | 0 | DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR, |
483 | 0 | &crypto->shared_secret); |
484 | 0 | ssh_dh_debug_crypto(crypto); |
485 | 0 | if (rc == SSH_ERROR) { |
486 | 0 | ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); |
487 | 0 | goto error; |
488 | 0 | } |
489 | 0 | rc = ssh_make_sessionid(session); |
490 | 0 | if (rc != SSH_OK) { |
491 | 0 | ssh_set_error(session, SSH_FATAL, "Could not create a session id"); |
492 | 0 | goto error; |
493 | 0 | } |
494 | 0 | sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); |
495 | 0 | if (sig_blob == NULL) { |
496 | 0 | ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); |
497 | 0 | goto error; |
498 | 0 | } |
499 | 0 | switch (crypto->kex_type){ |
500 | 0 | case SSH_KEX_DH_GROUP1_SHA1: |
501 | 0 | case SSH_KEX_DH_GROUP14_SHA1: |
502 | 0 | case SSH_KEX_DH_GROUP14_SHA256: |
503 | 0 | case SSH_KEX_DH_GROUP16_SHA512: |
504 | 0 | case SSH_KEX_DH_GROUP18_SHA512: |
505 | 0 | packet_type = SSH2_MSG_KEXDH_REPLY; |
506 | 0 | break; |
507 | 0 | #ifdef WITH_GEX |
508 | 0 | case SSH_KEX_DH_GEX_SHA1: |
509 | 0 | case SSH_KEX_DH_GEX_SHA256: |
510 | 0 | packet_type = SSH2_MSG_KEX_DH_GEX_REPLY; |
511 | 0 | break; |
512 | 0 | #endif /* WITH_GEX */ |
513 | 0 | default: |
514 | 0 | ssh_set_error(session, SSH_FATAL, "Invalid kex type"); |
515 | 0 | goto error; |
516 | 0 | } |
517 | 0 | rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, |
518 | 0 | NULL, &server_pubkey); |
519 | 0 | if (rc != SSH_OK){ |
520 | 0 | goto error; |
521 | 0 | } |
522 | 0 | rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob); |
523 | 0 | if (rc != SSH_OK){ |
524 | 0 | ssh_set_error_oom(session); |
525 | 0 | goto error; |
526 | 0 | } |
527 | 0 | rc = ssh_buffer_pack(session->out_buffer, |
528 | 0 | "bSBS", |
529 | 0 | packet_type, |
530 | 0 | pubkey_blob, |
531 | 0 | server_pubkey, |
532 | 0 | sig_blob); |
533 | 0 | SSH_STRING_FREE(sig_blob); |
534 | 0 | SSH_STRING_FREE(pubkey_blob); |
535 | | #if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L |
536 | | bignum_safe_free(server_pubkey); |
537 | | #endif |
538 | 0 | if(rc != SSH_OK) { |
539 | 0 | ssh_set_error_oom(session); |
540 | 0 | ssh_buffer_reinit(session->out_buffer); |
541 | 0 | goto error; |
542 | 0 | } |
543 | 0 | rc = ssh_packet_send(session); |
544 | 0 | if (rc == SSH_ERROR) { |
545 | 0 | goto error; |
546 | 0 | } |
547 | 0 | SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY"); |
548 | |
|
549 | 0 | if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { |
550 | 0 | ssh_buffer_reinit(session->out_buffer); |
551 | 0 | goto error; |
552 | 0 | } |
553 | 0 | session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; |
554 | 0 | if (ssh_packet_send(session) == SSH_ERROR) { |
555 | 0 | goto error; |
556 | 0 | } |
557 | 0 | SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); |
558 | |
|
559 | 0 | return SSH_OK; |
560 | 0 | error: |
561 | 0 | SSH_STRING_FREE(sig_blob); |
562 | 0 | SSH_STRING_FREE(pubkey_blob); |
563 | | #if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L |
564 | | bignum_safe_free(server_pubkey); |
565 | | #endif |
566 | |
|
567 | 0 | session->session_state = SSH_SESSION_STATE_ERROR; |
568 | 0 | ssh_dh_cleanup(session->next_crypto); |
569 | 0 | return SSH_ERROR; |
570 | 0 | } |
571 | | |
572 | | /** @internal |
573 | | * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete |
574 | | * Diffie-Hellman key exchange |
575 | | **/ |
576 | 0 | static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){ |
577 | 0 | (void)type; |
578 | 0 | (void)user; |
579 | 0 | SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXDH_INIT"); |
580 | 0 | ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks); |
581 | 0 | ssh_server_dh_process_init(session, packet); |
582 | 0 | return SSH_PACKET_USED; |
583 | 0 | } |
584 | | |
585 | | /** @internal |
586 | | * @brief Choose a fallback group for the DH Group exchange if the |
587 | | * moduli file is not readable |
588 | | * @param[in] pmax maximum requestsd group size |
589 | | * @param[out] modulus |
590 | | * @param[out] generator |
591 | | * @returns SSH_OK on success, SSH_ERROR otherwise |
592 | | */ |
593 | | int ssh_fallback_group(uint32_t pmax, |
594 | | bignum *modulus, |
595 | | bignum *generator) |
596 | 0 | { |
597 | 0 | *modulus = NULL; |
598 | 0 | *generator = NULL; |
599 | |
|
600 | 0 | if (pmax < 3072) { |
601 | 0 | bignum_dup(ssh_dh_group14, modulus); |
602 | 0 | } else if (pmax < 6144) { |
603 | 0 | bignum_dup(ssh_dh_group16, modulus); |
604 | 0 | } else { |
605 | 0 | bignum_dup(ssh_dh_group18, modulus); |
606 | 0 | } |
607 | 0 | if (*modulus == NULL) { |
608 | 0 | return SSH_ERROR; |
609 | 0 | } |
610 | | |
611 | 0 | bignum_dup(ssh_dh_generator, generator); |
612 | 0 | if (*generator == NULL) { |
613 | 0 | bignum_safe_free((*modulus)); |
614 | 0 | return SSH_ERROR; |
615 | 0 | } |
616 | | |
617 | 0 | return SSH_OK; |
618 | 0 | } |
619 | | |
620 | | #endif /* WITH_SERVER */ |
621 | | |
622 | | /** |
623 | | * @addtogroup libssh_session |
624 | | * |
625 | | * @{ |
626 | | */ |
627 | | |
628 | | bool ssh_dh_is_known_group(bignum modulus, bignum generator) |
629 | 0 | { |
630 | 0 | int cmp, bits; |
631 | 0 | bignum m = NULL; |
632 | |
|
633 | 0 | bits = bignum_num_bits(modulus); |
634 | 0 | if (bits < 3072) { |
635 | 0 | m = ssh_dh_group14; |
636 | 0 | } else if (bits < 6144) { |
637 | 0 | m = ssh_dh_group16; |
638 | 0 | } else { |
639 | 0 | m = ssh_dh_group18; |
640 | 0 | } |
641 | |
|
642 | 0 | cmp = bignum_cmp(m, modulus); |
643 | 0 | if (cmp != 0) { |
644 | 0 | return false; |
645 | 0 | } |
646 | | |
647 | 0 | cmp = bignum_cmp(ssh_dh_generator, generator); |
648 | 0 | if (cmp != 0) { |
649 | 0 | return false; |
650 | 0 | } |
651 | | |
652 | 0 | SSH_LOG(SSH_LOG_TRACE, "The received primes in FIPS are known"); |
653 | 0 | return true; |
654 | 0 | } |
655 | | |
656 | | ssh_key ssh_dh_get_current_server_publickey(ssh_session session) |
657 | 0 | { |
658 | 0 | if (session->current_crypto == NULL) { |
659 | 0 | return NULL; |
660 | 0 | } |
661 | | |
662 | 0 | return session->current_crypto->server_pubkey; |
663 | 0 | } |
664 | | |
665 | | /* Caller needs to free the blob */ |
666 | | int ssh_dh_get_current_server_publickey_blob(ssh_session session, |
667 | | ssh_string *pubkey_blob) |
668 | 0 | { |
669 | 0 | const ssh_key pubkey = ssh_dh_get_current_server_publickey(session); |
670 | |
|
671 | 0 | return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); |
672 | 0 | } |
673 | | |
674 | | ssh_key ssh_dh_get_next_server_publickey(ssh_session session) |
675 | 0 | { |
676 | 0 | return session->next_crypto->server_pubkey; |
677 | 0 | } |
678 | | |
679 | | /* Caller needs to free the blob */ |
680 | | int ssh_dh_get_next_server_publickey_blob(ssh_session session, |
681 | | ssh_string *pubkey_blob) |
682 | 0 | { |
683 | 0 | const ssh_key pubkey = ssh_dh_get_next_server_publickey(session); |
684 | |
|
685 | 0 | return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); |
686 | 0 | } |
687 | | |
688 | | /** |
689 | | * @internal |
690 | | * |
691 | | * @brief Convert a buffer into an unpadded base64 string. |
692 | | * The caller has to free the memory. |
693 | | * |
694 | | * @param hash What should be converted to a base64 string. |
695 | | * |
696 | | * @param len Length of the buffer to convert. |
697 | | * |
698 | | * @return The base64 string or NULL on error. |
699 | | * |
700 | | * @see ssh_string_free_char() |
701 | | */ |
702 | | static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len) |
703 | 0 | { |
704 | 0 | char *b64_padded = NULL; |
705 | 0 | char *b64_unpadded = NULL; |
706 | 0 | size_t k; |
707 | |
|
708 | 0 | b64_padded = (char *)bin_to_base64(hash, len); |
709 | 0 | if (b64_padded == NULL) { |
710 | 0 | return NULL; |
711 | 0 | } |
712 | 0 | for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--); |
713 | |
|
714 | 0 | b64_unpadded = strndup(b64_padded, k); |
715 | 0 | SAFE_FREE(b64_padded); |
716 | |
|
717 | 0 | return b64_unpadded; |
718 | 0 | } |
719 | | |
720 | | /** |
721 | | * @brief Get a hash as a human-readable hex- or base64-string. |
722 | | * |
723 | | * This gets an allocated fingerprint hash. If it is a SHA sum, it will |
724 | | * return an unpadded base64 string. If it is a MD5 sum, it will return a hex |
725 | | * string. Either way, the output is prepended by the hash-type. |
726 | | * |
727 | | * @warning Do NOT use MD5 or SHA1! Those hash functions are being deprecated. |
728 | | * |
729 | | * @param type Which sort of hash is given, use |
730 | | * SSH_PUBLICKEY_HASH_SHA256 or better. |
731 | | * |
732 | | * @param hash The hash to be converted to fingerprint. |
733 | | * |
734 | | * @param len Length of the buffer to convert. |
735 | | * |
736 | | * @return Returns the allocated fingerprint hash or NULL on error. The caller |
737 | | * needs to free the memory using ssh_string_free_char(). |
738 | | * |
739 | | * @see ssh_string_free_char() |
740 | | */ |
741 | | char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, |
742 | | unsigned char *hash, |
743 | | size_t len) |
744 | 0 | { |
745 | 0 | const char *prefix = "UNKNOWN"; |
746 | 0 | char *fingerprint = NULL; |
747 | 0 | char *str = NULL; |
748 | 0 | size_t str_len; |
749 | 0 | int rc; |
750 | |
|
751 | 0 | switch (type) { |
752 | 0 | case SSH_PUBLICKEY_HASH_SHA1: |
753 | 0 | case SSH_PUBLICKEY_HASH_SHA256: |
754 | 0 | fingerprint = ssh_get_b64_unpadded(hash, len); |
755 | 0 | break; |
756 | 0 | case SSH_PUBLICKEY_HASH_MD5: |
757 | 0 | fingerprint = ssh_get_hexa(hash, len); |
758 | 0 | break; |
759 | 0 | } |
760 | 0 | if (fingerprint == NULL) { |
761 | 0 | return NULL; |
762 | 0 | } |
763 | | |
764 | 0 | switch (type) { |
765 | 0 | case SSH_PUBLICKEY_HASH_MD5: |
766 | 0 | prefix = "MD5"; |
767 | 0 | break; |
768 | 0 | case SSH_PUBLICKEY_HASH_SHA1: |
769 | 0 | prefix = "SHA1"; |
770 | 0 | break; |
771 | 0 | case SSH_PUBLICKEY_HASH_SHA256: |
772 | 0 | prefix = "SHA256"; |
773 | 0 | break; |
774 | 0 | } |
775 | | |
776 | 0 | str_len = strlen(prefix); |
777 | 0 | if (str_len + 1 + strlen(fingerprint) + 1 < str_len) { |
778 | 0 | SAFE_FREE(fingerprint); |
779 | 0 | return NULL; |
780 | 0 | } |
781 | 0 | str_len += 1 + strlen(fingerprint) + 1; |
782 | |
|
783 | 0 | str = malloc(str_len); |
784 | 0 | if (str == NULL) { |
785 | 0 | SAFE_FREE(fingerprint); |
786 | 0 | return NULL; |
787 | 0 | } |
788 | 0 | rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint); |
789 | 0 | SAFE_FREE(fingerprint); |
790 | 0 | if (rc < 0 || rc < (int)(str_len - 1)) { |
791 | 0 | SAFE_FREE(str); |
792 | 0 | } |
793 | |
|
794 | 0 | return str; |
795 | 0 | } |
796 | | |
797 | | /** |
798 | | * @brief Print a hash as a human-readable hex- or base64-string. |
799 | | * |
800 | | * This prints an unpadded base64 strings for SHA sums and hex strings for MD5 |
801 | | * sum. Either way, the output is prepended by the hash-type. |
802 | | * |
803 | | * @param type Which sort of hash is given. Use |
804 | | * SSH_PUBLICKEY_HASH_SHA256 or better. |
805 | | * |
806 | | * @param hash The hash to be converted to fingerprint. |
807 | | * |
808 | | * @param len Length of the buffer to convert. |
809 | | * |
810 | | * @see ssh_get_publickey_hash() |
811 | | * @see ssh_get_fingerprint_hash() |
812 | | */ |
813 | | void ssh_print_hash(enum ssh_publickey_hash_type type, |
814 | | unsigned char *hash, |
815 | | size_t len) |
816 | 0 | { |
817 | 0 | char *fingerprint = NULL; |
818 | |
|
819 | 0 | fingerprint = ssh_get_fingerprint_hash(type, |
820 | 0 | hash, |
821 | 0 | len); |
822 | 0 | if (fingerprint == NULL) { |
823 | 0 | return; |
824 | 0 | } |
825 | | |
826 | 0 | fprintf(stderr, "%s\n", fingerprint); |
827 | |
|
828 | 0 | SAFE_FREE(fingerprint); |
829 | 0 | } |
830 | | |
831 | | /** @} */ |