int x509_extension_builder_openssl_dice_tcbinfo_build()

in projects/linux/asn1/dice/x509_extension_builder_openssl_dice_tcbinfo.c [63:203]


int x509_extension_builder_openssl_dice_tcbinfo_build (const struct x509_extension_builder *builder,
	struct x509_extension *extension)
{
	const struct x509_extension_builder_openssl_dice_tcbinfo *dice =
		(const struct x509_extension_builder_openssl_dice_tcbinfo*) builder;
	DICE_TCBINFO *tcbinfo;
	BIGNUM *svn;
	DICE_FWID *fwid;
	ASN1_OBJECT *fwid_oid;
	int fwid_len;
	int status;
	uint8_t *tcb_der = NULL;
	int tcb_der_len;

	if ((dice == NULL) || (extension == NULL)) {
		return DICE_TCBINFO_EXTENSION_INVALID_ARGUMENT;
	}

	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_len = SHA1_HASH_LENGTH;
			fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha1 ()));
			break;

		case HASH_TYPE_SHA256:
			fwid_len = SHA256_HASH_LENGTH;
			fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha256 ()));
			break;

		case HASH_TYPE_SHA384:
			fwid_len = SHA384_HASH_LENGTH;
			fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha384 ()));
			break;

		case HASH_TYPE_SHA512:
			fwid_len = SHA512_HASH_LENGTH;
			fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha512 ()));
			break;

		default:
			return DICE_TCBINFO_EXTENSION_UNKNOWN_FWID;
	}

	if (fwid_oid == NULL) {
		return -ERR_get_error ();
	}

	tcbinfo = DICE_TCBINFO_new ();
	if (tcbinfo == NULL) {
		status = -ERR_get_error ();
		goto err_tcb;
	}

	tcbinfo->version = ASN1_IA5STRING_new ();
	if (tcbinfo->version == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	tcbinfo->version->length = strlen (dice->tcb->version);
	tcbinfo->version->data = (unsigned char*) strdup (dice->tcb->version);
	if (tcbinfo->version->data == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	svn = BN_bin2bn (dice->tcb->svn, dice->tcb->svn_length, NULL);
	if (svn == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	tcbinfo->svn = BN_to_ASN1_INTEGER (svn, NULL);
	BN_free (svn);
	if (tcbinfo->svn == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	tcbinfo->digests = sk_DICE_FWID_new_null ();
	if (tcbinfo->digests == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	fwid = DICE_FWID_new ();
	if (fwid == NULL) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_build;
	}

	ASN1_OBJECT_free (fwid->hash_alg);
	fwid->hash_alg = fwid_oid;

	if (ASN1_OCTET_STRING_set (fwid->digest, dice->tcb->fwid, fwid_len) == 0) {
		status = -ERR_get_error ();
		goto err_fwid;
	}

	status = sk_DICE_FWID_push (tcbinfo->digests, fwid);
	if (status == 0) {
		status = DICE_TCBINFO_EXTENSION_NO_MEMORY;
		goto err_fwid;
	}

	tcb_der_len = i2d_DICE_TCBINFO (tcbinfo, &tcb_der);
	if (tcb_der_len < 0) {
		status = -ERR_get_error ();
		goto err_build;
	}

	x509_extension_builder_init_extension_descriptor (extension, false,
		X509_EXTENSION_BUILDER_DICE_TCBINFO_OID, X509_EXTENSION_BUILDER_DICE_TCBINFO_OID_LENGTH,
		tcb_der, tcb_der_len);

	DICE_TCBINFO_free (tcbinfo);
	return 0;

err_fwid:
	DICE_FWID_free (fwid);
err_build:
	DICE_TCBINFO_free (tcbinfo);
err_tcb:
	return status;
}