1 /* 2 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); 27 28 #include <openssl/crypto.h> 29 30 #include "ssh2.h" 31 #include "xmalloc.h" 32 #include "buffer.h" 33 #include "bufaux.h" 34 #include "packet.h" 35 #include "compat.h" 36 #include "cipher.h" 37 #include "kex.h" 38 #include "key.h" 39 #include "log.h" 40 #include "mac.h" 41 #include "match.h" 42 #include "dispatch.h" 43 #include "monitor.h" 44 45 #define KEX_COOKIE_LEN 16 46 47 /* Use privilege separation for sshd */ 48 int use_privsep; 49 struct monitor *pmonitor; 50 51 52 /* prototype */ 53 static void kex_kexinit_finish(Kex *); 54 static void kex_choose_conf(Kex *); 55 56 /* put algorithm proposal into buffer */ 57 static void 58 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 59 { 60 int i; 61 62 buffer_clear(b); 63 /* 64 * add a dummy cookie, the cookie will be overwritten by 65 * kex_send_kexinit(), each time a kexinit is set 66 */ 67 for (i = 0; i < KEX_COOKIE_LEN; i++) 68 buffer_put_char(b, 0); 69 for (i = 0; i < PROPOSAL_MAX; i++) 70 buffer_put_cstring(b, proposal[i]); 71 buffer_put_char(b, 0); /* first_kex_packet_follows */ 72 buffer_put_int(b, 0); /* uint32 reserved */ 73 } 74 75 /* parse buffer and return algorithm proposal */ 76 static char ** 77 kex_buf2prop(Buffer *raw) 78 { 79 Buffer b; 80 int i; 81 char **proposal; 82 83 proposal = xmalloc(PROPOSAL_MAX * sizeof(char *)); 84 85 buffer_init(&b); 86 buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 87 /* skip cookie */ 88 for (i = 0; i < KEX_COOKIE_LEN; i++) 89 buffer_get_char(&b); 90 /* extract kex init proposal strings */ 91 for (i = 0; i < PROPOSAL_MAX; i++) { 92 proposal[i] = buffer_get_string(&b,NULL); 93 debug2("kex_parse_kexinit: %s", proposal[i]); 94 } 95 /* first kex follows / reserved */ 96 i = buffer_get_char(&b); 97 debug2("kex_parse_kexinit: first_kex_follows %d ", i); 98 i = buffer_get_int(&b); 99 debug2("kex_parse_kexinit: reserved %d ", i); 100 buffer_free(&b); 101 return proposal; 102 } 103 104 static void 105 kex_prop_free(char **proposal) 106 { 107 int i; 108 109 for (i = 0; i < PROPOSAL_MAX; i++) 110 xfree(proposal[i]); 111 xfree(proposal); 112 } 113 114 static void 115 kex_protocol_error(int type, u_int32_t seq, void *ctxt) 116 { 117 error("Hm, kex protocol error: type %d seq %u", type, seq); 118 } 119 120 static void 121 kex_reset_dispatch(void) 122 { 123 dispatch_range(SSH2_MSG_TRANSPORT_MIN, 124 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 125 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 126 } 127 128 void 129 kex_finish(Kex *kex) 130 { 131 kex_reset_dispatch(); 132 133 packet_start(SSH2_MSG_NEWKEYS); 134 packet_send(); 135 /* packet_write_wait(); */ 136 debug("SSH2_MSG_NEWKEYS sent"); 137 138 debug("waiting for SSH2_MSG_NEWKEYS"); 139 packet_read_expect(SSH2_MSG_NEWKEYS); 140 packet_check_eom(); 141 debug("SSH2_MSG_NEWKEYS received"); 142 143 kex->done = 1; 144 buffer_clear(&kex->peer); 145 /* buffer_clear(&kex->my); */ 146 kex->flags &= ~KEX_INIT_SENT; 147 xfree(kex->name); 148 kex->name = NULL; 149 } 150 151 void 152 kex_send_kexinit(Kex *kex) 153 { 154 u_int32_t rand = 0; 155 u_char *cookie; 156 int i; 157 158 if (kex == NULL) { 159 error("kex_send_kexinit: no kex, cannot rekey"); 160 return; 161 } 162 if (kex->flags & KEX_INIT_SENT) { 163 debug("KEX_INIT_SENT"); 164 return; 165 } 166 kex->done = 0; 167 168 /* generate a random cookie */ 169 if (buffer_len(&kex->my) < KEX_COOKIE_LEN) 170 fatal("kex_send_kexinit: kex proposal too short"); 171 cookie = buffer_ptr(&kex->my); 172 for (i = 0; i < KEX_COOKIE_LEN; i++) { 173 if (i % 4 == 0) 174 rand = arc4random(); 175 cookie[i] = rand; 176 rand >>= 8; 177 } 178 packet_start(SSH2_MSG_KEXINIT); 179 packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); 180 packet_send(); 181 debug("SSH2_MSG_KEXINIT sent"); 182 kex->flags |= KEX_INIT_SENT; 183 } 184 185 void 186 kex_input_kexinit(int type, u_int32_t seq, void *ctxt) 187 { 188 char *ptr; 189 int dlen; 190 int i; 191 Kex *kex = (Kex *)ctxt; 192 193 debug("SSH2_MSG_KEXINIT received"); 194 if (kex == NULL) 195 fatal("kex_input_kexinit: no kex, cannot rekey"); 196 197 ptr = packet_get_raw(&dlen); 198 buffer_append(&kex->peer, ptr, dlen); 199 200 /* discard packet */ 201 for (i = 0; i < KEX_COOKIE_LEN; i++) 202 packet_get_char(); 203 for (i = 0; i < PROPOSAL_MAX; i++) 204 xfree(packet_get_string(NULL)); 205 (void) packet_get_char(); 206 (void) packet_get_int(); 207 packet_check_eom(); 208 209 kex_kexinit_finish(kex); 210 } 211 212 Kex * 213 kex_setup(char *proposal[PROPOSAL_MAX]) 214 { 215 Kex *kex; 216 217 kex = xmalloc(sizeof(*kex)); 218 memset(kex, 0, sizeof(*kex)); 219 buffer_init(&kex->peer); 220 buffer_init(&kex->my); 221 kex_prop2buf(&kex->my, proposal); 222 kex->done = 0; 223 224 kex_send_kexinit(kex); /* we start */ 225 kex_reset_dispatch(); 226 227 return kex; 228 } 229 230 static void 231 kex_kexinit_finish(Kex *kex) 232 { 233 if (!(kex->flags & KEX_INIT_SENT)) 234 kex_send_kexinit(kex); 235 236 kex_choose_conf(kex); 237 238 switch (kex->kex_type) { 239 case DH_GRP1_SHA1: 240 kexdh(kex); 241 break; 242 case DH_GEX_SHA1: 243 kexgex(kex); 244 break; 245 default: 246 fatal("Unsupported key exchange %d", kex->kex_type); 247 } 248 } 249 250 static void 251 choose_enc(Enc *enc, char *client, char *server) 252 { 253 char *name = match_list(client, server, NULL); 254 if (name == NULL) 255 fatal("no matching cipher found: client %s server %s", client, server); 256 if ((enc->cipher = cipher_by_name(name)) == NULL) 257 fatal("matching cipher is not supported: %s", name); 258 enc->name = name; 259 enc->enabled = 0; 260 enc->iv = NULL; 261 enc->key = NULL; 262 enc->key_len = cipher_keylen(enc->cipher); 263 enc->block_size = cipher_blocksize(enc->cipher); 264 } 265 static void 266 choose_mac(Mac *mac, char *client, char *server) 267 { 268 char *name = match_list(client, server, NULL); 269 if (name == NULL) 270 fatal("no matching mac found: client %s server %s", client, server); 271 if (mac_init(mac, name) < 0) 272 fatal("unsupported mac %s", name); 273 /* truncate the key */ 274 if (datafellows & SSH_BUG_HMAC) 275 mac->key_len = 16; 276 mac->name = name; 277 mac->key = NULL; 278 mac->enabled = 0; 279 } 280 static void 281 choose_comp(Comp *comp, char *client, char *server) 282 { 283 char *name = match_list(client, server, NULL); 284 if (name == NULL) 285 fatal("no matching comp found: client %s server %s", client, server); 286 if (strcmp(name, "zlib") == 0) { 287 comp->type = 1; 288 } else if (strcmp(name, "none") == 0) { 289 comp->type = 0; 290 } else { 291 fatal("unsupported comp %s", name); 292 } 293 comp->name = name; 294 } 295 static void 296 choose_kex(Kex *k, char *client, char *server) 297 { 298 k->name = match_list(client, server, NULL); 299 if (k->name == NULL) 300 fatal("no kex alg"); 301 if (strcmp(k->name, KEX_DH1) == 0) { 302 k->kex_type = DH_GRP1_SHA1; 303 } else if (strcmp(k->name, KEX_DHGEX) == 0) { 304 k->kex_type = DH_GEX_SHA1; 305 } else 306 fatal("bad kex alg %s", k->name); 307 } 308 static void 309 choose_hostkeyalg(Kex *k, char *client, char *server) 310 { 311 char *hostkeyalg = match_list(client, server, NULL); 312 if (hostkeyalg == NULL) 313 fatal("no hostkey alg"); 314 k->hostkey_type = key_type_from_name(hostkeyalg); 315 if (k->hostkey_type == KEY_UNSPEC) 316 fatal("bad hostkey alg '%s'", hostkeyalg); 317 xfree(hostkeyalg); 318 } 319 320 static void 321 kex_choose_conf(Kex *kex) 322 { 323 Newkeys *newkeys; 324 char **my, **peer; 325 char **cprop, **sprop; 326 int nenc, nmac, ncomp; 327 int mode; 328 int ctos; /* direction: if true client-to-server */ 329 int need; 330 331 my = kex_buf2prop(&kex->my); 332 peer = kex_buf2prop(&kex->peer); 333 334 if (kex->server) { 335 cprop=peer; 336 sprop=my; 337 } else { 338 cprop=my; 339 sprop=peer; 340 } 341 342 /* Algorithm Negotiation */ 343 for (mode = 0; mode < MODE_MAX; mode++) { 344 newkeys = xmalloc(sizeof(*newkeys)); 345 memset(newkeys, 0, sizeof(*newkeys)); 346 kex->newkeys[mode] = newkeys; 347 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); 348 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 349 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 350 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 351 choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); 352 choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); 353 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 354 debug("kex: %s %s %s %s", 355 ctos ? "client->server" : "server->client", 356 newkeys->enc.name, 357 newkeys->mac.name, 358 newkeys->comp.name); 359 } 360 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 361 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 362 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 363 need = 0; 364 for (mode = 0; mode < MODE_MAX; mode++) { 365 newkeys = kex->newkeys[mode]; 366 if (need < newkeys->enc.key_len) 367 need = newkeys->enc.key_len; 368 if (need < newkeys->enc.block_size) 369 need = newkeys->enc.block_size; 370 if (need < newkeys->mac.key_len) 371 need = newkeys->mac.key_len; 372 } 373 /* XXX need runden? */ 374 kex->we_need = need; 375 376 kex_prop_free(my); 377 kex_prop_free(peer); 378 } 379 380 static u_char * 381 derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) 382 { 383 Buffer b; 384 const EVP_MD *evp_md = EVP_sha1(); 385 EVP_MD_CTX md; 386 char c = id; 387 int have; 388 int mdsz = EVP_MD_size(evp_md); 389 u_char *digest = xmalloc(roundup(need, mdsz)); 390 391 buffer_init(&b); 392 buffer_put_bignum2(&b, shared_secret); 393 394 /* K1 = HASH(K || H || "A" || session_id) */ 395 EVP_DigestInit(&md, evp_md); 396 if (!(datafellows & SSH_BUG_DERIVEKEY)) 397 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 398 EVP_DigestUpdate(&md, hash, mdsz); 399 EVP_DigestUpdate(&md, &c, 1); 400 EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); 401 EVP_DigestFinal(&md, digest, NULL); 402 403 /* 404 * expand key: 405 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 406 * Key = K1 || K2 || ... || Kn 407 */ 408 for (have = mdsz; need > have; have += mdsz) { 409 EVP_DigestInit(&md, evp_md); 410 if (!(datafellows & SSH_BUG_DERIVEKEY)) 411 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); 412 EVP_DigestUpdate(&md, hash, mdsz); 413 EVP_DigestUpdate(&md, digest, have); 414 EVP_DigestFinal(&md, digest + have, NULL); 415 } 416 buffer_free(&b); 417 #ifdef DEBUG_KEX 418 fprintf(stderr, "key '%c'== ", c); 419 dump_digest("key", digest, need); 420 #endif 421 return digest; 422 } 423 424 Newkeys *current_keys[MODE_MAX]; 425 426 #define NKEYS 6 427 void 428 kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) 429 { 430 u_char *keys[NKEYS]; 431 int i, mode, ctos; 432 433 for (i = 0; i < NKEYS; i++) 434 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); 435 436 debug("kex_derive_keys"); 437 for (mode = 0; mode < MODE_MAX; mode++) { 438 current_keys[mode] = kex->newkeys[mode]; 439 kex->newkeys[mode] = NULL; 440 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); 441 current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; 442 current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; 443 current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; 444 } 445 } 446 447 Newkeys * 448 kex_get_newkeys(int mode) 449 { 450 Newkeys *ret; 451 452 ret = current_keys[mode]; 453 current_keys[mode] = NULL; 454 return ret; 455 } 456 457 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) 458 void 459 dump_digest(char *msg, u_char *digest, int len) 460 { 461 int i; 462 463 fprintf(stderr, "%s\n", msg); 464 for (i = 0; i< len; i++) { 465 fprintf(stderr, "%02x", digest[i]); 466 if (i%32 == 31) 467 fprintf(stderr, "\n"); 468 else if (i%8 == 7) 469 fprintf(stderr, " "); 470 } 471 fprintf(stderr, "\n"); 472 } 473 #endif 474