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
15uint64_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
29RSAPublicKey* 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
38void 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
48RSAPublicKey* 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
83int 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. */
124int 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