dropbear/gcm.c
Vladislav Grishenko d3d0d60076
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
2020-05-25 23:50:25 +08:00

121 lines
3.4 KiB
C

/*
* Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* Copyright (c) 2020 by Vladislav Grishenko
* 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 "algo.h"
#include "dbutil.h"
#include "gcm.h"
#if DROPBEAR_ENABLE_GCM_MODE
#define GHASH_LEN 16
static const struct dropbear_hash dropbear_ghash =
{NULL, 0, GHASH_LEN};
static int dropbear_gcm_start(int cipher, const unsigned char *IV,
const unsigned char *key, int keylen,
int UNUSED(num_rounds), dropbear_gcm_state *state) {
int err;
TRACE2(("enter dropbear_gcm_start"))
if ((err = gcm_init(&state->gcm, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
memcpy(state->iv, IV, GCM_NONCE_LEN);
TRACE2(("leave dropbear_gcm_start"))
return CRYPT_OK;
}
static int dropbear_gcm_crypt(unsigned int UNUSED(seq),
const unsigned char *in, unsigned char *out,
unsigned long len, unsigned long taglen,
dropbear_gcm_state *state, int direction) {
unsigned char *iv, tag[GHASH_LEN];
int i, err;
TRACE2(("enter dropbear_gcm_crypt"))
if (len < 4 || taglen != GHASH_LEN) {
return CRYPT_ERROR;
}
gcm_reset(&state->gcm);
if ((err = gcm_add_iv(&state->gcm,
state->iv, GCM_NONCE_LEN)) != CRYPT_OK) {
return err;
}
if ((err = gcm_add_aad(&state->gcm, in, 4)) != CRYPT_OK) {
return err;
}
if ((err = gcm_process(&state->gcm, (unsigned char *) in + 4,
len - 4, out + 4, direction)) != CRYPT_OK) {
return err;
}
if (direction == LTC_ENCRYPT) {
gcm_done(&state->gcm, out + len, &taglen);
} else {
gcm_done(&state->gcm, tag, &taglen);
if (constant_time_memcmp(in + len, tag, taglen) != 0) {
return CRYPT_ERROR;
}
}
/* increment invocation counter */
iv = state->iv + GCM_IVFIX_LEN;
for (i = GCM_IVCTR_LEN - 1; i >= 0 && ++iv[i] == 0; i--);
TRACE2(("leave dropbear_gcm_crypt"))
return CRYPT_OK;
}
static int dropbear_gcm_getlength(unsigned int UNUSED(seq),
const unsigned char *in, unsigned int *outlen,
unsigned long len, dropbear_gcm_state* UNUSED(state)) {
TRACE2(("enter dropbear_gcm_parse"))
if (len < 4) {
return CRYPT_ERROR;
}
LOAD32H(*outlen, in);
TRACE2(("leave dropbear_gcm_parse"))
return CRYPT_OK;
}
const struct dropbear_cipher_mode dropbear_mode_gcm =
{(void *)dropbear_gcm_start, NULL, NULL,
(void *)dropbear_gcm_crypt,
(void *)dropbear_gcm_getlength, &dropbear_ghash};
#endif /* DROPBEAR_ENABLE_GCM_MODE */