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