1 Star 8 Fork 11

xfan1024 / oh-dropbear

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
packet.c 20.94 KB
一键复制 编辑 原始数据 按行查看 历史
xfan1024 提交于 2021-08-13 14:40 . Init commit: dropbear-2020.81
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
/*
* Dropbear - a SSH2 server
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */
#include "includes.h"
#include "packet.h"
#include "session.h"
#include "dbutil.h"
#include "ssh.h"
#include "algo.h"
#include "buffer.h"
#include "kex.h"
#include "dbrandom.h"
#include "service.h"
#include "auth.h"
#include "channel.h"
#include "netio.h"
#include "runopts.h"
static int read_packet_init(void);
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
buffer * clear_buf, unsigned int clear_len,
unsigned char *output_mac);
static int checkmac(void);
/* For exact details see http://www.zlib.net/zlib_tech.html
* 5 bytes per 16kB block, plus 6 bytes for the stream.
* We might allocate 5 unnecessary bytes here if it's an
* exact multiple. */
#define ZLIB_COMPRESS_EXPANSION (((RECV_MAX_PAYLOAD_LEN/16384)+1)*5 + 6)
#define ZLIB_DECOMPRESS_INCR 1024
#ifndef DISABLE_ZLIB
static buffer* buf_decompress(const buffer* buf, unsigned int len);
static void buf_compress(buffer * dest, buffer * src, unsigned int len);
#endif
/* non-blocking function writing out a current encrypted packet */
void write_packet() {
ssize_t written;
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
/* 50 is somewhat arbitrary */
unsigned int iov_count = 50;
struct iovec iov[50];
#else
int len;
buffer* writebuf;
#endif
TRACE2(("enter write_packet"))
dropbear_assert(!isempty(&ses.writequeue));
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
packet_queue_to_iovec(&ses.writequeue, iov, &iov_count);
/* This may return EAGAIN. The main loop sometimes
calls write_packet() without bothering to test with select() since
it's likely to be necessary */
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
/* pretend to write one packet at a time */
/* TODO(fuzz): randomise amount written based on the fuzz input */
written = iov[0].iov_len;
}
else
#endif
{
written = writev(ses.sock_out, iov, iov_count);
if (written < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE2(("leave write_packet: EINTR"))
return;
} else {
dropbear_exit("Error writing: %s", strerror(errno));
}
}
}
packet_queue_consume(&ses.writequeue, written);
ses.writequeue_len -= written;
if (written == 0) {
ses.remoteclosed();
}
#else /* No writev () */
#if DROPBEAR_FUZZ
_Static_assert(0, "No fuzzing code for no-writev writes");
#endif
/* Get the next buffer in the queue of encrypted packets to write*/
writebuf = (buffer*)examine(&ses.writequeue);
len = writebuf->len - writebuf->pos;
dropbear_assert(len > 0);
/* Try to write as much as possible */
written = write(ses.sock_out, buf_getptr(writebuf, len), len);
if (written < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE2(("leave writepacket: EINTR"))
return;
} else {
dropbear_exit("Error writing: %s", strerror(errno));
}
}
if (written == 0) {
ses.remoteclosed();
}
ses.writequeue_len -= written;
if (written == len) {
/* We've finished with the packet, free it */
dequeue(&ses.writequeue);
buf_free(writebuf);
writebuf = NULL;
} else {
/* More packet left to write, leave it in the queue for later */
buf_incrpos(writebuf, written);
}
#endif /* writev */
TRACE2(("leave write_packet"))
}
/* Non-blocking function reading available portion of a packet into the
* ses's buffer, decrypting the length if encrypted, decrypting the
* full portion if possible */
void read_packet() {
int len;
unsigned int maxlen;
unsigned char blocksize;
TRACE2(("enter read_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
int ret;
/* In the first blocksize of a packet */
/* Read the first blocksize of the packet, so we can decrypt it and
* find the length of the whole packet */
ret = read_packet_init();
if (ret == DROPBEAR_FAILURE) {
/* didn't read enough to determine the length */
TRACE2(("leave read_packet: packetinit done"))
return;
}
}
/* Attempt to read the remainder of the packet, note that there
* mightn't be any available (EAGAIN) */
maxlen = ses.readbuf->len - ses.readbuf->pos;
if (maxlen == 0) {
/* Occurs when the packet is only a single block long and has all
* been read in read_packet_init(). Usually means that MAC is disabled
*/
len = 0;
} else {
len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
if (len == 0) {
ses.remoteclosed();
}
if (len < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE2(("leave read_packet: EINTR or EAGAIN"))
return;
} else {
dropbear_exit("Error reading: %s", strerror(errno));
}
}
buf_incrpos(ses.readbuf, len);
}
if ((unsigned int)len == maxlen) {
/* The whole packet has been read */
decrypt_packet();
/* The main select() loop process_packet() to
* handle the packet contents... */
}
TRACE2(("leave read_packet"))
}
/* Function used to read the initial portion of a packet, and determine the
* length. Only called during the first BLOCKSIZE of a packet. */
/* Returns DROPBEAR_SUCCESS if the length is determined,
* DROPBEAR_FAILURE otherwise */
static int read_packet_init() {
unsigned int maxlen;
int slen;
unsigned int len, plen;
unsigned int blocksize;
unsigned int macsize;
blocksize = ses.keys->recv.algo_crypt->blocksize;
macsize = ses.keys->recv.algo_mac->hashsize;
if (ses.readbuf == NULL) {
/* start of a new packet */
ses.readbuf = buf_new(INIT_READBUF);
}
maxlen = blocksize - ses.readbuf->pos;
/* read the rest of the packet if possible */
slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
maxlen);
if (slen == 0) {
ses.remoteclosed();
}
if (slen < 0) {
if (errno == EINTR || errno == EAGAIN) {
TRACE2(("leave read_packet_init: EINTR"))
return DROPBEAR_FAILURE;
}
dropbear_exit("Error reading: %s", strerror(errno));
}
buf_incrwritepos(ses.readbuf, slen);
if ((unsigned int)slen != maxlen) {
/* don't have enough bytes to determine length, get next time */
return DROPBEAR_FAILURE;
}
/* now we have the first block, need to get packet length, so we decrypt
* the first block (only need first 4 bytes) */
buf_setpos(ses.readbuf, 0);
#if DROPBEAR_AEAD_MODE
if (ses.keys->recv.crypt_mode->aead_crypt) {
if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq,
buf_getptr(ses.readbuf, blocksize), &plen,
blocksize,
&ses.keys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("Error decrypting");
}
len = plen + 4 + macsize;
} else
#endif
{
if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize),
buf_getwriteptr(ses.readbuf, blocksize),
blocksize,
&ses.keys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("Error decrypting");
}
plen = buf_getint(ses.readbuf) + 4;
len = plen + macsize;
}
TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
/* check packet length */
if ((len > RECV_MAX_PACKET_LEN) ||
(plen < blocksize) ||
(plen % blocksize != 0)) {
dropbear_exit("Integrity error (bad packet size %u)", len);
}
if (len > ses.readbuf->size) {
ses.readbuf = buf_resize(ses.readbuf, len);
}
buf_setlen(ses.readbuf, len);
buf_setpos(ses.readbuf, blocksize);
return DROPBEAR_SUCCESS;
}
/* handle the received packet */
void decrypt_packet() {
unsigned char blocksize;
unsigned char macsize;
unsigned int padlen;
unsigned int len;
TRACE2(("enter decrypt_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
macsize = ses.keys->recv.algo_mac->hashsize;
ses.kexstate.datarecv += ses.readbuf->len;
#if DROPBEAR_AEAD_MODE
if (ses.keys->recv.crypt_mode->aead_crypt) {
/* first blocksize is not decrypted yet */
buf_setpos(ses.readbuf, 0);
/* decrypt it in-place */
len = ses.readbuf->len - macsize - ses.readbuf->pos;
if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq,
buf_getptr(ses.readbuf, len + macsize),
buf_getwriteptr(ses.readbuf, len),
len, macsize,
&ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) {
dropbear_exit("Error decrypting");
}
buf_incrpos(ses.readbuf, len);
} else
#endif
{
/* we've already decrypted the first blocksize in read_packet_init */
buf_setpos(ses.readbuf, blocksize);
/* decrypt it in-place */
len = ses.readbuf->len - macsize - ses.readbuf->pos;
if (ses.keys->recv.crypt_mode->decrypt(
buf_getptr(ses.readbuf, len),
buf_getwriteptr(ses.readbuf, len),
len,
&ses.keys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("Error decrypting");
}
buf_incrpos(ses.readbuf, len);
/* check the hmac */
if (checkmac() != DROPBEAR_SUCCESS) {
dropbear_exit("Integrity error");
}
}
#if DROPBEAR_FUZZ
fuzz_dump(ses.readbuf->data, ses.readbuf->len);
#endif
/* get padding length */
buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
padlen = buf_getbyte(ses.readbuf);
/* payload length */
/* - 4 - 1 is for LEN and PADLEN values */
len = ses.readbuf->len - padlen - 4 - 1 - macsize;
if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
dropbear_exit("Bad packet size %u", len);
}
buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);
#ifndef DISABLE_ZLIB
if (is_compress_recv()) {
/* decompress */
ses.payload = buf_decompress(ses.readbuf, len);
buf_setpos(ses.payload, 0);
ses.payload_beginning = 0;
buf_free(ses.readbuf);
} else
#endif
{
ses.payload = ses.readbuf;
ses.payload_beginning = ses.payload->pos;
buf_setlen(ses.payload, ses.payload->pos + len);
}
ses.readbuf = NULL;
ses.recvseq++;
TRACE2(("leave decrypt_packet"))
}
/* Checks the mac at the end of a decrypted readbuf.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int checkmac() {
unsigned char mac_bytes[MAX_MAC_LEN];
unsigned int mac_size, contents_len;
mac_size = ses.keys->recv.algo_mac->hashsize;
contents_len = ses.readbuf->len - mac_size;
buf_setpos(ses.readbuf, 0);
make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
#if DROPBEAR_FUZZ
if (fuzz.fuzzing) {
/* fail 1 in 2000 times to test error path. */
unsigned int value = 0;
if (mac_size > sizeof(value)) {
memcpy(&value, mac_bytes, sizeof(value));
}
if (value % 2000 == 99) {
return DROPBEAR_FAILURE;
}
return DROPBEAR_SUCCESS;
}
#endif
/* compare the hash */
buf_setpos(ses.readbuf, contents_len);
if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
return DROPBEAR_FAILURE;
} else {
return DROPBEAR_SUCCESS;
}
}
#ifndef DISABLE_ZLIB
/* returns a pointer to a newly created buffer */
static buffer* buf_decompress(const buffer* buf, unsigned int len) {
int result;
buffer * ret;
z_streamp zstream;
zstream = ses.keys->recv.zstream;
ret = buf_new(len);
zstream->avail_in = len;
zstream->next_in = buf_getptr(buf, len);
/* decompress the payload, incrementally resizing the output buffer */
while (1) {
zstream->avail_out = ret->size - ret->pos;
zstream->next_out = buf_getwriteptr(ret, zstream->avail_out);
result = inflate(zstream, Z_SYNC_FLUSH);
buf_setlen(ret, ret->size - zstream->avail_out);
buf_setpos(ret, ret->len);
if (result != Z_BUF_ERROR && result != Z_OK) {
dropbear_exit("zlib error");
}
if (zstream->avail_in == 0 &&
(zstream->avail_out != 0 || result == Z_BUF_ERROR)) {
/* we can only exit if avail_out hasn't all been used,
* and there's no remaining input */
return ret;
}
if (zstream->avail_out == 0) {
int new_size = 0;
if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
/* Already been increased as large as it can go,
* yet didn't finish up the decompression */
dropbear_exit("bad packet, oversized decompressed");
}
new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
ret = buf_resize(ret, new_size);
}
}
}
#endif
/* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
static int packet_is_okay_kex(unsigned char type) {
if (type >= SSH_MSG_USERAUTH_REQUEST) {
return 0;
}
if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
return 0;
}
if (type == SSH_MSG_KEXINIT) {
/* XXX should this die horribly if !dataallowed ?? */
return 0;
}
return 1;
}
static void enqueue_reply_packet() {
struct packetlist * new_item = NULL;
new_item = m_malloc(sizeof(struct packetlist));
new_item->next = NULL;
new_item->payload = buf_newcopy(ses.writepayload);
buf_setpos(ses.writepayload, 0);
buf_setlen(ses.writepayload, 0);
if (ses.reply_queue_tail) {
ses.reply_queue_tail->next = new_item;
} else {
ses.reply_queue_head = new_item;
}
ses.reply_queue_tail = new_item;
}
void maybe_flush_reply_queue() {
struct packetlist *tmp_item = NULL, *curr_item = NULL;
if (!ses.dataallowed)
{
TRACE(("maybe_empty_reply_queue - no data allowed"))
return;
}
for (curr_item = ses.reply_queue_head; curr_item; ) {
CHECKCLEARTOWRITE();
buf_putbytes(ses.writepayload,
curr_item->payload->data, curr_item->payload->len);
buf_free(curr_item->payload);
tmp_item = curr_item;
curr_item = curr_item->next;
m_free(tmp_item);
encrypt_packet();
}
ses.reply_queue_head = ses.reply_queue_tail = NULL;
}
/* encrypt the writepayload, putting into writebuf, ready for write_packet()
* to put on the wire */
void encrypt_packet() {
unsigned char padlen;
unsigned char blocksize, mac_size;
buffer * writebuf; /* the packet which will go on the wire. This is
encrypted in-place. */
unsigned char packet_type;
unsigned int len, encrypt_buf_size;
unsigned char mac_bytes[MAX_MAC_LEN];
time_t now;
TRACE2(("enter encrypt_packet()"))
buf_setpos(ses.writepayload, 0);
packet_type = buf_getbyte(ses.writepayload);
buf_setpos(ses.writepayload, 0);
TRACE2(("encrypt_packet type is %d", packet_type))
if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
/* During key exchange only particular packets are allowed.
Since this packet_type isn't OK we just enqueue it to send
after the KEX, see maybe_flush_reply_queue */
enqueue_reply_packet();
return;
}
blocksize = ses.keys->trans.algo_crypt->blocksize;
mac_size = ses.keys->trans.algo_mac->hashsize;
/* Encrypted packet len is payload+5. We need to then make sure
* there is enough space for padding or MIN_PACKET_LEN.
* Add extra 3 since we need at least 4 bytes of padding */
encrypt_buf_size = (ses.writepayload->len+4+1)
+ MAX(MIN_PACKET_LEN, blocksize) + 3
/* add space for the MAC at the end */
+ mac_size
#ifndef DISABLE_ZLIB
/* some extra in case 'compression' makes it larger */
+ ZLIB_COMPRESS_EXPANSION
#endif
/* and an extra cleartext (stripped before transmission) byte for the
* packet type */
+ 1;
writebuf = buf_new(encrypt_buf_size);
buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
#ifndef DISABLE_ZLIB
/* compression */
if (is_compress_trans()) {
buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
} else
#endif
{
memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
buf_getptr(ses.writepayload, ses.writepayload->len),
ses.writepayload->len);
buf_incrwritepos(writebuf, ses.writepayload->len);
}
/* finished with payload */
buf_setpos(ses.writepayload, 0);
buf_setlen(ses.writepayload, 0);
/* length of padding - packet length excluding the packetlength uint32
* field in aead mode must be a multiple of blocksize, with a minimum of
* 4 bytes of padding */
len = writebuf->len;
#if DROPBEAR_AEAD_MODE
if (ses.keys->trans.crypt_mode->aead_crypt) {
len -= 4;
}
#endif
padlen = blocksize - len % blocksize;
if (padlen < 4) {
padlen += blocksize;
}
/* check for min packet length */
if (writebuf->len + padlen < MIN_PACKET_LEN) {
padlen += blocksize;
}
buf_setpos(writebuf, 0);
/* packet length excluding the packetlength uint32 */
buf_putint(writebuf, writebuf->len + padlen - 4);
/* padding len */
buf_putbyte(writebuf, padlen);
/* actual padding */
buf_setpos(writebuf, writebuf->len);
buf_incrlen(writebuf, padlen);
genrandom(buf_getptr(writebuf, padlen), padlen);
#if DROPBEAR_AEAD_MODE
if (ses.keys->trans.crypt_mode->aead_crypt) {
/* do the actual encryption, in-place */
buf_setpos(writebuf, 0);
/* encrypt it in-place*/
len = writebuf->len;
buf_incrlen(writebuf, mac_size);
if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
buf_getptr(writebuf, len),
buf_getwriteptr(writebuf, len + mac_size),
len, mac_size,
&ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
dropbear_exit("Error encrypting");
}
buf_incrpos(writebuf, len + mac_size);
} else
#endif
{
make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
/* do the actual encryption, in-place */
buf_setpos(writebuf, 0);
/* encrypt it in-place*/
len = writebuf->len;
if (ses.keys->trans.crypt_mode->encrypt(
buf_getptr(writebuf, len),
buf_getwriteptr(writebuf, len),
len,
&ses.keys->trans.cipher_state) != CRYPT_OK) {
dropbear_exit("Error encrypting");
}
buf_incrpos(writebuf, len);
/* stick the MAC on it */
buf_putbytes(writebuf, mac_bytes, mac_size);
}
/* Update counts */
ses.kexstate.datatrans += writebuf->len;
writebuf_enqueue(writebuf);
/* Update counts */
ses.transseq++;
now = monotonic_now();
ses.last_packet_time_any_sent = now;
/* idle timeout shouldn't be affected by responses to keepalives.
send_msg_keepalive() itself also does tricks with
ses.last_packet_idle_time - read that if modifying this code */
if (packet_type != SSH_MSG_REQUEST_FAILURE
&& packet_type != SSH_MSG_UNIMPLEMENTED
&& packet_type != SSH_MSG_IGNORE) {
ses.last_packet_time_idle = now;
}
TRACE2(("leave encrypt_packet()"))
}
void writebuf_enqueue(buffer * writebuf) {
/* enqueue the packet for sending. It will get freed after transmission. */
buf_setpos(writebuf, 0);
enqueue(&ses.writequeue, (void*)writebuf);
ses.writequeue_len += writebuf->len;
}
/* Create the packet mac, and append H(seqno|clearbuf) to the output */
/* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
buffer * clear_buf, unsigned int clear_len,
unsigned char *output_mac) {
unsigned char seqbuf[4];
unsigned long bufsize;
hmac_state hmac;
if (key_state->algo_mac->hashsize > 0) {
/* calculate the mac */
if (hmac_init(&hmac,
key_state->hash_index,
key_state->mackey,
key_state->algo_mac->keysize) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
/* sequence number */
STORE32H(seqno, seqbuf);
if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
/* the actual contents */
buf_setpos(clear_buf, 0);
if (hmac_process(&hmac,
buf_getptr(clear_buf, clear_len),
clear_len) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
bufsize = MAX_MAC_LEN;
if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
}
TRACE2(("leave writemac"))
}
#ifndef DISABLE_ZLIB
/* compresses len bytes from src, outputting to dest (starting from the
* respective current positions. dest must have sufficient space,
* len+ZLIB_COMPRESS_EXPANSION */
static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
unsigned int endpos = src->pos + len;
int result;
TRACE2(("enter buf_compress"))
dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
ses.keys->trans.zstream->avail_in = endpos - src->pos;
ses.keys->trans.zstream->next_in =
buf_getptr(src, ses.keys->trans.zstream->avail_in);
ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
ses.keys->trans.zstream->next_out =
buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
buf_setpos(dest, dest->len);
if (result != Z_OK) {
dropbear_exit("zlib error");
}
/* fails if destination buffer wasn't large enough */
dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
TRACE2(("leave buf_compress"))
}
#endif
1
https://gitee.com/xfan1024/oh-dropbear.git
git@gitee.com:xfan1024/oh-dropbear.git
xfan1024
oh-dropbear
oh-dropbear
master

搜索帮助