132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * Use of this source code is governed by a BSD-style license that can be
3d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * found in the LICENSE file.
4d183644564ec27c106a3eb1931f565fae167a058Randall Spangler *
5d183644564ec27c106a3eb1931f565fae167a058Randall Spangler * Host functions for keys.
6d183644564ec27c106a3eb1931f565fae167a058Randall Spangler */
7d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
8d183644564ec27c106a3eb1931f565fae167a058Randall Spangler/* TODO: change all 'return 0', 'return 1' into meaningful return codes */
9d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
10d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include <openssl/pem.h>
11d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
12d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include <stdio.h>
13d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include <stdlib.h>
14d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include <unistd.h>
15d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
16d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include "cryptolib.h"
1732a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler#include "host_common.h"
1832a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler#include "host_key.h"
19d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler#include "host_misc.h"
20d183644564ec27c106a3eb1931f565fae167a058Randall Spangler#include "vboot_common.h"
21d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
22d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
23a08b5c9d032be485fe6e2790c23e8c9bb9fca2adBill RichardsonVbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm) {
24d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
25d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  VbPrivateKey* key;
26d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  RSA* rsa_key;
27d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  FILE* f;
28d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
29d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (algorithm >= kNumAlgorithms) {
30abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("%s() called with invalid algorithm!\n", __FUNCTION__));
31d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
32d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
33d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
34d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  /* Read private key */
35d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  f = fopen(filename, "r");
36d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!f) {
37abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename));
38d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
39d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
40d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
41d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  fclose(f);
42d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!rsa_key) {
43abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("%s(): Couldn't read private key from file: %s\n", __FUNCTION__,
44abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson             filename));
45d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
46d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
47d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
48d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  /* Store key and algorithm in our struct */
4932a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey));
50d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!key) {
51d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    RSA_free(rsa_key);
52d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
53d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
54d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->rsa_private_key = rsa_key;
55d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->algorithm = algorithm;
56d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
57d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  /* Return the key */
58d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  return key;
59d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
60d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
61d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
62d183644564ec27c106a3eb1931f565fae167a058Randall Spanglervoid PrivateKeyFree(VbPrivateKey* key) {
63d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!key)
64d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return;
65d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (key->rsa_private_key)
66d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    RSA_free(key->rsa_private_key);
6732a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(key);
68d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
69d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
70d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
71abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson/* Write a private key to a file in .vbprivk format. */
72abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardsonint PrivateKeyWrite(const char* filename, const VbPrivateKey* key) {
73abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  uint8_t *outbuf = 0;
74abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  int buflen;
75abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  FILE *f;
76abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
77abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf);
78abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (buflen <= 0) {
7932a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to write private key buffer\n");
80abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    return 1;
81abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
82abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
83abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  f = fopen(filename, "wb");
84abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (!f) {
8532a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to open file %s\n", filename);
8632a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(outbuf);
87abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    return 1;
88abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
89abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
90abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (1 != fwrite(&key->algorithm, sizeof(key->algorithm), 1, f)) {
9132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to write to file %s\n", filename);
92abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    fclose(f);
9332a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(outbuf);
94abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    unlink(filename);  /* Delete any partial file */
95abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
96abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
97abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (1 != fwrite(outbuf, buflen, 1, f)) {
9832a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to write to file %s\n", filename);
99abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    fclose(f);
100abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    unlink(filename);  /* Delete any partial file */
10132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(outbuf);
102abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
103abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
104abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  fclose(f);
10532a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(outbuf);
106abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  return 0;
107abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson}
108abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
109abf055045802cb06c57ff2d7b187736bdcb3b138Bill RichardsonVbPrivateKey* PrivateKeyRead(const char* filename) {
110abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  VbPrivateKey *key;
111abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  uint64_t filelen = 0;
112abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  uint8_t *buffer;
113abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  const unsigned char *start;
11447b593d84920479ae5955fcc6664635328376a10Gaurav Shah
115abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  buffer = ReadFile(filename, &filelen);
116abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (!buffer) {
11732a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("unable to read from file %s\n", filename);
118abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    return 0;
119abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
120abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
12132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey));
122abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (!key) {
12332a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to allocate VbPrivateKey\n");
12432a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(buffer);
125abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    return 0;
126abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
127abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
128abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  key->algorithm = *(typeof(key->algorithm) *)buffer;
129abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  start = buffer + sizeof(key->algorithm);
130abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
131abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  key->rsa_private_key = d2i_RSAPrivateKey(0, &start,
132abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson                                           filelen - sizeof(key->algorithm));
133abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
134abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  if (!key->rsa_private_key) {
13532a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    VbExError("Unable to parse RSA private key\n");
13632a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(buffer);
13732a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(key);
138abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    return 0;
139abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  }
140abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
14132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(buffer);
142abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson  return key;
143abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson}
144abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
145abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson
146d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler/* Allocate a new public key with space for a [key_size] byte key. */
147d183644564ec27c106a3eb1931f565fae167a058Randall SpanglerVbPublicKey* PublicKeyAlloc(uint64_t key_size, uint64_t algorithm,
148d183644564ec27c106a3eb1931f565fae167a058Randall Spangler                            uint64_t version) {
14932a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  VbPublicKey* key = (VbPublicKey*)malloc(sizeof(VbPublicKey) + key_size);
150d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!key)
151d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
152d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
153d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->algorithm = algorithm;
154d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->key_version = version;
155d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->key_size = key_size;
156d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key->key_offset = sizeof(VbPublicKey);
157d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  return key;
158d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
159d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
160d55c64537245abca67a66fde5874b7f4a6cdc556Randall SpanglerVbPublicKey* PublicKeyReadKeyb(const char* filename, uint64_t algorithm,
161d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler                               uint64_t version) {
162d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  VbPublicKey* key;
163d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  uint8_t* key_data;
164d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  uint64_t key_size;
165d583a30a7c3bd369f82c0428666c7a708d5341d5Gaurav Shah  uint64_t expected_key_size;
166d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
167d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (algorithm >= kNumAlgorithms) {
168abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("PublicKeyReadKeyb() called with invalid algorithm!\n"));
169d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
170d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
171d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (version > 0xFFFF) {
172d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    /* Currently, TPM only supports 16-bit version */
173abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("PublicKeyReadKeyb() called with invalid version!\n"));
174d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
175d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
176d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
177d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  key_data = ReadFile(filename, &key_size);
178d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!key_data)
179d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
180d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
18147b593d84920479ae5955fcc6664635328376a10Gaurav Shah  if (!RSAProcessedKeySize(algorithm, &expected_key_size) ||
18247b593d84920479ae5955fcc6664635328376a10Gaurav Shah      expected_key_size != key_size) {
183abf055045802cb06c57ff2d7b187736bdcb3b138Bill Richardson    VBDEBUG(("PublicKeyReadKeyb() wrong key size for algorithm\n"));
18432a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(key_data);
185d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler    return NULL;
186d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  }
187d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
188d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  key = PublicKeyAlloc(key_size, algorithm, version);
189d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  if (!key) {
19032a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(key_data);
191d183644564ec27c106a3eb1931f565fae167a058Randall Spangler    return NULL;
192d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  }
193d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  Memcpy(GetPublicKeyData(key), key_data, key_size);
194d183644564ec27c106a3eb1931f565fae167a058Randall Spangler
19532a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(key_data);
196d183644564ec27c106a3eb1931f565fae167a058Randall Spangler  return key;
197d183644564ec27c106a3eb1931f565fae167a058Randall Spangler}
198d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
199d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
200f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardsonint PublicKeyLooksOkay(VbPublicKey *key, uint64_t file_size)
201f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson{
202f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  uint64_t key_size;
203f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson
204f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  /* Sanity-check key data */
205f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  if (0 != VerifyPublicKeyInside(key, file_size, key)) {
206f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    VBDEBUG(("PublicKeyRead() not a VbPublicKey\n"));
207f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    return 0;
208f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  }
209f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  if (key->algorithm >= kNumAlgorithms) {
210f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    VBDEBUG(("PublicKeyRead() invalid algorithm\n"));
211f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    return 0;
212f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  }
213f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  if (key->key_version > 0xFFFF) {
214f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    VBDEBUG(("PublicKeyRead() invalid version\n"));
215f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    return 0;  /* Currently, TPM only supports 16-bit version */
216f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  }
217f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
218f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson      key_size != key->key_size) {
219f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    VBDEBUG(("PublicKeyRead() wrong key size for algorithm\n"));
220f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson    return 0;
221f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  }
222f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson
223f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  /* Success */
224f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  return 1;
225f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson}
226f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson
227f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson
228f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson
229d55c64537245abca67a66fde5874b7f4a6cdc556Randall SpanglerVbPublicKey* PublicKeyRead(const char* filename) {
230d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  VbPublicKey* key;
231d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  uint64_t file_size;
232d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
233d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  key = (VbPublicKey*)ReadFile(filename, &file_size);
234d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  if (!key)
235d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler    return NULL;
236d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
237f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson  if (PublicKeyLooksOkay(key, file_size))
238f16ed878799cc7cf11545c36d6f332c76d612260Bill Richardson      return key;
239d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
240d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  /* Error */
24132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(key);
242d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  return NULL;
243d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler}
244d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
245d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spanglerint PublicKeyWrite(const char* filename, const VbPublicKey* key) {
2466a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  VbPublicKey* kcopy;
2476a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  int rv;
248d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
2496a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  /* Copy the key, so its data is contiguous with the header */
2506a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  kcopy = PublicKeyAlloc(key->key_size, 0, 0);
2516a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  if (!kcopy)
2526a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler    return 1;
2536a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  if (0 != PublicKeyCopy(kcopy, key)) {
25432a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler    free(kcopy);
2556a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler    return 1;
2566a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  }
257d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler
2586a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  /* Write the copy, then free it */
2596a97b3e2a1bee35bf3c00f2fb0faafde4aaab9e2Randall Spangler  rv = WriteFile(filename, kcopy, kcopy->key_offset + kcopy->key_size);
26032a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  free(kcopy);
261d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler  return rv;
262d55c64537245abca67a66fde5874b7f4a6cdc556Randall Spangler}
263