int x509_extension_builder_mbedtls_dice_tcbinfo_create_extension()

in core/asn1/dice/x509_extension_builder_mbedtls_dice_tcbinfo.c [27:156]


int x509_extension_builder_mbedtls_dice_tcbinfo_create_extension (
	const struct x509_extension_builder_mbedtls_dice_tcbinfo *dice, uint8_t *buffer, size_t length,
	struct x509_extension *extension)
{
	uint8_t *pos;
	int enc_length = 0;
	mbedtls_mpi svn;
	int fwid_length;
	char *fwid_oid;
	size_t fwid_oid_length;
	int ret;

	if (dice->tcb == NULL) {
		return DICE_TCBINFO_EXTENSION_INVALID_ARGUMENT;
	}

	if (dice->tcb->version == NULL) {
		return DICE_TCBINFO_EXTENSION_NO_VERSION;
	}

	if ((dice->tcb->svn == NULL) || (dice->tcb->svn_length == 0)) {
		return DICE_TCBINFO_EXTENSION_NO_SVN;
	}

	if (dice->tcb->fwid == NULL) {
		return DICE_TCBINFO_EXTENSION_NO_FWID;
	}

	switch (dice->tcb->fwid_hash) {
		case HASH_TYPE_SHA1:
			fwid_length = SHA1_HASH_LENGTH;
			fwid_oid = MBEDTLS_OID_DIGEST_ALG_SHA1;
			fwid_oid_length = MBEDTLS_OID_SIZE (MBEDTLS_OID_DIGEST_ALG_SHA1);
			break;

		case HASH_TYPE_SHA256:
			fwid_length = SHA256_HASH_LENGTH;
			fwid_oid = MBEDTLS_OID_DIGEST_ALG_SHA256;
			fwid_oid_length = MBEDTLS_OID_SIZE (MBEDTLS_OID_DIGEST_ALG_SHA256);
			break;

		case HASH_TYPE_SHA384:
			fwid_length = SHA384_HASH_LENGTH;
			fwid_oid = MBEDTLS_OID_DIGEST_ALG_SHA384;
			fwid_oid_length = MBEDTLS_OID_SIZE (MBEDTLS_OID_DIGEST_ALG_SHA384);
			break;

		case HASH_TYPE_SHA512:
			fwid_length = SHA512_HASH_LENGTH;
			fwid_oid = MBEDTLS_OID_DIGEST_ALG_SHA512;
			fwid_oid_length = MBEDTLS_OID_SIZE (MBEDTLS_OID_DIGEST_ALG_SHA512);
			break;

		default:
			return DICE_TCBINFO_EXTENSION_UNKNOWN_FWID;
	}

	pos = buffer + length;

	/* fwids		Fwids		OPTIONAL */

	/* fwid				OCTET_STRING */
	MBEDTLS_ASN1_CHK_ADD (enc_length,
		mbedtls_asn1_write_raw_buffer (&pos, buffer, dice->tcb->fwid, fwid_length));
	ret = x509_mbedtls_close_asn1_object (&pos, buffer, MBEDTLS_ASN1_OCTET_STRING, &enc_length);
	if (ret != 0) {
		return ret;
	}

	/* hashAlg			OBJECT IDENTIFIER */
	MBEDTLS_ASN1_CHK_ADD (enc_length,
		mbedtls_asn1_write_oid (&pos, buffer, fwid_oid, fwid_oid_length));

	/* fwid SEQUENCE */
	ret = x509_mbedtls_close_asn1_object (&pos, buffer,
		(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE), &enc_length);
	if (ret != 0) {
		return ret;
	}

	ret = x509_mbedtls_close_asn1_object (&pos, buffer,
		(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | 6), &enc_length);
	if (ret != 0) {
		return ret;
	}

	/* svn			INTEGER		OPTIONAL */
	/* mbedtls_asn1_write_int only writes 1 byte integers.  MPI is needed for larger ones. */
	mbedtls_mpi_init (&svn);
	ret = mbedtls_mpi_read_binary (&svn, dice->tcb->svn, dice->tcb->svn_length);
	if (ret != 0) {
		if (ret == MBEDTLS_ERR_MPI_ALLOC_FAILED) {
			ret = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		}

		return ret;
	}

	ret = mbedtls_asn1_write_mpi (&pos, buffer, &svn);
	mbedtls_mpi_free (&svn);
	if (ret < 0) {
		return ret;
	}

	enc_length += ret;
	*pos = (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 3);

	/* version		IA5String	OPTIONAL */
	MBEDTLS_ASN1_CHK_ADD (enc_length,
		mbedtls_asn1_write_ia5_string (&pos, buffer, dice->tcb->version,
		strlen (dice->tcb->version)));
	*pos = (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2);

	/* DiceTcbInfo ::= SEQUENCE */
	ret = x509_mbedtls_close_asn1_object (&pos, buffer,
		(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE), &enc_length);
	if (ret != 0) {
		return ret;
	}

	if (pos != buffer) {
		memmove (buffer, pos, enc_length);
	}

	x509_extension_builder_init_extension_descriptor (extension, false,
		X509_EXTENSION_BUILDER_DICE_TCBINFO_OID, X509_EXTENSION_BUILDER_DICE_TCBINFO_OID_LENGTH,
		buffer, enc_length);

	return 0;
}