asym_tpm.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define pr_fmt(fmt) "ASYM-TPM: "fmt
  3. #include <linux/slab.h>
  4. #include <linux/module.h>
  5. #include <linux/export.h>
  6. #include <linux/kernel.h>
  7. #include <linux/seq_file.h>
  8. #include <linux/scatterlist.h>
  9. #include <linux/tpm.h>
  10. #include <asm/unaligned.h>
  11. #include <keys/asymmetric-subtype.h>
  12. #include <crypto/asym_tpm_subtype.h>
  13. /*
  14. * Provide a part of a description of the key for /proc/keys.
  15. */
  16. static void asym_tpm_describe(const struct key *asymmetric_key,
  17. struct seq_file *m)
  18. {
  19. struct tpm_key *tk = asymmetric_key->payload.data[asym_crypto];
  20. if (!tk)
  21. return;
  22. seq_printf(m, "TPM1.2/Blob");
  23. }
  24. static void asym_tpm_destroy(void *payload0, void *payload3)
  25. {
  26. struct tpm_key *tk = payload0;
  27. if (!tk)
  28. return;
  29. kfree(tk->blob);
  30. tk->blob_len = 0;
  31. kfree(tk);
  32. }
  33. /*
  34. * Parse enough information out of TPM_KEY structure:
  35. * TPM_STRUCT_VER -> 4 bytes
  36. * TPM_KEY_USAGE -> 2 bytes
  37. * TPM_KEY_FLAGS -> 4 bytes
  38. * TPM_AUTH_DATA_USAGE -> 1 byte
  39. * TPM_KEY_PARMS -> variable
  40. * UINT32 PCRInfoSize -> 4 bytes
  41. * BYTE* -> PCRInfoSize bytes
  42. * TPM_STORE_PUBKEY
  43. * UINT32 encDataSize;
  44. * BYTE* -> encDataSize;
  45. *
  46. * TPM_KEY_PARMS:
  47. * TPM_ALGORITHM_ID -> 4 bytes
  48. * TPM_ENC_SCHEME -> 2 bytes
  49. * TPM_SIG_SCHEME -> 2 bytes
  50. * UINT32 parmSize -> 4 bytes
  51. * BYTE* -> variable
  52. */
  53. static int extract_key_parameters(struct tpm_key *tk)
  54. {
  55. const void *cur = tk->blob;
  56. uint32_t len = tk->blob_len;
  57. const void *pub_key;
  58. uint32_t sz;
  59. uint32_t key_len;
  60. if (len < 11)
  61. return -EBADMSG;
  62. /* Ensure this is a legacy key */
  63. if (get_unaligned_be16(cur + 4) != 0x0015)
  64. return -EBADMSG;
  65. /* Skip to TPM_KEY_PARMS */
  66. cur += 11;
  67. len -= 11;
  68. if (len < 12)
  69. return -EBADMSG;
  70. /* Make sure this is an RSA key */
  71. if (get_unaligned_be32(cur) != 0x00000001)
  72. return -EBADMSG;
  73. /* Make sure this is TPM_ES_RSAESPKCSv15 encoding scheme */
  74. if (get_unaligned_be16(cur + 4) != 0x0002)
  75. return -EBADMSG;
  76. /* Make sure this is TPM_SS_RSASSAPKCS1v15_DER signature scheme */
  77. if (get_unaligned_be16(cur + 6) != 0x0003)
  78. return -EBADMSG;
  79. sz = get_unaligned_be32(cur + 8);
  80. if (len < sz + 12)
  81. return -EBADMSG;
  82. /* Move to TPM_RSA_KEY_PARMS */
  83. len -= 12;
  84. cur += 12;
  85. /* Grab the RSA key length */
  86. key_len = get_unaligned_be32(cur);
  87. switch (key_len) {
  88. case 512:
  89. case 1024:
  90. case 1536:
  91. case 2048:
  92. break;
  93. default:
  94. return -EINVAL;
  95. }
  96. /* Move just past TPM_KEY_PARMS */
  97. cur += sz;
  98. len -= sz;
  99. if (len < 4)
  100. return -EBADMSG;
  101. sz = get_unaligned_be32(cur);
  102. if (len < 4 + sz)
  103. return -EBADMSG;
  104. /* Move to TPM_STORE_PUBKEY */
  105. cur += 4 + sz;
  106. len -= 4 + sz;
  107. /* Grab the size of the public key, it should jive with the key size */
  108. sz = get_unaligned_be32(cur);
  109. if (sz > 256)
  110. return -EINVAL;
  111. pub_key = cur + 4;
  112. tk->key_len = key_len;
  113. tk->pub_key = pub_key;
  114. tk->pub_key_len = sz;
  115. return 0;
  116. }
  117. /* Given the blob, parse it and load it into the TPM */
  118. struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len)
  119. {
  120. int r;
  121. struct tpm_key *tk;
  122. r = tpm_is_tpm2(NULL);
  123. if (r < 0)
  124. goto error;
  125. /* We don't support TPM2 yet */
  126. if (r > 0) {
  127. r = -ENODEV;
  128. goto error;
  129. }
  130. r = -ENOMEM;
  131. tk = kzalloc(sizeof(struct tpm_key), GFP_KERNEL);
  132. if (!tk)
  133. goto error;
  134. tk->blob = kmemdup(blob, blob_len, GFP_KERNEL);
  135. if (!tk->blob)
  136. goto error_memdup;
  137. tk->blob_len = blob_len;
  138. r = extract_key_parameters(tk);
  139. if (r < 0)
  140. goto error_extract;
  141. return tk;
  142. error_extract:
  143. kfree(tk->blob);
  144. tk->blob_len = 0;
  145. error_memdup:
  146. kfree(tk);
  147. error:
  148. return ERR_PTR(r);
  149. }
  150. EXPORT_SYMBOL_GPL(tpm_key_create);
  151. /*
  152. * TPM-based asymmetric key subtype
  153. */
  154. struct asymmetric_key_subtype asym_tpm_subtype = {
  155. .owner = THIS_MODULE,
  156. .name = "asym_tpm",
  157. .name_len = sizeof("asym_tpm") - 1,
  158. .describe = asym_tpm_describe,
  159. .destroy = asym_tpm_destroy,
  160. };
  161. EXPORT_SYMBOL_GPL(asym_tpm_subtype);
  162. MODULE_DESCRIPTION("TPM based asymmetric key subtype");
  163. MODULE_AUTHOR("Intel Corporation");
  164. MODULE_LICENSE("GPL v2");