/* 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 #include #include #include #include #include #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; }