// SPDX-License-Identifier: MIT OR BSD-3-Clause
/*
 * Copyright (C) 2016 The Android Open Source Project
 */

/* Implementation of RSA signature verification which uses a pre-processed
 * key for computation. The code extends libmincrypt RSA verification code to
 * support multiple RSA key lengths and hash digest algorithms.
 */

#include "avb_rsa.h"
#include "avb_sha.h"
#include "avb_util.h"
#include "avb_vbmeta_image.h"
#include <malloc.h>

typedef struct IAvbKey {
  unsigned int len; /* Length of n[] in number of uint32_t */
  uint32_t n0inv;   /* -1 / n[0] mod 2^32 */
  uint32_t* n;      /* modulus as array (host-byte order) */
  uint32_t* rr;     /* R^2 as array (host-byte order) */
} IAvbKey;

static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
  AvbRSAPublicKeyHeader h;
  IAvbKey* key = NULL;
  size_t expected_length;
  unsigned int i;
  const uint8_t* n;
  const uint8_t* rr;

  if (!avb_rsa_public_key_header_validate_and_byteswap(
          (const AvbRSAPublicKeyHeader*)data, &h)) {
    avb_error("Invalid key.\n");
    goto fail;
  }

  if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
        h.key_num_bits == 8192)) {
    avb_error("Unexpected key length.\n");
    goto fail;
  }

  expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
  if (length != expected_length) {
    avb_error("Key does not match expected length.\n");
    goto fail;
  }

  n = data + sizeof(AvbRSAPublicKeyHeader);
  rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;

  /* Store n and rr following the key header so we only have to do one
   * allocation.
   */
  key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
  if (key == NULL) {
    goto fail;
  }

  key->len = h.key_num_bits / 32;
  key->n0inv = h.n0inv;
  key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
  key->rr = key->n + key->len;

  /* Crypto-code below (modpowF4() and friends) expects the key in
   * little-endian format (rather than the format we're storing the
   * key in), so convert it.
   */
  for (i = 0; i < key->len; i++) {
    key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
    key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
  }
  return key;

fail:
  if (key != NULL) {
    avb_free(key);
  }
  return NULL;
}

static void iavb_free_parsed_key(IAvbKey* key) {
  avb_free(key);
}

/* a[] -= mod */
static void subM(const IAvbKey* 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 IAvbKey* 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 IAvbKey* 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 IAvbKey* 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 IAvbKey* key, uint8_t* inout) {
  uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
  uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
  uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
  if (a == NULL || aR == NULL || aaR == NULL) {
    goto out;
  }

  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);
  }

out:
  if (a != NULL) {
    avb_free(a);
  }
  if (aR != NULL) {
    avb_free(aR);
  }
  if (aaR != NULL) {
    avb_free(aaR);
  }
}

/* Verify a RSA PKCS1.5 signature against an expected hash.
 * Returns false on failure, true on success.
 */
bool avb_rsa_verify(const uint8_t* key,
                    size_t key_num_bytes,
                    const uint8_t* sig,
                    size_t sig_num_bytes,
                    const uint8_t* hash,
                    size_t hash_num_bytes,
                    const uint8_t* padding,
                    size_t padding_num_bytes) {
  uint8_t* buf = NULL;
  IAvbKey* parsed_key = NULL;
  bool success = false;

  if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
    avb_error("Invalid input.\n");
    goto out;
  }

  parsed_key = iavb_parse_key_data(key, key_num_bytes);
  if (parsed_key == NULL) {
    avb_error("Error parsing key.\n");
    goto out;
  }

  if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
    avb_error("Signature length does not match key length.\n");
    goto out;
  }

  if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
    avb_error("Padding length does not match hash and signature lengths.\n");
    goto out;
  }

  buf = (uint8_t*)avb_malloc(sig_num_bytes);
  if (buf == NULL) {
    avb_error("Error allocating memory.\n");
    goto out;
  }
  avb_memcpy(buf, sig, sig_num_bytes);

  modpowF4(parsed_key, buf);

  /* Check padding bytes.
   *
   * Even though there are probably no timing issues here, we use
   * avb_safe_memcmp() just to be on the safe side.
   */
  if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
    avb_error("Padding check failed.\n");
    goto out;
  }

  /* Check hash. */
  if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
    avb_error("Hash check failed.\n");
    goto out;
  }

  success = true;

out:
  if (parsed_key != NULL) {
    iavb_free_parsed_key(parsed_key);
  }
  if (buf != NULL) {
    avb_free(buf);
  }
  return success;
}
