dm-verity-verify-sig.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2019 Microsoft Corporation.
  4. *
  5. * Author: Jaskaran Singh Khurana <jaskarankhurana@linux.microsoft.com>
  6. *
  7. */
  8. #include <linux/device-mapper.h>
  9. #include <linux/verification.h>
  10. #include <keys/user-type.h>
  11. #include <linux/module.h>
  12. #include "dm-verity.h"
  13. #include "dm-verity-verify-sig.h"
  14. #define DM_VERITY_VERIFY_ERR(s) DM_VERITY_ROOT_HASH_VERIFICATION " " s
  15. static bool require_signatures;
  16. module_param(require_signatures, bool, 0444);
  17. MODULE_PARM_DESC(require_signatures,
  18. "Verify the roothash of dm-verity hash tree");
  19. #define DM_VERITY_IS_SIG_FORCE_ENABLED() \
  20. (require_signatures != false)
  21. bool verity_verify_is_sig_opt_arg(const char *arg_name)
  22. {
  23. return (!strcasecmp(arg_name,
  24. DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY));
  25. }
  26. static int verity_verify_get_sig_from_key(const char *key_desc,
  27. struct dm_verity_sig_opts *sig_opts)
  28. {
  29. struct key *key;
  30. const struct user_key_payload *ukp;
  31. int ret = 0;
  32. key = request_key(&key_type_user,
  33. key_desc, NULL);
  34. if (IS_ERR(key))
  35. return PTR_ERR(key);
  36. down_read(&key->sem);
  37. ukp = user_key_payload_locked(key);
  38. if (!ukp) {
  39. ret = -EKEYREVOKED;
  40. goto end;
  41. }
  42. sig_opts->sig = kmalloc(ukp->datalen, GFP_KERNEL);
  43. if (!sig_opts->sig) {
  44. ret = -ENOMEM;
  45. goto end;
  46. }
  47. sig_opts->sig_size = ukp->datalen;
  48. memcpy(sig_opts->sig, ukp->data, sig_opts->sig_size);
  49. end:
  50. up_read(&key->sem);
  51. key_put(key);
  52. return ret;
  53. }
  54. int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
  55. struct dm_verity *v,
  56. struct dm_verity_sig_opts *sig_opts,
  57. unsigned int *argc,
  58. const char *arg_name)
  59. {
  60. struct dm_target *ti = v->ti;
  61. int ret = 0;
  62. const char *sig_key = NULL;
  63. if (!*argc) {
  64. ti->error = DM_VERITY_VERIFY_ERR("Signature key not specified");
  65. return -EINVAL;
  66. }
  67. sig_key = dm_shift_arg(as);
  68. (*argc)--;
  69. ret = verity_verify_get_sig_from_key(sig_key, sig_opts);
  70. if (ret < 0)
  71. ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified");
  72. v->signature_key_desc = kstrdup(sig_key, GFP_KERNEL);
  73. if (!v->signature_key_desc)
  74. return -ENOMEM;
  75. return ret;
  76. }
  77. /*
  78. * verify_verify_roothash - Verify the root hash of the verity hash device
  79. * using builtin trusted keys.
  80. *
  81. * @root_hash: For verity, the roothash/data to be verified.
  82. * @root_hash_len: Size of the roothash/data to be verified.
  83. * @sig_data: The trusted signature that verifies the roothash/data.
  84. * @sig_len: Size of the signature.
  85. *
  86. */
  87. int verity_verify_root_hash(const void *root_hash, size_t root_hash_len,
  88. const void *sig_data, size_t sig_len)
  89. {
  90. int ret;
  91. if (!root_hash || root_hash_len == 0)
  92. return -EINVAL;
  93. if (!sig_data || sig_len == 0) {
  94. if (DM_VERITY_IS_SIG_FORCE_ENABLED())
  95. return -ENOKEY;
  96. else
  97. return 0;
  98. }
  99. ret = verify_pkcs7_signature(root_hash, root_hash_len, sig_data,
  100. sig_len, NULL, VERIFYING_UNSPECIFIED_SIGNATURE,
  101. NULL, NULL);
  102. return ret;
  103. }
  104. void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts)
  105. {
  106. kfree(sig_opts->sig);
  107. sig_opts->sig = NULL;
  108. sig_opts->sig_size = 0;
  109. }