summaryrefslogtreecommitdiff
path: root/host/lib/host_signature2.c
blob: 6bc900dd2be9afc89c79be21570e1d4a74e7d47c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Copyright (c) 2011 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.
 */

#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_key2.h"
#include "host_signature2.h"
#include "vb2_common.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)
{
	uint8_t digest[VB2_SHA512_DIGEST_SIZE];
	if (VB2_SUCCESS != vb2_digest_buffer(data, size, VB2_HASH_SHA512,
					     digest, sizeof(digest)))
		return NULL;

	struct vb2_signature *sig =
		vb2_alloc_signature(VB2_SHA512_DIGEST_SIZE, size);
	if (!sig)
		return NULL;

	memcpy(vb2_signature_data_mutable(sig), digest, VB2_SHA512_DIGEST_SIZE);
	return sig;
}

struct vb2_signature *vb2_calculate_signature(
		const uint8_t *data, uint32_t size,
		const struct vb2_private_key *key)
{
	uint8_t digest[VB2_MAX_DIGEST_SIZE];
	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_digest_buffer(data, size, key->hash_alg,
					     digest, digest_size))
		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, digest, 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;
}