blob: c0d0f64f0b80d561eb897bec2d97f1f1d859dada [file] [log] [blame]
/* 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) {
VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n"));
Free(sig);
return NULL;
}
/* Return the signature */
return sig;
}