132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 2729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * Use of this source code is governed by a BSD-style license that can be 3729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * found in the LICENSE file. 4729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * 5729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * Host functions for verified boot. 6729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler */ 7729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 8729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 9729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler#include "cryptolib.h" 10729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler#include "host_common.h" 1132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler#include "host_keyblock.h" 12729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler#include "vboot_common.h" 13729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 14729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 15729b87258b5dd499ce3c910499c010d3840628dfRandall SpanglerVbKeyBlockHeader* KeyBlockCreate(const VbPublicKey* data_key, 16729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler const VbPrivateKey* signing_key, 17729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint64_t flags) { 18729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 19729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler VbKeyBlockHeader* h; 20729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint64_t signed_size = sizeof(VbKeyBlockHeader) + data_key->key_size; 21729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint64_t block_size = (signed_size + SHA512_DIGEST_SIZE + 22138acfe1ba4b567f470c67e22a8d9e2225beafb0Randall Spangler (signing_key ? 23138acfe1ba4b567f470c67e22a8d9e2225beafb0Randall Spangler siglen_map[signing_key->algorithm] : 0)); 24729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint8_t* data_key_dest; 25729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint8_t* block_sig_dest; 26729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint8_t* block_chk_dest; 27729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler VbSignature *sigtmp; 28729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 29729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Allocate key block */ 3032a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler h = (VbKeyBlockHeader*)malloc(block_size); 31729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler if (!h) 32729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return NULL; 33729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler data_key_dest = (uint8_t*)(h + 1); 34729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler block_chk_dest = data_key_dest + data_key->key_size; 35729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler block_sig_dest = block_chk_dest + SHA512_DIGEST_SIZE; 36729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 37729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler Memcpy(h->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE); 38729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler h->header_version_major = KEY_BLOCK_HEADER_VERSION_MAJOR; 39729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler h->header_version_minor = KEY_BLOCK_HEADER_VERSION_MINOR; 40729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler h->key_block_size = block_size; 41729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler h->key_block_flags = flags; 42729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 43729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Copy data key */ 44729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler PublicKeyInit(&h->data_key, data_key_dest, data_key->key_size); 45729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler PublicKeyCopy(&h->data_key, data_key); 46729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 47729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Set up signature structs so we can calculate the signatures */ 48729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler SignatureInit(&h->key_block_checksum, block_chk_dest, 49729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler SHA512_DIGEST_SIZE, signed_size); 504f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson if (signing_key) 514f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson SignatureInit(&h->key_block_signature, block_sig_dest, 524f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson siglen_map[signing_key->algorithm], signed_size); 534f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson else 544f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson Memset(&h->key_block_signature, 0, sizeof(VbSignature)); 55729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 56729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Calculate checksum */ 57729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler sigtmp = CalculateChecksum((uint8_t*)h, signed_size); 58729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler SignatureCopy(&h->key_block_checksum, sigtmp); 5932a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler free(sigtmp); 60729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 61729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Calculate signature */ 624f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson if (signing_key) { 634f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson sigtmp = CalculateSignature((uint8_t*)h, signed_size, signing_key); 644f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson SignatureCopy(&h->key_block_signature, sigtmp); 6532a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler free(sigtmp); 664f36ef336036e01b0bd2b395dd55e15db0267266Bill Richardson } 67729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 68729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Return the header */ 69729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return h; 70729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler} 71729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 72068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah/* TODO(gauravsh): This could easily be integrated into KeyBlockCreate() 73068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah * since the code is almost a mirror - I have kept it as such to avoid changing 74068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah * the existing interface. */ 75068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav ShahVbKeyBlockHeader* KeyBlockCreate_external(const VbPublicKey* data_key, 76068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah const char* signing_key_pem_file, 77068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint64_t algorithm, 78068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint64_t flags, 79068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah const char* external_signer) { 80068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah VbKeyBlockHeader* h; 81068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint64_t signed_size = sizeof(VbKeyBlockHeader) + data_key->key_size; 82068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint64_t block_size = (signed_size + SHA512_DIGEST_SIZE + 83068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah siglen_map[algorithm]); 84068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint8_t* data_key_dest; 85068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint8_t* block_sig_dest; 86068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah uint8_t* block_chk_dest; 87068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah VbSignature *sigtmp; 88068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 89068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Allocate key block */ 9032a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler h = (VbKeyBlockHeader*)malloc(block_size); 91068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah if (!h) 92068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah return NULL; 93068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah if (!signing_key_pem_file || !data_key || !external_signer) 94068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah return NULL; 95068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 96068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah data_key_dest = (uint8_t*)(h + 1); 97068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah block_chk_dest = data_key_dest + data_key->key_size; 98068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah block_sig_dest = block_chk_dest + SHA512_DIGEST_SIZE; 99068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 100068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah Memcpy(h->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE); 101068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah h->header_version_major = KEY_BLOCK_HEADER_VERSION_MAJOR; 102068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah h->header_version_minor = KEY_BLOCK_HEADER_VERSION_MINOR; 103068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah h->key_block_size = block_size; 104068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah h->key_block_flags = flags; 105068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 106068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Copy data key */ 107068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah PublicKeyInit(&h->data_key, data_key_dest, data_key->key_size); 108068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah PublicKeyCopy(&h->data_key, data_key); 109068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 110068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Set up signature structs so we can calculate the signatures */ 111068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah SignatureInit(&h->key_block_checksum, block_chk_dest, 112068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah SHA512_DIGEST_SIZE, signed_size); 113068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah SignatureInit(&h->key_block_signature, block_sig_dest, 114068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah siglen_map[algorithm], signed_size); 115068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 116068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Calculate checksum */ 117068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah sigtmp = CalculateChecksum((uint8_t*)h, signed_size); 118068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah SignatureCopy(&h->key_block_checksum, sigtmp); 11932a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler free(sigtmp); 120068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 121068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Calculate signature */ 122068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah sigtmp = CalculateSignature_external((uint8_t*)h, signed_size, 123068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah signing_key_pem_file, algorithm, 124068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah external_signer); 125068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah SignatureCopy(&h->key_block_signature, sigtmp); 12632a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler free(sigtmp); 127068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah 128068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah /* Return the header */ 129068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah return h; 130068fc6f251bc80190ad976d18ffe4726a3f33026Gaurav Shah} 131729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 132729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler/* Read a key block from a .keyblock file. Caller owns the returned 13332a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler * pointer, and must free it with free(). 134729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * 135729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * Returns NULL if error. */ 136729b87258b5dd499ce3c910499c010d3840628dfRandall SpanglerVbKeyBlockHeader* KeyBlockRead(const char* filename) { 137729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 138729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler VbKeyBlockHeader* block; 139729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler uint64_t file_size; 140729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 141729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler block = (VbKeyBlockHeader*)ReadFile(filename, &file_size); 142729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler if (!block) { 143abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson VBDEBUG(("Error reading key block file: %s\n", filename)); 144729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return NULL; 145729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler } 146729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 147729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler /* Verify the hash of the key block, since we can do that without 148729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler * the public signing key. */ 149138acfe1ba4b567f470c67e22a8d9e2225beafb0Randall Spangler if (0 != KeyBlockVerify(block, file_size, NULL, 1)) { 1503401fdcd4125beea1a8cb1cc59ee27df89d4d88aSimon Glass VBDEBUG(("Invalid key block file: %s\n", filename)); 15132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler free(block); 152729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return NULL; 153729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler } 154729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 155729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return block; 156729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler} 157729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 158729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 159729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler/* Write a key block to a file in .keyblock format. */ 160729b87258b5dd499ce3c910499c010d3840628dfRandall Spanglerint KeyBlockWrite(const char* filename, const VbKeyBlockHeader* key_block) { 161729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 162729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler if (0 != WriteFile(filename, key_block, key_block->key_block_size)) { 163abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson VBDEBUG(("KeyBlockWrite() error writing key block\n")); 164729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return 1; 165729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler } 166729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler 167729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler return 0; 168729b87258b5dd499ce3c910499c010d3840628dfRandall Spangler} 169