kdf_sp800108.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SP800-108 Key-derivation function
  4. *
  5. * Copyright (C) 2021, Stephan Mueller <[email protected]>
  6. */
  7. #include <linux/fips.h>
  8. #include <linux/module.h>
  9. #include <crypto/kdf_sp800108.h>
  10. #include <crypto/internal/kdf_selftest.h>
  11. /*
  12. * SP800-108 CTR KDF implementation
  13. */
  14. int crypto_kdf108_ctr_generate(struct crypto_shash *kmd,
  15. const struct kvec *info, unsigned int info_nvec,
  16. u8 *dst, unsigned int dlen)
  17. {
  18. SHASH_DESC_ON_STACK(desc, kmd);
  19. __be32 counter = cpu_to_be32(1);
  20. const unsigned int h = crypto_shash_digestsize(kmd), dlen_orig = dlen;
  21. unsigned int i;
  22. int err = 0;
  23. u8 *dst_orig = dst;
  24. desc->tfm = kmd;
  25. while (dlen) {
  26. err = crypto_shash_init(desc);
  27. if (err)
  28. goto out;
  29. err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32));
  30. if (err)
  31. goto out;
  32. for (i = 0; i < info_nvec; i++) {
  33. err = crypto_shash_update(desc, info[i].iov_base,
  34. info[i].iov_len);
  35. if (err)
  36. goto out;
  37. }
  38. if (dlen < h) {
  39. u8 tmpbuffer[HASH_MAX_DIGESTSIZE];
  40. err = crypto_shash_final(desc, tmpbuffer);
  41. if (err)
  42. goto out;
  43. memcpy(dst, tmpbuffer, dlen);
  44. memzero_explicit(tmpbuffer, h);
  45. goto out;
  46. }
  47. err = crypto_shash_final(desc, dst);
  48. if (err)
  49. goto out;
  50. dlen -= h;
  51. dst += h;
  52. counter = cpu_to_be32(be32_to_cpu(counter) + 1);
  53. }
  54. out:
  55. if (err)
  56. memzero_explicit(dst_orig, dlen_orig);
  57. shash_desc_zero(desc);
  58. return err;
  59. }
  60. EXPORT_SYMBOL(crypto_kdf108_ctr_generate);
  61. /*
  62. * The seeding of the KDF
  63. */
  64. int crypto_kdf108_setkey(struct crypto_shash *kmd,
  65. const u8 *key, size_t keylen,
  66. const u8 *ikm, size_t ikmlen)
  67. {
  68. unsigned int ds = crypto_shash_digestsize(kmd);
  69. /* SP800-108 does not support IKM */
  70. if (ikm || ikmlen)
  71. return -EINVAL;
  72. /* Check according to SP800-108 section 7.2 */
  73. if (ds > keylen)
  74. return -EINVAL;
  75. /* Set the key for the MAC used for the KDF. */
  76. return crypto_shash_setkey(kmd, key, keylen);
  77. }
  78. EXPORT_SYMBOL(crypto_kdf108_setkey);
  79. /*
  80. * Test vector obtained from
  81. * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/CounterMode.zip
  82. */
  83. static const struct kdf_testvec kdf_ctr_hmac_sha256_tv_template[] = {
  84. {
  85. .key = "\xdd\x1d\x91\xb7\xd9\x0b\x2b\xd3"
  86. "\x13\x85\x33\xce\x92\xb2\x72\xfb"
  87. "\xf8\xa3\x69\x31\x6a\xef\xe2\x42"
  88. "\xe6\x59\xcc\x0a\xe2\x38\xaf\xe0",
  89. .keylen = 32,
  90. .ikm = NULL,
  91. .ikmlen = 0,
  92. .info = {
  93. .iov_base = "\x01\x32\x2b\x96\xb3\x0a\xcd\x19"
  94. "\x79\x79\x44\x4e\x46\x8e\x1c\x5c"
  95. "\x68\x59\xbf\x1b\x1c\xf9\x51\xb7"
  96. "\xe7\x25\x30\x3e\x23\x7e\x46\xb8"
  97. "\x64\xa1\x45\xfa\xb2\x5e\x51\x7b"
  98. "\x08\xf8\x68\x3d\x03\x15\xbb\x29"
  99. "\x11\xd8\x0a\x0e\x8a\xba\x17\xf3"
  100. "\xb4\x13\xfa\xac",
  101. .iov_len = 60
  102. },
  103. .expected = "\x10\x62\x13\x42\xbf\xb0\xfd\x40"
  104. "\x04\x6c\x0e\x29\xf2\xcf\xdb\xf0",
  105. .expectedlen = 16
  106. }
  107. };
  108. static int __init crypto_kdf108_init(void)
  109. {
  110. int ret;
  111. if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))
  112. return 0;
  113. ret = kdf_test(&kdf_ctr_hmac_sha256_tv_template[0], "hmac(sha256)",
  114. crypto_kdf108_setkey, crypto_kdf108_ctr_generate);
  115. if (ret) {
  116. if (fips_enabled)
  117. panic("alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
  118. ret);
  119. WARN(1,
  120. "alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
  121. ret);
  122. } else if (fips_enabled) {
  123. pr_info("alg: self-tests for CTR-KDF (hmac(sha256)) passed\n");
  124. }
  125. return ret;
  126. }
  127. static void __exit crypto_kdf108_exit(void) { }
  128. module_init(crypto_kdf108_init);
  129. module_exit(crypto_kdf108_exit);
  130. MODULE_LICENSE("GPL v2");
  131. MODULE_AUTHOR("Stephan Mueller <[email protected]>");
  132. MODULE_DESCRIPTION("Key Derivation Function conformant to SP800-108");