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