mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-24 08:47:06 +00:00
This makes it much simpler to keep track of what we're doing. vbutil_key can now wrap both .keyb and .pem keys. It figures out which is which by trying both and just using the one that works. vbutil_keyblock and vbutil_kernel now use .vbprivk files for signing. replace debug() with VBDEBUG(()) in host-side sources, too. rename PrivateKeyRead to PrivateKeyReadPem Add real PrivateKeyRead and PrivateKeyWrite for .vbprivk files. Review URL: http://codereview.chromium.org/2871033
136 lines
3.6 KiB
C
136 lines
3.6 KiB
C
/* 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;
|
|
}
|