121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/*
221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Copyright (C) 2016 The Android Open Source Project
321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
4c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * Permission is hereby granted, free of charge, to any person
5c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * obtaining a copy of this software and associated documentation
6c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * files (the "Software"), to deal in the Software without
7c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * restriction, including without limitation the rights to use, copy,
8c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * modify, merge, publish, distribute, sublicense, and/or sell copies
9c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * of the Software, and to permit persons to whom the Software is
10c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * furnished to do so, subject to the following conditions:
1121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
12c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * The above copyright notice and this permission notice shall be
13c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * included in all copies or substantial portions of the Software.
1421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
15c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * SOFTWARE.
2321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
2421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Use of this source code is governed by a BSD-style license that can be
2721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * found in the LICENSE file.
2821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
2921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
3021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* Implementation of RSA signature verification which uses a pre-processed
3121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * key for computation. The code extends libmincrypt RSA verification code to
3221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * support multiple RSA key lengths and hash digest algorithms.
3321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
3421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
3521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_rsa.h"
3621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_sha.h"
3721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_util.h"
3821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_vbmeta_image.h"
3921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
40047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthentypedef struct IAvbKey {
4121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  unsigned int len; /* Length of n[] in number of uint32_t */
4221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t n0inv;   /* -1 / n[0] mod 2^32 */
4321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* n;      /* modulus as array (host-byte order) */
4421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* rr;     /* R^2 as array (host-byte order) */
45047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen} IAvbKey;
4621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
47047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
4821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  AvbRSAPublicKeyHeader h;
49047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen  IAvbKey* key = NULL;
5021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t expected_length;
5121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  unsigned int i;
5221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const uint8_t* n;
5321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const uint8_t* rr;
5421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
5521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_rsa_public_key_header_validate_and_byteswap(
5621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen          (const AvbRSAPublicKeyHeader*)data, &h)) {
5721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Invalid key.\n");
5821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto fail;
5921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
6021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
6121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
6221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        h.key_num_bits == 8192)) {
6321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Unexpected key length.\n");
6421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto fail;
6521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
6621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
6721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
6821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (length != expected_length) {
6921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Key does not match expected length.\n");
7021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto fail;
7121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
7221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
7321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  n = data + sizeof(AvbRSAPublicKeyHeader);
7421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
7521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
7621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Store n and rr following the key header so we only have to do one
7721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * allocation.
7821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
79047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen  key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
804b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (key == NULL) {
814b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    goto fail;
824b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
8321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
8421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  key->len = h.key_num_bits / 32;
8521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  key->n0inv = h.n0inv;
86047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen  key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
8721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  key->rr = key->n + key->len;
8821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
8921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Crypto-code below (modpowF4() and friends) expects the key in
9021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * little-endian format (rather than the format we're storing the
9121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * key in), so convert it.
9221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
9321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < key->len; i++) {
9421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
9521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
9621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
9721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return key;
9821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
9921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenfail:
1004b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (key != NULL) {
1014b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    avb_free(key);
1024b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
10321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return NULL;
10421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
10521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
106047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic void iavb_free_parsed_key(IAvbKey* key) {
1074b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  avb_free(key);
1084b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen}
10921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
11021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* a[] -= mod */
111047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic void subM(const IAvbKey* key, uint32_t* a) {
11221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  int64_t A = 0;
11321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t i;
11421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < key->len; ++i) {
11521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    A += (uint64_t)a[i] - key->n[i];
11621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    a[i] = (uint32_t)A;
11721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    A >>= 32;
11821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
11921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
12021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
12121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* return a[] >= mod */
122047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic int geM(const IAvbKey* key, uint32_t* a) {
12321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t i;
12421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = key->len; i;) {
12521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    --i;
1264b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (a[i] < key->n[i]) {
1274b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      return 0;
1284b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    }
1294b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (a[i] > key->n[i]) {
1304b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      return 1;
1314b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    }
13221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
13321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return 1; /* equal */
13421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
13521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
13621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* montgomery c[] += a * b[] / R % mod */
137047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic void montMulAdd(const IAvbKey* key,
1384b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                       uint32_t* c,
1394b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                       const uint32_t a,
14021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                       const uint32_t* b) {
14121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t A = (uint64_t)a * b[0] + c[0];
14221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t d0 = (uint32_t)A * key->n0inv;
14321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
14421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t i;
14521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
14621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 1; i < key->len; ++i) {
14721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    A = (A >> 32) + (uint64_t)a * b[i] + c[i];
14821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
14921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    c[i - 1] = (uint32_t)B;
15021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
15121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
15221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  A = (A >> 32) + (B >> 32);
15321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
15421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  c[i - 1] = (uint32_t)A;
15521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
15621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (A >> 32) {
15721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    subM(key, c);
15821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
15921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
16021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
16121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* montgomery c[] = a[] * b[] / R % mod */
162047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
16321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t i;
16421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < key->len; ++i) {
16521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    c[i] = 0;
16621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
16721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < key->len; ++i) {
16821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    montMulAdd(key, c, a[i], b);
16921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
17021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
17121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
17221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* In-place public exponentiation. (65537}
17321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Input and output big-endian byte array in inout.
17421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
175047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthenstatic void modpowF4(const IAvbKey* key, uint8_t* inout) {
17621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
17721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
17821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
1794b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (a == NULL || aR == NULL || aaR == NULL) {
1804b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    goto out;
1814b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
18221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
18321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t* aaa = aaR; /* Re-use location. */
18421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  int i;
18521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
18621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Convert from big endian byte array to little endian word array. */
18721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < (int)key->len; ++i) {
18821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
18921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                   (inout[((key->len - 1 - i) * 4) + 1] << 16) |
19021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                   (inout[((key->len - 1 - i) * 4) + 2] << 8) |
19121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                   (inout[((key->len - 1 - i) * 4) + 3] << 0);
19221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    a[i] = tmp;
19321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
19421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
19521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M   */
19621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = 0; i < 16; i += 2) {
19721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    montMul(key, aaR, aR, aR);  /* aaR = aR * aR / R mod M */
19821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
19921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
20021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
20121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
20221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Make sure aaa < mod; aaa is at most 1x mod too large. */
20321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (geM(key, aaa)) {
20421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    subM(key, aaa);
20521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
20621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
20721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Convert to bigendian byte array */
20821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (i = (int)key->len - 1; i >= 0; --i) {
20921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    uint32_t tmp = aaa[i];
21021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    *inout++ = (uint8_t)(tmp >> 24);
21121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    *inout++ = (uint8_t)(tmp >> 16);
21221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    *inout++ = (uint8_t)(tmp >> 8);
21321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    *inout++ = (uint8_t)(tmp >> 0);
21421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
21521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
21621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenout:
2174b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (a != NULL) {
2184b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    avb_free(a);
2194b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
2204b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (aR != NULL) {
2214b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    avb_free(aR);
2224b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
2234b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (aaR != NULL) {
2244b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    avb_free(aaR);
2254b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
22621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
22721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
22821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/* Verify a RSA PKCS1.5 signature against an expected hash.
22921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Returns false on failure, true on success.
23021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
2314b6a634e48353da1e119ebe0287299f7b919d778David Zeuthenbool avb_rsa_verify(const uint8_t* key,
2324b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t key_num_bytes,
2334b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    const uint8_t* sig,
2344b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t sig_num_bytes,
2354b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    const uint8_t* hash,
2364b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t hash_num_bytes,
2374b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    const uint8_t* padding,
2384b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t padding_num_bytes) {
23921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint8_t* buf = NULL;
240047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen  IAvbKey* parsed_key = NULL;
24121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  bool success = false;
24221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
24321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
24421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Invalid input.\n");
24521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
24621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
24721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
248047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen  parsed_key = iavb_parse_key_data(key, key_num_bytes);
24921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (parsed_key == NULL) {
25021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Error parsing key.\n");
25121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
25221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
25321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
25521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Signature length does not match key length.\n");
25621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
25721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
25821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
26021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Padding length does not match hash and signature lengths.\n");
26121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
26221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
26321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
26421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  buf = (uint8_t*)avb_malloc(sig_num_bytes);
26521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (buf == NULL) {
26621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Error allocating memory.\n");
26721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
26821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
26921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memcpy(buf, sig, sig_num_bytes);
27021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
27121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  modpowF4(parsed_key, buf);
27221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
27321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Check padding bytes.
27421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   *
27521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * Even though there are probably no timing issues here, we use
27621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * avb_safe_memcmp() just to be on the safe side.
27721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
27821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
27921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Padding check failed.\n");
28021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
28121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
28221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
28321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Check hash. */
28421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
28521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Hash check failed.\n");
28621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto out;
28721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
28821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
28921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  success = true;
29021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
29121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenout:
2924b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (parsed_key != NULL) {
293047ecf7d2361ffcb39a5a4ec0709480f47ed76e2David Zeuthen    iavb_free_parsed_key(parsed_key);
2944b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
2954b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (buf != NULL) {
2964b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    avb_free(buf);
2974b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
29821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return success;
29921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
300