core/asn1/dme/dme_structure_raw_ecc.c (160 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "dme_structure_raw_ecc.h"
/**
* Encode the raw ECC DME key and ECDSA signature in DER.
*
* @param dme The DME container with buffers for DER encoding.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param key_der_length Output for the encoded length of the public key.
* @param signature_length Output for the encoded length of the signature.
*
* @return 0 if the DER encoding was successful or an error code.
*/
static int dme_structure_raw_ecc_encode_der (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_key_x, const uint8_t *dme_key_y, size_t key_length,
const uint8_t *signature_r, const uint8_t *signature_s, size_t *key_der_length,
size_t *signature_length)
{
int der_length;
if ((dme == NULL) || (dme_key_x == NULL) || (dme_key_y == NULL) || (signature_r == NULL) ||
(signature_s == NULL)) {
return DME_STRUCTURE_INVALID_ARGUMENT;
}
der_length = ecc_der_encode_public_key (dme_key_x, dme_key_y, key_length, dme->dme_key_der,
sizeof (dme->dme_key_der));
if (ROT_IS_ERROR (der_length)) {
return der_length;
}
*key_der_length = der_length;
/* It's not possible for this call to fail since the buffer will always be large enough, but
* check the return just to be sure. */
der_length = ecc_der_encode_ecdsa_signature (signature_r, signature_s, key_length,
dme->signature_der, sizeof (dme->signature_der));
if (ROT_IS_ERROR (der_length)) {
return der_length;
}
*signature_length = der_length;
return 0;
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-384 digest of the DICE Device ID public key.
* - SHA-384 measurement of DICE layer 0.
*
* This is DME structure type 1.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha384 (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha384 (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-384 digest of the DICE Device ID public key.
* - 32-byte freshness seed
* - SHA-384 measurement of DICE layer 0.
*
* This is DME structure type 2.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha384_with_challenge (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha384_with_challenge (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-256 digest of the DICE Device ID public key.
* - SHA-256 measurement of DICE layer 0.
*
* This is DME structure type 3.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha256 (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha256 (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-256 digest of the DICE Device ID public key.
* - 32-byte freshness seed
* - SHA-256 measurement of DICE layer 0.
*
* This is DME structure type 4.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha256_with_challenge (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha256_with_challenge (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-512 digest of the DICE Device ID public key.
* - SHA-512 measurement of DICE layer 0.
*
* This is DME structure type 5.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha512 (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha512 (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - SHA-512 digest of the DICE Device ID public key.
* - 32-byte freshness seed
* - SHA-521 measurement of DICE layer 0.
*
* This is DME structure type 6.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_sha512_with_challenge (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_sha512_with_challenge (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a DME structure that contains:
* - 64-byte device freshness seed, little-endian.
* - 64-byte firmware freshness seed, little-endian.
* - ECC-384 DICE Device ID public key, raw X,Y values, little-endian.
* - SHA-512 measurement of DICE layer 0, little-endian.
*
* This is DME structure type 7.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_le_ecc384_with_sha512_nonce_and_challenge (
struct dme_structure_raw_ecc *dme, const uint8_t *dme_struct_data, size_t dme_struct_length,
const uint8_t *dme_key_x, const uint8_t *dme_key_y, size_t key_length,
const uint8_t *signature_r, const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_le_ecc384_with_sha512_nonce_and_challenge (&dme->base,
dme_struct_data, dme_struct_length, dme->dme_key_der, key_der_length, dme->signature_der,
signature_length, sig_hash);
}
/**
* Initialize DME information for a device that uses a chained DME structure that contains:
* - SHA-384 digest of an intermediate signing key directly endorsed by DME.
* - SHA-384 measurement of DICE layer 0.
* - ECDSA P-384 signature over the previous fields using SHA-384 and the DME private key.
* - ECC P-384 public key of the intermediate signing key.
* - SHA-384 digest of the DICE Device ID public key.
*
* This is DME structure type 8.
*
* @param dme The DME information to initialize.
* @param dme_struct_data The DME structure data signed by the DME key.
* @param dme_struct_length Length of the DME structure.
* @param dme_key_x Raw X coordinate of the DME public key.
* @param dme_key_y Raw Y coordinate of the DME public key.
* @param key_length Length of the DME ECC key. This represents the length of a single public key
* coordinate. The DME key must be a P-384 key.
* @param signature_r Raw r value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param signature_s Raw s value of the ECDSA signature. This must be the same length as the
* public key coordinates.
* @param sig_hash The hash algorithm that was used to generate the signature.
*
* @return 0 if the DME information was successfully initialized or an error code.
*/
int dme_structure_raw_ecc_init_chained_ecc384_sha384 (struct dme_structure_raw_ecc *dme,
const uint8_t *dme_struct_data, size_t dme_struct_length, const uint8_t *dme_key_x,
const uint8_t *dme_key_y, size_t key_length, const uint8_t *signature_r,
const uint8_t *signature_s, enum hash_type sig_hash)
{
size_t key_der_length;
size_t signature_length;
int status;
if (key_length != ECC_KEY_LENGTH_384) {
return DME_STRUCTURE_UNSUPPORTED_KEY_LENGTH;
}
status = dme_structure_raw_ecc_encode_der (dme, dme_key_x, dme_key_y, key_length, signature_r,
signature_s, &key_der_length, &signature_length);
if (status != 0) {
return status;
}
return dme_structure_init_chained_ecc384_sha384 (&dme->base, dme_struct_data, dme_struct_length,
dme->dme_key_der, key_der_length, dme->signature_der, signature_length, sig_hash);
}