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 19static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key) 20{ 21 RSAPublicKey *rsa; 22 VbPublicKey *key = PublicKeyAlloc(orig_key->key_size, 0, 0); 23 24 PublicKeyCopy(key, orig_key); 25 key->algorithm = kNumAlgorithms; 26 TEST_EQ((size_t)PublicKeyToRSA(key), 0, 27 "PublicKeyToRSA() invalid algorithm"); 28 29 PublicKeyCopy(key, orig_key); 30 key->key_size -= 1; 31 TEST_EQ((size_t)PublicKeyToRSA(key), 0, 32 "PublicKeyToRSA() invalid size"); 33 34 rsa = PublicKeyToRSA(orig_key); 35 TEST_NEQ((size_t)rsa, 0, "PublicKeyToRSA() ok"); 36 if (rsa) { 37 TEST_EQ((int)rsa->algorithm, (int)key->algorithm, 38 "PublicKeyToRSA() algorithm"); 39 RSAPublicKeyFree(rsa); 40 } 41} 42 43static void VerifyDataTest(const VbPublicKey *public_key, 44 const VbPrivateKey *private_key) 45{ 46 const uint8_t test_data[] = "This is some test data to sign."; 47 const uint64_t test_size = sizeof(test_data); 48 VbSignature *sig; 49 RSAPublicKey *rsa; 50 51 sig = CalculateSignature(test_data, test_size, private_key); 52 TEST_PTR_NEQ(sig, 0, "VerifyData() calculate signature"); 53 54 rsa = PublicKeyToRSA(public_key); 55 TEST_PTR_NEQ(rsa, 0, "VerifyData() calculate rsa"); 56 57 if (!sig || !rsa) 58 return; 59 60 TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 0, 61 "VerifyData() ok"); 62 63 sig->sig_size -= 16; 64 TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1, 65 "VerifyData() wrong sig size"); 66 sig->sig_size += 16; 67 68 TEST_EQ(VerifyData(test_data, test_size - 1, sig, rsa), 1, 69 "VerifyData() input buffer too small"); 70 71 GetSignatureData(sig)[0] ^= 0x5A; 72 TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1, 73 "VerifyData() wrong sig"); 74 75 RSAPublicKeyFree(rsa); 76 free(sig); 77} 78 79static void VerifyDigestTest(const VbPublicKey *public_key, 80 const VbPrivateKey *private_key) 81{ 82 const uint8_t test_data[] = "This is some other test data to sign."; 83 VbSignature *sig; 84 RSAPublicKey *rsa; 85 uint8_t *digest; 86 87 sig = CalculateSignature(test_data, sizeof(test_data), private_key); 88 rsa = PublicKeyToRSA(public_key); 89 digest = DigestBuf(test_data, sizeof(test_data), 90 (int)public_key->algorithm); 91 TEST_NEQ(sig && rsa && digest, 0, "VerifyData() prerequisites"); 92 if (!sig || !rsa || !digest) 93 return; 94 95 TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok"); 96 97 GetSignatureData(sig)[0] ^= 0x5A; 98 TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig"); 99 100 sig->sig_size = 1; 101 TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() sig size"); 102 103 RSAPublicKeyFree(rsa); 104 free(sig); 105 VbExFree(digest); 106} 107 108static void ReSignKernelPreamble(VbKernelPreambleHeader *h, 109 const VbPrivateKey *key) 110{ 111 VbSignature *sig = CalculateSignature((const uint8_t *)h, 112 h->preamble_signature.data_size, key); 113 114 SignatureCopy(&h->preamble_signature, sig); 115 free(sig); 116} 117 118static void VerifyKernelPreambleTest(const VbPublicKey *public_key, 119 const VbPrivateKey *private_key) 120{ 121 VbKernelPreambleHeader *hdr; 122 VbKernelPreambleHeader *h; 123 RSAPublicKey *rsa; 124 unsigned hsize; 125 126 /* Create a dummy signature */ 127 VbSignature *body_sig = SignatureAlloc(56, 78); 128 129 rsa = PublicKeyToRSA(public_key); 130 hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig, 131 0, 0, 0, 0, private_key); 132 TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites"); 133 if (!hdr) 134 return; 135 hsize = (unsigned) hdr->preamble_size; 136 h = (VbKernelPreambleHeader *)malloc(hsize + 16384); 137 138 TEST_EQ(VerifyKernelPreamble(hdr, hsize, rsa), 0, 139 "VerifyKernelPreamble() ok using key"); 140 TEST_NEQ(VerifyKernelPreamble(hdr, hsize - 1, rsa), 0, 141 "VerifyKernelPreamble() size--"); 142 TEST_NEQ(VerifyKernelPreamble(hdr, 4, rsa), 0, 143 "VerifyKernelPreamble() size tiny"); 144 TEST_EQ(VerifyKernelPreamble(hdr, hsize + 1, rsa), 0, 145 "VerifyKernelPreamble() size++"); 146 147 /* Care about major version but not minor */ 148 Memcpy(h, hdr, hsize); 149 h->header_version_major++; 150 ReSignKernelPreamble(h, private_key); 151 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 152 "VerifyKernelPreamble() major++"); 153 154 Memcpy(h, hdr, hsize); 155 h->header_version_major--; 156 ReSignKernelPreamble(h, private_key); 157 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 158 "VerifyKernelPreamble() major--"); 159 160 Memcpy(h, hdr, hsize); 161 h->header_version_minor++; 162 ReSignKernelPreamble(h, private_key); 163 TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, 164 "VerifyKernelPreamble() minor++"); 165 166 Memcpy(h, hdr, hsize); 167 h->header_version_minor--; 168 ReSignKernelPreamble(h, private_key); 169 TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, 170 "VerifyKernelPreamble() minor--"); 171 172 /* Check signature */ 173 Memcpy(h, hdr, hsize); 174 h->preamble_signature.sig_offset = hsize; 175 ReSignKernelPreamble(h, private_key); 176 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 177 "VerifyKernelPreamble() sig off end"); 178 179 Memcpy(h, hdr, hsize); 180 h->preamble_signature.sig_size--; 181 ReSignKernelPreamble(h, private_key); 182 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 183 "VerifyKernelPreamble() sig too small"); 184 185 Memcpy(h, hdr, hsize); 186 GetSignatureData(&h->body_signature)[0] ^= 0x34; 187 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 188 "VerifyKernelPreamble() sig mismatch"); 189 190 /* Check that we signed header and body sig */ 191 Memcpy(h, hdr, hsize); 192 h->preamble_signature.data_size = 4; 193 h->body_signature.sig_offset = 0; 194 h->body_signature.sig_size = 0; 195 ReSignKernelPreamble(h, private_key); 196 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 197 "VerifyKernelPreamble() didn't sign header"); 198 199 Memcpy(h, hdr, hsize); 200 h->body_signature.sig_offset = hsize; 201 ReSignKernelPreamble(h, private_key); 202 TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, 203 "VerifyKernelPreamble() body sig off end"); 204 205 /* TODO: verify parser can support a bigger header. */ 206 207 free(h); 208 RSAPublicKeyFree(rsa); 209 free(hdr); 210} 211 212int test_algorithm(int key_algorithm, const char *keys_dir) 213{ 214 char filename[1024]; 215 int rsa_len = siglen_map[key_algorithm] * 8; 216 217 VbPrivateKey *private_key = NULL; 218 VbPublicKey *public_key = NULL; 219 220 printf("***Testing algorithm: %s\n", algo_strings[key_algorithm]); 221 222 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, rsa_len); 223 private_key = PrivateKeyReadPem(filename, key_algorithm); 224 if (!private_key) { 225 fprintf(stderr, "Error reading private_key: %s\n", filename); 226 return 1; 227 } 228 229 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, rsa_len); 230 public_key = PublicKeyReadKeyb(filename, key_algorithm, 1); 231 if (!public_key) { 232 fprintf(stderr, "Error reading public_key: %s\n", filename); 233 return 1; 234 } 235 236 VerifyPublicKeyToRSA(public_key); 237 VerifyDataTest(public_key, private_key); 238 VerifyDigestTest(public_key, private_key); 239 VerifyKernelPreambleTest(public_key, private_key); 240 241 if (public_key) 242 free(public_key); 243 if (private_key) 244 free(private_key); 245 246 return 0; 247} 248 249/* 250 * Test only the algorithms we use: 251 * 4 (rsa2048 sha256) 252 * 7 (rsa4096 sha256) 253 * 11 (rsa8192 sha512) 254 */ 255const int key_algs[] = {4, 7, 11}; 256 257int main(int argc, char *argv[]) { 258 if (argc == 2) { 259 int i; 260 261 for (i = 0; i < ARRAY_SIZE(key_algs); i++) { 262 if (test_algorithm(key_algs[i], argv[1])) 263 return 1; 264 } 265 266 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) { 267 /* Test all the algorithms */ 268 int alg; 269 270 for (alg = 0; alg < kNumAlgorithms; alg++) { 271 if (test_algorithm(alg, argv[1])) 272 return 1; 273 } 274 275 } else { 276 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]); 277 return -1; 278 } 279 280 if (vboot_api_stub_check_memory()) 281 return 255; 282 283 return gTestSuccess ? 0 : 255; 284} 285