comparison packet.c @ 1672:3a97f14c0235

Add Chacha20-Poly1305, AES128-GCM and AES256-GCM support (#93) * Add Chacha20-Poly1305 authenticated encryption * Add general AEAD approach. * Add [email protected] 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 [email protected] and [email protected] 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
author Vladislav Grishenko <themiron@users.noreply.github.com>
date Mon, 25 May 2020 20:50:25 +0500
parents c4bf28ccab97
children 3b9b427925a0
comparison
equal deleted inserted replaced
1671:5c8913b7464c 1672:3a97f14c0235
213 * DROPBEAR_FAILURE otherwise */ 213 * DROPBEAR_FAILURE otherwise */
214 static int read_packet_init() { 214 static int read_packet_init() {
215 215
216 unsigned int maxlen; 216 unsigned int maxlen;
217 int slen; 217 int slen;
218 unsigned int len; 218 unsigned int len, plen;
219 unsigned int blocksize; 219 unsigned int blocksize;
220 unsigned int macsize; 220 unsigned int macsize;
221 221
222 222
223 blocksize = ses.keys->recv.algo_crypt->blocksize; 223 blocksize = ses.keys->recv.algo_crypt->blocksize;
252 } 252 }
253 253
254 /* now we have the first block, need to get packet length, so we decrypt 254 /* now we have the first block, need to get packet length, so we decrypt
255 * the first block (only need first 4 bytes) */ 255 * the first block (only need first 4 bytes) */
256 buf_setpos(ses.readbuf, 0); 256 buf_setpos(ses.readbuf, 0);
257 if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 257 #if DROPBEAR_AEAD_MODE
258 buf_getwriteptr(ses.readbuf, blocksize), 258 if (ses.keys->recv.crypt_mode->aead_crypt) {
259 blocksize, 259 if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq,
260 &ses.keys->recv.cipher_state) != CRYPT_OK) { 260 buf_getptr(ses.readbuf, blocksize), &plen,
261 dropbear_exit("Error decrypting"); 261 blocksize,
262 } 262 &ses.keys->recv.cipher_state) != CRYPT_OK) {
263 len = buf_getint(ses.readbuf) + 4 + macsize; 263 dropbear_exit("Error decrypting");
264 }
265 len = plen + 4 + macsize;
266 } else
267 #endif
268 {
269 if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize),
270 buf_getwriteptr(ses.readbuf, blocksize),
271 blocksize,
272 &ses.keys->recv.cipher_state) != CRYPT_OK) {
273 dropbear_exit("Error decrypting");
274 }
275 plen = buf_getint(ses.readbuf) + 4;
276 len = plen + macsize;
277 }
264 278
265 TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize)) 279 TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
266 280
267 281
268 /* check packet length */ 282 /* check packet length */
269 if ((len > RECV_MAX_PACKET_LEN) || 283 if ((len > RECV_MAX_PACKET_LEN) ||
270 (len < MIN_PACKET_LEN + macsize) || 284 (plen < blocksize) ||
271 ((len - macsize) % blocksize != 0)) { 285 (plen % blocksize != 0)) {
272 dropbear_exit("Integrity error (bad packet size %u)", len); 286 dropbear_exit("Integrity error (bad packet size %u)", len);
273 } 287 }
274 288
275 if (len > ses.readbuf->size) { 289 if (len > ses.readbuf->size) {
276 ses.readbuf = buf_resize(ses.readbuf, len); 290 ses.readbuf = buf_resize(ses.readbuf, len);
292 blocksize = ses.keys->recv.algo_crypt->blocksize; 306 blocksize = ses.keys->recv.algo_crypt->blocksize;
293 macsize = ses.keys->recv.algo_mac->hashsize; 307 macsize = ses.keys->recv.algo_mac->hashsize;
294 308
295 ses.kexstate.datarecv += ses.readbuf->len; 309 ses.kexstate.datarecv += ses.readbuf->len;
296 310
297 /* we've already decrypted the first blocksize in read_packet_init */ 311 #if DROPBEAR_AEAD_MODE
298 buf_setpos(ses.readbuf, blocksize); 312 if (ses.keys->recv.crypt_mode->aead_crypt) {
299 313 /* first blocksize is not decrypted yet */
300 /* decrypt it in-place */ 314 buf_setpos(ses.readbuf, 0);
301 len = ses.readbuf->len - macsize - ses.readbuf->pos; 315
302 if (ses.keys->recv.crypt_mode->decrypt( 316 /* decrypt it in-place */
303 buf_getptr(ses.readbuf, len), 317 len = ses.readbuf->len - macsize - ses.readbuf->pos;
304 buf_getwriteptr(ses.readbuf, len), 318 if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq,
305 len, 319 buf_getptr(ses.readbuf, len + macsize),
306 &ses.keys->recv.cipher_state) != CRYPT_OK) { 320 buf_getwriteptr(ses.readbuf, len),
307 dropbear_exit("Error decrypting"); 321 len, macsize,
308 } 322 &ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) {
309 buf_incrpos(ses.readbuf, len); 323 dropbear_exit("Error decrypting");
310 324 }
311 /* check the hmac */ 325 buf_incrpos(ses.readbuf, len);
312 if (checkmac() != DROPBEAR_SUCCESS) { 326 } else
313 dropbear_exit("Integrity error"); 327 #endif
328 {
329 /* we've already decrypted the first blocksize in read_packet_init */
330 buf_setpos(ses.readbuf, blocksize);
331
332 /* decrypt it in-place */
333 len = ses.readbuf->len - macsize - ses.readbuf->pos;
334 if (ses.keys->recv.crypt_mode->decrypt(
335 buf_getptr(ses.readbuf, len),
336 buf_getwriteptr(ses.readbuf, len),
337 len,
338 &ses.keys->recv.cipher_state) != CRYPT_OK) {
339 dropbear_exit("Error decrypting");
340 }
341 buf_incrpos(ses.readbuf, len);
342
343 /* check the hmac */
344 if (checkmac() != DROPBEAR_SUCCESS) {
345 dropbear_exit("Integrity error");
346 }
314 } 347 }
315 348
316 /* get padding length */ 349 /* get padding length */
317 buf_setpos(ses.readbuf, PACKET_PADDING_OFF); 350 buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
318 padlen = buf_getbyte(ses.readbuf); 351 padlen = buf_getbyte(ses.readbuf);
555 588
556 /* finished with payload */ 589 /* finished with payload */
557 buf_setpos(ses.writepayload, 0); 590 buf_setpos(ses.writepayload, 0);
558 buf_setlen(ses.writepayload, 0); 591 buf_setlen(ses.writepayload, 0);
559 592
560 /* length of padding - packet length must be a multiple of blocksize, 593 /* length of padding - packet length excluding the packetlength uint32
561 * with a minimum of 4 bytes of padding */ 594 * field in aead mode must be a multiple of blocksize, with a minimum of
562 padlen = blocksize - (writebuf->len) % blocksize; 595 * 4 bytes of padding */
596 len = writebuf->len;
597 #if DROPBEAR_AEAD_MODE
598 if (ses.keys->trans.crypt_mode->aead_crypt) {
599 len -= 4;
600 }
601 #endif
602 padlen = blocksize - len % blocksize;
563 if (padlen < 4) { 603 if (padlen < 4) {
564 padlen += blocksize; 604 padlen += blocksize;
565 } 605 }
566 /* check for min packet length */ 606 /* check for min packet length */
567 if (writebuf->len + padlen < MIN_PACKET_LEN) { 607 if (writebuf->len + padlen < MIN_PACKET_LEN) {
577 /* actual padding */ 617 /* actual padding */
578 buf_setpos(writebuf, writebuf->len); 618 buf_setpos(writebuf, writebuf->len);
579 buf_incrlen(writebuf, padlen); 619 buf_incrlen(writebuf, padlen);
580 genrandom(buf_getptr(writebuf, padlen), padlen); 620 genrandom(buf_getptr(writebuf, padlen), padlen);
581 621
582 make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes); 622 #if DROPBEAR_AEAD_MODE
583 623 if (ses.keys->trans.crypt_mode->aead_crypt) {
584 /* do the actual encryption, in-place */ 624 /* do the actual encryption, in-place */
585 buf_setpos(writebuf, 0); 625 buf_setpos(writebuf, 0);
586 /* encrypt it in-place*/ 626 /* encrypt it in-place*/
587 len = writebuf->len; 627 len = writebuf->len;
588 if (ses.keys->trans.crypt_mode->encrypt( 628 buf_incrlen(writebuf, mac_size);
589 buf_getptr(writebuf, len), 629 if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
590 buf_getwriteptr(writebuf, len), 630 buf_getptr(writebuf, len),
591 len, 631 buf_getwriteptr(writebuf, len + mac_size),
592 &ses.keys->trans.cipher_state) != CRYPT_OK) { 632 len, mac_size,
593 dropbear_exit("Error encrypting"); 633 &ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
594 } 634 dropbear_exit("Error encrypting");
595 buf_incrpos(writebuf, len); 635 }
596 636 buf_incrpos(writebuf, len + mac_size);
597 /* stick the MAC on it */ 637 } else
598 buf_putbytes(writebuf, mac_bytes, mac_size); 638 #endif
639 {
640 make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
641
642 /* do the actual encryption, in-place */
643 buf_setpos(writebuf, 0);
644 /* encrypt it in-place*/
645 len = writebuf->len;
646 if (ses.keys->trans.crypt_mode->encrypt(
647 buf_getptr(writebuf, len),
648 buf_getwriteptr(writebuf, len),
649 len,
650 &ses.keys->trans.cipher_state) != CRYPT_OK) {
651 dropbear_exit("Error encrypting");
652 }
653 buf_incrpos(writebuf, len);
654
655 /* stick the MAC on it */
656 buf_putbytes(writebuf, mac_bytes, mac_size);
657 }
599 658
600 /* Update counts */ 659 /* Update counts */
601 ses.kexstate.datatrans += writebuf->len; 660 ses.kexstate.datatrans += writebuf->len;
602 661
603 writebuf_enqueue(writebuf); 662 writebuf_enqueue(writebuf);