Index: host/lib/host_signature.c |
diff --git a/host/lib/host_signature.c b/host/lib/host_signature.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..935e77310c6f01bcf183f7fb7cf654c433600f6e |
--- /dev/null |
+++ b/host/lib/host_signature.c |
@@ -0,0 +1,135 @@ |
+/* 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. |
+ * |
+ * Host functions for signature generation. |
+ */ |
+ |
+/* TODO: change all 'return 0', 'return 1' into meaningful return codes */ |
+ |
+#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 "file_keys.h" |
+#include "utility.h" |
+#include "vboot_common.h" |
+#include "host_common.h" |
+ |
+ |
+VbSignature* SignatureAlloc(uint64_t sig_size, uint64_t data_size) { |
+ VbSignature* sig = (VbSignature*)Malloc(sizeof(VbSignature) + sig_size); |
+ if (!sig) |
+ return NULL; |
+ |
+ sig->sig_offset = sizeof(VbSignature); |
+ sig->sig_size = sig_size; |
+ sig->data_size = data_size; |
+ return sig; |
+} |
+ |
+ |
+void SignatureInit(VbSignature* sig, uint8_t* sig_data, |
+ uint64_t sig_size, uint64_t data_size) { |
+ sig->sig_offset = OffsetOf(sig, sig_data); |
+ sig->sig_size = sig_size; |
+ sig->data_size = data_size; |
+} |
+ |
+ |
+int SignatureCopy(VbSignature* dest, const VbSignature* src) { |
+ if (dest->sig_size < src->sig_size) |
+ return 1; |
+ dest->sig_size = src->sig_size; |
+ dest->data_size = src->data_size; |
+ Memcpy(GetSignatureData(dest), GetSignatureDataC(src), src->sig_size); |
+ return 0; |
+} |
+ |
+ |
+VbSignature* CalculateChecksum(const uint8_t* data, uint64_t size) { |
+ |
+ uint8_t* header_checksum; |
+ VbSignature* sig; |
+ |
+ header_checksum = DigestBuf(data, size, SHA512_DIGEST_ALGORITHM); |
+ if (!header_checksum) |
+ return NULL; |
+ |
+ sig = SignatureAlloc(SHA512_DIGEST_SIZE, 0); |
+ if (!sig) { |
+ Free(header_checksum); |
+ return NULL; |
+ } |
+ sig->sig_offset = sizeof(VbSignature); |
+ sig->sig_size = SHA512_DIGEST_SIZE; |
+ sig->data_size = size; |
+ |
+ /* Signature data immediately follows the header */ |
+ Memcpy(GetSignatureData(sig), header_checksum, SHA512_DIGEST_SIZE); |
+ Free(header_checksum); |
+ return sig; |
+} |
+ |
+ |
+VbSignature* CalculateSignature(const uint8_t* data, uint64_t size, |
+ const VbPrivateKey* key) { |
+ |
+ uint8_t* digest; |
+ int digest_size = hash_size_map[key->algorithm]; |
+ |
+ const uint8_t* digestinfo = hash_digestinfo_map[key->algorithm]; |
+ int digestinfo_size = digestinfo_size_map[key->algorithm]; |
+ |
+ uint8_t* signature_digest; |
+ int signature_digest_len = digest_size + digestinfo_size; |
+ |
+ VbSignature* sig; |
+ int rv; |
+ |
+ /* Calculate the digest */ |
+ /* TODO: rename param 3 of DigestBuf to hash_type */ |
+ digest = DigestBuf(data, size, hash_type_map[key->algorithm]); |
+ if (!digest) |
+ return NULL; |
+ |
+ /* Prepend the digest info to the digest */ |
+ signature_digest = Malloc(signature_digest_len); |
+ if (!signature_digest) { |
+ Free(digest); |
+ return NULL; |
+ } |
+ Memcpy(signature_digest, digestinfo, digestinfo_size); |
+ Memcpy(signature_digest + digestinfo_size, digest, digest_size); |
+ Free(digest); |
+ |
+ /* Allocate output signature */ |
+ sig = SignatureAlloc(siglen_map[key->algorithm], size); |
+ if (!sig) { |
+ Free(signature_digest); |
+ return NULL; |
+ } |
+ |
+ /* Sign the signature_digest into our output buffer */ |
+ rv = RSA_private_encrypt(signature_digest_len, /* Input length */ |
+ signature_digest, /* Input data */ |
+ GetSignatureData(sig), /* Output sig */ |
+ key->rsa_private_key, /* Key to use */ |
+ RSA_PKCS1_PADDING); /* Padding to use */ |
+ Free(signature_digest); |
+ |
+ if (-1 == rv) { |
+ debug("SignatureBuf(): RSA_private_encrypt() failed.\n"); |
+ Free(sig); |
+ return NULL; |
+ } |
+ |
+ /* Return the signature */ |
+ return sig; |
+} |