1 /* Copyright (c) 2013 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 <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "cryptolib.h" 14 #include "file_keys.h" 15 #include "host_common.h" 16 #include "test_common.h" 17 #include "vboot_common.h" 18 19 20 static void ReChecksumKeyBlock(VbKeyBlockHeader *h) 21 { 22 uint8_t *newchk = DigestBuf((const uint8_t *)h, 23 h->key_block_checksum.data_size, 24 SHA512_DIGEST_ALGORITHM); 25 Memcpy(GetSignatureData(&h->key_block_checksum), newchk, 26 SHA512_DIGEST_SIZE); 27 VbExFree(newchk); 28 } 29 30 static void KeyBlockVerifyTest(const VbPublicKey *public_key, 31 const VbPrivateKey *private_key, 32 const VbPublicKey *data_key) 33 { 34 VbKeyBlockHeader *hdr; 35 VbKeyBlockHeader *h; 36 unsigned hsize; 37 38 hdr = KeyBlockCreate(data_key, private_key, 0x1234); 39 TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites"); 40 if (!hdr) 41 return; 42 hsize = (unsigned) hdr->key_block_size; 43 h = (VbKeyBlockHeader *)malloc(hsize + 1024); 44 45 TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0, 46 "KeyBlockVerify() ok using checksum"); 47 TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0, 48 "KeyBlockVerify() ok using key"); 49 TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0, 50 "KeyBlockVerify() missing key"); 51 52 TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0, 53 "KeyBlockVerify() size--"); 54 TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0, 55 "KeyBlockVerify() size++"); 56 57 Memcpy(h, hdr, hsize); 58 h->magic[0] &= 0x12; 59 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 60 "KeyBlockVerify() magic"); 61 62 /* Care about major version but not minor */ 63 Memcpy(h, hdr, hsize); 64 h->header_version_major++; 65 ReChecksumKeyBlock(h); 66 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 67 "KeyBlockVerify() major++"); 68 69 Memcpy(h, hdr, hsize); 70 h->header_version_major--; 71 ReChecksumKeyBlock(h); 72 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 73 "KeyBlockVerify() major--"); 74 75 Memcpy(h, hdr, hsize); 76 h->header_version_minor++; 77 ReChecksumKeyBlock(h); 78 TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 79 "KeyBlockVerify() minor++"); 80 81 Memcpy(h, hdr, hsize); 82 h->header_version_minor--; 83 ReChecksumKeyBlock(h); 84 TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 85 "KeyBlockVerify() minor--"); 86 87 /* Check hash */ 88 Memcpy(h, hdr, hsize); 89 h->key_block_checksum.sig_offset = hsize; 90 ReChecksumKeyBlock(h); 91 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 92 "KeyBlockVerify() checksum off end"); 93 94 Memcpy(h, hdr, hsize); 95 h->key_block_checksum.sig_size /= 2; 96 ReChecksumKeyBlock(h); 97 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 98 "KeyBlockVerify() checksum too small"); 99 100 Memcpy(h, hdr, hsize); 101 GetPublicKeyData(&h->data_key)[0] ^= 0x34; 102 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 103 "KeyBlockVerify() checksum mismatch"); 104 105 /* Check signature */ 106 Memcpy(h, hdr, hsize); 107 h->key_block_signature.sig_offset = hsize; 108 ReChecksumKeyBlock(h); 109 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, 110 "KeyBlockVerify() sig off end"); 111 112 Memcpy(h, hdr, hsize); 113 h->key_block_signature.sig_size--; 114 ReChecksumKeyBlock(h); 115 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, 116 "KeyBlockVerify() sig too small"); 117 118 Memcpy(h, hdr, hsize); 119 GetPublicKeyData(&h->data_key)[0] ^= 0x34; 120 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, 121 "KeyBlockVerify() sig mismatch"); 122 123 Memcpy(h, hdr, hsize); 124 h->key_block_checksum.data_size = h->key_block_size + 1; 125 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0, 126 "KeyBlockVerify() checksum data past end of block"); 127 128 /* Check that we signed header and data key */ 129 Memcpy(h, hdr, hsize); 130 h->key_block_checksum.data_size = 4; 131 h->data_key.key_offset = 0; 132 h->data_key.key_size = 0; 133 ReChecksumKeyBlock(h); 134 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 135 "KeyBlockVerify() didn't sign header"); 136 137 Memcpy(h, hdr, hsize); 138 h->data_key.key_offset = hsize; 139 ReChecksumKeyBlock(h); 140 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, 141 "KeyBlockVerify() data key off end"); 142 143 /* Corner cases for error checking */ 144 TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0, 145 "KeyBlockVerify size too small"); 146 147 /* 148 * TODO: verify parser can support a bigger header (i.e., one where 149 * data_key.key_offset is bigger than expected). 150 */ 151 152 free(h); 153 free(hdr); 154 } 155 156 static void ReSignFirmwarePreamble(VbFirmwarePreambleHeader *h, 157 const VbPrivateKey *key) 158 { 159 VbSignature *sig = CalculateSignature( 160 (const uint8_t *)h, h->preamble_signature.data_size, key); 161 162 SignatureCopy(&h->preamble_signature, sig); 163 free(sig); 164 } 165 166 static void VerifyFirmwarePreambleTest(const VbPublicKey *public_key, 167 const VbPrivateKey *private_key, 168 const VbPublicKey *kernel_subkey) 169 { 170 VbFirmwarePreambleHeader *hdr; 171 VbFirmwarePreambleHeader *h; 172 RSAPublicKey *rsa; 173 unsigned hsize; 174 175 /* Create a dummy signature */ 176 VbSignature* body_sig = SignatureAlloc(56, 78); 177 178 rsa = PublicKeyToRSA(public_key); 179 hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, 180 private_key, 0x5678); 181 TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites"); 182 if (!hdr) 183 return; 184 hsize = (unsigned) hdr->preamble_size; 185 h = (VbFirmwarePreambleHeader *)malloc(hsize + 16384); 186 187 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0, 188 "VerifyFirmwarePreamble() ok using key"); 189 TEST_NEQ(VerifyFirmwarePreamble(hdr, 4, rsa), 0, 190 "VerifyFirmwarePreamble() size tiny"); 191 TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0, 192 "VerifyFirmwarePreamble() size--"); 193 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0, 194 "VerifyFirmwarePreamble() size++"); 195 196 /* Care about major version but not minor */ 197 Memcpy(h, hdr, hsize); 198 h->header_version_major++; 199 ReSignFirmwarePreamble(h, private_key); 200 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 201 "VerifyFirmwarePreamble() major++"); 202 203 Memcpy(h, hdr, hsize); 204 h->header_version_major--; 205 ReSignFirmwarePreamble(h, private_key); 206 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 207 "VerifyFirmwarePreamble() major--"); 208 209 Memcpy(h, hdr, hsize); 210 h->header_version_minor++; 211 ReSignFirmwarePreamble(h, private_key); 212 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 213 "VerifyFirmwarePreamble() minor++"); 214 215 Memcpy(h, hdr, hsize); 216 h->header_version_minor--; 217 ReSignFirmwarePreamble(h, private_key); 218 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 219 "VerifyFirmwarePreamble() minor--"); 220 221 /* Check signature */ 222 Memcpy(h, hdr, hsize); 223 h->preamble_signature.sig_offset = hsize; 224 ReSignFirmwarePreamble(h, private_key); 225 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 226 "VerifyFirmwarePreamble() sig off end"); 227 228 Memcpy(h, hdr, hsize); 229 h->preamble_signature.sig_size--; 230 ReSignFirmwarePreamble(h, private_key); 231 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 232 "VerifyFirmwarePreamble() sig too small"); 233 234 Memcpy(h, hdr, hsize); 235 GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34; 236 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 237 "VerifyFirmwarePreamble() sig mismatch"); 238 239 /* Check that we signed header, kernel subkey, and body sig */ 240 Memcpy(h, hdr, hsize); 241 h->preamble_signature.data_size = 4; 242 h->kernel_subkey.key_offset = 0; 243 h->kernel_subkey.key_size = 0; 244 h->body_signature.sig_offset = 0; 245 h->body_signature.sig_size = 0; 246 ReSignFirmwarePreamble(h, private_key); 247 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 248 "VerifyFirmwarePreamble() didn't sign header"); 249 250 Memcpy(h, hdr, hsize); 251 h->kernel_subkey.key_offset = hsize; 252 ReSignFirmwarePreamble(h, private_key); 253 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 254 "VerifyFirmwarePreamble() kernel subkey off end"); 255 256 Memcpy(h, hdr, hsize); 257 h->body_signature.sig_offset = hsize; 258 ReSignFirmwarePreamble(h, private_key); 259 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, 260 "VerifyFirmwarePreamble() body sig off end"); 261 262 /* Check that we return flags properly for new and old structs */ 263 Memcpy(h, hdr, hsize); 264 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678, 265 "VbGetFirmwarePreambleFlags() v2.1"); 266 h->header_version_minor = 0; 267 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0, 268 "VbGetFirmwarePreambleFlags() v2.0"); 269 270 /* TODO: verify with extra padding at end of header. */ 271 272 free(h); 273 RSAPublicKeyFree(rsa); 274 free(hdr); 275 } 276 277 int test_permutation(int signing_key_algorithm, int data_key_algorithm, 278 const char *keys_dir) 279 { 280 char filename[1024]; 281 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8; 282 int data_rsa_len = siglen_map[data_key_algorithm] * 8; 283 284 VbPrivateKey *signing_private_key = NULL; 285 VbPublicKey *signing_public_key = NULL; 286 VbPublicKey *data_public_key = NULL; 287 288 printf("***Testing signing algorithm: %s\n", 289 algo_strings[signing_key_algorithm]); 290 printf("***With data key algorithm: %s\n", 291 algo_strings[data_key_algorithm]); 292 293 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len); 294 signing_private_key = PrivateKeyReadPem(filename, 295 signing_key_algorithm); 296 if (!signing_private_key) { 297 fprintf(stderr, "Error reading signing_private_key: %s\n", 298 filename); 299 return 1; 300 } 301 302 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len); 303 signing_public_key = PublicKeyReadKeyb(filename, 304 signing_key_algorithm, 1); 305 if (!signing_public_key) { 306 fprintf(stderr, "Error reading signing_public_key: %s\n", 307 filename); 308 return 1; 309 } 310 311 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len); 312 data_public_key = PublicKeyReadKeyb(filename, 313 data_key_algorithm, 1); 314 if (!data_public_key) { 315 fprintf(stderr, "Error reading data_public_key: %s\n", 316 filename); 317 return 1; 318 } 319 320 KeyBlockVerifyTest(signing_public_key, signing_private_key, 321 data_public_key); 322 VerifyFirmwarePreambleTest(signing_public_key, signing_private_key, 323 data_public_key); 324 325 if (signing_public_key) 326 free(signing_public_key); 327 if (signing_private_key) 328 free(signing_private_key); 329 if (data_public_key) 330 free(data_public_key); 331 332 return 0; 333 } 334 335 struct test_perm 336 { 337 int signing_algorithm; 338 int data_key_algorithm; 339 }; 340 341 /* 342 * Permutations of signing and data key algorithms in active use: 343 * 7 (rsa4096 sha256) - 4 (rsa2048 sha256) 344 * 11 (rsa8192 sha512) - 4 (rsa2048 sha256) 345 * 11 (rsa8192 sha512) - 7 (rsa4096 sha256) 346 */ 347 const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}}; 348 349 int main(int argc, char *argv[]) 350 { 351 if (argc == 2) { 352 /* Test only the algorithms we use */ 353 int i; 354 355 for (i = 0; i < ARRAY_SIZE(test_perms); i++) { 356 if (test_permutation(test_perms[i].signing_algorithm, 357 test_perms[i].data_key_algorithm, 358 argv[1])) 359 return 1; 360 } 361 362 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) { 363 /* Test all the algorithms */ 364 int sign_alg, data_alg; 365 366 for (sign_alg = 0; sign_alg < kNumAlgorithms; sign_alg++) { 367 for (data_alg = 0; data_alg < kNumAlgorithms; 368 data_alg++) { 369 if (test_permutation(sign_alg, data_alg, 370 argv[1])) 371 return 1; 372 } 373 } 374 } else { 375 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]); 376 return -1; 377 } 378 379 if (vboot_api_stub_check_memory()) 380 return 255; 381 382 return gTestSuccess ? 0 : 255; 383 } 384