static int _parse_safe_contents(ASN1_TYPE sc, const char *sc_name, gnutls_pkcs12_bag_t bag) { gnutls_datum_t content = { NULL, 0 }; int result; /* Step 1. Extract the content. */ result = _gnutls_x509_read_string(sc, sc_name, &content, ASN1_ETYPE_OCTET_STRING, 1); if (result < 0) { gnutls_assert(); goto cleanup; } result = _pkcs12_decode_safe_contents(&content, bag); if (result < 0) { gnutls_assert(); goto cleanup; } _gnutls_free_datum(&content); return 0; cleanup: _gnutls_free_datum(&content); return result; }
/* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue * otherwise. * * octet_string should be non-zero if we are to decode octet strings after * decoding. * * The output is allocated and stored in value. */ int _gnutls_x509_decode_and_read_attribute(ASN1_TYPE asn1_struct, const char *where, char *oid, int oid_size, gnutls_datum_t * value, int multi, int octet_string) { char tmpbuffer[128]; int len, result; /* Read the OID */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".type"); len = oid_size - 1; result = asn1_read_value(asn1_struct, tmpbuffer, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".value"); if (multi) _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), "s.?1"); /* .values.?1 */ if (octet_string) result = _gnutls_x509_read_string(asn1_struct, tmpbuffer, value, ASN1_ETYPE_OCTET_STRING, 0); else result = _gnutls_x509_read_value(asn1_struct, tmpbuffer, value); if (result < 0) { gnutls_assert(); return result; } return 0; }
static int _decode_pkcs8_eddsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, const char *oid) { int ret; gnutls_datum_t tmp; gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID; const gnutls_ecc_curve_entry_st *ce; gnutls_pk_params_init(&pkey->params); curve = gnutls_oid_to_ecc_curve(oid); if (curve == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid); return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } ce = _gnutls_ecc_curve_get_params(curve); if (_curve_is_eddsa(ce)) { ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); return gnutls_assert_val(ret); } if (tmp.size != ce->size) { gnutls_free(tmp.data); return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); } gnutls_free(pkey->params.raw_priv.data); pkey->params.algo = GNUTLS_PK_EDDSA_ED25519; pkey->params.raw_priv.data = tmp.data; pkey->params.raw_priv.size = tmp.size; pkey->params.curve = curve; tmp.data = NULL; return 0; } else { return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } }
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data, * which holds them. Returns an ASN1_TYPE of authenticatedSafe. */ static int _decode_pkcs12_auth_safe(ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe, gnutls_datum_t * raw) { char oid[MAX_OID_SIZE]; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; gnutls_datum_t auth_safe = { NULL, 0 }; int len, result; char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; len = sizeof(oid) - 1; result = asn1_read_value(pkcs12, "authSafe.contentType", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (strcmp(oid, DATA_OID) != 0) { gnutls_assert(); _gnutls_debug_log("Unknown PKCS12 Content OID '%s'\n", oid); return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; } /* Step 1. Read the content data */ result = _gnutls_x509_read_string(pkcs12, "authSafe.content", &auth_safe, ASN1_ETYPE_OCTET_STRING, 1); if (result < 0) { gnutls_assert(); goto cleanup; } /* Step 2. Extract the authenticatedSafe. */ if ((result = asn1_create_element (_gnutls_get_pkix(), "PKIX1.pkcs-12-AuthenticatedSafe", &c2)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = asn1_der_decoding(&c2, auth_safe.data, auth_safe.size, error_str); if (result != ASN1_SUCCESS) { gnutls_assert(); _gnutls_debug_log("DER error: %s\n", error_str); result = _gnutls_asn2err(result); goto cleanup; } if (raw == NULL) { _gnutls_free_datum(&auth_safe); } else { raw->data = auth_safe.data; raw->size = auth_safe.size; } if (authen_safe) *authen_safe = c2; else asn1_delete_structure(&c2); return 0; cleanup: if (c2) asn1_delete_structure(&c2); _gnutls_free_datum(&auth_safe); return result; }
int _pkcs12_decode_crt_bag(gnutls_pkcs12_bag_type_t type, const gnutls_datum_t * in, gnutls_datum_t * out) { int ret; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; switch (type) { case GNUTLS_BAG_CERTIFICATE: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-CertBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "certValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; case GNUTLS_BAG_CRL: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-CRLBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "crlValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; case GNUTLS_BAG_SECRET: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-SecretBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "secretValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; default: gnutls_assert(); asn1_delete_structure(&c2); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } asn1_delete_structure(&c2); return 0; cleanup: asn1_delete_structure(&c2); return ret; }