int mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) { Buffer b; int len; Enc *enc; Mac *mac; Comp *comp; Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode); debug3("%s: converting %p", __func__, newkey); if (newkey == NULL) { error("%s: newkey == NULL", __func__); return 0; } enc = &newkey->enc; mac = &newkey->mac; comp = &newkey->comp; buffer_init(&b); /* Enc structure */ buffer_put_cstring(&b, enc->name); /* The cipher struct is constant and shared, you export pointer */ buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); buffer_put_int(&b, enc->enabled); buffer_put_int(&b, enc->block_size); buffer_put_string(&b, enc->key, enc->key_len); packet_get_keyiv(mode, enc->iv, enc->iv_len); buffer_put_string(&b, enc->iv, enc->iv_len); /* Mac structure */ if (cipher_authlen(enc->cipher) == 0) { buffer_put_cstring(&b, mac->name); buffer_put_int(&b, mac->enabled); buffer_put_string(&b, mac->key, mac->key_len); } /* Comp structure */ buffer_put_int(&b, comp->type); buffer_put_int(&b, comp->enabled); buffer_put_cstring(&b, comp->name); len = buffer_len(&b); if (lenp != NULL) *lenp = len; if (blobp != NULL) { *blobp = xmalloc(len); memcpy(*blobp, buffer_ptr(&b), len); } explicit_bzero(buffer_ptr(&b), len); buffer_free(&b); return len; }
void mm_send_keystate(struct monitor *monitor) { Buffer m, *input, *output; u_char *blob, *p; u_int bloblen, plen; u_int32_t seqnr, packets; u_int64_t blocks, bytes; buffer_init(&m); if (!compat20) { u_char iv[24]; u_char *key; u_int ivlen, keylen; buffer_put_int(&m, packet_get_protocol_flags()); buffer_put_int(&m, packet_get_ssh1_cipher()); debug3("%s: Sending ssh1 KEY+IV", __func__); keylen = packet_get_encryption_key(NULL); key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ keylen = packet_get_encryption_key(key); buffer_put_string(&m, key, keylen); memset(key, 0, keylen); xfree(key); ivlen = packet_get_keyiv_len(MODE_OUT); packet_get_keyiv(MODE_OUT, iv, ivlen); buffer_put_string(&m, iv, ivlen); ivlen = packet_get_keyiv_len(MODE_OUT); packet_get_keyiv(MODE_IN, iv, ivlen); buffer_put_string(&m, iv, ivlen); goto skip; } else { /* Kex for rekeying */ mm_send_kex(&m, *monitor->m_pkex); } debug3("%s: Sending new keys: %p %p", __func__, packet_get_newkeys(MODE_OUT), packet_get_newkeys(MODE_IN)); /* Keys from Kex */ if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) fatal("%s: conversion of newkeys failed", __func__); buffer_put_string(&m, blob, bloblen); xfree(blob); if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) fatal("%s: conversion of newkeys failed", __func__); buffer_put_string(&m, blob, bloblen); xfree(blob); packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); buffer_put_int(&m, seqnr); buffer_put_int64(&m, blocks); buffer_put_int(&m, packets); buffer_put_int64(&m, bytes); packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes); buffer_put_int(&m, seqnr); buffer_put_int64(&m, blocks); buffer_put_int(&m, packets); buffer_put_int64(&m, bytes); debug3("%s: New keys have been sent", __func__); skip: /* More key context */ plen = packet_get_keycontext(MODE_OUT, NULL); p = xmalloc(plen+1); packet_get_keycontext(MODE_OUT, p); buffer_put_string(&m, p, plen); xfree(p); plen = packet_get_keycontext(MODE_IN, NULL); p = xmalloc(plen+1); packet_get_keycontext(MODE_IN, p); buffer_put_string(&m, p, plen); xfree(p); /* Compression state */ debug3("%s: Sending compression state", __func__); buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); /* Network I/O buffers */ input = (Buffer *)packet_get_input(); output = (Buffer *)packet_get_output(); buffer_put_string(&m, buffer_ptr(input), buffer_len(input)); buffer_put_string(&m, buffer_ptr(output), buffer_len(output)); /* Roaming */ if (compat20) { buffer_put_int64(&m, get_sent_bytes()); buffer_put_int64(&m, get_recv_bytes()); } mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); debug3("%s: Finished sending state", __func__); buffer_free(&m); }