1 /* 2 * Copyright (c) 2017-2018, Juniper Networks, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include <sys/cdefs.h> 26 __FBSDID("$FreeBSD$"); 27 28 #include "../libsecureboot-priv.h" 29 30 #include <unistd.h> 31 #include <err.h> 32 #include <verify_file.h> 33 34 /* keep clang quiet */ 35 extern char *Destdir; 36 extern size_t DestdirLen; 37 extern char *Skip; 38 extern time_t ve_utc; 39 40 size_t DestdirLen; 41 char *Destdir; 42 char *Skip; 43 44 int 45 main(int argc, char *argv[]) 46 { 47 int n; 48 int fd; 49 int c; 50 int Vflag; 51 int vflag; 52 char *cp; 53 char *prefix; 54 55 Destdir = NULL; 56 DestdirLen = 0; 57 prefix = NULL; 58 Skip = NULL; 59 60 n = ve_trust_init(); 61 Vflag = 0; 62 vflag = 0; 63 64 while ((c = getopt(argc, argv, "D:dp:s:T:u:Vv")) != -1) { 65 switch (c) { 66 case 'D': 67 Destdir = optarg; 68 DestdirLen = strlen(optarg); 69 break; 70 case 'd': 71 DebugVe++; 72 break; 73 case 'p': 74 prefix = optarg; 75 break; 76 case 's': 77 Skip = optarg; 78 break; 79 case 'T': 80 n = ve_trust_add(optarg); 81 printf("Local trust %s: %d\n", optarg, n); 82 break; 83 case 'V': 84 Vflag = 1; 85 break; 86 case 'v': 87 vflag = 1; 88 break; 89 case 'u': 90 ve_utc = (time_t)atoi(optarg); 91 break; 92 default: 93 errx(1, "unknown option: -%c", c); 94 break; 95 } 96 } 97 98 if (!vflag) { 99 printf("Trust %d\n", n); 100 #ifdef VE_PCR_SUPPORT 101 ve_pcr_updating_set(1); 102 #endif 103 ve_self_tests(); 104 } 105 for ( ; optind < argc; optind++) { 106 if (Vflag) { 107 /* 108 * Simulate what loader does. 109 * verify_file should "just work" 110 */ 111 fd = open(argv[optind], O_RDONLY); 112 if (fd > 0) { 113 /* 114 * See if verify_file is happy 115 */ 116 int x; 117 118 x = verify_file(fd, argv[optind], 0, VE_GUESS, __func__); 119 printf("verify_file(%s) = %d\n", argv[optind], x); 120 close(fd); 121 } 122 continue; 123 } 124 #ifdef VE_OPENPGP_SUPPORT 125 if (strstr(argv[optind], "asc")) { 126 cp = (char *)verify_asc(argv[optind], 1); 127 if (cp) { 128 printf("Verified: %s: %.28s...\n", 129 argv[optind], cp); 130 if (!vflag) 131 fingerprint_info_add(argv[optind], 132 prefix, Skip, cp, NULL); 133 } else { 134 fprintf(stderr, "%s: %s\n", 135 argv[optind], ve_error_get()); 136 } 137 } else 138 #endif 139 if (strstr(argv[optind], "sig")) { 140 cp = (char *)verify_sig(argv[optind], 1); 141 if (cp) { 142 printf("Verified: %s: %.28s...\n", 143 argv[optind], cp); 144 if (!vflag) 145 fingerprint_info_add(argv[optind], 146 prefix, Skip, cp, NULL); 147 } else { 148 fprintf(stderr, "%s: %s\n", 149 argv[optind], ve_error_get()); 150 } 151 } else if (strstr(argv[optind], "manifest")) { 152 cp = (char *)read_file(argv[optind], NULL); 153 if (cp) { 154 fingerprint_info_add(argv[optind], 155 prefix, Skip, cp, NULL); 156 } 157 } else { 158 fd = verify_open(argv[optind], O_RDONLY); 159 printf("verify_open(%s) = %d %s\n", argv[optind], fd, 160 (fd < 0) ? ve_error_get() : ""); 161 if (fd > 0) { 162 /* 163 * Check that vectx_* can also verify the file. 164 */ 165 void *vp; 166 char buf[BUFSIZ]; 167 struct stat st; 168 int error; 169 off_t off; 170 size_t nb; 171 172 fstat(fd, &st); 173 lseek(fd, 0, SEEK_SET); 174 off = st.st_size % 512; 175 vp = vectx_open(fd, argv[optind], off, 176 &st, &error, __func__); 177 if (!vp) { 178 printf("vectx_open(%s) failed: %d %s\n", 179 argv[optind], error, 180 ve_error_get()); 181 } else { 182 off = vectx_lseek(vp, 183 (st.st_size % 1024), SEEK_SET); 184 /* we can seek backwards! */ 185 off = vectx_lseek(vp, off/2, SEEK_SET); 186 if (off < st.st_size) { 187 nb = vectx_read(vp, buf, 188 sizeof(buf)); 189 if (nb > 0) 190 off += nb; 191 } 192 off = vectx_lseek(vp, 0, SEEK_END); 193 /* repeating that should be harmless */ 194 off = vectx_lseek(vp, 0, SEEK_END); 195 error = vectx_close(vp, VE_MUST, __func__); 196 if (error) { 197 printf("vectx_close(%s) == %d %s\n", 198 argv[optind], error, 199 ve_error_get()); 200 } else { 201 printf("vectx_close: Verified: %s\n", 202 argv[optind]); 203 } 204 } 205 close(fd); 206 } 207 } 208 } 209 #ifdef VE_PCR_SUPPORT 210 verify_pcr_export(); 211 printf("pcr=%s\n", getenv("loader.ve.pcr")); 212 #endif 213 return (0); 214 } 215 216