【问题标题】:CCM-AES from Linux Kernel来自 Linux 内核的 CCM-AES
【发布时间】:2012-10-28 09:50:36
【问题描述】:

我需要兼容 Solaris 加密机 SUN_CKM_AES_CCM。在 Linux 中,我相信我应该设置一个 AEAD 请求来获取“ccm(aes)”机械。 Linux Crypto 的文档看起来确实很差,最好的例子似乎是 tcrypt.c 测试和内核源代码。

在 Solaris 中,我使用 16 字节 hmac 和 12 字节 iv 对 512 字节块进行了测试加密。这需要保持不变,并希望结果是相同的。

然而,我认为应该行得通,却行不通;

   struct crypto_aead *tfm = NULL;
   struct aead_request *req;
   unsigned char key[16] = {
    0x5c, 0x95, 0x64, 0x42, 0x00, 0x82, 0x1c, 0x9e,
    0xd4, 0xac, 0x01, 0x83, 0xc4, 0x9c, 0x14, 0x97
   };
  unsigned int ivsize;
  int ret;
  struct scatterlist plaintext[1];
  struct scatterlist ciphertext[1];
  struct scatterlist hmactext[1];
  unsigned char *plaindata = NULL;
  unsigned char *cipherdata = NULL;
  unsigned char *hmacdata = NULL;
  unsigned char *ivp = NULL;
  int i;
  unsigned char d;
  struct tcrypt_result result;

  tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
  init_completion(&result.completion);
  req = aead_request_alloc(tfm, GFP_KERNEL);
  aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                          cipher_work_done, &result);

  crypto_aead_clear_flags(tfm, ~0);

  ret = crypto_aead_setkey(tfm, key, sizeof(key));

  ret = crypto_aead_setauthsize(tfm, 16); // authsize is hmac?

  ivsize = crypto_aead_ivsize(tfm);
  if (ivsize != 12) {
    printk("ivsize is not 12 %d - this needs to be fixed\n", ivsize);
  }

  plaindata  = kmalloc(512, GFP_KERNEL);
  cipherdata = kmalloc(512, GFP_KERNEL);
  hmacdata   = kmalloc(16, GFP_KERNEL);
  ivp        = kmalloc(ivsize, GFP_KERNEL);

  if (!plaindata || !cipherdata || !hmacdata || !ivp) goto out;

  // put 00 01 02 03 ... in the input buffer...
  for (i = 0, d = 0; i < 512; i++, d++)
    plaindata[i] = d;

  memset(cipherdata, 0, 512);
  memset(hmacdata, 0, 16);
  memset(ivp, 0, ivsize);

  // Put a8 a9 aa .... in iv
  for (i = 0,d=0xa8; i < 12; i++, d++)
    ivp[i] = d;

  sg_init_one(&plaintext[0],  plaindata,  512);
  sg_init_one(&ciphertext[0], cipherdata, 512);
  sg_init_one(&hmactext[0],   hmacdata,   16);

  aead_request_set_crypt(req, plaintext, ciphertext, 512, ivp);

  aead_request_set_assoc(req, hmactext, 16);

  ret = crypto_aead_encrypt(req);

  printk("cipher call returns %d \n", ret);

我们得到的结果是 ivsize 为 16(我认为无法将其设置为 12),并且加密失败并显示“-22”或 EINVAL。代码中有很多错误检查,在这里删除,确认所有之前的调用返回成功。

据我所知,我非常接近 tcrypt.c 来源。但是,我想知道强制ivsize = 16 是否意味着我无论如何都不能使用提供的算法。除此之外,很高兴看到加密调用成功以及密码数据输出中的内容。

代码被放入内核模块,并在 _init() 时间运行。最初我使用 blkcipher “aes”,它有效,但不是 ccm-aes 变体。这让我改用aead,但我无法开始工作。

【问题讨论】:

  • 那么,它适用于 16 字节 IV 吗?可能他们对这种 IV 大小进行了硬编码。此外,还有两种 AEAD 密码模式 - AEAD-CCM 和 AEAD-GCM。
  • CCM 不包括 HMAC,您是说 Solaris 正在使用 HMAC。是哪一个?
  • 代码看到 iv 是 16,但继续前进。然后以 -22 (EINVAL) 失败,我不确定为什么代码不起作用,因为它与 tcrypt.c 相同(嗯,我可以看到) Solaris 代码肯定会得到一个 16 字节的 HMAC,sha256 从什么我可以说,所以我需要做同样的事情。也许我应该考虑通过调用常规 blkcipher aes + 魔术来做我自己的 CCM-AES。这可行吗?
  • 好的,EINVAL 是由于static inline int crypto_ccm_check_iv(const u8 *iv) 造成的,这确保了我的 iv 的第一个字节在 1 到 7 之间。这是一个真正的要求吗?现在它“失败”并返回代码“0”,并且输出缓冲区被修改。这不正确,但向前迈进了一步。

标签: c linux cryptography kernel aes


【解决方案1】:

好的,这就是我学到的。

1) 让我们调用应用程序的 iv nonce。让我们调用内部加密的 iv iv。原来Solaris代码使用的是nonce-len=12,但是CCM-AES算法还是使用iv-len=16

来自 Solaris 内核源代码,iv 由:

iv[0] = 1..7, based on ivlen 16 - noncelen 12 = 2.
iv[1] = the nonce data (12 bytes).
iv[14] = 0
iv[15] = 1

所以,在 Linux 上,我想要 ivlen 16 的“ccm(aes)”,并正确准备来自 nonceiv

2) 当调用crypto_aead_encrypt() 时,先前的aead_request_set_assoc() 调用被忽略,HMAC 被放在密码缓冲区的末尾。就我而言,在密文 [512] 处,16 个字节。所以输入的长度必须是 +16。

使用 scatterlist,如果设置正确,“最后”的 HMAC 可能会有所不同。

3) 当调用crypto_aead_decrypt() 时,cryptolen 应该是 +16 (cipherinputlen + maclen)。 MAC 从输入缓冲区的末尾读取,即 16 字节的密文[512]。也可以是使用 scatterlist 的单独缓冲区。

4) crypto_aead_setauthsize() 检查给定的 len 是否正确,然后什么也不做。不要认为这实际上设置了大小!

5) aead_request_set_assoc() 必须设置,即使它只是一个零缓冲区。

【讨论】:

  • 感谢您的反馈。 CCM 的 IV 问题和 AEAD 数据的笨拙处理足以让我推荐 GCM 模式而不是 CCM。 CCM 在密码学上没有任何问题(据我所知),但协议没有经过深思熟虑。
  • 这是整个 Internet 上唯一解释 aead 函数集参数的文档。
  • 如果对其他人有帮助,这里是完整的来源; github.com/zfsrogue/spl-crypto/blob/master/module/spl/… 您可以忽略 Solaris 将 UIO 映射到 Linux scatterlist 等。另外,没有使用 COPY_DST,我做了自己的“gcm”和“ccm”模块版本,修复了 Linux 内核中的恐慌。默认的仍然可以恐慌。
猜你喜欢
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多