• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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