Mailing List Archive

Disable Weak cipher check for DES KCV
Hi,

We have a problem here where I need to encrypt a block of data with zeros.

<>
gcry_check_version (NULL);
unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char out[8];
unsigned char data[8];
gcry_error_t err = 0;
gcry_cipher_hd_t hd = nullptr;
err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
//auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES);
//auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES);
err = gcry_cipher_setkey (hd, key, sizeof(key));
std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl;
std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl;
gcry_cipher_encrypt(hd, out, sizeof(key), data, 8);
if (err) {
std::cerr << "Failed to perform cryptography" << std::endl;
std::cerr << " cipher: " << static_cast<int>(GCRY_CIPHER_DES) << std::endl;
std::cerr << " mode: " << static_cast<int>(GCRY_CIPHER_MODE_ECB) << std::endl;
//std::cerr << " keyBlock: " << BinToHex<std::string>(key) << std::endl;
//std::cerr << " out: " << BinToHex<std::string>(out) << std::endl;
//std::cerr << " data: " << BinToHex<std::string>(encryptedData) << std::endl;
}
</>

This blows on:

gpg_err_code: 43
gpg_strerror: Weak encryption key
cipher_encrypt: key not set

Tracked back t in a source to libcrypt / cipher / des.c

r. 1384 do_des_setkey
r. 1021 is_weak_key

if (is_weak_key (key)) {
_gcry_burn_stack (64);
return GPG_ERR_WEAK_KEY;
}

cipher.c
r.797

rc = c->spec->setkey (&c->context.c, key, keylen, c);
if (!rc) {

} else
c->marks.key = 0;

... then disallows weak key setting completely, resulting in a failure.

This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV.

May I propose a patch? (See in attachment).

Thanks & Cheers,
Jan
Re: Disable Weak cipher check for DES KCV [ In reply to ]
Hello,

On 21.12.2019 3.40, Jan Bilek wrote:
> Hi,
>
> We have a problem here where I need to encrypt a block of data with zeros.
>
> <>
>   gcry_check_version (NULL);
>   unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
>   unsigned char out[8];
>   unsigned char data[8];
>   gcry_error_t err = 0;
>   gcry_cipher_hd_t hd = nullptr;
>   err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
>   //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES);
>   //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES);
>   err = gcry_cipher_setkey (hd, key, sizeof(key));
>   std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl;
>   std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl;
>   gcry_cipher_encrypt(hd, out, sizeof(key), data, 8);
>   if (err) {
>     std::cerr << "Failed to perform cryptography" << std::endl;
>     std::cerr << "  cipher:     " << static_cast<int>(GCRY_CIPHER_DES) << std::endl;
>     std::cerr << "  mode:       " << static_cast<int>(GCRY_CIPHER_MODE_ECB) << std::endl;
>     //std::cerr << "  keyBlock:   " << BinToHex<std::string>(key) << std::endl;
>     //std::cerr << "  out:        " << BinToHex<std::string>(out) << std::endl;
>     //std::cerr << "  data:       " << BinToHex<std::string>(encryptedData) << std::endl;
>   }
> </>
>
> This blows on:
>
> gpg_err_code: 43
> gpg_strerror: Weak encryption key
> cipher_encrypt: key not set
>
> Tracked back t in a source to libcrypt / cipher / des.c
>
> r. 1384 do_des_setkey
> r. 1021 is_weak_key
>
>   if (is_weak_key (key)) {
>     _gcry_burn_stack (64);
>     return GPG_ERR_WEAK_KEY;
>   }
>
> cipher.c
> r.797 
>
>  rc = c->spec->setkey (&c->context.c, key, keylen, c);
>   if (!rc) {
>
>   } else
>     c->marks.key = 0;
>  
> ... then disallows weak key setting completely, resulting in a failure.
>
> This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV.

I tried to find KCV specification where zero key is used to encrypt actual key as input block for KCV value, but all KCV algorithms I managed to find encrypt zero input block with the actual key as key. Can you check your documentation for KCV if zero key is really used and give pointer/link to that spec for us?

-Jussi

>
> May I propose a patch? (See in attachment).
>
> Thanks & Cheers,
> Jan
>
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel@gnupg.org
> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
>


_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
RE: Disable Weak cipher check for DES KCV [ In reply to ]
Ping?


