mscode_parser.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Parse a Microsoft Individual Code Signing blob
  3. *
  4. * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define pr_fmt(fmt) "MSCODE: "fmt
  8. #include <linux/kernel.h>
  9. #ifndef __UBOOT__
  10. #include <linux/slab.h>
  11. #endif
  12. #include <linux/err.h>
  13. #include <linux/oid_registry.h>
  14. #include <crypto/pkcs7.h>
  15. #ifdef __UBOOT__
  16. #include <crypto/mscode.h>
  17. #else
  18. #include "verify_pefile.h"
  19. #endif
  20. #include "mscode.asn1.h"
  21. /*
  22. * Parse a Microsoft Individual Code Signing blob
  23. */
  24. int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
  25. size_t asn1hdrlen)
  26. {
  27. struct pefile_context *ctx = _ctx;
  28. content_data -= asn1hdrlen;
  29. data_len += asn1hdrlen;
  30. pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
  31. content_data);
  32. return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len);
  33. }
  34. /*
  35. * Check the content type OID
  36. */
  37. int mscode_note_content_type(void *context, size_t hdrlen,
  38. unsigned char tag,
  39. const void *value, size_t vlen)
  40. {
  41. enum OID oid;
  42. oid = look_up_OID(value, vlen);
  43. if (oid == OID__NR) {
  44. char buffer[50];
  45. sprint_oid(value, vlen, buffer, sizeof(buffer));
  46. pr_err("Unknown OID: %s\n", buffer);
  47. return -EBADMSG;
  48. }
  49. /*
  50. * pesign utility had a bug where it was putting
  51. * OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
  52. * So allow both OIDs.
  53. */
  54. if (oid != OID_msPeImageDataObjId &&
  55. oid != OID_msIndividualSPKeyPurpose) {
  56. pr_err("Unexpected content type OID %u\n", oid);
  57. return -EBADMSG;
  58. }
  59. return 0;
  60. }
  61. /*
  62. * Note the digest algorithm OID
  63. */
  64. int mscode_note_digest_algo(void *context, size_t hdrlen,
  65. unsigned char tag,
  66. const void *value, size_t vlen)
  67. {
  68. struct pefile_context *ctx = context;
  69. char buffer[50];
  70. enum OID oid;
  71. oid = look_up_OID(value, vlen);
  72. switch (oid) {
  73. case OID_md4:
  74. ctx->digest_algo = "md4";
  75. break;
  76. case OID_md5:
  77. ctx->digest_algo = "md5";
  78. break;
  79. case OID_sha1:
  80. ctx->digest_algo = "sha1";
  81. break;
  82. case OID_sha256:
  83. ctx->digest_algo = "sha256";
  84. break;
  85. case OID_sha384:
  86. ctx->digest_algo = "sha384";
  87. break;
  88. case OID_sha512:
  89. ctx->digest_algo = "sha512";
  90. break;
  91. case OID_sha224:
  92. ctx->digest_algo = "sha224";
  93. break;
  94. case OID__NR:
  95. sprint_oid(value, vlen, buffer, sizeof(buffer));
  96. pr_err("Unknown OID: %s\n", buffer);
  97. return -EBADMSG;
  98. default:
  99. pr_err("Unsupported content type: %u\n", oid);
  100. return -ENOPKG;
  101. }
  102. return 0;
  103. }
  104. /*
  105. * Note the digest we're guaranteeing with this certificate
  106. */
  107. int mscode_note_digest(void *context, size_t hdrlen,
  108. unsigned char tag,
  109. const void *value, size_t vlen)
  110. {
  111. struct pefile_context *ctx = context;
  112. ctx->digest = kmemdup(value, vlen, GFP_KERNEL);
  113. if (!ctx->digest)
  114. return -ENOMEM;
  115. ctx->digest_len = vlen;
  116. return 0;
  117. }