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