summaryrefslogtreecommitdiff
path: root/common/rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/rsa.c')
-rw-r--r--common/rsa.c259
1 files changed, 0 insertions, 259 deletions
diff --git a/common/rsa.c b/common/rsa.c
deleted file mode 100644
index 10f0afa4b4..0000000000
--- a/common/rsa.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "rsa.h"
-#include "sha256.h"
-#include "util.h"
-
-/**
- * a[] -= mod
- */
-static void sub_mod(const struct rsa_public_key *key, uint32_t *a)
-{
- int64_t A = 0;
- uint32_t i;
- for (i = 0; i < RSANUMWORDS; ++i) {
- A += (uint64_t)a[i] - key->n[i];
- a[i] = (uint32_t)A;
- A >>= 32;
- }
-}
-
-/**
- * Return a[] >= mod
- */
-static int ge_mod(const struct rsa_public_key *key, const uint32_t *a)
-{
- uint32_t i;
- for (i = RSANUMWORDS; 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 mont_mul_add(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t a,
- const uint32_t *b)
-{
- uint64_t A = mula32(a, b[0], c[0]);
- uint32_t d0 = (uint32_t)A * key->n0inv;
- uint64_t B = mula32(d0, key->n[0], A);
- uint32_t i;
-
- for (i = 1; i < RSANUMWORDS; ++i) {
- A = mulaa32(a, b[i], c[i], A >> 32);
- B = mulaa32(d0, key->n[i], A, B >> 32);
- c[i - 1] = (uint32_t)B;
- }
-
- A = (A >> 32) + (B >> 32);
-
- c[i - 1] = (uint32_t)A;
-
- if (A >> 32)
- sub_mod(key, c);
-}
-
-#ifdef CONFIG_RSA_EXPONENT_3
-/**
- * Montgomery c[] += 0 * b[] / R % mod
- */
-static void mont_mul_add_0(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *b)
-{
- uint32_t d0 = c[0] * key->n0inv;
- uint64_t B = mula32(d0, key->n[0], c[0]);
- uint32_t i;
-
- for (i = 1; i < RSANUMWORDS; ++i) {
- B = mulaa32(d0, key->n[i], c[i], B >> 32);
- c[i - 1] = (uint32_t)B;
- }
-
- c[i - 1] = B >> 32;
-}
-
-/* Montgomery c[] = a[] * 1 / R % key. */
-static void mont_mul_1(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *a)
-{
- int i;
-
- for (i = 0; i < RSANUMWORDS; ++i)
- c[i] = 0;
-
- mont_mul_add(key, c, 1, a);
- for (i = 1; i < RSANUMWORDS; ++i)
- mont_mul_add_0(key, c, a);
-}
-#endif
-
-/**
- * Montgomery c[] = a[] * b[] / R % mod
- */
-static void mont_mul(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *a,
- const uint32_t *b)
-{
- uint32_t i;
- for (i = 0; i < RSANUMWORDS; ++i)
- c[i] = 0;
-
- for (i = 0; i < RSANUMWORDS; ++i)
- mont_mul_add(key, c, a[i], b);
-}
-
-/**
- * In-place public exponentiation.
- * Exponent depends on the configuration (65537 (default), or 3).
- *
- * @param key Key to use in signing
- * @param inout Input and output big-endian byte array
- * @param workbuf32 Work buffer; caller must verify this is
- * 3 x RSANUMWORDS elements long.
- */
-static void mod_pow(const struct rsa_public_key *key, uint8_t *inout,
- uint32_t *workbuf32)
-{
- uint32_t *a = workbuf32;
- uint32_t *a_r = a + RSANUMWORDS;
- uint32_t *aa_r = a_r + RSANUMWORDS;
- uint32_t *aaa = aa_r; /* Re-use location. */
- int i;
-
- /* Convert from big endian byte array to little endian word array. */
- for (i = 0; i < RSANUMWORDS; ++i) {
- uint32_t tmp =
- (inout[((RSANUMWORDS - 1 - i) * 4) + 0] << 24) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 1] << 16) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 2] << 8) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 3] << 0);
- a[i] = tmp;
- }
-
- /* TODO(drinkcat): This operation could be precomputed to save time. */
- mont_mul(key, a_r, a, key->rr); /* a_r = a * RR / R mod M */
-#ifdef CONFIG_RSA_EXPONENT_3
- mont_mul(key, aa_r, a_r, a_r);
- mont_mul(key, a, aa_r, a_r);
- mont_mul_1(key, aaa, a);
-#else
- /* Exponent 65537 */
- for (i = 0; i < 16; i += 2) {
- mont_mul(key, aa_r, a_r, a_r); /* aa_r = a_r * a_r / R mod M */
- mont_mul(key, a_r, aa_r, aa_r);/* a_r = aa_r * aa_r / R mod M */
- }
- mont_mul(key, aaa, a_r, a); /* aaa = a_r * a / R mod M */
-#endif
-
- /* Make sure aaa < mod; aaa is at most 1x mod too large. */
- if (ge_mod(key, aaa))
- sub_mod(key, aaa);
-
- /* Convert to bigendian byte array */
- for (i = RSANUMWORDS - 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);
- }
-}
-
-/*
- * PKCS#1 padding (from the RSA PKCS#1 v2.1 standard)
- *
- * The DER-encoded padding is defined as follows :
- * 0x00 || 0x01 || PS || 0x00 || T
- *
- * T: DER Encoded DigestInfo value which depends on the hash function used,
- * for SHA-256:
- * (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
- *
- * Length(T) = 51 octets for SHA-256
- *
- * PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF
- */
-static const uint8_t sha256_tail[] = {
- 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x20
-};
-
-#define PKCS_PAD_SIZE (RSANUMBYTES - SHA256_DIGEST_SIZE)
-
-/**
- * Check PKCS#1 padding bytes
- *
- * @param sig Signature to verify
- * @return 0 if the padding is correct.
- */
-static int check_padding(const uint8_t *sig)
-{
- uint8_t *ptr = (uint8_t *)sig;
- int result = 0;
- int i;
-
- /* First 2 bytes are always 0x00 0x01 */
- result |= *ptr++ ^ 0x00;
- result |= *ptr++ ^ 0x01;
-
- /* Then 0xff bytes until the tail */
- for (i = 0; i < PKCS_PAD_SIZE - sizeof(sha256_tail) - 2; i++)
- result |= *ptr++ ^ 0xff;
-
- /* Check the tail. */
- result |= memcmp(ptr, sha256_tail, sizeof(sha256_tail));
-
- return !!result;
-}
-
-/*
- * Verify a SHA256WithRSA PKCS#1 v1.5 signature against an expected
- * SHA256 hash.
- *
- * @param key RSA public key
- * @param signature RSA signature
- * @param sha SHA-256 digest of the content to verify
- * @param workbuf32 Work buffer; caller must verify this is
- * 3 x RSANUMWORDS elements long.
- * @return 0 on failure, 1 on success.
- */
-int rsa_verify(const struct rsa_public_key *key, const uint8_t *signature,
- const uint8_t *sha, uint32_t *workbuf32)
-{
- uint8_t buf[RSANUMBYTES];
-
- /* Copy input to local workspace. */
- memcpy(buf, signature, RSANUMBYTES);
-
- mod_pow(key, buf, workbuf32); /* In-place exponentiation. */
-
- /* Check the PKCS#1 padding */
- if (check_padding(buf) != 0)
- return 0;
-
- /* Check the digest. */
- if (memcmp(buf + PKCS_PAD_SIZE, sha, SHA256_DIGEST_SIZE) != 0)
- return 0;
-
- return 1; /* All checked out OK. */
-}