diff options
author | Mathias L. Baumann <mathias.baumann_at_sociomantic.com> | 2017-02-04 13:30:41 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2017-02-04 13:31:02 +0200 |
commit | d1ee9a660571ce4a998c9ab2299d4f2419f99127 (patch) | |
tree | b327acebfeb639a838b0558088bccf7ae8f2ec80 /cipher | |
parent | 80bd6195c794a7900791a88b943f371dc480cf07 (diff) | |
download | libgcrypt-d1ee9a660571ce4a998c9ab2299d4f2419f99127.tar.gz |
Implement CFB with 8-bit mode
* cipher/cipher-cfb.c (_gcry_cipher_cfb8_encrypt)
(_gcry_cipher_cfg8_decrypt): Add 8-bit variants of decrypt/encrypt
functions.
* cipher/cipher-internal.h (_gcry_cipher_cfb8_encrypt)
(_gcry_cipher_cfg8_decrypt): Ditto.
* cipher/cipher.c: Adjust code flow to work with GCRY_CIPHER_MODE_CFB8.
* tests/basic.c: Add tests for cfb8 with AES and 3DES.
--
Signed-off-by: Mathias L. Baumann <mathias.baumann at sociomantic.com>
[JK: edit changelog, fix email malformed patch]
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/cipher-cfb.c | 86 | ||||
-rw-r--r-- | cipher/cipher-internal.h | 8 | ||||
-rw-r--r-- | cipher/cipher.c | 9 |
3 files changed, 103 insertions, 0 deletions
diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index 21c81ca2..cca5c1fb 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -233,3 +233,89 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, return 0; } + + +gcry_err_code_t +_gcry_cipher_cfb8_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) +{ + gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; + size_t blocksize = c->spec->blocksize; + unsigned int burn, nburn; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + burn = 0; + + while ( inbuflen > 0) + { + /* Encrypt the IV. */ + nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; + + outbuf[0] = c->lastiv[0] ^ inbuf[0]; + + /* Bitshift iv by 8 bit to the left */ + for (int i = 0; i < blocksize-1; i++) + c->u_iv.iv[i] = c->u_iv.iv[i+1]; + + /* append cipher text to iv */ + c->u_iv.iv[blocksize-1] = outbuf[0]; + + outbuf += 1; + inbuf += 1; + inbuflen -= 1; + } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + + return 0; +} + + +gcry_err_code_t +_gcry_cipher_cfb8_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) +{ + gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; + size_t blocksize = c->spec->blocksize; + unsigned int burn, nburn; + unsigned char appendee; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + burn = 0; + + while (inbuflen > 0) + { + /* Encrypt the IV. */ + nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv ); + burn = nburn > burn ? nburn : burn; + + /* inbuf might == outbuf, make sure we keep the value + so we can append it later */ + appendee = inbuf[0]; + + outbuf[0] = inbuf[0] ^ c->lastiv[0]; + + /* Bitshift iv by 8 bit to the left */ + for (int i = 0; i < blocksize-1; i++) + c->u_iv.iv[i] = c->u_iv.iv[i+1]; + + c->u_iv.iv[blocksize-1] = appendee; + + outbuf += 1; + inbuf += 1; + inbuflen -= 1; + } + + if (burn > 0) + _gcry_burn_stack (burn + 4 * sizeof(void *)); + + return 0; +} diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 33d0629c..ea9c33d3 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -348,6 +348,14 @@ gcry_err_code_t _gcry_cipher_cfb_decrypt /* */ (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen); +gcry_err_code_t _gcry_cipher_cfb8_encrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); +gcry_err_code_t _gcry_cipher_cfb8_decrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-ofb.c --*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index 06ce1dad..124700e9 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -415,6 +415,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_ECB: case GCRY_CIPHER_MODE_CBC: case GCRY_CIPHER_MODE_CFB: + case GCRY_CIPHER_MODE_CFB8: case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: @@ -902,6 +903,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CFB8: + rc = _gcry_cipher_cfb8_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_OFB: rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; @@ -1029,6 +1034,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CFB8: + rc = _gcry_cipher_cfb8_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_OFB: rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; |