mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
gpg: Simplify the AEAD decryption function.
* g10/decrypt-data.c (aead_set_nonce, aead_set_ad): Merge into ... (aead_set_nonce_and_ad): new single function. Change callers. (decrypt_data): Do not set the nonce and ad here. (aead_underflow): Get rid of the LAST_CHUNK_DONE hack. -- The main change here is that we now re-init the context only right before we decrypt and not after a checktag. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
ad989373f1
commit
618b86325f
@ -117,11 +117,15 @@ release_dfx_context (decode_filter_ctx_t dfx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set the nonce for AEAD. This also reset the decryption machinery
|
/* Set the nonce and the additional data for the current chunk. This
|
||||||
* so that the handle can be used for a new chunk. */
|
* also reset the decryption machinery * so that the handle can be
|
||||||
|
* used for a new chunk. If FINAL is set the final AEAD chunk is
|
||||||
|
* processed. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
aead_set_nonce (decode_filter_ctx_t dfx)
|
aead_set_nonce_and_ad (decode_filter_ctx_t dfx, int final)
|
||||||
{
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char ad[21];
|
||||||
unsigned char nonce[16];
|
unsigned char nonce[16];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -151,16 +155,9 @@ aead_set_nonce (decode_filter_ctx_t dfx)
|
|||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_printhex (nonce, i, "nonce:");
|
log_printhex (nonce, i, "nonce:");
|
||||||
return gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
|
err = gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
|
||||||
}
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
/* Set the additional data for the current chunk. If FINAL is set the
|
|
||||||
* final AEAD chunk is processed. */
|
|
||||||
static gpg_error_t
|
|
||||||
aead_set_ad (decode_filter_ctx_t dfx, int final)
|
|
||||||
{
|
|
||||||
unsigned char ad[21];
|
|
||||||
|
|
||||||
ad[0] = (0xc0 | PKT_ENCRYPTED_AEAD);
|
ad[0] = (0xc0 | PKT_ENCRYPTED_AEAD);
|
||||||
ad[1] = 1;
|
ad[1] = 1;
|
||||||
@ -371,14 +368,6 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = aead_set_nonce (dfx);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
rc = aead_set_ad (dfx, 0);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else /* CFB encryption. */
|
else /* CFB encryption. */
|
||||||
{
|
{
|
||||||
@ -606,7 +595,6 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
size_t totallen = 0; /* The number of bytes to return on success or EOF. */
|
size_t totallen = 0; /* The number of bytes to return on success or EOF. */
|
||||||
size_t off = 0; /* The offset into the buffer. */
|
size_t off = 0; /* The offset into the buffer. */
|
||||||
size_t len; /* The current number of bytes in BUF+OFF. */
|
size_t len; /* The current number of bytes in BUF+OFF. */
|
||||||
int last_chunk_done = 0; /* Flag that we processed the last chunk. */
|
|
||||||
|
|
||||||
log_assert (size > 48); /* Our code requires at least this size. */
|
log_assert (size > 48); /* Our code requires at least this size. */
|
||||||
|
|
||||||
@ -655,10 +643,10 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
}
|
}
|
||||||
/* log_printhex (dfx->holdback, dfx->holdbacklen, "holdback:"); */
|
/* log_printhex (dfx->holdback, dfx->holdbacklen, "holdback:"); */
|
||||||
|
|
||||||
/* Decrypt the buffer. This requires a loop because a chunk may end
|
/* Decrypt the buffer. This first requires a loop to handle the
|
||||||
* within the buffer. */
|
* case when a chunk ends within the buffer. */
|
||||||
if (DBG_FILTER)
|
if (DBG_FILTER)
|
||||||
log_debug ("decrypt loop: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
|
log_debug ("decrypt: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
|
||||||
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, len,
|
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, len,
|
||||||
dfx->eof_seen? " eof":"");
|
dfx->eof_seen? " eof":"");
|
||||||
|
|
||||||
@ -669,6 +657,15 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
|
|
||||||
if (DBG_FILTER)
|
if (DBG_FILTER)
|
||||||
log_debug ("chunksize will be reached: n=%zu\n", n);
|
log_debug ("chunksize will be reached: n=%zu\n", n);
|
||||||
|
|
||||||
|
if (!dfx->chunklen)
|
||||||
|
{
|
||||||
|
/* First data for this chunk - prepare. */
|
||||||
|
err = aead_set_nonce_and_ad (dfx, 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* log_printhex (buf, n, "ciph:"); */
|
/* log_printhex (buf, n, "ciph:"); */
|
||||||
gcry_cipher_final (dfx->cipher_hd);
|
gcry_cipher_final (dfx->cipher_hd);
|
||||||
err = gcry_cipher_decrypt (dfx->cipher_hd, buf+off, n, NULL, 0);
|
err = gcry_cipher_decrypt (dfx->cipher_hd, buf+off, n, NULL, 0);
|
||||||
@ -710,7 +707,6 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
err = gpg_error (GPG_ERR_TRUNCATED);
|
err = gpg_error (GPG_ERR_TRUNCATED);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
last_chunk_done = 1;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -735,25 +731,23 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
err = aead_checktag (dfx, 0, tagbuf);
|
err = aead_checktag (dfx, 0, tagbuf);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
dfx->chunklen = 0;
|
||||||
/* Prepare a new chunk. */
|
dfx->chunkindex++;
|
||||||
if (!last_chunk_done)
|
|
||||||
{
|
|
||||||
dfx->chunklen = 0;
|
|
||||||
dfx->chunkindex++;
|
|
||||||
err = aead_set_nonce (dfx);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
err = aead_set_ad (dfx, 0);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last_chunk_done)
|
/* The bulk decryption of our buffer. */
|
||||||
|
if (len)
|
||||||
{
|
{
|
||||||
|
if (!dfx->chunklen)
|
||||||
|
{
|
||||||
|
/* First data for this chunk - prepare. */
|
||||||
|
err = aead_set_nonce_and_ad (dfx, 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (dfx->eof_seen)
|
if (dfx->eof_seen)
|
||||||
{
|
{
|
||||||
/* This is the last block of the last chunk. Its length may
|
/* This is the last block of the last chunk. Its length may
|
||||||
@ -777,28 +771,24 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
if (dfx->eof_seen)
|
if (dfx->eof_seen)
|
||||||
{
|
{
|
||||||
if (DBG_FILTER)
|
if (DBG_FILTER)
|
||||||
log_debug ("eof seen: holdback buffer has the %s.\n",
|
log_debug ("eof seen: holdback buffer has the last and final tag\n");
|
||||||
last_chunk_done? "final tag":"last and final tag");
|
|
||||||
|
|
||||||
if (!last_chunk_done)
|
log_assert (dfx->holdbacklen >= 32);
|
||||||
|
if (dfx->chunklen)
|
||||||
{
|
{
|
||||||
log_assert (dfx->holdbacklen >= 32);
|
|
||||||
err = aead_checktag (dfx, 0, dfx->holdback);
|
err = aead_checktag (dfx, 0, dfx->holdback);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
dfx->chunklen = 0;
|
||||||
|
dfx->chunkindex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the final chunk. */
|
/* Check the final chunk. */
|
||||||
if (dfx->chunklen)
|
err = aead_set_nonce_and_ad (dfx, 1);
|
||||||
dfx->chunkindex++;
|
|
||||||
err = aead_set_nonce (dfx);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
err = aead_set_ad (dfx, 1);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
gcry_cipher_final (dfx->cipher_hd);
|
gcry_cipher_final (dfx->cipher_hd);
|
||||||
/* Decrypt an empty string. */
|
/* Decrypt an empty string (using HOLDBACK as a dummy). */
|
||||||
err = gcry_cipher_decrypt (dfx->cipher_hd, dfx->holdback, 0, NULL, 0);
|
err = gcry_cipher_decrypt (dfx->cipher_hd, dfx->holdback, 0, NULL, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -806,7 +796,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
|
|||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
err = aead_checktag (dfx, 1, dfx->holdback+(last_chunk_done?0:16));
|
err = aead_checktag (dfx, 1, dfx->holdback+16);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
err = gpg_error (GPG_ERR_EOF);
|
err = gpg_error (GPG_ERR_EOF);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user