xref: /aosp_15_r20/external/vboot_reference/host/lib21/host_signature.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2014 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Host functions for signatures.
6  */
7 
8 #include <openssl/rsa.h>
9 
10 #include "2common.h"
11 #include "2rsa.h"
12 #include "2sha.h"
13 #include "2sysincludes.h"
14 #include "host_common.h"
15 #include "host_common21.h"
16 #include "host_key21.h"
17 #include "host_misc.h"
18 #include "host_p11.h"
19 #include "host_signature21.h"
20 
vb2_digest_info(enum vb2_hash_algorithm hash_alg,const uint8_t ** buf_ptr,uint32_t * size_ptr)21 vb2_error_t vb2_digest_info(enum vb2_hash_algorithm hash_alg,
22 			    const uint8_t **buf_ptr, uint32_t *size_ptr)
23 {
24 	*buf_ptr = NULL;
25 	*size_ptr = 0;
26 
27 	switch (hash_alg) {
28 #if VB2_SUPPORT_SHA1
29 	case VB2_HASH_SHA1:
30 		{
31 			static const uint8_t info[] = {
32 				0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
33 				0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
34 			};
35 			*buf_ptr = info;
36 			*size_ptr = sizeof(info);
37 			return VB2_SUCCESS;
38 		}
39 #endif
40 #if VB2_SUPPORT_SHA256
41 	case VB2_HASH_SHA256:
42 		{
43 			static const uint8_t info[] = {
44 				0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
45 				0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
46 				0x00, 0x04, 0x20
47 			};
48 			*buf_ptr = info;
49 			*size_ptr = sizeof(info);
50 			return VB2_SUCCESS;
51 		}
52 #endif
53 #if VB2_SUPPORT_SHA512
54 	case VB2_HASH_SHA512:
55 		{
56 			static const uint8_t info[] = {
57 				0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
58 				0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
59 				0x00, 0x04, 0x40
60 			};
61 			*buf_ptr = info;
62 			*size_ptr = sizeof(info);
63 			return VB2_SUCCESS;
64 		}
65 #endif
66 	default:
67 		return VB2_ERROR_DIGEST_INFO;
68 	}
69 }
70 
vb21_sign_data(struct vb21_signature ** sig_ptr,const uint8_t * data,uint32_t size,const struct vb2_private_key * key,const char * desc)71 vb2_error_t vb21_sign_data(struct vb21_signature **sig_ptr, const uint8_t *data,
72 			   uint32_t size, const struct vb2_private_key *key,
73 			   const char *desc)
74 {
75 	struct vb21_signature s = {
76 		.c.magic = VB21_MAGIC_SIGNATURE,
77 		.c.struct_version_major = VB21_SIGNATURE_VERSION_MAJOR,
78 		.c.struct_version_minor = VB21_SIGNATURE_VERSION_MINOR,
79 		.c.fixed_size = sizeof(s),
80 		.sig_alg = key->sig_alg,
81 		.hash_alg = key->hash_alg,
82 		.data_size = size,
83 		.id = key->id,
84 	};
85 
86 	vb2_error_t rv;
87 	struct vb2_digest_context dc;
88 	uint32_t digest_size;
89 	const uint8_t *info = NULL;
90 	uint32_t info_size = 0;
91 	uint32_t sig_digest_size;
92 	uint8_t *sig_digest = NULL;
93 	uint8_t *buf = NULL;
94 
95 	*sig_ptr = NULL;
96 
97 	/* Use key description if no description supplied */
98 	if (!desc)
99 		desc = key->desc;
100 
101 	s.c.desc_size = vb2_desc_size(desc);
102 
103 	s.sig_offset = s.c.fixed_size + s.c.desc_size;
104 	s.sig_size = vb2_sig_size(key->sig_alg, key->hash_alg);
105 	if (!s.sig_size) {
106 		rv = VB2_SIGN_DATA_SIG_SIZE;
107 		goto done;
108 	}
109 
110 	s.c.total_size = s.sig_offset + s.sig_size;
111 	/* Allocate signature buffer and copy header */
112 	buf = calloc(1, s.c.total_size);
113 	if (!buf) {
114 		rv = VB2_ERROR_UNKNOWN;
115 		goto done;
116 	}
117 	memcpy(buf, &s, sizeof(s));
118 
119 	/* strcpy() is ok because we allocated buffer based on desc length */
120 	if (desc)
121 		strcpy((char *)buf + s.c.fixed_size, desc);
122 
123 	/* If it is PKCS11#11 key, we could sign with pkcs11_sign instead */
124 	if (key->key_location == PRIVATE_KEY_P11) {
125 		/* RSA-encrypt the signature */
126 		rv = pkcs11_sign(key->p11_key, key->hash_alg, data, size,
127 				 buf + s.sig_offset, s.sig_size);
128 		goto done;
129 	}
130 
131 	/* Determine digest size and allocate buffer */
132 	if (s.sig_alg != VB2_SIG_NONE) {
133 		if (vb2_digest_info(s.hash_alg, &info, &info_size)) {
134 			rv = VB2_SIGN_DATA_DIGEST_INFO;
135 			goto done;
136 		}
137 	}
138 
139 	digest_size = vb2_digest_size(key->hash_alg);
140 	if (!digest_size) {
141 		rv = VB2_SIGN_DATA_DIGEST_SIZE;
142 		goto done;
143 	}
144 
145 	sig_digest_size = info_size + digest_size;
146 	sig_digest = malloc(sig_digest_size);
147 	if (!sig_digest) {
148 		rv = VB2_SIGN_DATA_DIGEST_ALLOC;
149 		goto done;
150 	}
151 
152 	/* Prepend digest info, if any */
153 	if (info_size)
154 		memcpy(sig_digest, info, info_size);
155 
156 	/* Calculate hash digest */
157 	if (vb2_digest_init(&dc, false, s.hash_alg, 0)) {
158 		rv = VB2_SIGN_DATA_DIGEST_INIT;
159 		goto done;
160 	}
161 
162 	if (vb2_digest_extend(&dc, data, size)) {
163 		rv = VB2_SIGN_DATA_DIGEST_EXTEND;
164 		goto done;
165 	}
166 
167 	if (vb2_digest_finalize(&dc, sig_digest + info_size, digest_size)) {
168 		rv = VB2_SIGN_DATA_DIGEST_FINALIZE;
169 		goto done;
170 	}
171 
172 	if (s.sig_alg == VB2_SIG_NONE) {
173 		/* Bare hash signature is just the digest */
174 		memcpy(buf + s.sig_offset, sig_digest, sig_digest_size);
175 	} else {
176 		/* RSA-encrypt the signature */
177 		if (RSA_private_encrypt(sig_digest_size,
178 					sig_digest,
179 					buf + s.sig_offset,
180 					key->rsa_private_key,
181 					RSA_PKCS1_PADDING) == -1) {
182 			rv = VB2_SIGN_DATA_RSA_ENCRYPT;
183 			goto done;
184 		}
185 	}
186 	rv = VB2_SUCCESS;
187 done:
188 	free(sig_digest);
189 	if (rv == VB2_SUCCESS)
190 		*sig_ptr = (struct vb21_signature *)buf;
191 	else
192 		free(buf);
193 	return rv;
194 }
195 
vb21_sig_size_for_key(uint32_t * size_ptr,const struct vb2_private_key * key,const char * desc)196 vb2_error_t vb21_sig_size_for_key(uint32_t *size_ptr,
197 				  const struct vb2_private_key *key,
198 				  const char *desc)
199 {
200 	uint32_t size = vb2_sig_size(key->sig_alg, key->hash_alg);
201 
202 	if (!size)
203 		return VB2_ERROR_SIG_SIZE_FOR_KEY;
204 
205 	size += sizeof(struct vb21_signature);
206 	size += vb2_desc_size(desc ? desc : key->desc);
207 
208 	*size_ptr = size;
209 	return VB2_SUCCESS;
210 }
211 
vb21_sig_size_for_keys(uint32_t * size_ptr,const struct vb2_private_key ** key_list,uint32_t key_count)212 vb2_error_t vb21_sig_size_for_keys(uint32_t *size_ptr,
213 				   const struct vb2_private_key **key_list,
214 				   uint32_t key_count)
215 {
216 	uint32_t total = 0, size = 0;
217 	vb2_error_t rv, i;
218 
219 	*size_ptr = 0;
220 
221 	for (i = 0; i < key_count; i++) {
222 		rv = vb21_sig_size_for_key(&size, key_list[i], NULL);
223 		if (rv)
224 			return rv;
225 		total += size;
226 	}
227 
228 	*size_ptr = total;
229 	return VB2_SUCCESS;
230 }
231 
vb21_sign_object(uint8_t * buf,uint32_t sig_offset,const struct vb2_private_key * key,const char * desc)232 vb2_error_t vb21_sign_object(uint8_t *buf, uint32_t sig_offset,
233 			     const struct vb2_private_key *key,
234 			     const char *desc)
235 {
236 	struct vb21_struct_common *c = (struct vb21_struct_common *)buf;
237 	struct vb21_signature *sig = NULL;
238 	vb2_error_t rv;
239 
240 	rv = vb21_sign_data(&sig, buf, sig_offset, key, desc);
241 	if (rv)
242 		return rv;
243 
244 	if (sig_offset + sig->c.total_size > c->total_size) {
245 		free(sig);
246 		return VB2_SIGN_OBJECT_OVERFLOW;
247 	}
248 
249 	memcpy(buf + sig_offset, sig, sig->c.total_size);
250 	free(sig);
251 
252 	return VB2_SUCCESS;
253 }
254 
vb21_sign_object_multiple(uint8_t * buf,uint32_t sig_offset,const struct vb2_private_key ** key_list,uint32_t key_count)255 vb2_error_t vb21_sign_object_multiple(uint8_t *buf, uint32_t sig_offset,
256 				      const struct vb2_private_key **key_list,
257 				      uint32_t key_count)
258 {
259 	struct vb21_struct_common *c = (struct vb21_struct_common *)buf;
260 	uint32_t sig_next = sig_offset;
261 	vb2_error_t rv, i;
262 
263 	for (i = 0; i < key_count; i++)	{
264 		struct vb21_signature *sig = NULL;
265 
266 		rv = vb21_sign_data(&sig, buf, sig_offset, key_list[i], NULL);
267 		if (rv)
268 			return rv;
269 
270 		if (sig_next + sig->c.total_size > c->total_size) {
271 			free(sig);
272 			return VB2_SIGN_OBJECT_OVERFLOW;
273 		}
274 
275 		memcpy(buf + sig_next, sig, sig->c.total_size);
276 		sig_next += sig->c.total_size;
277 		free(sig);
278 	}
279 
280 	return VB2_SUCCESS;
281 }
282