diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2022-01-05 12:05:40 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2022-01-05 12:05:40 +0900 |
commit | 746b8e29969be56e086191dbe93978f7e0355aa0 (patch) | |
tree | 3a86cb0e60e9d09813cc347d2ef5ee903e1dad0f /cipher/cipher-aeswrap.c | |
parent | f9ba07942b10c72af50bd73c92c4851b6981546e (diff) | |
download | libgcrypt-746b8e29969be56e086191dbe93978f7e0355aa0.tar.gz |
cipher: Add an API to retrieve unwrapped key length for KWP.
* cipher/cipher-aeswrap.c (_gcry_cipher_keywrap_decrypt)
(_gcry_cipher_keywrap_decrypt_padding): Merged into...
(_gcry_cipher_keywrap_decrypt_auto): ... this.
Write length information to struct gcry_cipher_handle.
* cipher/cipher-internal.h (struct gcry_cipher_handle): Add
u_mode.wrap.
* cipher/cipher.c (_gcry_cipher_setup_mode_ops): Use
_gcry_cipher_keywrap_decrypt_auto.
(_gcry_cipher_info): Support GCRYCTL_GET_KEYLEN for
GCRY_CIPHER_MODE_AESWRAP. Not that it's not length of KEK,
but length of unwrapped key.
* tests/aeswrap.c (check_one_with_padding): Add check
for length of unwrapped key.
--
Fixes-commit: 2914f169f95467b9c789000105773b38ad2dea5a
GnuPG-bug-id: 5752
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'cipher/cipher-aeswrap.c')
-rw-r--r-- | cipher/cipher-aeswrap.c | 93 |
1 files changed, 29 insertions, 64 deletions
diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index 86c4897f..62987d0f 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -259,67 +259,12 @@ unwrap (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, size_t inbuflen) } -/* Perform the Key Unwrap algorithm as specified by RFC3394. We - implement this as a mode usable with any cipher algorithm of - blocksize 128. */ -gcry_err_code_t -_gcry_cipher_keywrap_decrypt (gcry_cipher_hd_t c, - byte *outbuf, size_t outbuflen, - const byte *inbuf, size_t inbuflen) -{ - gcry_err_code_t err; - - /* We require a cipher with a 128 bit block length. */ - if (c->spec->blocksize != 16) - return GPG_ERR_INV_LENGTH; - - /* The output buffer must be able to hold the input data minus one - additional block. Fixme: The caller has more restrictive checks - - we may want to fix them for this mode. */ - if (outbuflen + 8 < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - /* Input data must be multiple of 64 bits. */ - if (inbuflen % 8) - return GPG_ERR_INV_ARG; - - /* We need at least three 64 bit blocks. */ - if ((inbuflen / 8) < 3) - return GPG_ERR_INV_ARG; - - err = unwrap (c, outbuf, inbuf, inbuflen); - if (!err) - { - int j, x; - unsigned char *a; - - a = c->lastiv; /* We use c->LASTIV as buffer for A. */ - - /* If an IV has been set we compare against this Alternative Initial - Value; if it has not been set we compare against the standard IV. */ - if (c->marks.iv) - j = memcmp (a, c->u_iv.iv, 8); - else - { - for (j=0, x=0; x < 8; x++) - if (a[x] != 0xa6) - { - j=1; - break; - } - } - - if (j) - err = GPG_ERR_CHECKSUM; - } - - return err; -} - -/* Perform the Key Unwrap algorithm as specified by RFC5649. */ +/* Perform the Key Unwrap algorithm as specified by RFC3394 and + RFC5649. */ gcry_err_code_t -_gcry_cipher_keywrap_decrypt_padding (gcry_cipher_hd_t c, - byte *outbuf, size_t outbuflen, - const byte *inbuf, size_t inbuflen) +_gcry_cipher_keywrap_decrypt_auto (gcry_cipher_hd_t c, + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { gcry_err_code_t err; @@ -365,7 +310,10 @@ _gcry_cipher_keywrap_decrypt_padding (gcry_cipher_hd_t c, break; } if (!err) - memcpy (outbuf, t+8, plen); + { + memcpy (outbuf, t+8, 8); + memcpy (c->u_mode.wrap.plen, t+4, 4); + } } } } @@ -382,9 +330,11 @@ _gcry_cipher_keywrap_decrypt_padding (gcry_cipher_hd_t c, a = c->lastiv; /* We use c->LASTIV as buffer for A. */ - if (memcmp (a, icv2, 4)) - err = GPG_ERR_CHECKSUM; - else + /* If an IV has been set we compare against this Alternative Initial + Value; if it has not been set we compare against the standard IV. */ + if (c->marks.iv && !memcmp (a, c->u_iv.iv, 8)) + memset (c->u_mode.wrap.plen, 0, 4); + else if (!memcmp (a, icv2, 4)) /* It's a packet wrapped by KWP. */ { unsigned int plen = (a[4]<<24) | (a[5]<<16) | (a[6]<<8) | a[7]; int padlen = inbuflen - 8 - plen; @@ -402,6 +352,21 @@ _gcry_cipher_keywrap_decrypt_padding (gcry_cipher_hd_t c, break; } } + if (!err) + memcpy (c->u_mode.wrap.plen, a+4, 4); + } + else /* It's a packet wrapped by KW. */ + { + int i; + + for (i = 0; i < 8; i++) + if (a[i] != 0xa6) + { + err = GPG_ERR_CHECKSUM; + break; + } + if (!err) + memset (c->u_mode.wrap.plen, 0, 4); } } } |