1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 * 5 * Tests for firmware image library. 6 */ 7 8 #include <stdio.h> 9 10 #include "2sysincludes.h" 11 #include "2rsa.h" 12 13 #include "file_keys.h" 14 #include "host_common.h" 15 #include "host_key.h" 16 #include "host_keyblock.h" 17 #include "host_signature.h" 18 #include "vb2_common.h" 19 #include "vboot_common.h" 20 #include "test_common.h" 21 22 static void resign_keyblock(struct vb2_keyblock *h, const VbPrivateKey *key) 23 { 24 VbSignature *sig = 25 CalculateSignature((const uint8_t *)h, 26 h->keyblock_signature.data_size, key); 27 28 SignatureCopy((VbSignature *)&h->keyblock_signature, sig); 29 free(sig); 30 } 31 32 static void test_verify_keyblock(const VbPublicKey *public_key, 33 const VbPrivateKey *private_key, 34 const VbPublicKey *data_key) 35 { 36 uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES] 37 __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); 38 struct vb2_workbuf wb; 39 struct vb2_public_key key; 40 struct vb2_keyblock *hdr; 41 struct vb2_keyblock *h; 42 uint32_t hsize; 43 44 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); 45 46 /* Unpack public key */ 47 TEST_SUCC(vb2_unpack_key(&key, (uint8_t *)public_key, 48 public_key->key_offset + public_key->key_size), 49 "vb2_verify_keyblock public key"); 50 51 hdr = (struct vb2_keyblock *) 52 KeyBlockCreate(data_key, private_key, 0x1234); 53 TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites"); 54 if (!hdr) 55 return; 56 hsize = hdr->keyblock_size; 57 h = (struct vb2_keyblock *)malloc(hsize + 2048); 58 59 Memcpy(h, hdr, hsize); 60 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), 61 "vb2_verify_keyblock() ok using key"); 62 63 Memcpy(h, hdr, hsize); 64 TEST_EQ(vb2_verify_keyblock(h, hsize - 1, &key, &wb), 65 VB2_ERROR_KEYBLOCK_SIZE, "vb2_verify_keyblock() size--"); 66 67 /* Buffer is allowed to be bigger than keyblock */ 68 Memcpy(h, hdr, hsize); 69 TEST_SUCC(vb2_verify_keyblock(h, hsize + 1, &key, &wb), 70 "vb2_verify_keyblock() size++"); 71 72 Memcpy(h, hdr, hsize); 73 h->magic[0] &= 0x12; 74 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 75 VB2_ERROR_KEYBLOCK_MAGIC, "vb2_verify_keyblock() magic"); 76 77 /* Care about major version but not minor */ 78 Memcpy(h, hdr, hsize); 79 h->header_version_major++; 80 resign_keyblock(h, private_key); 81 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 82 VB2_ERROR_KEYBLOCK_HEADER_VERSION, 83 "vb2_verify_keyblock() major++"); 84 85 Memcpy(h, hdr, hsize); 86 h->header_version_major--; 87 resign_keyblock(h, private_key); 88 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 89 VB2_ERROR_KEYBLOCK_HEADER_VERSION, 90 "vb2_verify_keyblock() major--"); 91 92 Memcpy(h, hdr, hsize); 93 h->header_version_minor++; 94 resign_keyblock(h, private_key); 95 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), 96 "vb2_verify_keyblock() minor++"); 97 98 Memcpy(h, hdr, hsize); 99 h->header_version_minor--; 100 resign_keyblock(h, private_key); 101 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), 102 "vb2_verify_keyblock() minor--"); 103 104 /* Check signature */ 105 Memcpy(h, hdr, hsize); 106 h->keyblock_signature.sig_offset = hsize; 107 resign_keyblock(h, private_key); 108 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 109 VB2_ERROR_KEYBLOCK_SIG_OUTSIDE, 110 "vb2_verify_keyblock() sig off end"); 111 112 Memcpy(h, hdr, hsize); 113 h->keyblock_signature.sig_size--; 114 resign_keyblock(h, private_key); 115 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 116 VB2_ERROR_KEYBLOCK_SIG_INVALID, 117 "vb2_verify_keyblock() sig too small"); 118 119 Memcpy(h, hdr, hsize); 120 ((uint8_t *)vb2_packed_key_data(&h->data_key))[0] ^= 0x34; 121 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 122 VB2_ERROR_KEYBLOCK_SIG_INVALID, 123 "vb2_verify_keyblock() sig mismatch"); 124 125 Memcpy(h, hdr, hsize); 126 h->keyblock_signature.data_size = h->keyblock_size + 1; 127 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 128 VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH, 129 "vb2_verify_keyblock() sig data past end of block"); 130 131 /* Check that we signed header and data key */ 132 Memcpy(h, hdr, hsize); 133 h->keyblock_signature.data_size = 4; 134 h->data_key.key_offset = 0; 135 h->data_key.key_size = 0; 136 resign_keyblock(h, private_key); 137 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 138 VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE, 139 "vb2_verify_keyblock() didn't sign header"); 140 141 Memcpy(h, hdr, hsize); 142 h->data_key.key_offset = hsize; 143 resign_keyblock(h, private_key); 144 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), 145 VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE, 146 "vb2_verify_keyblock() data key off end"); 147 148 /* Corner cases for error checking */ 149 TEST_EQ(vb2_verify_keyblock(NULL, 4, &key, &wb), 150 VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER, 151 "vb2_verify_keyblock size too small"); 152 153 /* 154 * TODO: verify parser can support a bigger header (i.e., one where 155 * data_key.key_offset is bigger than expected). 156 */ 157 158 free(h); 159 free(hdr); 160 } 161 162 static void resign_fw_preamble(struct vb2_fw_preamble *h, 163 const VbPrivateKey *key) 164 { 165 VbSignature *sig = CalculateSignature( 166 (const uint8_t *)h, h->preamble_signature.data_size, key); 167 168 SignatureCopy((VbSignature *)&h->preamble_signature, sig); 169 free(sig); 170 } 171 172 static void test_verify_fw_preamble(const VbPublicKey *public_key, 173 const VbPrivateKey *private_key, 174 const VbPublicKey *kernel_subkey) 175 { 176 struct vb2_fw_preamble *hdr; 177 struct vb2_fw_preamble *h; 178 struct vb2_public_key rsa; 179 uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES] 180 __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); 181 struct vb2_workbuf wb; 182 uint32_t hsize; 183 184 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); 185 186 /* Create a dummy signature */ 187 VbSignature *body_sig = SignatureAlloc(56, 78); 188 189 TEST_SUCC(vb2_unpack_key(&rsa, (uint8_t *)public_key, 190 public_key->key_offset + public_key->key_size), 191 "vb2_verify_fw_preamble() prereq key"); 192 193 hdr = (struct vb2_fw_preamble *) 194 CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, 195 private_key, 0x5678); 196 TEST_PTR_NEQ(hdr, NULL, 197 "VerifyFirmwarePreamble() prereq test preamble"); 198 if (!hdr) 199 return; 200 hsize = (uint32_t) hdr->preamble_size; 201 h = (struct vb2_fw_preamble *)malloc(hsize + 16384); 202 203 Memcpy(h, hdr, hsize); 204 TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 205 "vb2_verify_fw_preamble() ok using key"); 206 207 Memcpy(h, hdr, hsize); 208 TEST_EQ(vb2_verify_fw_preamble(h, 4, &rsa, &wb), 209 VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER, 210 "vb2_verify_fw_preamble() size tiny"); 211 212 Memcpy(h, hdr, hsize); 213 TEST_EQ(vb2_verify_fw_preamble(h, hsize - 1, &rsa, &wb), 214 VB2_ERROR_PREAMBLE_SIZE, 215 "vb2_verify_fw_preamble() size--"); 216 217 /* Buffer is allowed to be bigger than preamble */ 218 Memcpy(h, hdr, hsize); 219 TEST_SUCC(vb2_verify_fw_preamble(h, hsize + 1, &rsa, &wb), 220 "vb2_verify_fw_preamble() size++"); 221 222 /* Care about major version but not minor */ 223 Memcpy(h, hdr, hsize); 224 h->header_version_major++; 225 resign_fw_preamble(h, private_key); 226 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 227 VB2_ERROR_PREAMBLE_HEADER_VERSION 228 , "vb2_verify_fw_preamble() major++"); 229 230 Memcpy(h, hdr, hsize); 231 h->header_version_major--; 232 resign_fw_preamble(h, private_key); 233 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 234 VB2_ERROR_PREAMBLE_HEADER_VERSION, 235 "vb2_verify_fw_preamble() major--"); 236 237 Memcpy(h, hdr, hsize); 238 h->header_version_minor++; 239 resign_fw_preamble(h, private_key); 240 TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 241 "vb2_verify_fw_preamble() minor++"); 242 243 Memcpy(h, hdr, hsize); 244 h->header_version_minor--; 245 resign_fw_preamble(h, private_key); 246 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 247 VB2_ERROR_PREAMBLE_HEADER_OLD, 248 "vb2_verify_fw_preamble() 2.0 not supported"); 249 250 /* Check signature */ 251 Memcpy(h, hdr, hsize); 252 h->preamble_signature.sig_offset = hsize; 253 resign_fw_preamble(h, private_key); 254 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 255 VB2_ERROR_PREAMBLE_SIG_OUTSIDE, 256 "vb2_verify_fw_preamble() sig off end"); 257 258 Memcpy(h, hdr, hsize); 259 h->preamble_signature.sig_size--; 260 resign_fw_preamble(h, private_key); 261 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 262 VB2_ERROR_PREAMBLE_SIG_INVALID, 263 "vb2_verify_fw_preamble() sig too small"); 264 265 Memcpy(h, hdr, hsize); 266 ((uint8_t *)vb2_packed_key_data(&h->kernel_subkey))[0] ^= 0x34; 267 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 268 VB2_ERROR_PREAMBLE_SIG_INVALID, 269 "vb2_verify_fw_preamble() sig mismatch"); 270 271 /* Check that we signed header, kernel subkey, and body sig */ 272 Memcpy(h, hdr, hsize); 273 h->preamble_signature.data_size = 4; 274 h->kernel_subkey.key_offset = 0; 275 h->kernel_subkey.key_size = 0; 276 h->body_signature.sig_offset = 0; 277 h->body_signature.sig_size = 0; 278 resign_fw_preamble(h, private_key); 279 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 280 VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE, 281 "vb2_verify_fw_preamble() didn't sign header"); 282 283 Memcpy(h, hdr, hsize); 284 h->kernel_subkey.key_offset = hsize; 285 resign_fw_preamble(h, private_key); 286 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 287 VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE, 288 "vb2_verify_fw_preamble() kernel subkey off end"); 289 290 Memcpy(h, hdr, hsize); 291 h->body_signature.sig_offset = hsize; 292 resign_fw_preamble(h, private_key); 293 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb), 294 VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE, 295 "vb2_verify_fw_preamble() body sig off end"); 296 297 /* TODO: verify with extra padding at end of header. */ 298 299 free(h); 300 free(hdr); 301 } 302 303 int test_permutation(int signing_key_algorithm, int data_key_algorithm, 304 const char *keys_dir) 305 { 306 char filename[1024]; 307 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8; 308 int data_rsa_len = siglen_map[data_key_algorithm] * 8; 309 310 VbPrivateKey *signing_private_key = NULL; 311 VbPublicKey *signing_public_key = NULL; 312 VbPublicKey *data_public_key = NULL; 313 314 printf("***Testing signing algorithm: %s\n", 315 algo_strings[signing_key_algorithm]); 316 printf("***With data key algorithm: %s\n", 317 algo_strings[data_key_algorithm]); 318 319 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len); 320 signing_private_key = PrivateKeyReadPem(filename, 321 signing_key_algorithm); 322 if (!signing_private_key) { 323 fprintf(stderr, "Error reading signing_private_key: %s\n", 324 filename); 325 return 1; 326 } 327 328 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len); 329 signing_public_key = PublicKeyReadKeyb(filename, 330 signing_key_algorithm, 1); 331 if (!signing_public_key) { 332 fprintf(stderr, "Error reading signing_public_key: %s\n", 333 filename); 334 return 1; 335 } 336 337 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len); 338 data_public_key = PublicKeyReadKeyb(filename, 339 data_key_algorithm, 1); 340 if (!data_public_key) { 341 fprintf(stderr, "Error reading data_public_key: %s\n", 342 filename); 343 return 1; 344 } 345 346 test_verify_keyblock(signing_public_key, signing_private_key, 347 data_public_key); 348 test_verify_fw_preamble(signing_public_key, signing_private_key, 349 data_public_key); 350 351 if (signing_public_key) 352 free(signing_public_key); 353 if (signing_private_key) 354 free(signing_private_key); 355 if (data_public_key) 356 free(data_public_key); 357 358 return 0; 359 } 360 361 struct test_perm 362 { 363 int signing_algorithm; 364 int data_key_algorithm; 365 }; 366 367 /* Permutations of signing and data key algorithms in active use */ 368 const struct test_perm test_perms[] = { 369 {VB2_ALG_RSA4096_SHA256, VB2_ALG_RSA2048_SHA256}, 370 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA2048_SHA256}, 371 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA4096_SHA256}, 372 }; 373 374 int main(int argc, char *argv[]) 375 { 376 if (argc == 2) { 377 /* Test only the algorithms we use */ 378 int i; 379 380 for (i = 0; i < ARRAY_SIZE(test_perms); i++) { 381 if (test_permutation(test_perms[i].signing_algorithm, 382 test_perms[i].data_key_algorithm, 383 argv[1])) 384 return 1; 385 } 386 387 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) { 388 /* Test all the algorithms */ 389 int sign_alg, data_alg; 390 391 for (sign_alg = 0; sign_alg < VB2_ALG_COUNT; sign_alg++) { 392 for (data_alg = 0; data_alg < VB2_ALG_COUNT; 393 data_alg++) { 394 if (test_permutation(sign_alg, data_alg, 395 argv[1])) 396 return 1; 397 } 398 } 399 } else { 400 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]); 401 return -1; 402 } 403 404 return gTestSuccess ? 0 : 255; 405 } 406