mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
host,test: Remove unneeded vb1 rsa functions
Another in a continued stream of refactoring. This change removes more of the vb1 rsa library code and associated tests, in favor of their vb2 equivalents. This change touches only host-side code and its tests, not firmware. BUG=chromium:611535 BRANCH=none TEST=make runtests; emerge-kevin coreboot depthcharge Change-Id: I1973bc2f03c60da62232e30bab0fa5fe791b6b34 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/400901
This commit is contained in:
committed by
chrome-bot
parent
13b109762a
commit
5a9f498182
@@ -22,74 +22,4 @@
|
||||
#define RSA4096NUMWORDS (RSA4096NUMBYTES / sizeof(uint32_t))
|
||||
#define RSA8192NUMWORDS (RSA8192NUMBYTES / sizeof(uint32_t))
|
||||
|
||||
typedef struct RSAPublicKey {
|
||||
uint32_t len; /* Length of n[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
|
||||
uint32_t* n; /* modulus as little endian array */
|
||||
uint32_t* rr; /* R^2 as little endian array */
|
||||
unsigned int algorithm; /* Algorithm to use when verifying with the key */
|
||||
} RSAPublicKey;
|
||||
|
||||
/* Verify a RSA PKCS1.5 signature [sig] of [sig_type] and length [sig_len]
|
||||
* against an expected [hash] using [key]. Returns 0 on failure, 1 on success.
|
||||
*/
|
||||
int RSAVerify(const RSAPublicKey *key,
|
||||
const uint8_t* sig,
|
||||
const uint32_t sig_len,
|
||||
const uint8_t sig_type,
|
||||
const uint8_t* hash);
|
||||
|
||||
/* Perform RSA signature verification on [buf] of length [len] against expected
|
||||
* signature [sig] using signature algorithm [algorithm]. The public key used
|
||||
* for verification can either be in the form of a pre-process key blob
|
||||
* [key_blob] or RSAPublicKey structure [key]. One of [key_blob] or [key] must
|
||||
* be non-NULL, and the other NULL or the function will fail.
|
||||
*
|
||||
* Returns 1 on verification success, 0 on verification failure or invalid
|
||||
* arguments.
|
||||
*
|
||||
* Note: This function is for use in the firmware and assumes all pointers point
|
||||
* to areas in the memory of the right size.
|
||||
*
|
||||
*/
|
||||
int RSAVerifyBinary_f(const uint8_t* key_blob,
|
||||
const RSAPublicKey* key,
|
||||
const uint8_t* buf,
|
||||
uint64_t len,
|
||||
const uint8_t* sig,
|
||||
unsigned int algorithm);
|
||||
|
||||
/* Version of RSAVerifyBinary_f() where instead of the raw binary blob
|
||||
* of data, its digest is passed as the argument. */
|
||||
int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob,
|
||||
const RSAPublicKey* key,
|
||||
const uint8_t* digest,
|
||||
const uint8_t* sig,
|
||||
unsigned int algorithm);
|
||||
|
||||
|
||||
/* ----Some additional utility functions for RSA.---- */
|
||||
|
||||
/* Returns the size of a pre-processed RSA public key in
|
||||
* [out_size] with the algorithm [algorithm].
|
||||
*
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size);
|
||||
|
||||
/* Allocate a new RSAPublicKey structure and initialize its pointer fields to
|
||||
* NULL */
|
||||
RSAPublicKey* RSAPublicKeyNew(void);
|
||||
|
||||
/* Deep free the contents of [key]. */
|
||||
void RSAPublicKeyFree(RSAPublicKey* key);
|
||||
|
||||
/* Create a RSAPublic key structure from binary blob [buf] of length
|
||||
* [len].
|
||||
*
|
||||
* Caller owns the returned key and must free it.
|
||||
*/
|
||||
RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len);
|
||||
|
||||
|
||||
#endif /* VBOOT_REFERENCE_RSA_H_ */
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Implementation of RSA signature verification which uses a pre-processed
|
||||
* key for computation. The code extends Android's RSA verification code to
|
||||
* support multiple RSA key lengths and hash digest algorithms.
|
||||
*/
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "2sysincludes.h"
|
||||
#include "2common.h"
|
||||
#include "cryptolib.h"
|
||||
#include "vboot_api.h"
|
||||
#include "utility.h"
|
||||
|
||||
/* a[] -= mod */
|
||||
static void subM(const RSAPublicKey *key, uint32_t *a) {
|
||||
int64_t A = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
A += (uint64_t)a[i] - key->n[i];
|
||||
a[i] = (uint32_t)A;
|
||||
A >>= 32;
|
||||
}
|
||||
}
|
||||
|
||||
/* return a[] >= mod */
|
||||
static int geM(const RSAPublicKey *key, uint32_t *a) {
|
||||
uint32_t i;
|
||||
for (i = key->len; i;) {
|
||||
--i;
|
||||
if (a[i] < key->n[i]) return 0;
|
||||
if (a[i] > key->n[i]) return 1;
|
||||
}
|
||||
return 1; /* equal */
|
||||
}
|
||||
|
||||
/* montgomery c[] += a * b[] / R % mod */
|
||||
static void montMulAdd(const RSAPublicKey *key,
|
||||
uint32_t* c,
|
||||
const uint32_t a,
|
||||
const uint32_t* b) {
|
||||
uint64_t A = (uint64_t)a * b[0] + c[0];
|
||||
uint32_t d0 = (uint32_t)A * key->n0inv;
|
||||
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 1; i < key->len; ++i) {
|
||||
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
|
||||
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
|
||||
c[i - 1] = (uint32_t)B;
|
||||
}
|
||||
|
||||
A = (A >> 32) + (B >> 32);
|
||||
|
||||
c[i - 1] = (uint32_t)A;
|
||||
|
||||
if (A >> 32) {
|
||||
subM(key, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* montgomery c[] = a[] * b[] / R % mod */
|
||||
static void montMul(const RSAPublicKey *key,
|
||||
uint32_t* c,
|
||||
uint32_t* a,
|
||||
uint32_t* b) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
c[i] = 0;
|
||||
}
|
||||
for (i = 0; i < key->len; ++i) {
|
||||
montMulAdd(key, c, a[i], b);
|
||||
}
|
||||
}
|
||||
|
||||
/* In-place public exponentiation. (65537}
|
||||
* Input and output big-endian byte array in inout.
|
||||
*/
|
||||
static void modpowF4(const RSAPublicKey *key,
|
||||
uint8_t* inout) {
|
||||
uint32_t* a = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t));
|
||||
uint32_t* aR = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t));
|
||||
uint32_t* aaR = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t));
|
||||
|
||||
uint32_t* aaa = aaR; /* Re-use location. */
|
||||
int i;
|
||||
|
||||
/* Convert from big endian byte array to little endian word array. */
|
||||
for (i = 0; i < (int)key->len; ++i) {
|
||||
uint32_t tmp =
|
||||
(inout[((key->len - 1 - i) * 4) + 0] << 24) |
|
||||
(inout[((key->len - 1 - i) * 4) + 1] << 16) |
|
||||
(inout[((key->len - 1 - i) * 4) + 2] << 8) |
|
||||
(inout[((key->len - 1 - i) * 4) + 3] << 0);
|
||||
a[i] = tmp;
|
||||
}
|
||||
|
||||
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
|
||||
for (i = 0; i < 16; i+=2) {
|
||||
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||
montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
|
||||
}
|
||||
montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
|
||||
|
||||
|
||||
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
|
||||
if (geM(key, aaa)) {
|
||||
subM(key, aaa);
|
||||
}
|
||||
|
||||
/* Convert to bigendian byte array */
|
||||
for (i = (int)key->len - 1; i >= 0; --i) {
|
||||
uint32_t tmp = aaa[i];
|
||||
*inout++ = (uint8_t)(tmp >> 24);
|
||||
*inout++ = (uint8_t)(tmp >> 16);
|
||||
*inout++ = (uint8_t)(tmp >> 8);
|
||||
*inout++ = (uint8_t)(tmp >> 0);
|
||||
}
|
||||
|
||||
VbExFree(a);
|
||||
VbExFree(aR);
|
||||
VbExFree(aaR);
|
||||
}
|
||||
|
||||
/* Verify a RSA PKCS1.5 signature against an expected hash.
|
||||
* Returns 0 on failure, 1 on success.
|
||||
*/
|
||||
int RSAVerify(const RSAPublicKey *key,
|
||||
const uint8_t *sig,
|
||||
const uint32_t sig_len,
|
||||
const uint8_t sig_type,
|
||||
const uint8_t *hash) {
|
||||
uint8_t* buf;
|
||||
const uint8_t* padding;
|
||||
int padding_len;
|
||||
int success = 1;
|
||||
|
||||
if (!key || !sig || !hash)
|
||||
return 0;
|
||||
|
||||
if (sig_len != (key->len * sizeof(uint32_t))) {
|
||||
VBDEBUG(("Signature is of incorrect length!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig_type >= kNumAlgorithms) {
|
||||
VBDEBUG(("Invalid signature type!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key->len != siglen_map[sig_type] / sizeof(uint32_t)) {
|
||||
VBDEBUG(("Wrong key passed in!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = (uint8_t*) VbExMalloc(sig_len);
|
||||
if (!buf)
|
||||
return 0;
|
||||
memcpy(buf, sig, sig_len);
|
||||
|
||||
modpowF4(key, buf);
|
||||
|
||||
/* Determine padding to use depending on the signature type. */
|
||||
padding = padding_map[sig_type];
|
||||
padding_len = padding_size_map[sig_type];
|
||||
|
||||
/* Even though there are probably no timing issues here, we use
|
||||
* vb2_safe_memcmp() just to be on the safe side. */
|
||||
|
||||
/* Check pkcs1.5 padding bytes. */
|
||||
if (vb2_safe_memcmp(buf, padding, padding_len)) {
|
||||
VBDEBUG(("In RSAVerify(): Padding check failed!\n"));
|
||||
success = 0;
|
||||
}
|
||||
|
||||
/* Check hash. */
|
||||
if (vb2_safe_memcmp(buf + padding_len, hash, sig_len - padding_len)) {
|
||||
VBDEBUG(("In RSAVerify(): Hash check failed!\n"));
|
||||
success = 0;
|
||||
}
|
||||
VbExFree(buf);
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Implementation of RSA utility functions.
|
||||
*/
|
||||
|
||||
#include "sysincludes.h"
|
||||
#include "2sysincludes.h"
|
||||
|
||||
#include "2common.h"
|
||||
#include "2sha.h"
|
||||
#include "cryptolib.h"
|
||||
#include "stateful_util.h"
|
||||
#include "utility.h"
|
||||
#include "vboot_api.h"
|
||||
|
||||
uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size) {
|
||||
int key_len; /* Key length in bytes. (int type matches siglen_map) */
|
||||
if (algorithm < kNumAlgorithms) {
|
||||
key_len = siglen_map[algorithm];
|
||||
/* Total size needed by a RSAPublicKey buffer is =
|
||||
* 2 * key_len bytes for the n and rr arrays
|
||||
* + sizeof len + sizeof n0inv.
|
||||
*/
|
||||
*out_size = (2 * key_len + sizeof(uint32_t) + sizeof(uint32_t));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
RSAPublicKey* RSAPublicKeyNew(void) {
|
||||
RSAPublicKey* key = (RSAPublicKey*) VbExMalloc(sizeof(RSAPublicKey));
|
||||
key->n = NULL;
|
||||
key->rr = NULL;
|
||||
key->len = 0;
|
||||
key->algorithm = kNumAlgorithms;
|
||||
return key;
|
||||
}
|
||||
|
||||
void RSAPublicKeyFree(RSAPublicKey* key) {
|
||||
if (key) {
|
||||
if (key->n)
|
||||
VbExFree(key->n);
|
||||
if (key->rr)
|
||||
VbExFree(key->rr);
|
||||
VbExFree(key);
|
||||
}
|
||||
}
|
||||
|
||||
RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len) {
|
||||
RSAPublicKey* key = RSAPublicKeyNew();
|
||||
MemcpyState st;
|
||||
uint64_t key_len;
|
||||
|
||||
StatefulInit(&st, (void*)buf, len);
|
||||
|
||||
StatefulMemcpy(&st, &key->len, sizeof(key->len));
|
||||
/* key length in bytes (avoiding possible 32-bit rollover) */
|
||||
key_len = key->len;
|
||||
key_len *= sizeof(uint32_t);
|
||||
|
||||
/* Sanity Check the key length. */
|
||||
if (RSA1024NUMBYTES != key_len &&
|
||||
RSA2048NUMBYTES != key_len &&
|
||||
RSA4096NUMBYTES != key_len &&
|
||||
RSA8192NUMBYTES != key_len) {
|
||||
RSAPublicKeyFree(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key->n = (uint32_t*) VbExMalloc(key_len);
|
||||
key->rr = (uint32_t*) VbExMalloc(key_len);
|
||||
|
||||
StatefulMemcpy(&st, &key->n0inv, sizeof(key->n0inv));
|
||||
StatefulMemcpy(&st, key->n, key_len);
|
||||
StatefulMemcpy(&st, key->rr, key_len);
|
||||
if (st.overrun || st.remaining_len != 0) { /* Underrun or overrun. */
|
||||
RSAPublicKeyFree(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int RSAVerifyBinary_f(const uint8_t* key_blob,
|
||||
const RSAPublicKey* key,
|
||||
const uint8_t* buf,
|
||||
uint64_t len,
|
||||
const uint8_t* sig,
|
||||
unsigned int algorithm) {
|
||||
RSAPublicKey* verification_key = NULL;
|
||||
uint8_t digest[VB2_MAX_DIGEST_SIZE];
|
||||
uint64_t key_size;
|
||||
int sig_size;
|
||||
int success = 0;
|
||||
|
||||
if (algorithm >= (unsigned int)kNumAlgorithms)
|
||||
return 0; /* Invalid algorithm. */
|
||||
if (!RSAProcessedKeySize(algorithm, &key_size))
|
||||
return 0;
|
||||
sig_size = siglen_map[algorithm];
|
||||
|
||||
if (key_blob && !key)
|
||||
verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
|
||||
else if (!key_blob && key)
|
||||
verification_key = (RSAPublicKey*) key; /* Supress const warning. */
|
||||
else
|
||||
return 0; /* Both can't be NULL or non-NULL. */
|
||||
|
||||
/* Ensure we have a valid key. */
|
||||
if (!verification_key)
|
||||
return 0;
|
||||
|
||||
if (VB2_SUCCESS == vb2_digest_buffer(buf, len, vb2_crypto_to_hash(algorithm),
|
||||
digest, sizeof(digest))) {
|
||||
success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
|
||||
(uint8_t)algorithm, digest);
|
||||
}
|
||||
|
||||
if (!key)
|
||||
RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Version of RSAVerifyBinary_f() where instead of the raw binary blob
|
||||
* of data, its digest is passed as the argument. */
|
||||
int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob,
|
||||
const RSAPublicKey* key,
|
||||
const uint8_t* digest,
|
||||
const uint8_t* sig,
|
||||
unsigned int algorithm) {
|
||||
RSAPublicKey* verification_key = NULL;
|
||||
uint64_t key_size;
|
||||
int sig_size;
|
||||
int success;
|
||||
|
||||
if (algorithm >= (unsigned int)kNumAlgorithms)
|
||||
return 0; /* Invalid algorithm. */
|
||||
if (!RSAProcessedKeySize(algorithm, &key_size))
|
||||
return 0;
|
||||
sig_size = siglen_map[algorithm];
|
||||
|
||||
if (key_blob && !key)
|
||||
verification_key = RSAPublicKeyFromBuf(key_blob, key_size);
|
||||
else if (!key_blob && key)
|
||||
verification_key = (RSAPublicKey*) key; /* Supress const warning. */
|
||||
else
|
||||
return 0; /* Both can't be NULL or non-NULL. */
|
||||
|
||||
/* Ensure we have a valid key. */
|
||||
if (!verification_key)
|
||||
return 0;
|
||||
|
||||
success = RSAVerify(verification_key, sig, (uint32_t)sig_size,
|
||||
(uint8_t)algorithm, digest);
|
||||
|
||||
if (!key)
|
||||
RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */
|
||||
return success;
|
||||
}
|
||||
Reference in New Issue
Block a user