verifiers.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2017 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * Verifiers helper.
  19. */
  20. #include <grub/file.h>
  21. #include <grub/verify.h>
  22. #include <grub/dl.h>
  23. GRUB_MOD_LICENSE ("GPLv3+");
  24. struct grub_file_verifier *grub_file_verifiers;
  25. struct grub_verified
  26. {
  27. grub_file_t file;
  28. void *buf;
  29. };
  30. typedef struct grub_verified *grub_verified_t;
  31. static void
  32. verified_free (grub_verified_t verified)
  33. {
  34. if (verified)
  35. {
  36. grub_free (verified->buf);
  37. grub_free (verified);
  38. }
  39. }
  40. static grub_ssize_t
  41. verified_read (struct grub_file *file, char *buf, grub_size_t len)
  42. {
  43. grub_verified_t verified = file->data;
  44. grub_memcpy (buf, (char *) verified->buf + file->offset, len);
  45. return len;
  46. }
  47. static grub_err_t
  48. verified_close (struct grub_file *file)
  49. {
  50. grub_verified_t verified = file->data;
  51. grub_file_close (verified->file);
  52. verified_free (verified);
  53. file->data = 0;
  54. /* Device and name are freed by parent. */
  55. file->device = 0;
  56. file->name = 0;
  57. return grub_errno;
  58. }
  59. struct grub_fs verified_fs =
  60. {
  61. .name = "verified_read",
  62. .fs_read = verified_read,
  63. .fs_close = verified_close
  64. };
  65. static grub_file_t
  66. grub_verifiers_open (grub_file_t io, enum grub_file_type type)
  67. {
  68. grub_verified_t verified = NULL;
  69. struct grub_file_verifier *ver;
  70. void *context;
  71. grub_file_t ret = 0;
  72. grub_err_t err;
  73. int defer = 0;
  74. grub_dprintf ("verify", "file: %s type: %d\n", io->name, type);
  75. if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE
  76. || (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE
  77. || (type & GRUB_FILE_TYPE_SKIP_SIGNATURE))
  78. return io;
  79. if (io->device->disk &&
  80. (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
  81. || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
  82. return io;
  83. FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
  84. {
  85. enum grub_verify_flags flags = 0;
  86. err = ver->init (io, type, &context, &flags);
  87. if (err)
  88. goto fail_noclose;
  89. if (flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
  90. {
  91. defer = 1;
  92. continue;
  93. }
  94. if (!(flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION))
  95. break;
  96. }
  97. if (!ver)
  98. {
  99. if (defer)
  100. {
  101. grub_error (GRUB_ERR_ACCESS_DENIED,
  102. N_("verification requested but nobody cares: %s"), io->name);
  103. goto fail_noclose;
  104. }
  105. /* No verifiers wanted to verify. Just return underlying file. */
  106. return io;
  107. }
  108. ret = grub_malloc (sizeof (*ret));
  109. if (!ret)
  110. {
  111. goto fail;
  112. }
  113. *ret = *io;
  114. ret->fs = &verified_fs;
  115. ret->not_easily_seekable = 0;
  116. if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
  117. {
  118. grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
  119. N_("big file signature isn't implemented yet"));
  120. goto fail;
  121. }
  122. verified = grub_malloc (sizeof (*verified));
  123. if (!verified)
  124. {
  125. goto fail;
  126. }
  127. verified->buf = grub_malloc (ret->size);
  128. if (!verified->buf)
  129. {
  130. goto fail;
  131. }
  132. if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
  133. {
  134. if (!grub_errno)
  135. grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
  136. io->name);
  137. goto fail;
  138. }
  139. err = ver->write (context, verified->buf, ret->size);
  140. if (err)
  141. goto fail;
  142. err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
  143. if (err)
  144. goto fail;
  145. if (ver->close)
  146. ver->close (context);
  147. FOR_LIST_ELEMENTS_NEXT(ver, grub_file_verifiers)
  148. {
  149. enum grub_verify_flags flags = 0;
  150. err = ver->init (io, type, &context, &flags);
  151. if (err)
  152. goto fail_noclose;
  153. if (flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION ||
  154. /* Verification done earlier. So, we are happy here. */
  155. flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
  156. continue;
  157. err = ver->write (context, verified->buf, ret->size);
  158. if (err)
  159. goto fail;
  160. err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
  161. if (err)
  162. goto fail;
  163. if (ver->close)
  164. ver->close (context);
  165. }
  166. verified->file = io;
  167. ret->data = verified;
  168. return ret;
  169. fail:
  170. if (ver->close)
  171. ver->close (context);
  172. fail_noclose:
  173. verified_free (verified);
  174. grub_free (ret);
  175. return NULL;
  176. }
  177. grub_err_t
  178. grub_verify_string (char *str, enum grub_verify_string_type type)
  179. {
  180. struct grub_file_verifier *ver;
  181. grub_dprintf ("verify", "string: %s, type: %d\n", str, type);
  182. FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
  183. {
  184. grub_err_t err;
  185. err = ver->verify_string ? ver->verify_string (str, type) : GRUB_ERR_NONE;
  186. if (err)
  187. return err;
  188. }
  189. return GRUB_ERR_NONE;
  190. }
  191. void
  192. grub_verifiers_init (void)
  193. {
  194. grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
  195. }