blob: bfdfd6b0c99f664d4cf631d22b9952b88cf7b27a [file]
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "avb_mldsa.h"
#include "avb_util.h"
#include "avb_vbmeta_image.h"
bool avb_mldsa_public_key_header_validate_and_byteswap(
const AvbMLDSAPublicKeyHeader* src, AvbMLDSAPublicKeyHeader* dest) {
avb_memcpy(dest, src, sizeof(AvbMLDSAPublicKeyHeader));
dest->key_num_bytes = avb_be32toh(dest->key_num_bytes);
return true;
}
static bool avb_mldsa_validate_public_key(const uint8_t* key,
size_t key_num_bytes,
AvbAlgorithmType algorithm,
AvbMLDSAPublicKeyHeader* out_header) {
uint32_t expected_key_num_bytes;
if (key == NULL || out_header == NULL) {
avb_error("Invalid input.\n");
return false;
}
if (key_num_bytes < sizeof(AvbMLDSAPublicKeyHeader)) {
avb_error("Invalid key length.\n");
return false;
}
if (!avb_mldsa_public_key_header_validate_and_byteswap(
(const AvbMLDSAPublicKeyHeader*)key, out_header)) {
avb_error("Invalid key.\n");
return false;
}
switch (algorithm) {
case AVB_ALGORITHM_TYPE_MLDSA65:
expected_key_num_bytes = 1952;
break;
case AVB_ALGORITHM_TYPE_MLDSA87:
expected_key_num_bytes = 2592;
break;
default:
avb_error("Unexpected algorithm.\n");
return false;
}
if (out_header->key_num_bytes != expected_key_num_bytes) {
avb_error("Unexpected key length.\n");
return false;
}
if (key_num_bytes !=
sizeof(AvbMLDSAPublicKeyHeader) + out_header->key_num_bytes) {
avb_error("Key does not match expected length.\n");
return false;
}
return true;
}
bool avb_mldsa_prehash_init(AvbMLDSAPrehashCtx* ctx,
AvbAlgorithmType algorithm,
const uint8_t* key,
size_t key_num_bytes,
const uint8_t* context,
size_t context_len) {
AvbMLDSAPublicKeyHeader h;
if (ctx == NULL) {
avb_error("Invalid input.\n");
return false;
}
if (!avb_mldsa_validate_public_key(key, key_num_bytes, algorithm, &h)) {
return false;
}
return avb_mldsa_prehash_init_impl(ctx,
algorithm,
key + sizeof(AvbMLDSAPublicKeyHeader),
h.key_num_bytes,
context,
context_len);
}
bool avb_mldsa_verify_message_representative(
AvbAlgorithmType algorithm,
const uint8_t* key,
size_t key_num_bytes,
const uint8_t* sig,
size_t sig_num_bytes,
const uint8_t msg_rep[AVB_MLDSA_MU_BYTES]) {
AvbMLDSAPublicKeyHeader h;
uint32_t expected_sig_num_bytes;
if (key == NULL || sig == NULL || msg_rep == NULL) {
avb_error("Invalid input.\n");
return false;
}
if (!avb_mldsa_validate_public_key(key, key_num_bytes, algorithm, &h)) {
return false;
}
switch (algorithm) {
case AVB_ALGORITHM_TYPE_MLDSA65:
expected_sig_num_bytes = 3309;
break;
case AVB_ALGORITHM_TYPE_MLDSA87:
expected_sig_num_bytes = 4627;
break;
default:
avb_error("Unexpected algorithm.\n");
return false;
}
if (sig_num_bytes != expected_sig_num_bytes) {
avb_error("Signature length does not match key length.\n");
return false;
}
return avb_mldsa_verify_message_representative_impl(
algorithm,
key + sizeof(AvbMLDSAPublicKeyHeader),
h.key_num_bytes,
sig,
sig_num_bytes,
msg_rep);
}