digsig_asymmetric.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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/key-type.h>
  15. #include <crypto/public_key.h>
  16. #include <keys/asymmetric-type.h>
  17. #include "integrity.h"
  18. /*
  19. * signature format v2 - for using with asymmetric keys
  20. */
  21. struct signature_v2_hdr {
  22. uint8_t version; /* signature format version */
  23. uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
  24. uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/
  25. uint16_t sig_size; /* signature size */
  26. uint8_t sig[0]; /* signature payload */
  27. } __packed;
  28. /*
  29. * Request an asymmetric key.
  30. */
  31. static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
  32. {
  33. struct key *key;
  34. char name[12];
  35. sprintf(name, "id:%x", keyid);
  36. pr_debug("key search: \"%s\"\n", name);
  37. if (keyring) {
  38. /* search in specific keyring */
  39. key_ref_t kref;
  40. kref = keyring_search(make_key_ref(keyring, 1),
  41. &key_type_asymmetric, name);
  42. if (IS_ERR(kref))
  43. key = ERR_CAST(kref);
  44. else
  45. key = key_ref_to_ptr(kref);
  46. } else {
  47. key = request_key(&key_type_asymmetric, name, NULL);
  48. }
  49. if (IS_ERR(key)) {
  50. pr_warn("Request for unknown key '%s' err %ld\n",
  51. name, PTR_ERR(key));
  52. switch (PTR_ERR(key)) {
  53. /* Hide some search errors */
  54. case -EACCES:
  55. case -ENOTDIR:
  56. case -EAGAIN:
  57. return ERR_PTR(-ENOKEY);
  58. default:
  59. return key;
  60. }
  61. }
  62. pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
  63. return key;
  64. }
  65. int asymmetric_verify(struct key *keyring, const char *sig,
  66. int siglen, const char *data, int datalen)
  67. {
  68. struct public_key_signature pks;
  69. struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
  70. struct key *key;
  71. int ret = -ENOMEM;
  72. if (siglen <= sizeof(*hdr))
  73. return -EBADMSG;
  74. siglen -= sizeof(*hdr);
  75. if (siglen != __be16_to_cpu(hdr->sig_size))
  76. return -EBADMSG;
  77. if (hdr->hash_algo >= PKEY_HASH__LAST)
  78. return -ENOPKG;
  79. key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
  80. if (IS_ERR(key))
  81. return PTR_ERR(key);
  82. memset(&pks, 0, sizeof(pks));
  83. pks.pkey_hash_algo = hdr->hash_algo;
  84. pks.digest = (u8 *)data;
  85. pks.digest_size = datalen;
  86. pks.nr_mpi = 1;
  87. pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
  88. if (pks.rsa.s)
  89. ret = verify_signature(key, &pks);
  90. mpi_free(pks.rsa.s);
  91. key_put(key);
  92. pr_debug("%s() = %d\n", __func__, ret);
  93. return ret;
  94. }