1 /* Copyright (c) 2011 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 * Host functions for verified boot.
6 */
7
8
9 #include "cryptolib.h"
10 #include "host_common.h"
11 #include "host_keyblock.h"
12 #include "vboot_common.h"
13
14
KeyBlockCreate(const VbPublicKey * data_key,const VbPrivateKey * signing_key,uint64_t flags)15 VbKeyBlockHeader* KeyBlockCreate(const VbPublicKey* data_key,
16 const VbPrivateKey* signing_key,
17 uint64_t flags) {
18
19 VbKeyBlockHeader* h;
20 uint64_t signed_size = sizeof(VbKeyBlockHeader) + data_key->key_size;
21 uint64_t block_size = (signed_size + SHA512_DIGEST_SIZE +
22 (signing_key ?
23 siglen_map[signing_key->algorithm] : 0));
24 uint8_t* data_key_dest;
25 uint8_t* block_sig_dest;
26 uint8_t* block_chk_dest;
27 VbSignature *sigtmp;
28
29 /* Allocate key block */
30 h = (VbKeyBlockHeader*)malloc(block_size);
31 if (!h)
32 return NULL;
33 data_key_dest = (uint8_t*)(h + 1);
34 block_chk_dest = data_key_dest + data_key->key_size;
35 block_sig_dest = block_chk_dest + SHA512_DIGEST_SIZE;
36
37 Memcpy(h->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE);
38 h->header_version_major = KEY_BLOCK_HEADER_VERSION_MAJOR;
39 h->header_version_minor = KEY_BLOCK_HEADER_VERSION_MINOR;
40 h->key_block_size = block_size;
41 h->key_block_flags = flags;
42
43 /* Copy data key */
44 PublicKeyInit(&h->data_key, data_key_dest, data_key->key_size);
45 PublicKeyCopy(&h->data_key, data_key);
46
47 /* Set up signature structs so we can calculate the signatures */
48 SignatureInit(&h->key_block_checksum, block_chk_dest,
49 SHA512_DIGEST_SIZE, signed_size);
50 if (signing_key)
51 SignatureInit(&h->key_block_signature, block_sig_dest,
52 siglen_map[signing_key->algorithm], signed_size);
53 else
54 Memset(&h->key_block_signature, 0, sizeof(VbSignature));
55
56 /* Calculate checksum */
57 sigtmp = CalculateChecksum((uint8_t*)h, signed_size);
58 SignatureCopy(&h->key_block_checksum, sigtmp);
59 free(sigtmp);
60
61 /* Calculate signature */
62 if (signing_key) {
63 sigtmp = CalculateSignature((uint8_t*)h, signed_size, signing_key);
64 SignatureCopy(&h->key_block_signature, sigtmp);
65 free(sigtmp);
66 }
67
68 /* Return the header */
69 return h;
70 }
71
72 /* TODO(gauravsh): This could easily be integrated into KeyBlockCreate()
73 * since the code is almost a mirror - I have kept it as such to avoid changing
74 * the existing interface. */
KeyBlockCreate_external(const VbPublicKey * data_key,const char * signing_key_pem_file,uint64_t algorithm,uint64_t flags,const char * external_signer)75 VbKeyBlockHeader* KeyBlockCreate_external(const VbPublicKey* data_key,
76 const char* signing_key_pem_file,
77 uint64_t algorithm,
78 uint64_t flags,
79 const char* external_signer) {
80 VbKeyBlockHeader* h;
81 uint64_t signed_size = sizeof(VbKeyBlockHeader) + data_key->key_size;
82 uint64_t block_size = (signed_size + SHA512_DIGEST_SIZE +
83 siglen_map[algorithm]);
84 uint8_t* data_key_dest;
85 uint8_t* block_sig_dest;
86 uint8_t* block_chk_dest;
87 VbSignature *sigtmp;
88
89 /* Allocate key block */
90 h = (VbKeyBlockHeader*)malloc(block_size);
91 if (!h)
92 return NULL;
93 if (!signing_key_pem_file || !data_key || !external_signer)
94 return NULL;
95
96 data_key_dest = (uint8_t*)(h + 1);
97 block_chk_dest = data_key_dest + data_key->key_size;
98 block_sig_dest = block_chk_dest + SHA512_DIGEST_SIZE;
99
100 Memcpy(h->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE);
101 h->header_version_major = KEY_BLOCK_HEADER_VERSION_MAJOR;
102 h->header_version_minor = KEY_BLOCK_HEADER_VERSION_MINOR;
103 h->key_block_size = block_size;
104 h->key_block_flags = flags;
105
106 /* Copy data key */
107 PublicKeyInit(&h->data_key, data_key_dest, data_key->key_size);
108 PublicKeyCopy(&h->data_key, data_key);
109
110 /* Set up signature structs so we can calculate the signatures */
111 SignatureInit(&h->key_block_checksum, block_chk_dest,
112 SHA512_DIGEST_SIZE, signed_size);
113 SignatureInit(&h->key_block_signature, block_sig_dest,
114 siglen_map[algorithm], signed_size);
115
116 /* Calculate checksum */
117 sigtmp = CalculateChecksum((uint8_t*)h, signed_size);
118 SignatureCopy(&h->key_block_checksum, sigtmp);
119 free(sigtmp);
120
121 /* Calculate signature */
122 sigtmp = CalculateSignature_external((uint8_t*)h, signed_size,
123 signing_key_pem_file, algorithm,
124 external_signer);
125 SignatureCopy(&h->key_block_signature, sigtmp);
126 free(sigtmp);
127
128 /* Return the header */
129 return h;
130 }
131
132 /* Read a key block from a .keyblock file. Caller owns the returned
133 * pointer, and must free it with free().
134 *
135 * Returns NULL if error. */
KeyBlockRead(const char * filename)136 VbKeyBlockHeader* KeyBlockRead(const char* filename) {
137
138 VbKeyBlockHeader* block;
139 uint64_t file_size;
140
141 block = (VbKeyBlockHeader*)ReadFile(filename, &file_size);
142 if (!block) {
143 VBDEBUG(("Error reading key block file: %s\n", filename));
144 return NULL;
145 }
146
147 /* Verify the hash of the key block, since we can do that without
148 * the public signing key. */
149 if (0 != KeyBlockVerify(block, file_size, NULL, 1)) {
150 VBDEBUG(("Invalid key block file: %s\n", filename));
151 free(block);
152 return NULL;
153 }
154
155 return block;
156 }
157
158
159 /* Write a key block to a file in .keyblock format. */
KeyBlockWrite(const char * filename,const VbKeyBlockHeader * key_block)160 int KeyBlockWrite(const char* filename, const VbKeyBlockHeader* key_block) {
161
162 if (0 != WriteFile(filename, key_block, key_block->key_block_size)) {
163 VBDEBUG(("KeyBlockWrite() error writing key block\n"));
164 return 1;
165 }
166
167 return 0;
168 }
169