Skip to content

Commit 5d93a1f

Browse files
committed
Merge branch 'buffer-fix' into pre-stage
Last round of fixes to handle excessive memory usage.
2 parents 865d67b + aa5383c commit 5d93a1f

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

cipher.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,47 @@ cipher_blocksize(const struct sshcipher *c)
178178
return (c->block_size);
179179
}
180180

181+
uint64_t
182+
cipher_rekey_blocks(const struct sshcipher *c)
183+
{
184+
/*
185+
* Chacha20-Poly1305 does not benefit from data-based rekeying,
186+
* per "The Security of ChaCha20-Poly1305 in the Multi-user Setting",
187+
* Degabriele, J. P., Govinden, J, Gunther, F. and Paterson K.
188+
* ACM CCS 2021; https://eprint.iacr.org/2023/085.pdf
189+
*
190+
* Cryptanalysis aside, we do still want do need to prevent the SSH
191+
* sequence number wrapping and also to rekey to provide some
192+
* protection for long lived sessions against key disclosure at the
193+
* endpoints, so arrange for rekeying every 2**32 blocks as the
194+
* 128-bit block ciphers do (i.e. every 32GB data).
195+
*/
196+
if ((c->flags & CFLAG_CHACHAPOLY) != 0)
197+
return (uint64_t)1 << 32;
198+
199+
/* there is no actual need to rekey the NULL cipher but
200+
* rekeying is a necessary step. In part, as mentioned above,
201+
* to keep the seqnr from wrapping. So we set it to the
202+
* maximum possible -cjr 4/10/23 */
203+
if ((c->flags & CFLAG_NONE) != 0)
204+
return (uint64_t)1 << 32;
205+
206+
/*
207+
* The 2^(blocksize*2) limit is too expensive for 3DES,
208+
* so enforce a 1GB data limit for small blocksizes.
209+
* See discussion in RFC4344 section 3.2.
210+
*/
211+
if (c->block_size < 16)
212+
return ((uint64_t)1 << 30) / c->block_size;
213+
/*
214+
* Otherwise, use the RFC4344 s3.2 recommendation of 2**(L/4) blocks
215+
* before rekeying where L is the blocksize in bits.
216+
* Most other ciphers have a 128 bit blocksize, so this equates to
217+
* 2**32 blocks / 64GB data.
218+
*/
219+
return (uint64_t)1 << (c->block_size * 2);
220+
}
221+
181222
u_int
182223
cipher_keylen(const struct sshcipher *c)
183224
{

cipher.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
6363
const u_char *, u_int);
6464
void cipher_free(struct sshcipher_ctx *);
6565
u_int cipher_blocksize(const struct sshcipher *);
66+
uint64_t cipher_rekey_blocks(const struct sshcipher *);
6667
u_int cipher_keylen(const struct sshcipher *);
6768
u_int cipher_seclen(const struct sshcipher *);
6869
u_int cipher_authlen(const struct sshcipher *);

packet.c

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
#endif
6464
#include <signal.h>
6565
#include <time.h>
66+
#ifdef HAVE_UTIL_H
67+
# include <util.h>
68+
#endif
6669

6770
/*
6871
* Explicitly include OpenSSL before zlib as some versions of OpenSSL have
@@ -888,6 +891,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
888891
const char *wmsg;
889892
int r, crypt_type;
890893
const char *dir = mode == MODE_OUT ? "out" : "in";
894+
char blocks_s[FMT_SCALED_STRSIZE], bytes_s[FMT_SCALED_STRSIZE];
891895

892896
debug2_f("mode %d", mode);
893897

@@ -956,29 +960,20 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
956960
}
957961
comp->enabled = 1;
958962
}
959-
/*
960-
* The 2^(blocksize*2) limit is too expensive for 3DES,
961-
* so enforce a 1GB limit for small blocksizes.
962-
* See RFC4344 section 3.2.
963-
*/
964963

965-
/* we really don't need to rekey if we are using the none cipher
966-
* but there isn't a good way to disable it entirely that I can find
967-
* and using a blocksize larger that 16 doesn't work (dunno why)
968-
* so this seems to be a good limit for now - CJR 10/16/2020*/
969-
if (ssh->none == 1) {
970-
*max_blocks = (u_int64_t)1 << (31*2);
971-
} else {
972-
if (enc->block_size >= 16)
973-
*max_blocks = (u_int64_t)1 << (enc->block_size*2);
974-
else
975-
*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
976-
}
977-
if (state->rekey_limit)
978-
*max_blocks = MINIMUM(*max_blocks,
979-
state->rekey_limit / enc->block_size);
980-
debug("rekey %s after %llu blocks", dir,
981-
(unsigned long long)*max_blocks);
964+
/* get the maximum number of blocks the cipher can
965+
* handle safely */
966+
*max_blocks = cipher_rekey_blocks(enc->cipher);
967+
968+
/* these lines support the debug */
969+
strlcpy(blocks_s, "?", sizeof(blocks_s));
970+
strlcpy(bytes_s, "?", sizeof(bytes_s));
971+
if (*max_blocks * enc->block_size < LLONG_MAX) {
972+
fmt_scaled((long long)*max_blocks, blocks_s);
973+
fmt_scaled((long long)*max_blocks * enc->block_size, bytes_s);
974+
}
975+
debug("rekey %s after %s blocks / %sB data", dir, blocks_s, bytes_s);
976+
982977
return 0;
983978
}
984979

@@ -2241,6 +2236,14 @@ ssh_packet_set_server(struct ssh *ssh)
22412236
ssh->kex->server = 1; /* XXX unify? */
22422237
}
22432238

2239+
/* Set the state of the connection to post auth
2240+
* While we are here also decrease the size of
2241+
* packet_max_size to something more reasonable.
2242+
* In this case thats 33k. Which is the size of
2243+
* the largest packet we expect to see and some space
2244+
* for overhead. This reduces memory usage in high
2245+
* BDP environments without impacting performance
2246+
* -cjr 4/11/23 */
22442247
void
22452248
ssh_packet_set_authenticated(struct ssh *ssh)
22462249
{

sshbuf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ sshbuf_allocate(struct sshbuf *buf, size_t len)
425425
* up being somewhat overallocated but works quickly */
426426
need = (4*1024*1024);
427427
rlen = ROUNDUP(buf->alloc + need, SSHBUF_SIZE_INC);
428-
/* debug_f ("Post: label: %s, %p, rlen is %zu need is %zu win_max is %zu max_size is %zu",
429-
buf->label, buf, rlen, need, buf->window_max, buf->max_size);*/
428+
/* debug_f ("Post: label: %s, %p, rlen is %zu need is %zu win_max is %zu max_size is %zu", */
429+
/* buf->label, buf, rlen, need, buf->window_max, buf->max_size); */
430430
}
431431
SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
432432

0 commit comments

Comments
 (0)