blob: 9923185ad209a9c9dec89f2b4a432a16da44b00d [file] [log] [blame]
/* Copyright 2011 The ChromiumOS Authors
* 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.
*/
#include <openssl/rsa.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "2sysincludes.h"
#include "2common.h"
#include "2rsa.h"
#include "2sha.h"
#include "file_keys.h"
#include "host_common.h"
#include "host_key21.h"
#include "host_signature21.h"
#include "host_p11.h"
struct vb2_signature *vb2_alloc_signature(uint32_t sig_size,
uint32_t data_size)
{
struct vb2_signature *sig = (struct vb2_signature *)
calloc(sizeof(*sig) + sig_size, 1);
if (!sig)
return NULL;
sig->sig_offset = sizeof(*sig);
sig->sig_size = sig_size;
sig->data_size = data_size;
return sig;
}
void vb2_init_signature(struct vb2_signature *sig, uint8_t *sig_data,
uint32_t sig_size, uint32_t data_size)
{
memset(sig, 0, sizeof(*sig));
sig->sig_offset = vb2_offset_of(sig, sig_data);
sig->sig_size = sig_size;
sig->data_size = data_size;
}
vb2_error_t vb2_copy_signature(struct vb2_signature *dest,
const struct vb2_signature *src)
{
if (dest->sig_size < src->sig_size)
return VB2_ERROR_SIG_SIZE;
dest->sig_size = src->sig_size;
dest->data_size = src->data_size;
memcpy(vb2_signature_data_mutable(dest),
vb2_signature_data(src),
src->sig_size);
return VB2_SUCCESS;
}
struct vb2_signature *vb2_sha512_signature(const uint8_t *data, uint32_t size)
{
struct vb2_hash hash;
if (VB2_SUCCESS != vb2_hash_calculate(false, data, size,
VB2_HASH_SHA512, &hash))
return NULL;
struct vb2_signature *sig =
vb2_alloc_signature(sizeof(hash.sha512), size);
if (!sig)
return NULL;
memcpy(vb2_signature_data_mutable(sig), hash.sha512,
sizeof(hash.sha512));
return sig;
}
struct vb2_signature *vb2_calculate_signature(
const uint8_t *data, uint32_t size,
const struct vb2_private_key *key)
{
if (key->key_location == PRIVATE_KEY_P11) {
const uint32_t sig_size = vb2_rsa_sig_size(key->sig_alg);
struct vb2_signature *sig =
(struct vb2_signature *)vb2_alloc_signature(sig_size, size);
if (!sig)
return NULL;
if (pkcs11_sign(key->p11_key, key->hash_alg, data, size,
vb2_signature_data_mutable(sig), sig_size) != VB2_SUCCESS) {
fprintf(stderr, "%s: pkcs11_sign failed\n", __func__);
free(sig);
return NULL;
}
return sig;
}
struct vb2_hash hash;
uint32_t digest_size = vb2_digest_size(key->hash_alg);
uint32_t digest_info_size = 0;
const uint8_t *digest_info = NULL;
if (VB2_SUCCESS != vb2_digest_info(key->hash_alg,
&digest_info, &digest_info_size))
return NULL;
/* Calculate the digest */
if (VB2_SUCCESS != vb2_hash_calculate(false, data, size, key->hash_alg,
&hash))
return NULL;
/* Prepend the digest info to the digest */
int signature_digest_len = digest_size + digest_info_size;
uint8_t *signature_digest = malloc(signature_digest_len);
if (!signature_digest)
return NULL;
memcpy(signature_digest, digest_info, digest_info_size);
memcpy(signature_digest + digest_info_size, hash.raw, digest_size);
/* Allocate output signature */
struct vb2_signature *sig = (struct vb2_signature *)
vb2_alloc_signature(vb2_rsa_sig_size(key->sig_alg), size);
if (!sig) {
free(signature_digest);
return NULL;
}
/* Sign the signature_digest into our output buffer */
int rv = RSA_private_encrypt(signature_digest_len, /* Input length */
signature_digest, /* Input data */
vb2_signature_data_mutable(sig), /* Output sig */
key->rsa_private_key, /* Key to use */
RSA_PKCS1_PADDING); /* Padding */
free(signature_digest);
if (-1 == rv) {
fprintf(stderr, "%s: RSA_private_encrypt() failed\n", __func__);
free(sig);
return NULL;
}
/* Return the signature */
return sig;
}
struct vb2_signature *
vb2_create_signature_from_hash(const struct vb2_hash *hash)
{
const uint32_t hsize = vb2_digest_size(hash->algo);
/* Unsupported algorithm */
if (!hsize)
return NULL;
const uint32_t full_hsize = offsetof(struct vb2_hash, raw) + hsize;
/* The body size is unknown, so set it to zero */
struct vb2_signature *sig =
(struct vb2_signature *)vb2_alloc_signature(full_hsize, 0);
if (!sig)
return NULL;
if (!memcpy(vb2_signature_data_mutable(sig), hash, full_hsize)) {
free(sig);
return NULL;
}
return sig;
}