mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
Add Chacha20-Poly1305, AES128-GCM and AES256-GCM support (#93)
* Add Chacha20-Poly1305 authenticated encryption * Add general AEAD approach. * Add chacha20-poly1305@openssh.com algo using LibTomCrypt chacha and poly1305 routines. Chacha20-Poly1305 is generally faster than AES256 on CPU w/o dedicated AES instructions, having the same key size. Compiling in will add ~5,5kB to binary size on x86-64. function old new delta chacha_crypt - 1397 +1397 _poly1305_block - 608 +608 poly1305_done - 595 +595 dropbear_chachapoly_crypt - 457 +457 .rodata 26976 27392 +416 poly1305_process - 290 +290 poly1305_init - 221 +221 chacha_setup - 218 +218 encrypt_packet 1068 1270 +202 dropbear_chachapoly_getlength - 147 +147 decrypt_packet 756 897 +141 chacha_ivctr64 - 137 +137 read_packet 543 637 +94 dropbear_chachapoly_start - 94 +94 read_kex_algos 792 880 +88 chacha_keystream - 69 +69 dropbear_mode_chachapoly - 48 +48 sshciphers 280 320 +40 dropbear_mode_none 24 48 +24 dropbear_mode_ctr 24 48 +24 dropbear_mode_cbc 24 48 +24 dropbear_chachapoly_mac - 24 +24 dropbear_chachapoly - 24 +24 gen_new_keys 848 854 +6 ------------------------------------------------------------------------------ (add/remove: 14/0 grow/shrink: 10/0 up/down: 5388/0) Total: 5388 bytes * Add AES128-GCM and AES256-GCM authenticated encryption * Add general AES-GCM mode. * Add aes128-gcm@openssh.com and aes256-gcm@openssh.com algo using LibTomCrypt gcm routines. AES-GCM is combination of AES CTR mode and GHASH, slower than AES-CTR on CPU w/o dedicated AES/GHASH instructions therefore disabled by default. Compiling in will add ~6kB to binary size on x86-64. function old new delta gcm_process - 1060 +1060 .rodata 26976 27808 +832 gcm_gf_mult - 820 +820 gcm_add_aad - 660 +660 gcm_shift_table - 512 +512 gcm_done - 471 +471 gcm_add_iv - 384 +384 gcm_init - 347 +347 dropbear_gcm_crypt - 309 +309 encrypt_packet 1068 1270 +202 decrypt_packet 756 897 +141 gcm_reset - 118 +118 read_packet 543 637 +94 read_kex_algos 792 880 +88 sshciphers 280 360 +80 gcm_mult_h - 80 +80 dropbear_gcm_start - 62 +62 dropbear_mode_gcm - 48 +48 dropbear_mode_none 24 48 +24 dropbear_mode_ctr 24 48 +24 dropbear_mode_cbc 24 48 +24 dropbear_ghash - 24 +24 dropbear_gcm_getlength - 24 +24 gen_new_keys 848 854 +6 ------------------------------------------------------------------------------ (add/remove: 14/0 grow/shrink: 10/0 up/down: 6434/0) Total: 6434 bytes
This commit is contained in:
committed by
GitHub
parent
91e537e427
commit
d3d0d60076
143
packet.c
143
packet.c
@@ -215,7 +215,7 @@ static int read_packet_init() {
|
||||
|
||||
unsigned int maxlen;
|
||||
int slen;
|
||||
unsigned int len;
|
||||
unsigned int len, plen;
|
||||
unsigned int blocksize;
|
||||
unsigned int macsize;
|
||||
|
||||
@@ -254,21 +254,35 @@ static int read_packet_init() {
|
||||
/* 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 (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");
|
||||
#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;
|
||||
}
|
||||
len = buf_getint(ses.readbuf) + 4 + macsize;
|
||||
|
||||
TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
|
||||
|
||||
|
||||
/* check packet length */
|
||||
if ((len > RECV_MAX_PACKET_LEN) ||
|
||||
(len < MIN_PACKET_LEN + macsize) ||
|
||||
((len - macsize) % blocksize != 0)) {
|
||||
(plen < blocksize) ||
|
||||
(plen % blocksize != 0)) {
|
||||
dropbear_exit("Integrity error (bad packet size %u)", len);
|
||||
}
|
||||
|
||||
@@ -294,23 +308,42 @@ void decrypt_packet() {
|
||||
|
||||
ses.kexstate.datarecv += ses.readbuf->len;
|
||||
|
||||
/* we've already decrypted the first blocksize in read_packet_init */
|
||||
buf_setpos(ses.readbuf, blocksize);
|
||||
#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->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);
|
||||
/* 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);
|
||||
|
||||
/* check the hmac */
|
||||
if (checkmac() != DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Integrity error");
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
|
||||
/* get padding length */
|
||||
@@ -557,9 +590,16 @@ void encrypt_packet() {
|
||||
buf_setpos(ses.writepayload, 0);
|
||||
buf_setlen(ses.writepayload, 0);
|
||||
|
||||
/* length of padding - packet length must be a multiple of blocksize,
|
||||
* with a minimum of 4 bytes of padding */
|
||||
padlen = blocksize - (writebuf->len) % blocksize;
|
||||
/* 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;
|
||||
}
|
||||
@@ -579,23 +619,42 @@ void encrypt_packet() {
|
||||
buf_incrlen(writebuf, padlen);
|
||||
genrandom(buf_getptr(writebuf, padlen), padlen);
|
||||
|
||||
make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
|
||||
#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");
|
||||
/* 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);
|
||||
}
|
||||
buf_incrpos(writebuf, len);
|
||||
|
||||
/* stick the MAC on it */
|
||||
buf_putbytes(writebuf, mac_bytes, mac_size);
|
||||
|
||||
/* Update counts */
|
||||
ses.kexstate.datatrans += writebuf->len;
|
||||
|
||||
Reference in New Issue
Block a user