summaryrefslogtreecommitdiff
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/Makefile5
-rw-r--r--host/include/file_keys.h43
-rw-r--r--host/include/signature_digest.h35
-rw-r--r--host/lib/file_keys.c121
-rw-r--r--host/lib/signature_digest.c74
-rw-r--r--host/linktest/main.c13
6 files changed, 289 insertions, 2 deletions
diff --git a/host/Makefile b/host/Makefile
index 7f1c9f15..29b8231c 100644
--- a/host/Makefile
+++ b/host/Makefile
@@ -14,12 +14,13 @@ INCLUDES += \
# find ./lib -iname '*.c' | sort
ALL_SRCS = \
+ ./lib/file_keys.c \
./lib/host_common.c \
./lib/host_key.c \
./lib/host_keyblock.c \
./lib/host_misc.c \
- ./lib/host_signature.c
-
+ ./lib/host_signature.c \
+ ./lib/signature_digest.c
test : $(HOSTLIB)
$(CC) $(CFLAGS) $(INCLUDES) -o $(BUILD_ROOT)/a.out $(TESTDIR)/main.c \
diff --git a/host/include/file_keys.h b/host/include/file_keys.h
new file mode 100644
index 00000000..285a3e5b
--- /dev/null
+++ b/host/include/file_keys.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Utility functions for file and key handling.
+ */
+
+#ifndef VBOOT_REFERENCE_FILE_KEYS_H_
+#define VBOOT_REFERENCE_FILE_KEYS_H_
+
+#include "cryptolib.h"
+
+/* Read file named [input_file] into a buffer and stores the length into
+ * [len].
+ *
+ * Returns a pointer to the buffer. Caller owns the returned pointer and
+ * must free it.
+ */
+uint8_t* BufferFromFile(const char* input_file, uint64_t* len);
+
+/* Read a pre-processed RSA Public Key from file [input_file].
+ *
+ * Returns a pointer to the read key. Caller owns the returned pointer and
+ * must free it.
+ */
+RSAPublicKey* RSAPublicKeyFromFile(const char* input_file);
+
+/* Returns the appropriate digest for the data in [input_file]
+ * based on the signature [algorithm].
+ * Caller owns the returned digest and must free it.
+ */
+uint8_t* DigestFile(char* input_file, int sig_algorithm);
+
+/* Helper function to invoke external program to calculate signature on
+ * [input_file] using private key [key_file] and signature algorithm
+ * [algorithm].
+ *
+ * Returns the signature. Caller owns the buffer and must Free() it.
+ */
+uint8_t* SignatureFile(const char* input_file, const char* key_file,
+ int algorithm);
+
+#endif /* VBOOT_REFERENCE_FILE_KEYS_H_ */
diff --git a/host/include/signature_digest.h b/host/include/signature_digest.h
new file mode 100644
index 00000000..55662b94
--- /dev/null
+++ b/host/include/signature_digest.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef VBOOT_REFERENCE_SIGNATURE_DIGEST_H_
+#define VBOOT_REFERENCE_SIGNATURE_DIGEST_H_
+
+#include <inttypes.h>
+
+/* Returns a buffer with DigestInfo (which depends on [algorithm])
+ * prepended to [digest].
+ */
+uint8_t* PrependDigestInfo(int algorithm, uint8_t* digest);
+
+/* Function that outputs the message digest of the contents of a buffer in a
+ * format that can be used as input to OpenSSL for an RSA signature.
+ * Needed until the stable OpenSSL release supports SHA-256/512 digests for
+ * RSA signatures.
+ *
+ * Returns DigestInfo || Digest where DigestInfo is the OID depending on the
+ * choice of the hash algorithm (see padding.c). Caller owns the returned
+ * pointer and must Free() it.
+ */
+uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len, int algorithm);
+
+/* Calculates the signature on a buffer [buf] of length [len] using
+ * the private RSA key file from [key_file] and signature algorithm
+ * [algorithm].
+ *
+ * Returns the signature. Caller owns the buffer and must Free() it.
+ */
+uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file,
+ int algorithm);
+#endif /* VBOOT_REFERENCE_SIGNATURE_DIGEST_H_ */
diff --git a/host/lib/file_keys.c b/host/lib/file_keys.c
new file mode 100644
index 00000000..c7774306
--- /dev/null
+++ b/host/lib/file_keys.c
@@ -0,0 +1,121 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Utility functions for file and key handling.
+ */
+
+#include "file_keys.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cryptolib.h"
+#include "signature_digest.h"
+#include "utility.h"
+
+uint8_t* BufferFromFile(const char* input_file, uint64_t* len) {
+ int fd;
+ struct stat stat_fd;
+ uint8_t* buf = NULL;
+
+ if ((fd = open(input_file, O_RDONLY)) == -1) {
+ debug("Couldn't open file %s\n", input_file);
+ return NULL;
+ }
+
+ if (-1 == fstat(fd, &stat_fd)) {
+ debug("Couldn't stat file %s\n", input_file);
+ return NULL;
+ }
+ *len = stat_fd.st_size;
+
+ buf = (uint8_t*) Malloc(*len);
+ if (!buf) {
+ error("Couldn't allocate %ld bytes for file %s\n", *len, input_file);
+ return NULL;
+ }
+
+ if (*len != read(fd, buf, *len)) {
+ debug("Couldn't read file %s into a buffer\n", input_file);
+ return NULL;
+ }
+
+ close(fd);
+ return buf;
+}
+
+RSAPublicKey* RSAPublicKeyFromFile(const char* input_file) {
+ uint64_t len;
+ RSAPublicKey* key = NULL;
+ uint8_t* buf = BufferFromFile(input_file, &len);
+ if (buf)
+ key = RSAPublicKeyFromBuf(buf, len);
+ Free(buf);
+ return key;
+}
+
+uint8_t* DigestFile(char* input_file, int sig_algorithm) {
+ int input_fd, len;
+ uint8_t data[SHA1_BLOCK_SIZE];
+ uint8_t* digest = NULL;
+ DigestContext ctx;
+
+ if( (input_fd = open(input_file, O_RDONLY)) == -1 ) {
+ debug("Couldn't open %s\n", input_file);
+ return NULL;
+ }
+ DigestInit(&ctx, sig_algorithm);
+ while ( (len = read(input_fd, data, SHA1_BLOCK_SIZE)) ==
+ SHA1_BLOCK_SIZE)
+ DigestUpdate(&ctx, data, len);
+ if (len != -1)
+ DigestUpdate(&ctx, data, len);
+ digest = DigestFinal(&ctx);
+ close(input_fd);
+ return digest;
+}
+
+uint8_t* SignatureFile(const char* input_file, const char* key_file,
+ int algorithm) {
+ char* sign_utility = "./sign_data.sh";
+ char* cmd; /* Command line to invoke. */
+ int cmd_len;
+ FILE* cmd_out; /* File descriptor to command output. */
+ uint8_t* signature = NULL;
+ int signature_size = siglen_map[algorithm];
+
+ /* Build command line:
+ * sign_data.sh <algorithm> <key file> <input file>
+ */
+ cmd_len = (strlen(sign_utility) + 1 + /* +1 for space. */
+ 2 + 1 + /* For [algorithm]. */
+ strlen(key_file) + 1 + /* +1 for space. */
+ strlen(input_file) +
+ 1); /* For the trailing '\0'. */
+ cmd = (char*) Malloc(cmd_len);
+ snprintf(cmd, cmd_len, "%s %d %s %s", sign_utility, algorithm, key_file,
+ input_file);
+ cmd_out = popen(cmd, "r");
+ Free(cmd);
+ if (!cmd_out) {
+ debug("Couldn't execute: %s\n", cmd);
+ return NULL;
+ }
+
+ signature = (uint8_t*) Malloc(signature_size);
+ if (fread(signature, signature_size, 1, cmd_out) != 1) {
+ debug("Couldn't read signature.\n");
+ pclose(cmd_out);
+ Free(signature);
+ return NULL;
+ }
+
+ pclose(cmd_out);
+ return signature;
+}
diff --git a/host/lib/signature_digest.c b/host/lib/signature_digest.c
new file mode 100644
index 00000000..4dba95a6
--- /dev/null
+++ b/host/lib/signature_digest.c
@@ -0,0 +1,74 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "signature_digest.h"
+#define OPENSSL_NO_SHA
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "cryptolib.h"
+#include "utility.h"
+
+uint8_t* PrependDigestInfo(int algorithm, uint8_t* digest) {
+ const int digest_size = hash_size_map[algorithm];
+ const int digestinfo_size = digestinfo_size_map[algorithm];
+ const uint8_t* digestinfo = hash_digestinfo_map[algorithm];
+ uint8_t* p = Malloc(digestinfo_size + digest_size);
+ Memcpy(p, digestinfo, digestinfo_size);
+ Memcpy(p + digestinfo_size, digest, digest_size);
+ return p;
+}
+
+uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len, int algorithm) {
+ uint8_t* info_digest = NULL;
+ uint8_t* digest = NULL;
+
+ if (algorithm >= kNumAlgorithms) {
+ debug("SignatureDigest() called with invalid algorithm!\n");
+ } else if ((digest = DigestBuf(buf, len, algorithm))) {
+ info_digest = PrependDigestInfo(algorithm, digest);
+ }
+ Free(digest);
+ return info_digest;
+}
+
+uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file,
+ int algorithm) {
+ FILE* key_fp = NULL;
+ RSA* key = NULL;
+ uint8_t* signature = NULL;
+ uint8_t* signature_digest = SignatureDigest(buf, len, algorithm);
+ int signature_digest_len = (hash_size_map[algorithm] +
+ digestinfo_size_map[algorithm]);
+ key_fp = fopen(key_file, "r");
+ if (!key_fp) {
+ debug("SignatureBuf(): Couldn't open key file: %s\n", key_file);
+ Free(signature_digest);
+ return NULL;
+ }
+ if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL)))
+ signature = (uint8_t*) Malloc(siglen_map[algorithm]);
+ else
+ debug("SignatureBuf(): Couldn't read private key from file: %s\n",
+ key_file);
+ if (signature) {
+ if (-1 == RSA_private_encrypt(signature_digest_len, /* Input length. */
+ signature_digest, /* Input data. */
+ signature, /* Output signature. */
+ key, /* Key to use. */
+ RSA_PKCS1_PADDING)) /* Padding to use. */
+ debug("SignatureBuf(): RSA_private_encrypt() failed.\n");
+ }
+ fclose(key_fp);
+ if (key)
+ RSA_free(key);
+ Free(signature_digest);
+ return signature;
+}
diff --git a/host/linktest/main.c b/host/linktest/main.c
index 5fb7dd3d..93c5ac2a 100644
--- a/host/linktest/main.c
+++ b/host/linktest/main.c
@@ -1,6 +1,8 @@
#include <stdio.h>
#include "host_common.h"
+#include "file_keys.h"
+#include "signature_digest.h"
int main(void)
{
@@ -32,5 +34,16 @@ int main(void)
CreateFirmwarePreamble(0, 0, 0, 0);
CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0);
+ /* file_keys.h */
+ BufferFromFile(0, 0);
+ RSAPublicKeyFromFile(0);
+ DigestFile(0, 0);
+ SignatureFile(0, 0, 0);
+
+ /* signature_digest.h */
+ PrependDigestInfo(0, 0);
+ SignatureDigest(0, 0, 0);
+ SignatureBuf(0, 0, 0, 0);
+
return 0;
}