On 2019-12-21 11:40:06+10:00 Jan Bilek wrote:

Hi,

We have a problem here where I need to encrypt a block of data with zeros.

<>
gcry_check_version (NULL);
unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char out[8];
unsigned char data[8];
gcry_error_t err = 0;
gcry_cipher_hd_t hd = nullptr;
err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
//auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES);
//auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES);
err = gcry_cipher_setkey (hd, key, sizeof(key));
std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl;
std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl;
gcry_cipher_encrypt(hd, out, sizeof(key), data, 8);
if (err) {
std::cerr << "Failed to perform cryptography" << std::endl;
std::cerr << " cipher: " << static_cast<int>(GCRY_CIPHER_DES) << std::endl;
std::cerr << " mode: " << static_cast<int>(GCRY_CIPHER_MODE_ECB) << std::endl;
//std::cerr << " keyBlock: " << BinToHex<std::string>(key) << std::endl;
//std::cerr << " out: " << BinToHex<std::string>(out) << std::endl;
//std::cerr << " data: " << BinToHex<std::string>(encryptedData) << std::endl;
}
</>

This blows on:

gpg_err_code: 43
gpg_strerror: Weak encryption key
cipher_encrypt: key not set

Tracked back t in a source to libcrypt / cipher / des.c

r. 1384 do_des_setkey
r. 1021 is_weak_key

if (is_weak_key (key)) {
_gcry_burn_stack (64);
return GPG_ERR_WEAK_KEY;
}

cipher.c
r.797

rc = c->spec->setkey (&c->context.c, key, keylen, c);
if (!rc) {

} else
c->marks.key = 0;

... then disallows weak key setting completely, resulting in a failure.

This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV.

May I propose a patch? (See in attachment).

Thanks & Cheers,
Jan
Re: Disable Weak cipher check for DES KCV [ In reply to ]
Hello,

Apparently my first reply went only to the mailing list.

There I wrote: "I tried to find KCV specification where zero key is used to encrypt actual key as input block for KCV value, but all KCV algorithms I managed to find encrypt zero input block with the actual key as key. Can you check your documentation for KCV if zero key is really used and give pointer/link to that spec for us?"

-Jussi

On 4.1.2020 12.33, Jan Bilek wrote:
> Ping?
>  
>
> On 2019-12-21 11:40:06+10:00 Jan Bilek wrote:
>
> Hi,
>
> We have a problem here where I need to encrypt a block of data with zeros.
>
> <>
>   gcry_check_version (NULL);
>   unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
>   unsigned char out[8];
>   unsigned char data[8];
>   gcry_error_t err = 0;
>   gcry_cipher_hd_t hd = nullptr;
>   err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
>   //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES);
>   //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES);
>   err = gcry_cipher_setkey (hd, key, sizeof(key));
>   std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl;
>   std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl;
>   gcry_cipher_encrypt(hd, out, sizeof(key), data, 8);
>   if (err) {
>     std::cerr << "Failed to perform cryptography" << std::endl;
>     std::cerr << "  cipher:     " << static_cast<int>(GCRY_CIPHER_DES) << std::endl;
>     std::cerr << "  mode:       " << static_cast<int>(GCRY_CIPHER_MODE_ECB) << std::endl;
>     //std::cerr << "  keyBlock:   " << BinToHex<std::string>(key) << std::endl;
>     //std::cerr << "  out:        " << BinToHex<std::string>(out) << std::endl;
>     //std::cerr << "  data:       " << BinToHex<std::string>(encryptedData) << std::endl;
>   }
> </>
>
> This blows on:
>
> gpg_err_code: 43
> gpg_strerror: Weak encryption key
> cipher_encrypt: key not set
>
> Tracked back t in a source to libcrypt / cipher / des.c
>
> r. 1384 do_des_setkey
> r. 1021 is_weak_key
>
>   if (is_weak_key (key)) {
>     _gcry_burn_stack (64);
>     return GPG_ERR_WEAK_KEY;
>   }
>
> cipher.c
> r.797 
>
>  rc = c->spec->setkey (&c->context.c, key, keylen, c);
>   if (!rc) {
>
>   } else
>     c->marks.key = 0;
>  
> ... then disallows weak key setting completely, resulting in a failure.
>
> This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV.
>
> May I propose a patch? (See in attachment).
>
> Thanks & Cheers,
> Jan
>
>
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel@gnupg.org
> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
>


