diff options
Diffstat (limited to 'firmware/lib/cryptolib/rsa.c')
-rw-r--r-- | firmware/lib/cryptolib/rsa.c | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/firmware/lib/cryptolib/rsa.c b/firmware/lib/cryptolib/rsa.c deleted file mode 100644 index a4c7262b..00000000 --- a/firmware/lib/cryptolib/rsa.c +++ /dev/null @@ -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; -} |