/* This function will convert an attribute value, specified by the OID, * to a string. The result will be a null terminated string. * * res may be null. This will just return the res_size, needed to * hold the string. */ int _gnutls_x509_dn_to_string(const char *oid, void *value, int value_size, gnutls_datum_t * str) { const struct oid_to_string *oentry; int ret; gnutls_datum_t tmp; size_t size; if (value == NULL || value_size <= 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } oentry = get_oid_entry(oid); if (oentry == NULL) { /* unknown OID -> hex */ unknown_oid: str->size = value_size * 2 + 2; str->data = gnutls_malloc(str->size); if (str->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); size = str->size; ret = data2hex(value, value_size, str->data, &size); if (ret < 0) { gnutls_assert(); gnutls_free(str->data); return ret; } str->size = size; return 0; } if (oentry->asn_desc != NULL) { /* complex */ ret = decode_complex_string(oentry, value, value_size, &tmp); if (ret < 0) { /* we failed decoding -> handle it as unknown OID */ goto unknown_oid; } } else { ret = _gnutls_x509_decode_string(oentry->etype, value, value_size, &tmp); if (ret < 0) { /* we failed decoding -> handle it as unknown OID */ goto unknown_oid; } } ret = str_escape(&tmp, str); _gnutls_free_datum(&tmp); if (ret < 0) return gnutls_assert_val(ret); return 0; }
/* Reads a value from an ASN1 tree, then interprets it as the provided * type of string and returns the output in an allocated variable. * * Note that this function always places a null character * at the end of a readable string value (which is not accounted into size) */ int _gnutls_x509_read_string(ASN1_TYPE c, const char *root, gnutls_datum_t * ret, unsigned int etype) { int len = 0, result; size_t slen; uint8_t *tmp = NULL; unsigned rtype; result = asn1_read_value_type(c, root, NULL, &len, &rtype); if (result != ASN1_MEM_ERROR) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } if (rtype == ASN1_ETYPE_BIT_STRING) len /= 8; tmp = gnutls_malloc((size_t) len + 1); if (tmp == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value(c, root, tmp, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (rtype == ASN1_ETYPE_BIT_STRING) len /= 8; /* Extract the STRING. */ slen = (size_t) len; result = _gnutls_x509_decode_string(etype, tmp, slen, ret); if (result < 0) { gnutls_assert(); goto cleanup; } gnutls_free(tmp); return 0; cleanup: gnutls_free(tmp); return result; }
/* Decodes the SafeContents, and puts the output in * the given bag. */ int _pkcs12_decode_safe_contents(const gnutls_datum_t * content, gnutls_pkcs12_bag_t bag) { char oid[MAX_OID_SIZE], root[MAX_NAME_SIZE]; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int len, result; int bag_type; gnutls_datum_t attr_val; gnutls_datum_t t; int count = 0, attributes, j; unsigned i; /* Step 1. Extract the SEQUENCE. */ if ((result = asn1_create_element (_gnutls_get_pkix(), "PKIX1.pkcs-12-SafeContents", &c2)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = asn1_der_decoding(&c2, content->data, content->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Count the number of bags */ result = asn1_number_of_elements(c2, "", &count); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } bag->bag_elements = MIN(MAX_BAG_ELEMENTS, count); for (i = 0; i < bag->bag_elements; i++) { snprintf(root, sizeof(root), "?%u.bagId", i + 1); len = sizeof(oid); result = asn1_read_value(c2, root, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Bag type */ bag_type = oid2bag(oid); if (bag_type < 0) { gnutls_assert(); goto cleanup; } /* Read the Bag Value */ snprintf(root, sizeof(root), "?%u.bagValue", i + 1); result = _gnutls_x509_read_value(c2, root, &bag->element[i].data); if (result < 0) { gnutls_assert(); goto cleanup; } if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL || bag_type == GNUTLS_BAG_SECRET) { gnutls_datum_t tmp = bag->element[i].data; bag->element[i].data.data = NULL; bag->element[i].data.size = 0; result = _pkcs12_decode_crt_bag(bag_type, &tmp, &bag->element[i].data); _gnutls_free_datum(&tmp); if (result < 0) { gnutls_assert(); goto cleanup; } } /* read the bag attributes */ snprintf(root, sizeof(root), "?%u.bagAttributes", i + 1); result = asn1_number_of_elements(c2, root, &attributes); if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (attributes < 0) attributes = 1; if (result != ASN1_ELEMENT_NOT_FOUND) for (j = 0; j < attributes; j++) { snprintf(root, sizeof(root), "?%u.bagAttributes.?%u", i + 1, j + 1); result = _gnutls_x509_decode_and_read_attribute (c2, root, oid, sizeof(oid), &attr_val, 1, 0); if (result < 0) { gnutls_assert(); continue; /* continue in case we find some known attributes */ } if (strcmp(oid, KEY_ID_OID) == 0) { result = _gnutls_x509_decode_string (ASN1_ETYPE_OCTET_STRING, attr_val.data, attr_val.size, &t, 1); _gnutls_free_datum(&attr_val); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } _gnutls_free_datum(&bag->element[i].local_key_id); bag->element[i].local_key_id.data = t.data; bag->element[i].local_key_id.size = t.size; } else if (strcmp(oid, FRIENDLY_NAME_OID) == 0 && bag->element[i].friendly_name == NULL) { result = _gnutls_x509_decode_string (ASN1_ETYPE_BMP_STRING, attr_val.data, attr_val.size, &t, 1); _gnutls_free_datum(&attr_val); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } gnutls_free(bag->element[i].friendly_name); bag->element[i].friendly_name = (char *) t.data; } else { _gnutls_free_datum(&attr_val); _gnutls_debug_log ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid); } } bag->element[i].type = bag_type; } result = 0; cleanup: if (c2) asn1_delete_structure(&c2); return result; }
static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk, const gnutls_datum_t * fdata, gnutls_tpmkey_fmt_t format, TSS_HKEY * tpm_key) { int ret, err; gnutls_datum_t asn1 = { NULL, 0 }; if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) { gnutls_datum_t td; ret = gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata, &asn1); if (ret) { gnutls_assert(); _gnutls_debug_log ("Error decoding TSS key blob: %s\n", gnutls_strerror(ret)); return ret; } ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING, asn1.data, asn1.size, &td); if (ret < 0) { gnutls_assert(); goto cleanup; } gnutls_free(asn1.data); asn1.data = td.data; asn1.size = td.size; } else { /* DER */ UINT32 tint2; UINT32 type; asn1.size = fdata->size; asn1.data = gnutls_malloc(asn1.size); if (asn1.data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } tint2 = asn1.size; err = Tspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type, &tint2, asn1.data); if (err != 0) { gnutls_assert(); ret = tss_err(err); goto cleanup; } asn1.size = tint2; } /* ... we get it here instead. */ err = Tspi_Context_LoadKeyByBlob(tpm_ctx, srk, asn1.size, asn1.data, tpm_key); if (err != 0) { gnutls_assert(); ret = tss_err(err); goto cleanup; } ret = 0; cleanup: gnutls_free(asn1.data); return ret; }