_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
RE: Disable Weak cipher check for DES KCV [ In reply to ]
Hi Jussi,

No problem and thanks for coming back on my email.

You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated).

Hope it makes better sense now.

Cheers,
Jan

On 2020-01-06 00:36:19+10:00 Jussi Kivilinna wrote:


Hello,

Apparently my first reply went only to the mailing list.

There I wrote: "I tried to find KCV specification where zero key is used to encrypt actual key as input block for KCV value, but all KCV algorithms I managed to find encrypt zero input block with the actual key as key. Can you check your documentation for KCV if zero key is really used and give pointer/link to that spec for us?"

-Jussi

On 4.1.2020 12.33, Jan Bilek wrote:
&amp;gt; Ping?
&amp;gt; &amp;nbsp;
&amp;gt;
&amp;gt; On 2019-12-21 11:40:06+10:00 Jan Bilek wrote:
&amp;gt;
&amp;gt; Hi,
&amp;gt;
&amp;gt; We have a problem here where I need to encrypt a block of data with zeros.
&amp;gt;
&amp;gt; &amp;lt;&amp;gt;
&amp;gt; &amp;nbsp;&amp;nbsp;gcry_check_version (NULL);
&amp;gt; &amp;nbsp; unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
&amp;gt; &amp;nbsp; unsigned char out[8];
&amp;gt; &amp;nbsp; unsigned char data[8];
&amp;gt; &amp;nbsp; gcry_error_t err = 0;
&amp;gt; &amp;nbsp; gcry_cipher_hd_t hd = nullptr;
&amp;gt; &amp;nbsp; err = gcry_cipher_open(&amp;amp;hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
&amp;gt; &amp;nbsp; //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES);
&amp;gt; &amp;nbsp; //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES);
&amp;gt; &amp;nbsp; err = gcry_cipher_setkey (hd, key, sizeof(key));
&amp;gt; &amp;nbsp; std::cerr &amp;lt;&amp;lt; "gpg_err_code: " &amp;lt;&amp;lt; gpg_err_code(err) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; std::cerr &amp;lt;&amp;lt; "gpg_strerror: " &amp;lt;&amp;lt; gpg_strerror(err) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; gcry_cipher_encrypt(hd, out, sizeof(key), data, 8);
&amp;gt; &amp;nbsp; if (err) {
&amp;gt; &amp;nbsp; &amp;nbsp; std::cerr &amp;lt;&amp;lt; "Failed to perform cryptography" &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; &amp;nbsp; std::cerr &amp;lt;&amp;lt; " &amp;nbsp;cipher: &amp;nbsp; &amp;nbsp; " &amp;lt;&amp;lt; static_cast&lt;int&gt;(GCRY_CIPHER_DES) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; &amp;nbsp; std::cerr &amp;lt;&amp;lt; " &amp;nbsp;mode: &amp;nbsp; &amp;nbsp; &amp;nbsp; " &amp;lt;&amp;lt; static_cast&lt;int&gt;(GCRY_CIPHER_MODE_ECB) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; &amp;nbsp; //std::cerr &amp;lt;&amp;lt; " &amp;nbsp;keyBlock: &amp;nbsp; " &amp;lt;&amp;lt; BinToHex&lt;std::string&gt;(key) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; &amp;nbsp; //std::cerr &amp;lt;&amp;lt; " &amp;nbsp;out: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;" &amp;lt;&amp;lt; BinToHex&lt;std::string&gt;(out) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; &amp;nbsp; //std::cerr &amp;lt;&amp;lt; " &amp;nbsp;data: &amp;nbsp; &amp;nbsp; &amp;nbsp; " &amp;lt;&amp;lt; BinToHex&lt;std::string&gt;(encryptedData) &amp;lt;&amp;lt; std::endl;
&amp;gt; &amp;nbsp; }
&amp;gt;
&amp;gt;
&amp;gt; This blows on:
&amp;gt;
&amp;gt; gpg_err_code: 43
&amp;gt; gpg_strerror: Weak encryption key
&amp;gt; cipher_encrypt: key not set
&amp;gt;
&amp;gt; Tracked back t&amp;nbsp;in a source&amp;nbsp;to libcrypt / cipher / des.c
&amp;gt;
&amp;gt; r. 1384&amp;nbsp;do_des_setkey
&amp;gt; r. 1021 is_weak_key
&amp;gt;
&amp;gt; &amp;nbsp;&amp;nbsp;if (is_weak_key (key)) {
&amp;gt; &amp;nbsp; &amp;nbsp; _gcry_burn_stack (64);
&amp;gt; &amp;nbsp; &amp;nbsp; return GPG_ERR_WEAK_KEY;
&amp;gt; &amp;nbsp; }
&amp;gt;
&amp;gt; cipher.c
&amp;gt; r.797&amp;nbsp;
&amp;gt;
&amp;gt; &amp;nbsp;rc = c-&amp;gt;spec-&amp;gt;setkey (&amp;amp;c-&amp;gt;context.c, key, keylen, c);
&amp;gt; &amp;nbsp; if (!rc) {
&amp;gt;
&amp;gt; &amp;nbsp;&amp;nbsp;} else
&amp;gt; &amp;nbsp; &amp;nbsp; c-&amp;gt;marks.key = 0;
&amp;gt; &amp;nbsp;
&amp;gt; ... then disallows weak key setting completely, resulting in a failure.
&amp;gt;
&amp;gt; This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV.
&amp;gt;
&amp;gt; May I propose a patch? (See in attachment).
&amp;gt;
&amp;gt; Thanks &amp;amp; Cheers,
&amp;gt; Jan
&amp;gt;
&amp;gt;
&amp;gt; _______________________________________________
&amp;gt; Gcrypt-devel mailing list
&amp;gt; Gcrypt-devel@gnupg.org
&amp;gt; http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
&amp;gt;

&lt;/std::string&gt;&lt;/std::string&gt;&lt;/std::string&gt;&lt;/int&gt;&lt;/int&gt;
Re: Disable Weak cipher check for DES KCV [ In reply to ]
Hello,

On 9.1.2020 3.57, Jan Bilek wrote:
> Hi Jussi,
>
> No problem and thanks for coming back on my email.
>
> You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated).
>
> Hope it makes better sense now.

