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