digsig_asymmetric.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright (C) 2013 Intel Corporation
  3. *
  4. * Author:
  5. * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, version 2 of the License.
  10. *
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/err.h>
  14. #include <linux/ratelimit.h>
  15. #include <linux/key-type.h>
  16. #include <crypto/public_key.h>
  17. #include <crypto/hash_info.h>
  18. #include <keys/asymmetric-type.h>
  19. #include <keys/system_keyring.h>
  20. #include "integrity.h"
  21. /*
  22. * Request an asymmetric key.
  23. */
  24. static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
  25. {
  26. struct key *key;
  27. char name[12];
  28. sprintf(name, "id:%08x", keyid);
  29. pr_debug("key search: \"%s\"\n", name);
  30. key = get_ima_blacklist_keyring();
  31. if (key) {
  32. key_ref_t kref;
  33. kref = keyring_search(make_key_ref(key, 1),
  34. &key_type_asymmetric, name);
  35. if (!IS_ERR(kref)) {
  36. pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
  37. return ERR_PTR(-EKEYREJECTED);
  38. }
  39. }
  40. if (keyring) {
  41. /* search in specific keyring */
  42. key_ref_t kref;
  43. kref = keyring_search(make_key_ref(keyring, 1),
  44. &key_type_asymmetric, name);
  45. if (IS_ERR(kref))
  46. key = ERR_CAST(kref);
  47. else
  48. key = key_ref_to_ptr(kref);
  49. } else {
  50. key = request_key(&key_type_asymmetric, name, NULL);
  51. }
  52. if (IS_ERR(key)) {
  53. pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
  54. name, PTR_ERR(key));
  55. switch (PTR_ERR(key)) {
  56. /* Hide some search errors */
  57. case -EACCES:
  58. case -ENOTDIR:
  59. case -EAGAIN:
  60. return ERR_PTR(-ENOKEY);
  61. default:
  62. return key;
  63. }
  64. }
  65. pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
  66. return key;
  67. }
  68. int asymmetric_verify(struct key *keyring, const char *sig,
  69. int siglen, const char *data, int datalen)
  70. {
  71. struct public_key_signature pks;
  72. struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
  73. struct key *key;
  74. int ret = -ENOMEM;
  75. if (siglen <= sizeof(*hdr))
  76. return -EBADMSG;
  77. siglen -= sizeof(*hdr);
  78. if (siglen != be16_to_cpu(hdr->sig_size))
  79. return -EBADMSG;
  80. if (hdr->hash_algo >= HASH_ALGO__LAST)
  81. return -ENOPKG;
  82. key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
  83. if (IS_ERR(key))
  84. return PTR_ERR(key);
  85. memset(&pks, 0, sizeof(pks));
  86. pks.pkey_algo = "rsa";
  87. pks.hash_algo = hash_algo_name[hdr->hash_algo];
  88. pks.encoding = "pkcs1";
  89. pks.digest = (u8 *)data;
  90. pks.digest_size = datalen;
  91. pks.s = hdr->sig;
  92. pks.s_size = siglen;
  93. ret = verify_signature(key, &pks);
  94. key_put(key);
  95. pr_debug("%s() = %d\n", __func__, ret);
  96. return ret;
  97. }
  98. /**
  99. * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
  100. * @kmod_name: kernel module name
  101. *
  102. * We have situation, when public_key_verify_signature() in case of RSA
  103. * algorithm use alg_name to store internal information in order to
  104. * construct an algorithm on the fly, but crypto_larval_lookup() will try
  105. * to use alg_name in order to load kernel module with same name.
  106. * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
  107. * we are safe to fail such module request from crypto_larval_lookup().
  108. *
  109. * In this way we prevent modprobe execution during digsig verification
  110. * and avoid possible deadlock if modprobe and/or it's dependencies
  111. * also signed with digsig.
  112. */
  113. int integrity_kernel_module_request(char *kmod_name)
  114. {
  115. if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
  116. return -EINVAL;
  117. return 0;
  118. }