Ok. I guess for such testing use-case, we could add new gcry_cipher_ctl command to allow weak-keys on cipher object. After command is given to cipher object, setkey would still return weak-key error code, but otherwise setup algorithm for encryption/decryption. Usage would be like this:

err = gcry_cipher_open(&handle, algo, mode, 0)
assert(err == 0)
err = gcry_cipher_ctl(handle, GCRYCTL_ALLOW_WEAK_KEY, NULL, 1)
assert(err == 0)
err = gcry_cipher_setkey(handle, weak_key_buf, weak_key_len)
assert(err == GPG_ERR_WEAK_KEY)
err = gcry_cipher_encrypt(handle, out, outlen, in, inlen)
assert(err == 0)
err = gcry_cipher_close(handle)
assert(err == 0)

-Jussi

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
RE: Disable Weak cipher check for DES KCV [ In reply to ]
I love it! Let me know if we can support this somehow from our side.

BR,
Jan


On 2020-01-23 07:09:02+10:00 Jussi Kivilinna wrote:

Hello,

On 9.1.2020 3.57, Jan Bilek wrote:
&amp;gt; Hi Jussi,
&amp;gt;
&amp;gt; No problem and thanks for coming back on my email.
&amp;gt;
&amp;gt; You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated).
&amp;gt;
&amp;gt; Hope it makes better sense now.

Ok. I guess for such testing use-case, we could add new gcry_cipher_ctl command to allow weak-keys on cipher object. After command is given to cipher object, setkey would still return weak-key error code, but otherwise setup algorithm for encryption/decryption. Usage would be like this:

err = gcry_cipher_open(&amp;amp;handle, algo, mode, 0)
assert(err == 0)
err = gcry_cipher_ctl(handle, GCRYCTL_ALLOW_WEAK_KEY, NULL, 1)
assert(err == 0)
err = gcry_cipher_setkey(handle, weak_key_buf, weak_key_len)
assert(err == GPG_ERR_WEAK_KEY)
err = gcry_cipher_encrypt(handle, out, outlen, in, inlen)
assert(err == 0)
err = gcry_cipher_close(handle)
assert(err == 0)

-Jussi