mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-22 06:53:46 +00:00
Refine buffer handling in stream_decrypt
This commit is contained in:
+40
-16
@@ -243,6 +243,11 @@ stream_cipher_ctx_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
void
|
||||
stream_cipher_ctx_release(cipher_ctx_t *cipher_ctx)
|
||||
{
|
||||
if (cipher_ctx->chunk != NULL) {
|
||||
bfree(cipher_ctx->chunk);
|
||||
ss_free(cipher_ctx->chunk);
|
||||
cipher_ctx->chunk = NULL;
|
||||
}
|
||||
mbedtls_cipher_free(cipher_ctx->evp);
|
||||
ss_free(cipher_ctx->evp);
|
||||
}
|
||||
@@ -489,22 +494,38 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
|
||||
static buffer_t tmp = { 0, 0, 0, NULL };
|
||||
|
||||
size_t nonce_len = 0;
|
||||
int err = CRYPTO_OK;
|
||||
int err = CRYPTO_OK;
|
||||
|
||||
brealloc(&tmp, ciphertext->len, capacity);
|
||||
buffer_t *plaintext = &tmp;
|
||||
plaintext->len = ciphertext->len;
|
||||
|
||||
if (!cipher_ctx->init) {
|
||||
if (ciphertext->len <= cipher->nonce_len)
|
||||
return CRYPTO_ERROR;
|
||||
if (cipher_ctx->chunk == NULL) {
|
||||
cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));
|
||||
memset(cipher_ctx->chunk, 0, sizeof(buffer_t));
|
||||
balloc(cipher_ctx->chunk, cipher->nonce_len);
|
||||
}
|
||||
|
||||
uint8_t *nonce = cipher_ctx->nonce;
|
||||
nonce_len = cipher->nonce_len;
|
||||
size_t left_len = min(cipher->nonce_len - cipher_ctx->chunk->len,
|
||||
ciphertext->len);
|
||||
|
||||
if (left_len > 0) {
|
||||
memcpy(cipher_ctx->chunk->data, ciphertext->data, left_len);
|
||||
memmove(ciphertext->data, ciphertext->data + left_len,
|
||||
ciphertext->len - left_len);
|
||||
cipher_ctx->chunk->len += left_len;
|
||||
ciphertext->len -= left_len;
|
||||
}
|
||||
|
||||
if (cipher_ctx->chunk->len < cipher->nonce_len)
|
||||
return CRYPTO_NEED_MORE;
|
||||
|
||||
uint8_t *nonce = cipher_ctx->nonce;
|
||||
size_t nonce_len = cipher->nonce_len;
|
||||
plaintext->len -= nonce_len;
|
||||
|
||||
memcpy(nonce, ciphertext->data, nonce_len);
|
||||
memcpy(nonce, cipher_ctx->chunk->data, nonce_len);
|
||||
cipher_ctx_set_nonce(cipher_ctx, nonce, nonce_len, 0);
|
||||
cipher_ctx->counter = 0;
|
||||
cipher_ctx->init = 1;
|
||||
@@ -519,30 +540,33 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
}
|
||||
}
|
||||
|
||||
if (ciphertext->len <= 0)
|
||||
return CRYPTO_NEED_MORE;
|
||||
|
||||
if (cipher->method >= SALSA20) {
|
||||
int padding = cipher_ctx->counter % SODIUM_BLOCK_SIZE;
|
||||
brealloc(plaintext, (plaintext->len + padding) * 2, capacity);
|
||||
|
||||
if (padding) {
|
||||
brealloc(ciphertext, ciphertext->len + padding, capacity);
|
||||
memmove(ciphertext->data + nonce_len + padding, ciphertext->data + nonce_len,
|
||||
ciphertext->len - nonce_len);
|
||||
sodium_memzero(ciphertext->data + nonce_len, padding);
|
||||
memmove(ciphertext->data + padding, ciphertext->data,
|
||||
ciphertext->len);
|
||||
sodium_memzero(ciphertext->data, padding);
|
||||
}
|
||||
crypto_stream_xor_ic((uint8_t *)plaintext->data,
|
||||
(const uint8_t *)(ciphertext->data + nonce_len),
|
||||
(uint64_t)(ciphertext->len - nonce_len + padding),
|
||||
(const uint8_t *)(ciphertext->data),
|
||||
(uint64_t)(ciphertext->len + padding),
|
||||
(const uint8_t *)cipher_ctx->nonce,
|
||||
cipher_ctx->counter / SODIUM_BLOCK_SIZE, cipher->key,
|
||||
cipher->method);
|
||||
cipher_ctx->counter += ciphertext->len - nonce_len;
|
||||
cipher_ctx->counter += ciphertext->len;
|
||||
if (padding) {
|
||||
memmove(plaintext->data, plaintext->data + padding, plaintext->len);
|
||||
}
|
||||
} else {
|
||||
err = cipher_ctx_update(cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,
|
||||
(const uint8_t *)(ciphertext->data + nonce_len),
|
||||
ciphertext->len - nonce_len);
|
||||
(const uint8_t *)(ciphertext->data),
|
||||
ciphertext->len);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
@@ -552,7 +576,7 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
|
||||
#ifdef DEBUG
|
||||
dump("PLAIN", plaintext->data, plaintext->len);
|
||||
dump("CIPHER", ciphertext->data + nonce_len, ciphertext->len - nonce_len);
|
||||
dump("CIPHER", ciphertext->data, ciphertext->len);
|
||||
#endif
|
||||
|
||||
brealloc(ciphertext, plaintext->len, capacity);
|
||||
|
||||
Reference in New Issue
Block a user