diff mbox

[for-2.9,1/2] crypto: add 3des-ede support when using libgcrypt/nettle

Message ID 1481099622-188132-2-git-send-email-longpeng2@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Longpeng(Mike) Dec. 7, 2016, 8:33 a.m. UTC
Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
support when using libgcrypt or nettle.

Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
 crypto/cipher-gcrypt.c     |  6 ++++++
 crypto/cipher-nettle.c     | 37 +++++++++++++++++++++++++++++++++++++
 crypto/cipher.c            |  7 +++++--
 qapi/crypto.json           |  3 ++-
 tests/test-crypto-cipher.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 94 insertions(+), 3 deletions(-)

Comments

Gonglei (Arei) Dec. 7, 2016, 8:52 a.m. UTC | #1
> -----Original Message-----
> From: longpeng
> Sent: Wednesday, December 07, 2016 4:34 PM
> To: berrange@redhat.com; eblake@redhat.com; armbru@redhat.com;
> Gonglei (Arei)
> Cc: qemu-devel@nongnu.org; Wubin (H); Zhoujian (jay, Euler); longpeng
> Subject: [PATCH for-2.9 1/2] crypto: add 3des-ede support when using
> libgcrypt/nettle
> 
> Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
> support when using libgcrypt or nettle.
> 
> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
> ---
>  crypto/cipher-gcrypt.c     |  6 ++++++
>  crypto/cipher-nettle.c     | 37
> +++++++++++++++++++++++++++++++++++++
>  crypto/cipher.c            |  7 +++++--
>  qapi/crypto.json           |  3 ++-
>  tests/test-crypto-cipher.c | 44
> ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 94 insertions(+), 3 deletions(-)
> 
> diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
> index c550db9..5dd0db1 100644
> --- a/crypto/cipher-gcrypt.c
> +++ b/crypto/cipher-gcrypt.c
> @@ -29,6 +29,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm
> alg,
>  {
>      switch (alg) {
>      case QCRYPTO_CIPHER_ALG_DES_RFB:
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> @@ -99,6 +100,10 @@ QCryptoCipher
> *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          gcryalg = GCRY_CIPHER_DES;
>          break;
> 
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
> +        gcryalg = GCRY_CIPHER_3DES;
> +        break;
> +
>      case QCRYPTO_CIPHER_ALG_AES_128:
>          gcryalg = GCRY_CIPHER_AES128;
>          break;
> @@ -200,6 +205,7 @@ QCryptoCipher
> *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          case QCRYPTO_CIPHER_ALG_TWOFISH_256:
>              ctx->blocksize = 16;
>              break;
> +        case QCRYPTO_CIPHER_ALG_3DES_EDE:
>          case QCRYPTO_CIPHER_ALG_CAST5_128:
>              ctx->blocksize = 8;
>              break;
> diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
> index cd094cd..0353b4d 100644
> --- a/crypto/cipher-nettle.c
> +++ b/crypto/cipher-nettle.c
> @@ -78,6 +78,18 @@ static void des_decrypt_native(cipher_ctx_t ctx,
> cipher_length_t length,
>      des_decrypt(ctx, length, dst, src);
>  }
> 
> +static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_encrypt(ctx, length, dst, src);
> +}
> +
> +static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_decrypt(ctx, length, dst, src);
> +}
> +
>  static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
>                                     uint8_t *dst, const uint8_t *src)
>  {
> @@ -140,6 +152,18 @@ static void des_decrypt_wrapper(const void *ctx,
> size_t length,
>      des_decrypt(ctx, length, dst, src);
>  }
> 
> +static void des3_encrypt_wrapper(const void *ctx, size_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_encrypt(ctx, length, dst, src);
> +}
> +
> +static void des3_decrypt_wrapper(const void *ctx, size_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_decrypt(ctx, length, dst, src);
> +}
> +
>  static void cast128_encrypt_wrapper(const void *ctx, size_t length,
>                                      uint8_t *dst, const uint8_t *src)
>  {
> @@ -197,6 +221,7 @@ bool
> qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
>  {
>      switch (alg) {
>      case QCRYPTO_CIPHER_ALG_DES_RFB:
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> @@ -270,6 +295,18 @@ QCryptoCipher
> *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          ctx->blocksize = DES_BLOCK_SIZE;
>          break;
> 
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
> +        ctx->ctx = g_new0(struct des3_ctx, 1);
> +        des3_set_key(ctx->ctx, key);
> +
> +        ctx->alg_encrypt_native = des3_encrypt_native;
> +        ctx->alg_decrypt_native = des3_decrypt_native;
> +        ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
> +        ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;
> +
> +        ctx->blocksize = DES3_BLOCK_SIZE;
> +        break;
> +
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> diff --git a/crypto/cipher.c b/crypto/cipher.c
> index a9bca41..97147b1 100644
> --- a/crypto/cipher.c
> +++ b/crypto/cipher.c
> @@ -28,6 +28,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX]
> = {
>      [QCRYPTO_CIPHER_ALG_AES_192] = 24,
>      [QCRYPTO_CIPHER_ALG_AES_256] = 32,
>      [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
> +    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 24,
>      [QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
> @@ -42,6 +43,7 @@ static size_t
> alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
>      [QCRYPTO_CIPHER_ALG_AES_192] = 16,
>      [QCRYPTO_CIPHER_ALG_AES_256] = 16,
>      [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
> +    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 8,
>      [QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
>      [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
> @@ -107,8 +109,9 @@
> qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
>      }
> 
>      if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> -        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
> -            error_setg(errp, "XTS mode not compatible with DES-RFB");
> +        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
> +                || alg == QCRYPTO_CIPHER_ALG_3DES_EDE) {
> +            error_setg(errp, "XTS mode not compatible with
> DES-RFB/3DES-EDE");
>              return false;
>          }
>          if (nkey % 2) {
> diff --git a/qapi/crypto.json b/qapi/crypto.json
> index 5c9d7d4..848b6cd 100644
> --- a/qapi/crypto.json
> +++ b/qapi/crypto.json
> @@ -63,6 +63,7 @@
>  # @aes-192: AES with 192 bit / 24 byte keys
>  # @aes-256: AES with 256 bit / 32 byte keys
>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys

Missing since 2.9 here.

>  # @cast5-128: Cast5 with 128 bit / 16 byte keys
>  # @serpent-128: Serpent with 128 bit / 16 byte keys
>  # @serpent-192: Serpent with 192 bit / 24 byte keys
> @@ -75,7 +76,7 @@
>  { 'enum': 'QCryptoCipherAlgorithm',
>    'prefix': 'QCRYPTO_CIPHER_ALG',
>    'data': ['aes-128', 'aes-192', 'aes-256',
> -           'des-rfb',
> +           'des-rfb', '3des-ede',
>             'cast5-128',
>             'serpent-128', 'serpent-192', 'serpent-256',
>             'twofish-128', 'twofish-192', 'twofish-256']}
> diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c
> index 5d9e535..8874b61 100644
> --- a/tests/test-crypto-cipher.c
> +++ b/tests/test-crypto-cipher.c
> @@ -165,6 +165,50 @@ static QCryptoCipherTestData test_data[] = {
>              "ffd29f1bb5596ad94ea2d8e6196b7f09"
>              "30d8ed0bf2773af36dd82a6280c20926",
>      },
> +#if defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT)
> +    {
> +        /* Borrowed from linux-kernel crypto/testmgr.h */
> +        .path = "/crypto/cipher/3des-ede-cbc",
> +        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
> +        .mode = QCRYPTO_CIPHER_MODE_CBC,
> +        .key =
> +            "e9c0ff2e760b6424444d995a12d640c0"
> +            "eac284e81495dbe8",
> +        .iv =
> +            "7d3388930f93b242",
> +        .plaintext =
> +            "6f54206f614d796e5320636565727374"
> +            "54206f6f4d206e612079655372637465"
> +            "20736f54206f614d796e532063656572"
> +            "737454206f6f4d206e61207965537263"
> +            "746520736f54206f614d796e53206365"
> +            "6572737454206f6f4d206e6120796553"
> +            "7263746520736f54206f614d796e5320"
> +            "63656572737454206f6f4d206e610a79",
> +        .ciphertext =
> +            "0e2db6973c5633f4671721c76e8ad549"
> +            "74b34905c51cd0ed12565c5396b6007d"
> +            "9048fcf58d2939cc8ad5351836234ed7"
> +            "76d1da0c9467bb048bf2036ca8cfb6ea"
> +            "226447aa8f7513bf9fc2c3f0c956c57a"
> +            "71632e897b1e12cae25fafd8a4f8c97a"
> +            "d6f92131624445a6d6bc5ad32d5443cc"
> +            "9ddea570e942458a6bfab19113b0d919",
> +    },
> +    {
> +        /* Borrowed from linux-kernel crypto/testmgr.h */
> +        .path = "/crypto/cipher/3des-ede-ecb",
> +        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
> +        .mode = QCRYPTO_CIPHER_MODE_ECB,
> +        .key =
> +            "0123456789abcdef5555555555555555"
> +            "fedcba9876543210",
> +        .plaintext =
> +            "736f6d6564617461",
> +        .ciphertext =
> +            "18d748e563620572",
> +    },
> +#endif

Pls adds the CTR mode test case as well.

You'd better split the patch set into two patches so that Denial can take this one.
and I can take the patch 2.

Thanks for your work.

-Gonglei

>      {
>          /* RFC 2144, Appendix B.1 */
>          .path = "/crypto/cipher/cast5-128",
> --
> 1.8.3.1
>
Longpeng(Mike) Dec. 7, 2016, 9:19 a.m. UTC | #2
On 2016/12/7 16:52, Gonglei (Arei) wrote:

>> -----Original Message-----
>> From: longpeng
>> Sent: Wednesday, December 07, 2016 4:34 PM
>> To: berrange@redhat.com; eblake@redhat.com; armbru@redhat.com;
>> Gonglei (Arei)
>> Cc: qemu-devel@nongnu.org; Wubin (H); Zhoujian (jay, Euler); longpeng
>> Subject: [PATCH for-2.9 1/2] crypto: add 3des-ede support when using
>> libgcrypt/nettle
>>
>> Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
>> support when using libgcrypt or nettle.
>>
>> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
>> ---
......
>> --- a/qapi/crypto.json
>> +++ b/qapi/crypto.json
>> @@ -63,6 +63,7 @@
>>  # @aes-192: AES with 192 bit / 24 byte keys
>>  # @aes-256: AES with 256 bit / 32 byte keys
>>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
>> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys
> 
> Missing since 2.9 here.
> 

Okay, I will add it in V2.

>>  # @cast5-128: Cast5 with 128 bit / 16 byte keys
>>  # @serpent-128: Serpent with 128 bit / 16 byte keys
>>  # @serpent-192: Serpent with 192 bit / 24 byte keys
......
>> +    {
>> +        /* Borrowed from linux-kernel crypto/testmgr.h */
>> +        .path = "/crypto/cipher/3des-ede-ecb",
>> +        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
>> +        .mode = QCRYPTO_CIPHER_MODE_ECB,
>> +        .key =
>> +            "0123456789abcdef5555555555555555"
>> +            "fedcba9876543210",
>> +        .plaintext =
>> +            "736f6d6564617461",
>> +        .ciphertext =
>> +            "18d748e563620572",
>> +    },
>> +#endif
> 
> Pls adds the CTR mode test case as well.
> 

Okay!

But I confuse with the 3DES's iv length now. I saw that cbc(3des-ede)'s iv-len
can be 8 or 16 bytes, and ctr(3des-ede)'s iv-len is 24 bytes(according to
linux-kernel crypto/testmgr.h).

However, I think qcrypto_cipher_get_iv_len() cannot distinguish a cipher alg
with more than one iv-len.

Daniel, do you have any idea ?

> You'd better split the patch set into two patches so that Denial can take this one.
> and I can take the patch 2.
> 

Okay, thanks.

> Thanks for your work.
> 
> -Gonglei
> 
>>      {
>>          /* RFC 2144, Appendix B.1 */
>>          .path = "/crypto/cipher/cast5-128",
>> --
>> 1.8.3.1
>>
> 
> 
> .
>
Longpeng(Mike) Dec. 7, 2016, 9:21 a.m. UTC | #3
On 2016/12/7 17:19, Longpeng (Mike) wrote:

> 
> 
> On 2016/12/7 16:52, Gonglei (Arei) wrote:
> 
>>> -----Original Message-----
>>> From: longpeng
>>> Sent: Wednesday, December 07, 2016 4:34 PM
>>> To: berrange@redhat.com; eblake@redhat.com; armbru@redhat.com;
>>> Gonglei (Arei)
>>> Cc: qemu-devel@nongnu.org; Wubin (H); Zhoujian (jay, Euler); longpeng
>>> Subject: [PATCH for-2.9 1/2] crypto: add 3des-ede support when using
>>> libgcrypt/nettle
>>>
>>> Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
>>> support when using libgcrypt or nettle.
>>>
>>> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
>>> ---
> ......
>>> --- a/qapi/crypto.json
>>> +++ b/qapi/crypto.json
>>> @@ -63,6 +63,7 @@
>>>  # @aes-192: AES with 192 bit / 24 byte keys
>>>  # @aes-256: AES with 256 bit / 32 byte keys
>>>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
>>> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys
>>
>> Missing since 2.9 here.
>>
> 
> Okay, I will add it in V2.
> 
>>>  # @cast5-128: Cast5 with 128 bit / 16 byte keys
>>>  # @serpent-128: Serpent with 128 bit / 16 byte keys
>>>  # @serpent-192: Serpent with 192 bit / 24 byte keys
> ......
>>> +    {
>>> +        /* Borrowed from linux-kernel crypto/testmgr.h */
>>> +        .path = "/crypto/cipher/3des-ede-ecb",
>>> +        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
>>> +        .mode = QCRYPTO_CIPHER_MODE_ECB,
>>> +        .key =
>>> +            "0123456789abcdef5555555555555555"
>>> +            "fedcba9876543210",
>>> +        .plaintext =
>>> +            "736f6d6564617461",
>>> +        .ciphertext =
>>> +            "18d748e563620572",
>>> +    },
>>> +#endif
>>
>> Pls adds the CTR mode test case as well.
>>
> 
> Okay!
> 
> But I confuse with the 3DES's iv length now. I saw that cbc(3des-ede)'s iv-len
> can be 8 or 16 bytes, and ctr(3des-ede)'s iv-len is 24 bytes(according to
> linux-kernel crypto/testmgr.h).
> 

s/24/16

> However, I think qcrypto_cipher_get_iv_len() cannot distinguish a cipher alg
> with more than one iv-len.
> 
> Daniel, do you have any idea ?
> 
>> You'd better split the patch set into two patches so that Denial can take this one.
>> and I can take the patch 2.
>>
> 
> Okay, thanks.
> 
>> Thanks for your work.
>>
>> -Gonglei
>>
>>>      {
>>>          /* RFC 2144, Appendix B.1 */
>>>          .path = "/crypto/cipher/cast5-128",
>>> --
>>> 1.8.3.1
>>>
>>
>>
>> .
>>
> 
>
Daniel P. Berrangé Dec. 7, 2016, 9:37 a.m. UTC | #4
On Wed, Dec 07, 2016 at 04:33:41PM +0800, Longpeng(Mike) wrote:
> Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
> support when using libgcrypt or nettle.
> 
> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
> ---
>  crypto/cipher-gcrypt.c     |  6 ++++++
>  crypto/cipher-nettle.c     | 37 +++++++++++++++++++++++++++++++++++++
>  crypto/cipher.c            |  7 +++++--
>  qapi/crypto.json           |  3 ++-
>  tests/test-crypto-cipher.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 94 insertions(+), 3 deletions(-)
> 
> diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
> index c550db9..5dd0db1 100644
> --- a/crypto/cipher-gcrypt.c
> +++ b/crypto/cipher-gcrypt.c
> @@ -29,6 +29,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
>  {
>      switch (alg) {
>      case QCRYPTO_CIPHER_ALG_DES_RFB:
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> @@ -99,6 +100,10 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          gcryalg = GCRY_CIPHER_DES;
>          break;
>  
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
> +        gcryalg = GCRY_CIPHER_3DES;
> +        break;
> +
>      case QCRYPTO_CIPHER_ALG_AES_128:
>          gcryalg = GCRY_CIPHER_AES128;
>          break;
> @@ -200,6 +205,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          case QCRYPTO_CIPHER_ALG_TWOFISH_256:
>              ctx->blocksize = 16;
>              break;
> +        case QCRYPTO_CIPHER_ALG_3DES_EDE:
>          case QCRYPTO_CIPHER_ALG_CAST5_128:
>              ctx->blocksize = 8;
>              break;
> diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
> index cd094cd..0353b4d 100644
> --- a/crypto/cipher-nettle.c
> +++ b/crypto/cipher-nettle.c
> @@ -78,6 +78,18 @@ static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
>      des_decrypt(ctx, length, dst, src);
>  }
>  
> +static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_encrypt(ctx, length, dst, src);
> +}
> +
> +static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_decrypt(ctx, length, dst, src);
> +}
> +
>  static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
>                                     uint8_t *dst, const uint8_t *src)
>  {
> @@ -140,6 +152,18 @@ static void des_decrypt_wrapper(const void *ctx, size_t length,
>      des_decrypt(ctx, length, dst, src);
>  }
>  
> +static void des3_encrypt_wrapper(const void *ctx, size_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_encrypt(ctx, length, dst, src);
> +}
> +
> +static void des3_decrypt_wrapper(const void *ctx, size_t length,
> +                                uint8_t *dst, const uint8_t *src)
> +{
> +    des3_decrypt(ctx, length, dst, src);
> +}
> +
>  static void cast128_encrypt_wrapper(const void *ctx, size_t length,
>                                      uint8_t *dst, const uint8_t *src)
>  {
> @@ -197,6 +221,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
>  {
>      switch (alg) {
>      case QCRYPTO_CIPHER_ALG_DES_RFB:
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> @@ -270,6 +295,18 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
>          ctx->blocksize = DES_BLOCK_SIZE;
>          break;
>  
> +    case QCRYPTO_CIPHER_ALG_3DES_EDE:
> +        ctx->ctx = g_new0(struct des3_ctx, 1);
> +        des3_set_key(ctx->ctx, key);
> +
> +        ctx->alg_encrypt_native = des3_encrypt_native;
> +        ctx->alg_decrypt_native = des3_decrypt_native;
> +        ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
> +        ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;
> +
> +        ctx->blocksize = DES3_BLOCK_SIZE;
> +        break;
> +
>      case QCRYPTO_CIPHER_ALG_AES_128:
>      case QCRYPTO_CIPHER_ALG_AES_192:
>      case QCRYPTO_CIPHER_ALG_AES_256:
> diff --git a/crypto/cipher.c b/crypto/cipher.c
> index a9bca41..97147b1 100644
> --- a/crypto/cipher.c
> +++ b/crypto/cipher.c
> @@ -28,6 +28,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
>      [QCRYPTO_CIPHER_ALG_AES_192] = 24,
>      [QCRYPTO_CIPHER_ALG_AES_256] = 32,
>      [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
> +    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 24,
>      [QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
> @@ -42,6 +43,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
>      [QCRYPTO_CIPHER_ALG_AES_192] = 16,
>      [QCRYPTO_CIPHER_ALG_AES_256] = 16,
>      [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
> +    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 8,
>      [QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
>      [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
>      [QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
> @@ -107,8 +109,9 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
>      }
>  
>      if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> -        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
> -            error_setg(errp, "XTS mode not compatible with DES-RFB");
> +        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
> +                || alg == QCRYPTO_CIPHER_ALG_3DES_EDE) {
> +            error_setg(errp, "XTS mode not compatible with DES-RFB/3DES-EDE");
>              return false;
>          }
>          if (nkey % 2) {
> diff --git a/qapi/crypto.json b/qapi/crypto.json
> index 5c9d7d4..848b6cd 100644
> --- a/qapi/crypto.json
> +++ b/qapi/crypto.json
> @@ -63,6 +63,7 @@
>  # @aes-192: AES with 192 bit / 24 byte keys
>  # @aes-256: AES with 256 bit / 32 byte keys
>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys

Lets just call this '3des' as 'ede' is can be assumed, eg

    # @3des: 3DES (EDE) with 192 bit / 24 byte keys


Regards,
Daniel
Daniel P. Berrangé Dec. 7, 2016, 9:43 a.m. UTC | #5
On Wed, Dec 07, 2016 at 05:19:38PM +0800, Longpeng (Mike) wrote:
> 
> 
> On 2016/12/7 16:52, Gonglei (Arei) wrote:
> 
> >> -----Original Message-----
> >> From: longpeng
> >> Sent: Wednesday, December 07, 2016 4:34 PM
> >> To: berrange@redhat.com; eblake@redhat.com; armbru@redhat.com;
> >> Gonglei (Arei)
> >> Cc: qemu-devel@nongnu.org; Wubin (H); Zhoujian (jay, Euler); longpeng
> >> Subject: [PATCH for-2.9 1/2] crypto: add 3des-ede support when using
> >> libgcrypt/nettle
> >>
> >> Libgcrypt and nettle support 3des-ede, so this patch add 3des-ede
> >> support when using libgcrypt or nettle.
> >>
> >> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
> >> ---
> ......
> >> --- a/qapi/crypto.json
> >> +++ b/qapi/crypto.json
> >> @@ -63,6 +63,7 @@
> >>  # @aes-192: AES with 192 bit / 24 byte keys
> >>  # @aes-256: AES with 256 bit / 32 byte keys
> >>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
> >> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys
> > 
> > Missing since 2.9 here.
> > 
> 
> Okay, I will add it in V2.
> 
> >>  # @cast5-128: Cast5 with 128 bit / 16 byte keys
> >>  # @serpent-128: Serpent with 128 bit / 16 byte keys
> >>  # @serpent-192: Serpent with 192 bit / 24 byte keys
> ......
> >> +    {
> >> +        /* Borrowed from linux-kernel crypto/testmgr.h */
> >> +        .path = "/crypto/cipher/3des-ede-ecb",
> >> +        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
> >> +        .mode = QCRYPTO_CIPHER_MODE_ECB,
> >> +        .key =
> >> +            "0123456789abcdef5555555555555555"
> >> +            "fedcba9876543210",
> >> +        .plaintext =
> >> +            "736f6d6564617461",
> >> +        .ciphertext =
> >> +            "18d748e563620572",
> >> +    },
> >> +#endif
> > 
> > Pls adds the CTR mode test case as well.
> > 
> 
> Okay!
> 
> But I confuse with the 3DES's iv length now. I saw that cbc(3des-ede)'s iv-len
> can be 8 or 16 bytes, and ctr(3des-ede)'s iv-len is 24 bytes(according to
> linux-kernel crypto/testmgr.h).
> 
> However, I think qcrypto_cipher_get_iv_len() cannot distinguish a cipher alg
> with more than one iv-len.
> 
> Daniel, do you have any idea ?

Both nettle and libgcrypt require that the iv len match the block size of
the cipher, so iv-len for 3des must always be 24


Regards,
Daniel
Longpeng(Mike) Dec. 7, 2016, 9:46 a.m. UTC | #6
Hi Daniel,

On 2016/12/7 17:37, Daniel P. Berrange wrote:

> On Wed, Dec 07, 2016 at 04:33:41PM +0800, Longpeng(Mike) wrote:
......
>> diff --git a/qapi/crypto.json b/qapi/crypto.json
>> index 5c9d7d4..848b6cd 100644
>> --- a/qapi/crypto.json
>> +++ b/qapi/crypto.json
>> @@ -63,6 +63,7 @@
>>  # @aes-192: AES with 192 bit / 24 byte keys
>>  # @aes-256: AES with 256 bit / 32 byte keys
>>  # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
>> +# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys
> 
> Lets just call this '3des' as 'ede' is can be assumed, eg
> 
>     # @3des: 3DES (EDE) with 192 bit / 24 byte keys
> 

Okay, I will fix it in V2, thanks. :)

> 
> Regards,
> Daniel
diff mbox

Patch

diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
index c550db9..5dd0db1 100644
--- a/crypto/cipher-gcrypt.c
+++ b/crypto/cipher-gcrypt.c
@@ -29,6 +29,7 @@  bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
 {
     switch (alg) {
     case QCRYPTO_CIPHER_ALG_DES_RFB:
+    case QCRYPTO_CIPHER_ALG_3DES_EDE:
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
     case QCRYPTO_CIPHER_ALG_AES_256:
@@ -99,6 +100,10 @@  QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
         gcryalg = GCRY_CIPHER_DES;
         break;
 
+    case QCRYPTO_CIPHER_ALG_3DES_EDE:
+        gcryalg = GCRY_CIPHER_3DES;
+        break;
+
     case QCRYPTO_CIPHER_ALG_AES_128:
         gcryalg = GCRY_CIPHER_AES128;
         break;
@@ -200,6 +205,7 @@  QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
         case QCRYPTO_CIPHER_ALG_TWOFISH_256:
             ctx->blocksize = 16;
             break;
+        case QCRYPTO_CIPHER_ALG_3DES_EDE:
         case QCRYPTO_CIPHER_ALG_CAST5_128:
             ctx->blocksize = 8;
             break;
diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
index cd094cd..0353b4d 100644
--- a/crypto/cipher-nettle.c
+++ b/crypto/cipher-nettle.c
@@ -78,6 +78,18 @@  static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
     des_decrypt(ctx, length, dst, src);
 }
 
+static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_encrypt(ctx, length, dst, src);
+}
+
+static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_decrypt(ctx, length, dst, src);
+}
+
 static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
                                    uint8_t *dst, const uint8_t *src)
 {
@@ -140,6 +152,18 @@  static void des_decrypt_wrapper(const void *ctx, size_t length,
     des_decrypt(ctx, length, dst, src);
 }
 
+static void des3_encrypt_wrapper(const void *ctx, size_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_encrypt(ctx, length, dst, src);
+}
+
+static void des3_decrypt_wrapper(const void *ctx, size_t length,
+                                uint8_t *dst, const uint8_t *src)
+{
+    des3_decrypt(ctx, length, dst, src);
+}
+
 static void cast128_encrypt_wrapper(const void *ctx, size_t length,
                                     uint8_t *dst, const uint8_t *src)
 {
@@ -197,6 +221,7 @@  bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
 {
     switch (alg) {
     case QCRYPTO_CIPHER_ALG_DES_RFB:
+    case QCRYPTO_CIPHER_ALG_3DES_EDE:
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
     case QCRYPTO_CIPHER_ALG_AES_256:
@@ -270,6 +295,18 @@  QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
         ctx->blocksize = DES_BLOCK_SIZE;
         break;
 
+    case QCRYPTO_CIPHER_ALG_3DES_EDE:
+        ctx->ctx = g_new0(struct des3_ctx, 1);
+        des3_set_key(ctx->ctx, key);
+
+        ctx->alg_encrypt_native = des3_encrypt_native;
+        ctx->alg_decrypt_native = des3_decrypt_native;
+        ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
+        ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;
+
+        ctx->blocksize = DES3_BLOCK_SIZE;
+        break;
+
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
     case QCRYPTO_CIPHER_ALG_AES_256:
diff --git a/crypto/cipher.c b/crypto/cipher.c
index a9bca41..97147b1 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -28,6 +28,7 @@  static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_192] = 24,
     [QCRYPTO_CIPHER_ALG_AES_256] = 32,
     [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 24,
     [QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
     [QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
@@ -42,6 +43,7 @@  static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_192] = 16,
     [QCRYPTO_CIPHER_ALG_AES_256] = 16,
     [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+    [QCRYPTO_CIPHER_ALG_3DES_EDE] = 8,
     [QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
     [QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
@@ -107,8 +109,9 @@  qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
     }
 
     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
-            error_setg(errp, "XTS mode not compatible with DES-RFB");
+        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
+                || alg == QCRYPTO_CIPHER_ALG_3DES_EDE) {
+            error_setg(errp, "XTS mode not compatible with DES-RFB/3DES-EDE");
             return false;
         }
         if (nkey % 2) {
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 5c9d7d4..848b6cd 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -63,6 +63,7 @@ 
 # @aes-192: AES with 192 bit / 24 byte keys
 # @aes-256: AES with 256 bit / 32 byte keys
 # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
+# @3des-ede: 3DES-EDE with 192 bit / 24 byte keys
 # @cast5-128: Cast5 with 128 bit / 16 byte keys
 # @serpent-128: Serpent with 128 bit / 16 byte keys
 # @serpent-192: Serpent with 192 bit / 24 byte keys
@@ -75,7 +76,7 @@ 
 { 'enum': 'QCryptoCipherAlgorithm',
   'prefix': 'QCRYPTO_CIPHER_ALG',
   'data': ['aes-128', 'aes-192', 'aes-256',
-           'des-rfb',
+           'des-rfb', '3des-ede',
            'cast5-128',
            'serpent-128', 'serpent-192', 'serpent-256',
            'twofish-128', 'twofish-192', 'twofish-256']}
diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c
index 5d9e535..8874b61 100644
--- a/tests/test-crypto-cipher.c
+++ b/tests/test-crypto-cipher.c
@@ -165,6 +165,50 @@  static QCryptoCipherTestData test_data[] = {
             "ffd29f1bb5596ad94ea2d8e6196b7f09"
             "30d8ed0bf2773af36dd82a6280c20926",
     },
+#if defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT)
+    {
+        /* Borrowed from linux-kernel crypto/testmgr.h */
+        .path = "/crypto/cipher/3des-ede-cbc",
+        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
+        .mode = QCRYPTO_CIPHER_MODE_CBC,
+        .key =
+            "e9c0ff2e760b6424444d995a12d640c0"
+            "eac284e81495dbe8",
+        .iv =
+            "7d3388930f93b242",
+        .plaintext =
+            "6f54206f614d796e5320636565727374"
+            "54206f6f4d206e612079655372637465"
+            "20736f54206f614d796e532063656572"
+            "737454206f6f4d206e61207965537263"
+            "746520736f54206f614d796e53206365"
+            "6572737454206f6f4d206e6120796553"
+            "7263746520736f54206f614d796e5320"
+            "63656572737454206f6f4d206e610a79",
+        .ciphertext =
+            "0e2db6973c5633f4671721c76e8ad549"
+            "74b34905c51cd0ed12565c5396b6007d"
+            "9048fcf58d2939cc8ad5351836234ed7"
+            "76d1da0c9467bb048bf2036ca8cfb6ea"
+            "226447aa8f7513bf9fc2c3f0c956c57a"
+            "71632e897b1e12cae25fafd8a4f8c97a"
+            "d6f92131624445a6d6bc5ad32d5443cc"
+            "9ddea570e942458a6bfab19113b0d919",
+    },
+    {
+        /* Borrowed from linux-kernel crypto/testmgr.h */
+        .path = "/crypto/cipher/3des-ede-ecb",
+        .alg = QCRYPTO_CIPHER_ALG_3DES_EDE,
+        .mode = QCRYPTO_CIPHER_MODE_ECB,
+        .key =
+            "0123456789abcdef5555555555555555"
+            "fedcba9876543210",
+        .plaintext =
+            "736f6d6564617461",
+        .ciphertext =
+            "18d748e563620572",
+    },
+#endif
     {
         /* RFC 2144, Appendix B.1 */
         .path = "/crypto/cipher/cast5-128",