• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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