1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Implementation of RSA utility functions.
6 */
7
8 #include "sysincludes.h"
9
10 #include "cryptolib.h"
11 #include "stateful_util.h"
12 #include "utility.h"
13 #include "vboot_api.h"
14
RSAProcessedKeySize(uint64_t algorithm,uint64_t * out_size)15 uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size) {
16 int key_len; /* Key length in bytes. (int type matches siglen_map) */
17 if (algorithm < kNumAlgorithms) {
18 key_len = siglen_map[algorithm];
19 /* Total size needed by a RSAPublicKey buffer is =
20 * 2 * key_len bytes for the n and rr arrays
21 * + sizeof len + sizeof n0inv.
22 */
23 *out_size = (2 * key_len + sizeof(uint32_t) + sizeof(uint32_t));
24 return 1;
25 }
26 return 0;
27 }
28
RSAPublicKeyNew(void)29 RSAPublicKey* RSAPublicKeyNew(void) {
30 RSAPublicKey* key = (RSAPublicKey*) VbExMalloc(sizeof(RSAPublicKey));
31 key->n = NULL;
32 key->rr = NULL;
33 key->len = 0;
34 key->algorithm = kNumAlgorithms;
35 return key;
36 }
37
RSAPublicKeyFree(RSAPublicKey * key)38 void RSAPublicKeyFree(RSAPublicKey* key) {
39 if (key) {
40 if (key->n)
41 VbExFree(key->n);
42 if (key->rr)
43 VbExFree(key->rr);
44 VbExFree(key);
45 }
46 }
47
RSAPublicKeyFromBuf(const uint8_t * buf,uint64_t len)48 RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len) {
49 RSAPublicKey* key = RSAPublicKeyNew();
50 MemcpyState st;
51 uint64_t key_len;
52
53 StatefulInit(&st, (void*)buf, len);
54
55 StatefulMemcpy(&st, &key->len, sizeof(key->len));
56 /* key length in bytes (avoiding possible 32-bit rollover) */
57 key_len = key->len;
58 key_len *= sizeof(uint32_t);
59
60 /* Sanity Check the key length. */
61 if (RSA1024NUMBYTES != key_len &&
62 RSA2048NUMBYTES != key_len &&
63 RSA4096NUMBYTES != key_len &&
64 RSA8192NUMBYTES != key_len) {
65 RSAPublicKeyFree(key);
66 return NULL;
67 }
68
69 key->n = (uint32_t*) VbExMalloc(key_len);
70 key->rr = (uint32_t*) VbExMalloc(key_len);
71
72 StatefulMemcpy(&st, &key->n0inv, sizeof(key->n0inv));
73 StatefulMemcpy(&st, key->n, key_len);
74 StatefulMemcpy(&st, key->rr, key_len);
75 if (st.overrun || st.remaining_len != 0) { /* Underrun or overrun. */
76 RSAPublicKeyFree(key);
77 return NULL;
78 }
79
80 return key;
81 }
82
RSAVerifyBinary_f(const uint8_t * key_blob,const RSAPublicKey * key,const uint8_t * buf,uint64_t len,const uint8_t * sig,unsigned int algorithm)83 int RSAVerifyBinary_f(const uint8_t* key_blob,
84 const RSAPublicKey* key,
85 const uint8_t* buf,
86 uint64_t len,
87 const uint8_t* sig,
88 unsigned int algorithm) {
89 RSAPublicKey* verification_key = NULL;
90 uint8_t* digest = NULL;
91 uint64_t key_size;
92 int sig_size;
93 int success;
94
95 if (algorithm >= (unsigned int)kNumAlgorithms)
96 return 0; /* Invalid algorithm. */
97 if (!RSAProcessedKeySize(algorithm, &key_size))
98 return 0;
99 sig_size = siglen_map[algorithm];
100
101 if (key_blob && !key)
102 verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
103 else if (!key_blob && key)
104 verification_key = (RSAPublicKey*) key; /* Supress const warning. */
105 else
106 return 0; /* Both can't be NULL or non-NULL. */
107
108 /* Ensure we have a valid key. */
109 if (!verification_key)
110 return 0;
111
112 digest = DigestBuf(buf, len, algorithm);
113 success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
114 (uint8_t)algorithm, digest);
115
116 VbExFree(digest);
117 if (!key)
118 RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */
119 return success;
120 }
121
122 /* Version of RSAVerifyBinary_f() where instead of the raw binary blob
123 * of data, its digest is passed as the argument. */
RSAVerifyBinaryWithDigest_f(const uint8_t * key_blob,const RSAPublicKey * key,const uint8_t * digest,const uint8_t * sig,unsigned int algorithm)124 int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob,
125 const RSAPublicKey* key,
126 const uint8_t* digest,
127 const uint8_t* sig,
128 unsigned int algorithm) {
129 RSAPublicKey* verification_key = NULL;
130 uint64_t key_size;
131 int sig_size;
132 int success;
133
134 if (algorithm >= (unsigned int)kNumAlgorithms)
135 return 0; /* Invalid algorithm. */
136 if (!RSAProcessedKeySize(algorithm, &key_size))
137 return 0;
138 sig_size = siglen_map[algorithm];
139
140 if (key_blob && !key)
141 verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
142 else if (!key_blob && key)
143 verification_key = (RSAPublicKey*) key; /* Supress const warning. */
144 else
145 return 0; /* Both can't be NULL or non-NULL. */
146
147 /* Ensure we have a valid key. */
148 if (!verification_key)
149 return 0;
150
151 success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
152 (uint8_t)algorithm, digest);
153
154 if (!key)
155 RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */
156 return success;
157 }
158