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