restrict.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /* Instantiate a public key crypto key from an X.509 Certificate
  2. *
  3. * Copyright (C) 2012, 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) "ASYM: "fmt
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/err.h>
  15. #include <crypto/public_key.h>
  16. #include "asymmetric_keys.h"
  17. static bool use_builtin_keys;
  18. static struct asymmetric_key_id *ca_keyid;
  19. #ifndef MODULE
  20. static struct {
  21. struct asymmetric_key_id id;
  22. unsigned char data[10];
  23. } cakey;
  24. static int __init ca_keys_setup(char *str)
  25. {
  26. if (!str) /* default system keyring */
  27. return 1;
  28. if (strncmp(str, "id:", 3) == 0) {
  29. struct asymmetric_key_id *p = &cakey.id;
  30. size_t hexlen = (strlen(str) - 3) / 2;
  31. int ret;
  32. if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
  33. pr_err("Missing or invalid ca_keys id\n");
  34. return 1;
  35. }
  36. ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
  37. if (ret < 0)
  38. pr_err("Unparsable ca_keys id hex string\n");
  39. else
  40. ca_keyid = p; /* owner key 'id:xxxxxx' */
  41. } else if (strcmp(str, "builtin") == 0) {
  42. use_builtin_keys = true;
  43. }
  44. return 1;
  45. }
  46. __setup("ca_keys=", ca_keys_setup);
  47. #endif
  48. /**
  49. * restrict_link_by_signature - Restrict additions to a ring of public keys
  50. * @trust_keyring: A ring of keys that can be used to vouch for the new cert.
  51. * @type: The type of key being added.
  52. * @payload: The payload of the new key.
  53. *
  54. * Check the new certificate against the ones in the trust keyring. If one of
  55. * those is the signing key and validates the new certificate, then mark the
  56. * new certificate as being trusted.
  57. *
  58. * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a
  59. * matching parent certificate in the trusted list, -EKEYREJECTED if the
  60. * signature check fails or the key is blacklisted, -ENOPKG if the signature
  61. * uses unsupported crypto, or some other error if there is a matching
  62. * certificate but the signature check cannot be performed.
  63. */
  64. int restrict_link_by_signature(struct key *trust_keyring,
  65. const struct key_type *type,
  66. const union key_payload *payload)
  67. {
  68. const struct public_key_signature *sig;
  69. struct key *key;
  70. int ret;
  71. pr_devel("==>%s()\n", __func__);
  72. if (!trust_keyring)
  73. return -ENOKEY;
  74. if (type != &key_type_asymmetric)
  75. return -EOPNOTSUPP;
  76. sig = payload->data[asym_auth];
  77. if (!sig)
  78. return -ENOPKG;
  79. if (!sig->auth_ids[0] && !sig->auth_ids[1])
  80. return -ENOKEY;
  81. if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
  82. return -EPERM;
  83. /* See if we have a key that signed this one. */
  84. key = find_asymmetric_key(trust_keyring,
  85. sig->auth_ids[0], sig->auth_ids[1],
  86. false);
  87. if (IS_ERR(key))
  88. return -ENOKEY;
  89. if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
  90. ret = -ENOKEY;
  91. else
  92. ret = verify_signature(key, sig);
  93. key_put(key);
  94. return ret;
  95. }