| 1 |
/* |
| 2 |
* (C) 2011- TeraTerm Project |
| 3 |
* All rights reserved. |
| 4 |
* |
| 5 |
* Redistribution and use in source and binary forms, with or without |
| 6 |
* modification, are permitted provided that the following conditions |
| 7 |
* are met: |
| 8 |
* |
| 9 |
* 1. Redistributions of source code must retain the above copyright |
| 10 |
* notice, this list of conditions and the following disclaimer. |
| 11 |
* 2. Redistributions in binary form must reproduce the above copyright |
| 12 |
* notice, this list of conditions and the following disclaimer in the |
| 13 |
* documentation and/or other materials provided with the distribution. |
| 14 |
* 3. The name of the author may not be used to endorse or promote products |
| 15 |
* derived from this software without specific prior written permission. |
| 16 |
* |
| 17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| 18 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 19 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 20 |
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 21 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 22 |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
*/ |
| 28 |
|
| 29 |
#include "ttxssh.h" |
| 30 |
#include "kex.h" |
| 31 |
|
| 32 |
|
| 33 |
char *myproposal[PROPOSAL_MAX] = { |
| 34 |
KEX_DEFAULT_KEX, |
| 35 |
KEX_DEFAULT_PK_ALG, |
| 36 |
KEX_DEFAULT_ENCRYPT, |
| 37 |
KEX_DEFAULT_ENCRYPT, |
| 38 |
KEX_DEFAULT_MAC, |
| 39 |
KEX_DEFAULT_MAC, |
| 40 |
KEX_DEFAULT_COMP, |
| 41 |
KEX_DEFAULT_COMP, |
| 42 |
KEX_DEFAULT_LANG, |
| 43 |
KEX_DEFAULT_LANG, |
| 44 |
}; |
| 45 |
|
| 46 |
struct ssh2_kex_algorithm_t { |
| 47 |
kex_algorithm kextype; |
| 48 |
char *name; |
| 49 |
const EVP_MD *(*evp_md)(void); |
| 50 |
}; |
| 51 |
|
| 52 |
static const struct ssh2_kex_algorithm_t ssh2_kex_algorithms[] = { |
| 53 |
{KEX_DH_GRP1_SHA1, "diffie-hellman-group1-sha1", EVP_sha1}, // RFC4253 |
| 54 |
{KEX_DH_GRP14_SHA1, "diffie-hellman-group14-sha1", EVP_sha1}, // RFC4253 |
| 55 |
{KEX_DH_GEX_SHA1, "diffie-hellman-group-exchange-sha1", EVP_sha1}, // RFC4419 |
| 56 |
{KEX_DH_GEX_SHA256, "diffie-hellman-group-exchange-sha256", EVP_sha256}, // RFC4419 |
| 57 |
{KEX_ECDH_SHA2_256, "ecdh-sha2-nistp256", EVP_sha256}, // RFC5656 |
| 58 |
{KEX_ECDH_SHA2_384, "ecdh-sha2-nistp384", EVP_sha384}, // RFC5656 |
| 59 |
{KEX_ECDH_SHA2_521, "ecdh-sha2-nistp521", EVP_sha512}, // RFC5656 |
| 60 |
{KEX_DH_GRP14_SHA256, "diffie-hellman-group14-sha256", EVP_sha256}, // RFC8268 |
| 61 |
{KEX_DH_GRP16_SHA512, "diffie-hellman-group16-sha512", EVP_sha512}, // RFC8268 |
| 62 |
{KEX_DH_GRP18_SHA512, "diffie-hellman-group18-sha512", EVP_sha512}, // RFC8268 |
| 63 |
{KEX_DH_NONE , NULL, NULL}, |
| 64 |
}; |
| 65 |
|
| 66 |
|
| 67 |
extern SSHKeys current_keys[MODE_MAX]; |
| 68 |
|
| 69 |
|
| 70 |
char* get_kex_algorithm_name(kex_algorithm kextype) |
| 71 |
{ |
| 72 |
const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms; |
| 73 |
|
| 74 |
while (ptr->name != NULL) { |
| 75 |
if (kextype == ptr->kextype) { |
| 76 |
return ptr->name; |
| 77 |
} |
| 78 |
ptr++; |
| 79 |
} |
| 80 |
|
| 81 |
// not found. |
| 82 |
return "unknown"; |
| 83 |
} |
| 84 |
|
| 85 |
const EVP_MD* get_kex_algorithm_EVP_MD(kex_algorithm kextype) |
| 86 |
{ |
| 87 |
const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms; |
| 88 |
|
| 89 |
while (ptr->name != NULL) { |
| 90 |
if (kextype == ptr->kextype) { |
| 91 |
return ptr->evp_md(); |
| 92 |
} |
| 93 |
ptr++; |
| 94 |
} |
| 95 |
|
| 96 |
// not found. |
| 97 |
return EVP_md_null(); |
| 98 |
} |
| 99 |
|
| 100 |
void normalize_kex_order(char *buf) |
| 101 |
{ |
| 102 |
static char default_strings[] = { |
| 103 |
KEX_ECDH_SHA2_256, |
| 104 |
KEX_ECDH_SHA2_384, |
| 105 |
KEX_ECDH_SHA2_521, |
| 106 |
KEX_DH_GRP18_SHA512, |
| 107 |
KEX_DH_GRP16_SHA512, |
| 108 |
KEX_DH_GRP14_SHA256, |
| 109 |
KEX_DH_GEX_SHA256, |
| 110 |
KEX_DH_GEX_SHA1, |
| 111 |
KEX_DH_GRP14_SHA1, |
| 112 |
KEX_DH_GRP1_SHA1, |
| 113 |
KEX_DH_NONE, |
| 114 |
}; |
| 115 |
|
| 116 |
normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings)); |
| 117 |
} |
| 118 |
|
| 119 |
kex_algorithm choose_SSH2_kex_algorithm(char *server_proposal, char *my_proposal) |
| 120 |
{ |
| 121 |
kex_algorithm type = KEX_DH_UNKNOWN; |
| 122 |
char str_kextype[40]; |
| 123 |
const struct ssh2_kex_algorithm_t *ptr = ssh2_kex_algorithms; |
| 124 |
|
| 125 |
choose_SSH2_proposal(server_proposal, my_proposal, str_kextype, sizeof(str_kextype)); |
| 126 |
|
| 127 |
while (ptr->name != NULL) { |
| 128 |
if (strcmp(ptr->name, str_kextype) == 0) { |
| 129 |
type = ptr->kextype; |
| 130 |
break; |
| 131 |
} |
| 132 |
ptr++; |
| 133 |
} |
| 134 |
|
| 135 |
return (type); |
| 136 |
} |
| 137 |
|
| 138 |
// KEX�A���S���Y���D���������������Amyproposal[]�������������B |
| 139 |
// (2011.2.28 yutaka) |
| 140 |
void SSH2_update_kex_myproposal(PTInstVar pvar) |
| 141 |
{ |
| 142 |
static char buf[512]; // TODO: malloc()�������� |
| 143 |
int index; |
| 144 |
int len, i; |
| 145 |
|
| 146 |
// ���M�������������������������A�O�������B(2006.6.26 maya) |
| 147 |
if (pvar->socket != INVALID_SOCKET) { |
| 148 |
return; |
| 149 |
} |
| 150 |
|
| 151 |
buf[0] = '\0'; |
| 152 |
for (i = 0 ; pvar->settings.KexOrder[i] != 0 ; i++) { |
| 153 |
index = pvar->settings.KexOrder[i] - '0'; |
| 154 |
if (index == KEX_DH_NONE) // disabled line |
| 155 |
break; |
| 156 |
strncat_s(buf, sizeof(buf), get_kex_algorithm_name(index), _TRUNCATE); |
| 157 |
strncat_s(buf, sizeof(buf), ",", _TRUNCATE); |
| 158 |
} |
| 159 |
len = strlen(buf); |
| 160 |
if (len > 0) |
| 161 |
buf[len - 1] = '\0'; // get rid of comma |
| 162 |
myproposal[PROPOSAL_KEX_ALGS] = buf; |
| 163 |
} |
| 164 |
|
| 165 |
|
| 166 |
static DH *dh_new_group_asc(const char *gen, const char *modulus) |
| 167 |
{ |
| 168 |
DH *dh = NULL; |
| 169 |
BIGNUM *p = NULL, *g = NULL; |
| 170 |
|
| 171 |
if ((dh = DH_new()) == NULL) { |
| 172 |
printf("dh_new_group_asc: DH_new"); |
| 173 |
goto error; |
| 174 |
} |
| 175 |
|
| 176 |
// P��G�����J�����������f�����g�������� |
| 177 |
if (BN_hex2bn(&p, modulus) == 0) { |
| 178 |
printf("BN_hex2bn p"); |
| 179 |
goto error; |
| 180 |
} |
| 181 |
|
| 182 |
if (BN_hex2bn(&g, gen) == 0) { |
| 183 |
printf("BN_hex2bn g"); |
| 184 |
goto error; |
| 185 |
} |
| 186 |
|
| 187 |
// BN_hex2bn()�����������|�C���^��DH�\�������Z�b�g�����B |
| 188 |
DH_set0_pqg(dh, p, NULL, g); |
| 189 |
|
| 190 |
return (dh); |
| 191 |
|
| 192 |
error: |
| 193 |
BN_free(g); |
| 194 |
BN_free(p); |
| 195 |
DH_free(dh); |
| 196 |
return (NULL); |
| 197 |
} |
| 198 |
|
| 199 |
|
| 200 |
DH *dh_new_group1(void) |
| 201 |
{ |
| 202 |
static char *gen = "2", *group1 = |
| 203 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" |
| 204 |
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" |
| 205 |
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" |
| 206 |
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" |
| 207 |
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" |
| 208 |
"FFFFFFFF" "FFFFFFFF"; |
| 209 |
|
| 210 |
return (dh_new_group_asc(gen, group1)); |
| 211 |
} |
| 212 |
|
| 213 |
|
| 214 |
DH *dh_new_group14(void) |
| 215 |
{ |
| 216 |
static char *gen = "2", *group14 = |
| 217 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" |
| 218 |
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" |
| 219 |
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" |
| 220 |
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" |
| 221 |
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" |
| 222 |
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" |
| 223 |
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" |
| 224 |
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" |
| 225 |
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" |
| 226 |
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" |
| 227 |
"15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"; |
| 228 |
|
| 229 |
return (dh_new_group_asc(gen, group14)); |
| 230 |
} |
| 231 |
|
| 232 |
// ���g�p |
| 233 |
DH *dh_new_group15(void) |
| 234 |
{ |
| 235 |
static char *gen = "2", *group15 = |
| 236 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" |
| 237 |
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" |
| 238 |
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" |
| 239 |
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" |
| 240 |
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" |
| 241 |
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" |
| 242 |
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" |
| 243 |
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" |
| 244 |
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" |
| 245 |
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" |
| 246 |
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64" |
| 247 |
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7" |
| 248 |
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B" |
| 249 |
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C" |
| 250 |
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31" |
| 251 |
"43DB5BFC" "E0FD108E" "4B82D120" "A93AD2CA" "FFFFFFFF" "FFFFFFFF"; |
| 252 |
return (dh_new_group_asc(gen, group15)); |
| 253 |
} |
| 254 |
|
| 255 |
DH *dh_new_group16(void) |
| 256 |
{ |
| 257 |
static char *gen = "2", *group16 = |
| 258 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" |
| 259 |
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" |
| 260 |
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" |
| 261 |
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" |
| 262 |
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" |
| 263 |
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" |
| 264 |
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" |
| 265 |
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" |
| 266 |
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" |
| 267 |
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" |
| 268 |
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64" |
| 269 |
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7" |
| 270 |
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B" |
| 271 |
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C" |
| 272 |
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31" |
| 273 |
"43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7" |
| 274 |
"88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA" |
| 275 |
"2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6" |
| 276 |
"287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED" |
| 277 |
"1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9" |
| 278 |
"93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199" |
| 279 |
"FFFFFFFF" "FFFFFFFF"; |
| 280 |
return (dh_new_group_asc(gen, group16)); |
| 281 |
} |
| 282 |
|
| 283 |
// ���g�p |
| 284 |
DH *dh_new_group17(void) |
| 285 |
{ |
| 286 |
static char *gen = "2", *group17 = |
| 287 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" |
| 288 |
"8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" |
| 289 |
"302B0A6D" "F25F1437" "4FE1356D" "6D51C245" "E485B576" "625E7EC6" "F44C42E9" |
| 290 |
"A637ED6B" "0BFF5CB6" "F406B7ED" "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" |
| 291 |
"49286651" "ECE45B3D" "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" |
| 292 |
"FD24CF5F" "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" |
| 293 |
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" "E39E772C" |
| 294 |
"180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" |
| 295 |
"3995497C" "EA956AE5" "15D22618" "98FA0510" "15728E5A" "8AAAC42D" "AD33170D" |
| 296 |
"04507A33" "A85521AB" "DF1CBA64" "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" |
| 297 |
"B3970F85" "A6E1E4C7" "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" |
| 298 |
"1AD2EE6B" "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C" |
| 299 |
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31" "43DB5BFC" |
| 300 |
"E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7" "88719A10" "BDBA5B26" |
| 301 |
"99C32718" "6AF4E23C" "1A946834" "B6150BDA" "2583E9CA" "2AD44CE8" "DBBBC2DB" |
| 302 |
"04DE8EF9" "2E8EFC14" "1FBECAA6" "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" |
| 303 |
"233BA186" "515BE7ED" "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" |
| 304 |
"D5B05AA9" "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492" |
| 305 |
"36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD" "F8FF9406" |
| 306 |
"AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831" "179727B0" "865A8918" |
| 307 |
"DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B" "DB7F1447" "E6CC254B" "33205151" |
| 308 |
"2BD7AF42" "6FB8F401" "378CD2BF" "5983CA01" "C64B92EC" "F032EA15" "D1721D03" |
| 309 |
"F482D7CE" "6E74FEF6" "D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" |
| 310 |
"BEC7E8F3" "23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA" |
| 311 |
"CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328" "06A1D58B" |
| 312 |
"B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C" "DA56C9EC" "2EF29632" |
| 313 |
"387FE8D7" "6E3C0468" "043E8F66" "3F4860EE" "12BF2D5B" "0B7474D6" "E694F91E" |
| 314 |
"6DCC4024" "FFFFFFFF" "FFFFFFFF"; |
| 315 |
return (dh_new_group_asc(gen, group17)); |
| 316 |
} |
| 317 |
|
| 318 |
DH *dh_new_group18(void) |
| 319 |
{ |
| 320 |
static char *gen = "2", *group18 = |
| 321 |
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" |
| 322 |
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" |
| 323 |
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" |
| 324 |
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" |
| 325 |
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" |
| 326 |
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" |
| 327 |
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" |
| 328 |
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" |
| 329 |
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" |
| 330 |
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" |
| 331 |
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64" |
| 332 |
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7" |
| 333 |
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B" |
| 334 |
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C" |
| 335 |
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31" |
| 336 |
"43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7" |
| 337 |
"88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA" |
| 338 |
"2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6" |
| 339 |
"287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED" |
| 340 |
"1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9" |
| 341 |
"93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492" |
| 342 |
"36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD" |
| 343 |
"F8FF9406" "AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831" |
| 344 |
"179727B0" "865A8918" "DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B" |
| 345 |
"DB7F1447" "E6CC254B" "33205151" "2BD7AF42" "6FB8F401" "378CD2BF" |
| 346 |
"5983CA01" "C64B92EC" "F032EA15" "D1721D03" "F482D7CE" "6E74FEF6" |
| 347 |
"D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" "BEC7E8F3" |
| 348 |
"23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA" |
| 349 |
"CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328" |
| 350 |
"06A1D58B" "B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C" |
| 351 |
"DA56C9EC" "2EF29632" "387FE8D7" "6E3C0468" "043E8F66" "3F4860EE" |
| 352 |
"12BF2D5B" "0B7474D6" "E694F91E" "6DBE1159" "74A3926F" "12FEE5E4" |
| 353 |
"38777CB6" "A932DF8C" "D8BEC4D0" "73B931BA" "3BC832B6" "8D9DD300" |
| 354 |
"741FA7BF" "8AFC47ED" "2576F693" "6BA42466" "3AAB639C" "5AE4F568" |
| 355 |
"3423B474" "2BF1C978" "238F16CB" "E39D652D" "E3FDB8BE" "FC848AD9" |
| 356 |
"22222E04" "A4037C07" "13EB57A8" "1A23F0C7" "3473FC64" "6CEA306B" |
| 357 |
"4BCBC886" "2F8385DD" "FA9D4B7F" "A2C087E8" "79683303" "ED5BDD3A" |
| 358 |
"062B3CF5" "B3A278A6" "6D2A13F8" "3F44F82D" "DF310EE0" "74AB6A36" |
| 359 |
"4597E899" "A0255DC1" "64F31CC5" "0846851D" "F9AB4819" "5DED7EA1" |
| 360 |
"B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92" |
| 361 |
"4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47" |
| 362 |
"9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71" |
| 363 |
"60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF"; |
| 364 |
return (dh_new_group_asc(gen, group18)); |
| 365 |
} |
| 366 |
|
| 367 |
|
| 368 |
// DH������������ |
| 369 |
void dh_gen_key(PTInstVar pvar, DH *dh, int we_need /* bytes */ ) |
| 370 |
{ |
| 371 |
int i; |
| 372 |
BIGNUM *pub_key; |
| 373 |
BIGNUM *priv_key; |
| 374 |
|
| 375 |
priv_key = NULL; |
| 376 |
|
| 377 |
// ����������������(X)������ |
| 378 |
for (i = 0 ; i < 10 ; i++) { // retry counter |
| 379 |
if (priv_key != NULL) { |
| 380 |
BN_clear_free(priv_key); |
| 381 |
} |
| 382 |
priv_key = BN_new(); |
| 383 |
DH_set0_key(dh, NULL, priv_key); |
| 384 |
if (priv_key == NULL) |
| 385 |
goto error; |
| 386 |
if (BN_rand(priv_key, 2*(we_need*8), 0, 0) == 0) |
| 387 |
goto error; |
| 388 |
if (DH_generate_key(dh) == 0) |
| 389 |
goto error; |
| 390 |
DH_get0_key(dh, &pub_key, NULL); |
| 391 |
if (dh_pub_is_valid(dh, pub_key)) |
| 392 |
break; |
| 393 |
} |
| 394 |
if (i >= 10) { |
| 395 |
goto error; |
| 396 |
} |
| 397 |
return; |
| 398 |
|
| 399 |
error:; |
| 400 |
notify_fatal_error(pvar, "error occurred @ dh_gen_key()", TRUE); |
| 401 |
|
| 402 |
} |
| 403 |
|
| 404 |
|
| 405 |
int dh_estimate(int bits) |
| 406 |
{ |
| 407 |
if (bits <= 112) |
| 408 |
return 2048; |
| 409 |
if (bits <= 128) |
| 410 |
return 3072; |
| 411 |
if (bits <= 192) |
| 412 |
return 7680; |
| 413 |
return 8192; |
| 414 |
} |
| 415 |
|
| 416 |
|
| 417 |
// shared secret ���v�Z���� (DH �����O���[�v�p) |
| 418 |
unsigned char *kex_dh_hash(const EVP_MD *evp_md, |
| 419 |
char *client_version_string, |
| 420 |
char *server_version_string, |
| 421 |
char *ckexinit, int ckexinitlen, |
| 422 |
char *skexinit, int skexinitlen, |
| 423 |
u_char *serverhostkeyblob, int sbloblen, |
| 424 |
BIGNUM *client_dh_pub, |
| 425 |
BIGNUM *server_dh_pub, |
| 426 |
BIGNUM *shared_secret, |
| 427 |
unsigned int *hashlen) |
| 428 |
{ |
| 429 |
buffer_t *b; |
| 430 |
static unsigned char digest[EVP_MAX_MD_SIZE]; |
| 431 |
EVP_MD_CTX *md = NULL; |
| 432 |
|
| 433 |
md = EVP_MD_CTX_new(); |
| 434 |
if (md == NULL) |
| 435 |
goto error; |
| 436 |
|
| 437 |
b = buffer_init(); |
| 438 |
buffer_put_string(b, client_version_string, strlen(client_version_string)); |
| 439 |
buffer_put_string(b, server_version_string, strlen(server_version_string)); |
| 440 |
|
| 441 |
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ |
| 442 |
buffer_put_int(b, ckexinitlen+1); |
| 443 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 444 |
buffer_append(b, ckexinit, ckexinitlen); |
| 445 |
buffer_put_int(b, skexinitlen+1); |
| 446 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 447 |
buffer_append(b, skexinit, skexinitlen); |
| 448 |
|
| 449 |
buffer_put_string(b, serverhostkeyblob, sbloblen); |
| 450 |
buffer_put_bignum2(b, client_dh_pub); |
| 451 |
buffer_put_bignum2(b, server_dh_pub); |
| 452 |
buffer_put_bignum2(b, shared_secret); |
| 453 |
|
| 454 |
// yutaka |
| 455 |
//debug_print(38, buffer_ptr(b), buffer_len(b)); |
| 456 |
|
| 457 |
EVP_DigestInit(md, evp_md); |
| 458 |
EVP_DigestUpdate(md, buffer_ptr(b), buffer_len(b)); |
| 459 |
EVP_DigestFinal(md, digest, NULL); |
| 460 |
|
| 461 |
buffer_free(b); |
| 462 |
|
| 463 |
//write_buffer_file(digest, EVP_MD_size(evp_md)); |
| 464 |
|
| 465 |
*hashlen = EVP_MD_size(evp_md); |
| 466 |
|
| 467 |
error: |
| 468 |
if (md) |
| 469 |
EVP_MD_CTX_free(md); |
| 470 |
|
| 471 |
return digest; |
| 472 |
} |
| 473 |
|
| 474 |
|
| 475 |
// shared secret ���v�Z���� (DH GEX�p) |
| 476 |
unsigned char *kex_dh_gex_hash(const EVP_MD *evp_md, |
| 477 |
char *client_version_string, |
| 478 |
char *server_version_string, |
| 479 |
char *ckexinit, int ckexinitlen, |
| 480 |
char *skexinit, int skexinitlen, |
| 481 |
u_char *serverhostkeyblob, int sbloblen, |
| 482 |
int kexgex_min, |
| 483 |
int kexgex_bits, |
| 484 |
int kexgex_max, |
| 485 |
BIGNUM *kexgex_p, |
| 486 |
BIGNUM *kexgex_g, |
| 487 |
BIGNUM *client_dh_pub, |
| 488 |
BIGNUM *server_dh_pub, |
| 489 |
BIGNUM *shared_secret, |
| 490 |
unsigned int *hashlen) |
| 491 |
{ |
| 492 |
buffer_t *b; |
| 493 |
static unsigned char digest[EVP_MAX_MD_SIZE]; |
| 494 |
EVP_MD_CTX *md = NULL; |
| 495 |
|
| 496 |
md = EVP_MD_CTX_new(); |
| 497 |
if (md == NULL) |
| 498 |
goto error; |
| 499 |
|
| 500 |
b = buffer_init(); |
| 501 |
buffer_put_string(b, client_version_string, strlen(client_version_string)); |
| 502 |
buffer_put_string(b, server_version_string, strlen(server_version_string)); |
| 503 |
|
| 504 |
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ |
| 505 |
buffer_put_int(b, ckexinitlen+1); |
| 506 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 507 |
buffer_append(b, ckexinit, ckexinitlen); |
| 508 |
buffer_put_int(b, skexinitlen+1); |
| 509 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 510 |
buffer_append(b, skexinit, skexinitlen); |
| 511 |
|
| 512 |
buffer_put_string(b, serverhostkeyblob, sbloblen); |
| 513 |
|
| 514 |
// DH group size���r�b�g�������Z���� |
| 515 |
buffer_put_int(b, kexgex_min); |
| 516 |
buffer_put_int(b, kexgex_bits); |
| 517 |
buffer_put_int(b, kexgex_max); |
| 518 |
|
| 519 |
// DH�����f���������������Z���� |
| 520 |
buffer_put_bignum2(b, kexgex_p); |
| 521 |
buffer_put_bignum2(b, kexgex_g); |
| 522 |
|
| 523 |
buffer_put_bignum2(b, client_dh_pub); |
| 524 |
buffer_put_bignum2(b, server_dh_pub); |
| 525 |
buffer_put_bignum2(b, shared_secret); |
| 526 |
|
| 527 |
// yutaka |
| 528 |
//debug_print(38, buffer_ptr(b), buffer_len(b)); |
| 529 |
|
| 530 |
EVP_DigestInit(md, evp_md); |
| 531 |
EVP_DigestUpdate(md, buffer_ptr(b), buffer_len(b)); |
| 532 |
EVP_DigestFinal(md, digest, NULL); |
| 533 |
|
| 534 |
buffer_free(b); |
| 535 |
|
| 536 |
//write_buffer_file(digest, EVP_MD_size(evp_md)); |
| 537 |
|
| 538 |
*hashlen = EVP_MD_size(evp_md); |
| 539 |
|
| 540 |
error: |
| 541 |
if (md) |
| 542 |
EVP_MD_CTX_free(md); |
| 543 |
|
| 544 |
return digest; |
| 545 |
} |
| 546 |
|
| 547 |
|
| 548 |
unsigned char *kex_ecdh_hash(const EVP_MD *evp_md, |
| 549 |
const EC_GROUP *ec_group, |
| 550 |
char *client_version_string, |
| 551 |
char *server_version_string, |
| 552 |
char *ckexinit, int ckexinitlen, |
| 553 |
char *skexinit, int skexinitlen, |
| 554 |
u_char *serverhostkeyblob, int sbloblen, |
| 555 |
const EC_POINT *client_dh_pub, |
| 556 |
const EC_POINT *server_dh_pub, |
| 557 |
BIGNUM *shared_secret, |
| 558 |
unsigned int *hashlen) |
| 559 |
{ |
| 560 |
buffer_t *b; |
| 561 |
static unsigned char digest[EVP_MAX_MD_SIZE]; |
| 562 |
EVP_MD_CTX *md = NULL; |
| 563 |
|
| 564 |
md = EVP_MD_CTX_new(); |
| 565 |
if (md == NULL) |
| 566 |
goto error; |
| 567 |
|
| 568 |
b = buffer_init(); |
| 569 |
buffer_put_string(b, client_version_string, strlen(client_version_string)); |
| 570 |
buffer_put_string(b, server_version_string, strlen(server_version_string)); |
| 571 |
|
| 572 |
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ |
| 573 |
buffer_put_int(b, ckexinitlen+1); |
| 574 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 575 |
buffer_append(b, ckexinit, ckexinitlen); |
| 576 |
buffer_put_int(b, skexinitlen+1); |
| 577 |
buffer_put_char(b, SSH2_MSG_KEXINIT); |
| 578 |
buffer_append(b, skexinit, skexinitlen); |
| 579 |
|
| 580 |
buffer_put_string(b, serverhostkeyblob, sbloblen); |
| 581 |
|
| 582 |
buffer_put_ecpoint(b, ec_group, client_dh_pub); |
| 583 |
buffer_put_ecpoint(b, ec_group, server_dh_pub); |
| 584 |
buffer_put_bignum2(b, shared_secret); |
| 585 |
|
| 586 |
// yutaka |
| 587 |
//debug_print(38, buffer_ptr(b), buffer_len(b)); |
| 588 |
|
| 589 |
EVP_DigestInit(md, evp_md); |
| 590 |
EVP_DigestUpdate(md, buffer_ptr(b), buffer_len(b)); |
| 591 |
EVP_DigestFinal(md, digest, NULL); |
| 592 |
|
| 593 |
buffer_free(b); |
| 594 |
|
| 595 |
//write_buffer_file(digest, EVP_MD_size(evp_md)); |
| 596 |
|
| 597 |
*hashlen = EVP_MD_size(evp_md); |
| 598 |
|
| 599 |
error: |
| 600 |
if (md) |
| 601 |
EVP_MD_CTX_free(md); |
| 602 |
|
| 603 |
return digest; |
| 604 |
} |
| 605 |
|
| 606 |
|
| 607 |
int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) |
| 608 |
{ |
| 609 |
int i; |
| 610 |
int n = BN_num_bits(dh_pub); |
| 611 |
int bits_set = 0; |
| 612 |
const BIGNUM *p; |
| 613 |
|
| 614 |
// OpenSSL 1.1.0���ABIGNUM�\������neg�����o�[�������A�N�Z�X�������������������A |
| 615 |
// BN_is_negative�������u�������BOpenSSL 1.0.2�����}�N�����`���������������A |
| 616 |
// OpenSSL 1.0.2�����A�����������������B |
| 617 |
if (BN_is_negative(dh_pub)) { |
| 618 |
//logit("invalid public DH value: negativ"); |
| 619 |
return 0; |
| 620 |
} |
| 621 |
for (i = 0; i <= n; i++) |
| 622 |
if (BN_is_bit_set(dh_pub, i)) |
| 623 |
bits_set++; |
| 624 |
//debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); |
| 625 |
|
| 626 |
/* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ |
| 627 |
DH_get0_pqg(dh, &p, NULL, NULL); |
| 628 |
if (bits_set > 1 && (BN_cmp(dh_pub, p) == -1)) |
| 629 |
return 1; |
| 630 |
//logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); |
| 631 |
return 0; |
| 632 |
} |
| 633 |
|
| 634 |
|
| 635 |
static u_char *derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret, |
| 636 |
char *session_id, int session_id_len, |
| 637 |
const EVP_MD *evp_md) |
| 638 |
{ |
| 639 |
buffer_t *b; |
| 640 |
EVP_MD_CTX *md = NULL; |
| 641 |
char c = id; |
| 642 |
int have; |
| 643 |
int mdsz = EVP_MD_size(evp_md); |
| 644 |
u_char *digest = malloc(roundup(need, mdsz)); |
| 645 |
|
| 646 |
md = EVP_MD_CTX_new(); |
| 647 |
if (md == NULL) |
| 648 |
goto skip; |
| 649 |
|
| 650 |
if (digest == NULL) |
| 651 |
goto skip; |
| 652 |
|
| 653 |
b = buffer_init(); |
| 654 |
if (b == NULL) |
| 655 |
goto skip; |
| 656 |
|
| 657 |
buffer_put_bignum2(b, shared_secret); |
| 658 |
|
| 659 |
/* K1 = HASH(K || H || "A" || session_id) */ |
| 660 |
EVP_DigestInit(md, evp_md); |
| 661 |
EVP_DigestUpdate(md, buffer_ptr(b), buffer_len(b)); |
| 662 |
EVP_DigestUpdate(md, hash, mdsz); |
| 663 |
EVP_DigestUpdate(md, &c, 1); |
| 664 |
EVP_DigestUpdate(md, session_id, session_id_len); |
| 665 |
EVP_DigestFinal(md, digest, NULL); |
| 666 |
|
| 667 |
/* |
| 668 |
* expand key: |
| 669 |
* Kn = HASH(K || H || K1 || K2 || ... || Kn-1) |
| 670 |
* Key = K1 || K2 || ... || Kn |
| 671 |
*/ |
| 672 |
for (have = mdsz; need > have; have += mdsz) { |
| 673 |
EVP_DigestInit(md, evp_md); |
| 674 |
EVP_DigestUpdate(md, buffer_ptr(b), buffer_len(b)); |
| 675 |
EVP_DigestUpdate(md, hash, mdsz); |
| 676 |
EVP_DigestUpdate(md, digest, have); |
| 677 |
EVP_DigestFinal(md, digest + have, NULL); |
| 678 |
} |
| 679 |
buffer_free(b); |
| 680 |
|
| 681 |
skip:; |
| 682 |
if (md) |
| 683 |
EVP_MD_CTX_free(md); |
| 684 |
|
| 685 |
return digest; |
| 686 |
} |
| 687 |
|
| 688 |
|
| 689 |
void kex_derive_keys(PTInstVar pvar, int need, u_char *hash, BIGNUM *shared_secret, |
| 690 |
char *session_id, int session_id_len) |
| 691 |
{ |
| 692 |
#define NKEYS 6 |
| 693 |
u_char *keys[NKEYS]; |
| 694 |
int i, mode, ctos; |
| 695 |
|
| 696 |
for (i = 0; i < NKEYS; i++) { |
| 697 |
keys[i] = derive_key('A'+i, need, hash, shared_secret, session_id, session_id_len, |
| 698 |
get_kex_algorithm_EVP_MD(pvar->kex_type)); |
| 699 |
//debug_print(i, keys[i], need); |
| 700 |
} |
| 701 |
|
| 702 |
for (mode = 0; mode < MODE_MAX; mode++) { |
| 703 |
if (mode == MODE_OUT) |
| 704 |
ctos = 1; |
| 705 |
else |
| 706 |
ctos = 0; |
| 707 |
|
| 708 |
#if 0 |
| 709 |
// free already allocated buffer (2004.12.27 yutaka) |
| 710 |
// �L�[����������MAC corrupt���������������B(2005.1.5 yutaka) |
| 711 |
if (current_keys[mode].enc.iv != NULL) |
| 712 |
free(current_keys[mode].enc.iv); |
| 713 |
if (current_keys[mode].enc.key != NULL) |
| 714 |
free(current_keys[mode].enc.key); |
| 715 |
if (current_keys[mode].mac.key != NULL) |
| 716 |
free(current_keys[mode].mac.key); |
| 717 |
#endif |
| 718 |
|
| 719 |
// setting |
| 720 |
current_keys[mode].enc.iv = keys[ctos ? 0 : 1]; |
| 721 |
current_keys[mode].enc.key = keys[ctos ? 2 : 3]; |
| 722 |
current_keys[mode].mac.key = keys[ctos ? 4 : 5]; |
| 723 |
|
| 724 |
//debug_print(20 + mode*3, current_keys[mode]->enc.iv, 8); |
| 725 |
//debug_print(21 + mode*3, current_keys[mode]->enc.key, 24); |
| 726 |
//debug_print(22 + mode*3, current_keys[mode]->mac.key, 24); |
| 727 |
} |
| 728 |
} |