pkcs8_parser.c 4.1 KB

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