pkcs8_parser.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* PKCS#8 Private Key parser [RFC 5208].
  3. *
  4. * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define pr_fmt(fmt) "PKCS8: "fmt
  8. #include <linux/module.h>
  9. #include <linux/kernel.h>
  10. #include <linux/export.h>
  11. #include <linux/slab.h>
  12. #include <linux/err.h>
  13. #include <linux/oid_registry.h>
  14. #include <keys/asymmetric-subtype.h>
  15. #include <keys/asymmetric-parser.h>
  16. #include <crypto/public_key.h>
  17. #include "pkcs8.asn1.h"
  18. struct pkcs8_parse_context {
  19. struct public_key *pub;
  20. unsigned long data; /* Start of data */
  21. enum OID last_oid; /* Last OID encountered */
  22. enum OID algo_oid; /* Algorithm OID */
  23. u32 key_size;
  24. const void *key;
  25. };
  26. /*
  27. * Note an OID when we find one for later processing when we know how to
  28. * interpret it.
  29. */
  30. int pkcs8_note_OID(void *context, size_t hdrlen,
  31. unsigned char tag,
  32. const void *value, size_t vlen)
  33. {
  34. struct pkcs8_parse_context *ctx = context;
  35. ctx->last_oid = look_up_OID(value, vlen);
  36. if (ctx->last_oid == OID__NR) {
  37. char buffer[50];
  38. sprint_oid(value, vlen, buffer, sizeof(buffer));
  39. pr_info("Unknown OID: [%lu] %s\n",
  40. (unsigned long)value - ctx->data, buffer);
  41. }
  42. return 0;
  43. }
  44. /*
  45. * Note the version number of the ASN.1 blob.
  46. */
  47. int pkcs8_note_version(void *context, size_t hdrlen,
  48. unsigned char tag,
  49. const void *value, size_t vlen)
  50. {
  51. if (vlen != 1 || ((const u8 *)value)[0] != 0) {
  52. pr_warn("Unsupported PKCS#8 version\n");
  53. return -EBADMSG;
  54. }
  55. return 0;
  56. }
  57. /*
  58. * Note the public algorithm.
  59. */
  60. int pkcs8_note_algo(void *context, size_t hdrlen,
  61. unsigned char tag,
  62. const void *value, size_t vlen)
  63. {
  64. struct pkcs8_parse_context *ctx = context;
  65. if (ctx->last_oid != OID_rsaEncryption)
  66. return -ENOPKG;
  67. ctx->pub->pkey_algo = "rsa";
  68. return 0;
  69. }
  70. /*
  71. * Note the key data of the ASN.1 blob.
  72. */
  73. int pkcs8_note_key(void *context, size_t hdrlen,
  74. unsigned char tag,
  75. const void *value, size_t vlen)
  76. {
  77. struct pkcs8_parse_context *ctx = context;
  78. ctx->key = value;
  79. ctx->key_size = vlen;
  80. return 0;
  81. }
  82. /*
  83. * Parse a PKCS#8 private key blob.
  84. */
  85. static struct public_key *pkcs8_parse(const void *data, size_t datalen)
  86. {
  87. struct pkcs8_parse_context ctx;
  88. struct public_key *pub;
  89. long ret;
  90. memset(&ctx, 0, sizeof(ctx));
  91. ret = -ENOMEM;
  92. ctx.pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
  93. if (!ctx.pub)
  94. goto error;
  95. ctx.data = (unsigned long)data;
  96. /* Attempt to decode the private key */
  97. ret = asn1_ber_decoder(&pkcs8_decoder, &ctx, data, datalen);
  98. if (ret < 0)
  99. goto error_decode;
  100. ret = -ENOMEM;
  101. pub = ctx.pub;
  102. pub->key = kmemdup(ctx.key, ctx.key_size, GFP_KERNEL);
  103. if (!pub->key)
  104. goto error_decode;
  105. pub->keylen = ctx.key_size;
  106. pub->key_is_private = true;
  107. return pub;
  108. error_decode:
  109. kfree(ctx.pub);
  110. error:
  111. return ERR_PTR(ret);
  112. }
  113. /*
  114. * Attempt to parse a data blob for a key as a PKCS#8 private key.
  115. */
  116. static int pkcs8_key_preparse(struct key_preparsed_payload *prep)
  117. {
  118. struct public_key *pub;
  119. pub = pkcs8_parse(prep->data, prep->datalen);
  120. if (IS_ERR(pub))
  121. return PTR_ERR(pub);
  122. pr_devel("Cert Key Algo: %s\n", pub->pkey_algo);
  123. pub->id_type = "PKCS8";
  124. /* We're pinning the module by being linked against it */
  125. __module_get(public_key_subtype.owner);
  126. prep->payload.data[asym_subtype] = &public_key_subtype;
  127. prep->payload.data[asym_key_ids] = NULL;
  128. prep->payload.data[asym_crypto] = pub;
  129. prep->payload.data[asym_auth] = NULL;
  130. prep->quotalen = 100;
  131. return 0;
  132. }
  133. static struct asymmetric_key_parser pkcs8_key_parser = {
  134. .owner = THIS_MODULE,
  135. .name = "pkcs8",
  136. .parse = pkcs8_key_preparse,
  137. };
  138. /*
  139. * Module stuff
  140. */
  141. static int __init pkcs8_key_init(void)
  142. {
  143. return register_asymmetric_key_parser(&pkcs8_key_parser);
  144. }
  145. static void __exit pkcs8_key_exit(void)
  146. {
  147. unregister_asymmetric_key_parser(&pkcs8_key_parser);
  148. }
  149. module_init(pkcs8_key_init);
  150. module_exit(pkcs8_key_exit);
  151. MODULE_DESCRIPTION("PKCS#8 certificate parser");
  152. MODULE_LICENSE("GPL");