xref: /aosp_15_r20/external/vboot_reference/host/lib/signature_digest.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2010 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 
6 #include <openssl/pem.h>
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 
12 #include "2common.h"
13 #include "2rsa.h"
14 #include "2sha.h"
15 #include "2sysincludes.h"
16 #include "host_common.h"
17 #include "host_signature21.h"
18 #include "signature_digest.h"
19 
PrependDigestInfo(enum vb2_hash_algorithm hash_alg,uint8_t * digest)20 uint8_t* PrependDigestInfo(enum vb2_hash_algorithm hash_alg, uint8_t* digest)
21 {
22 	const int digest_size = vb2_digest_size(hash_alg);
23 	uint32_t digestinfo_size = 0;
24 	const uint8_t* digestinfo = NULL;
25 
26 	if (VB2_SUCCESS != vb2_digest_info(hash_alg, &digestinfo,
27 					   &digestinfo_size))
28 		return NULL;
29 
30 	uint8_t* p = malloc(digestinfo_size + digest_size);
31 	memcpy(p, digestinfo, digestinfo_size);
32 	memcpy(p + digestinfo_size, digest, digest_size);
33 	return p;
34 }
35 
SignatureDigest(const uint8_t * buf,uint64_t len,unsigned int algorithm)36 uint8_t* SignatureDigest(const uint8_t* buf, uint64_t len,
37 			 unsigned int algorithm)
38 {
39 	uint8_t* info_digest  = NULL;
40 
41 	struct vb2_hash hash;
42 
43 	if (algorithm >= VB2_ALG_COUNT) {
44 		fprintf(stderr,
45 			"SignatureDigest(): Called with invalid algorithm!\n");
46 		return NULL;
47 	}
48 
49 	if (VB2_SUCCESS == vb2_hash_calculate(false, buf, len,
50 					      vb2_crypto_to_hash(algorithm),
51 					      &hash)) {
52 		info_digest = PrependDigestInfo(hash.algo, hash.raw);
53 	}
54 	return info_digest;
55 }
56 
SignatureBuf(const uint8_t * buf,uint64_t len,const char * key_file,unsigned int algorithm)57 uint8_t* SignatureBuf(const uint8_t* buf, uint64_t len, const char* key_file,
58 		      unsigned int algorithm)
59 {
60 	const enum vb2_hash_algorithm hash_alg = vb2_crypto_to_hash(algorithm);
61 	FILE* key_fp = NULL;
62 	RSA* key = NULL;
63 	uint8_t* signature = NULL;
64 	uint8_t* signature_digest = SignatureDigest(buf, len, algorithm);
65 	if (!signature_digest) {
66 		fprintf(stderr, "SignatureBuf(): "
67 			"Couldn't get signature digest\n");
68 		return NULL;
69 	}
70 
71 	const int digest_size = vb2_digest_size(hash_alg);
72 
73 	uint32_t digestinfo_size = 0;
74 	const uint8_t* digestinfo = NULL;
75 	if (VB2_SUCCESS != vb2_digest_info(hash_alg, &digestinfo,
76 					   &digestinfo_size)) {
77 		fprintf(stderr, "SignatureBuf(): Couldn't get digest info\n");
78 		free(signature_digest);
79 		return NULL;
80 	}
81 
82 	int signature_digest_len = digest_size + digestinfo_size;
83 
84 	key_fp  = fopen(key_file, "r");
85 	if (!key_fp) {
86 		fprintf(stderr, "SignatureBuf(): Couldn't open key file: %s\n",
87 			key_file);
88 		free(signature_digest);
89 		return NULL;
90 	}
91 	if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL)))
92 		signature = (uint8_t *)malloc(
93 		    vb2_rsa_sig_size(vb2_crypto_to_signature(algorithm)));
94 	else
95 		fprintf(stderr, "SignatureBuf(): "
96 			"Couldn't read private key from: %s\n", key_file);
97 	if (signature) {
98 		if (-1 == RSA_private_encrypt(
99 				signature_digest_len,  /* Input length. */
100 				signature_digest,  /* Input data. */
101 				signature,  /* Output signature. */
102 				key,  /* Key to use. */
103 				RSA_PKCS1_PADDING))  /* Padding to use. */
104 			fprintf(stderr, "SignatureBuf(): "
105 				"RSA_private_encrypt() failed.\n");
106 	}
107 	fclose(key_fp);
108 	if (key)
109 		RSA_free(key);
110 	free(signature_digest);
111 	return signature;
112 }
113