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