pkcs7_trust.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* Validate the trust chain of a PKCS#7 message.
  2. *
  3. * Copyright (C) 2012 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) "PKCS7: "fmt
  12. #include <linux/kernel.h>
  13. #include <linux/export.h>
  14. #include <linux/slab.h>
  15. #include <linux/err.h>
  16. #include <linux/asn1.h>
  17. #include <linux/key.h>
  18. #include <keys/asymmetric-type.h>
  19. #include "public_key.h"
  20. #include "pkcs7_parser.h"
  21. /**
  22. * Check the trust on one PKCS#7 SignedInfo block.
  23. */
  24. static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
  25. struct pkcs7_signed_info *sinfo,
  26. struct key *trust_keyring)
  27. {
  28. struct public_key_signature *sig = &sinfo->sig;
  29. struct x509_certificate *x509, *last = NULL, *p;
  30. struct key *key;
  31. bool trusted;
  32. int ret;
  33. kenter(",%u,", sinfo->index);
  34. if (sinfo->unsupported_crypto) {
  35. kleave(" = -ENOPKG [cached]");
  36. return -ENOPKG;
  37. }
  38. for (x509 = sinfo->signer; x509; x509 = x509->signer) {
  39. if (x509->seen) {
  40. if (x509->verified) {
  41. trusted = x509->trusted;
  42. goto verified;
  43. }
  44. kleave(" = -ENOKEY [cached]");
  45. return -ENOKEY;
  46. }
  47. x509->seen = true;
  48. /* Look to see if this certificate is present in the trusted
  49. * keys.
  50. */
  51. key = x509_request_asymmetric_key(trust_keyring,
  52. x509->id, x509->skid,
  53. false);
  54. if (!IS_ERR(key)) {
  55. /* One of the X.509 certificates in the PKCS#7 message
  56. * is apparently the same as one we already trust.
  57. * Verify that the trusted variant can also validate
  58. * the signature on the descendant.
  59. */
  60. pr_devel("sinfo %u: Cert %u as key %x\n",
  61. sinfo->index, x509->index, key_serial(key));
  62. goto matched;
  63. }
  64. if (key == ERR_PTR(-ENOMEM))
  65. return -ENOMEM;
  66. /* Self-signed certificates form roots of their own, and if we
  67. * don't know them, then we can't accept them.
  68. */
  69. if (x509->next == x509) {
  70. kleave(" = -ENOKEY [unknown self-signed]");
  71. return -ENOKEY;
  72. }
  73. might_sleep();
  74. last = x509;
  75. sig = &last->sig;
  76. }
  77. /* No match - see if the root certificate has a signer amongst the
  78. * trusted keys.
  79. */
  80. if (last && (last->akid_id || last->akid_skid)) {
  81. key = x509_request_asymmetric_key(trust_keyring,
  82. last->akid_id,
  83. last->akid_skid,
  84. false);
  85. if (!IS_ERR(key)) {
  86. x509 = last;
  87. pr_devel("sinfo %u: Root cert %u signer is key %x\n",
  88. sinfo->index, x509->index, key_serial(key));
  89. goto matched;
  90. }
  91. if (PTR_ERR(key) != -ENOKEY)
  92. return PTR_ERR(key);
  93. }
  94. /* As a last resort, see if we have a trusted public key that matches
  95. * the signed info directly.
  96. */
  97. key = x509_request_asymmetric_key(trust_keyring,
  98. sinfo->signing_cert_id,
  99. NULL,
  100. false);
  101. if (!IS_ERR(key)) {
  102. pr_devel("sinfo %u: Direct signer is key %x\n",
  103. sinfo->index, key_serial(key));
  104. x509 = NULL;
  105. goto matched;
  106. }
  107. if (PTR_ERR(key) != -ENOKEY)
  108. return PTR_ERR(key);
  109. kleave(" = -ENOKEY [no backref]");
  110. return -ENOKEY;
  111. matched:
  112. ret = verify_signature(key, sig);
  113. trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags);
  114. key_put(key);
  115. if (ret < 0) {
  116. if (ret == -ENOMEM)
  117. return ret;
  118. kleave(" = -EKEYREJECTED [verify %d]", ret);
  119. return -EKEYREJECTED;
  120. }
  121. verified:
  122. if (x509) {
  123. x509->verified = true;
  124. for (p = sinfo->signer; p != x509; p = p->signer) {
  125. p->verified = true;
  126. p->trusted = trusted;
  127. }
  128. }
  129. sinfo->trusted = trusted;
  130. kleave(" = 0");
  131. return 0;
  132. }
  133. /**
  134. * pkcs7_validate_trust - Validate PKCS#7 trust chain
  135. * @pkcs7: The PKCS#7 certificate to validate
  136. * @trust_keyring: Signing certificates to use as starting points
  137. * @_trusted: Set to true if trustworth, false otherwise
  138. *
  139. * Validate that the certificate chain inside the PKCS#7 message intersects
  140. * keys we already know and trust.
  141. *
  142. * Returns, in order of descending priority:
  143. *
  144. * (*) -EKEYREJECTED if a signature failed to match for which we have a valid
  145. * key, or:
  146. *
  147. * (*) 0 if at least one signature chain intersects with the keys in the trust
  148. * keyring, or:
  149. *
  150. * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
  151. * chain.
  152. *
  153. * (*) -ENOKEY if we couldn't find a match for any of the signature chains in
  154. * the message.
  155. *
  156. * May also return -ENOMEM.
  157. */
  158. int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
  159. struct key *trust_keyring,
  160. bool *_trusted)
  161. {
  162. struct pkcs7_signed_info *sinfo;
  163. struct x509_certificate *p;
  164. int cached_ret = -ENOKEY;
  165. int ret;
  166. *_trusted = false;
  167. for (p = pkcs7->certs; p; p = p->next)
  168. p->seen = false;
  169. for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
  170. ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring);
  171. switch (ret) {
  172. case -ENOKEY:
  173. continue;
  174. case -ENOPKG:
  175. if (cached_ret == -ENOKEY)
  176. cached_ret = -ENOPKG;
  177. continue;
  178. case 0:
  179. *_trusted |= sinfo->trusted;
  180. cached_ret = 0;
  181. continue;
  182. default:
  183. return ret;
  184. }
  185. }
  186. return cached_ret;
  187. }
  188. EXPORT_SYMBOL_GPL(pkcs7_validate_trust);