/* This will encode and write the AttributeTypeAndValue field. * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute. * In all cases only one value is written. */ int _gnutls_x509_encode_and_write_attribute(const char *given_oid, ASN1_TYPE asn1_struct, const char *where, const void *_data, int data_size, int multi) { const uint8_t *data = _data; char tmp[128]; int result; const struct oid_to_string *oentry; oentry = get_oid_entry(given_oid); if (oentry == NULL) { gnutls_assert(); _gnutls_debug_log("Cannot find OID: %s\n", given_oid); return GNUTLS_E_X509_UNSUPPORTED_OID; } /* write the data (value) */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".value"); if (multi != 0) { /* if not writing an AttributeTypeAndValue, but an Attribute */ _gnutls_str_cat(tmp, sizeof(tmp), "s"); /* values */ result = asn1_write_value(asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST"); } if (oentry->asn_desc != NULL) { /* write a complex string API */ result = write_complex_string(asn1_struct, tmp, oentry, data, data_size); if (result < 0) return gnutls_assert_val(result); } else { /* write a simple string */ gnutls_datum_t td; td.data = (void *) data; td.size = data_size; result = _gnutls_x509_write_string(asn1_struct, tmp, &td, oentry->etype); if (result < 0) { gnutls_assert(); goto error; } } /* write the type */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".type"); result = asn1_write_value(asn1_struct, tmp, given_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = 0; error: return result; }
/** * gnutls_x509_crt_set_policy: * @cert: should contain a #gnutls_x509_crt_t structure * @policy: A pointer to a policy structure. * @critical: use non-zero if the extension is marked as critical * * This function will set the certificate policy extension (2.5.29.32). * Multiple calls to this function append a new policy. * * Note the maximum text size for the qualifier %GNUTLS_X509_QUALIFIER_NOTICE * is 200 characters. This function will fail with %GNUTLS_E_INVALID_REQUEST * if this is exceeded. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1.5 **/ int gnutls_x509_crt_set_policy(gnutls_x509_crt_t crt, struct gnutls_x509_policy_st *policy, unsigned int critical) { int result; unsigned i; gnutls_datum_t der_data, tmpd, prev_der_data = { NULL, 0 }; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; const char *oid; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = _gnutls_x509_crt_get_extension(crt, "2.5.29.32", 0, &prev_der_data, NULL); if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_assert(); return result; } result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.certificatePolicies", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (prev_der_data.data != NULL) { result = asn1_der_decoding(&c2, prev_der_data.data, prev_der_data.size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } } /* 1. write a new policy */ result = asn1_write_value(c2, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* 2. Add the OID. */ result = asn1_write_value(c2, "?LAST.policyIdentifier", policy->oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } for (i = 0; i < MIN(policy->qualifiers, GNUTLS_MAX_QUALIFIERS); i++) { result = asn1_write_value(c2, "?LAST.policyQualifiers", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (policy->qualifier[i].type == GNUTLS_X509_QUALIFIER_URI) oid = "1.3.6.1.5.5.7.2.1"; else if (policy->qualifier[i].type == GNUTLS_X509_QUALIFIER_NOTICE) oid = "1.3.6.1.5.5.7.2.2"; else { result = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); goto cleanup; } result = asn1_write_value(c2, "?LAST.policyQualifiers.?LAST.policyQualifierId", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (policy->qualifier[i].type == GNUTLS_X509_QUALIFIER_URI) { tmpd.data = (void *) policy->qualifier[i].data; tmpd.size = policy->qualifier[i].size; result = _gnutls_x509_write_string(c2, "?LAST.policyQualifiers.?LAST.qualifier", &tmpd, ASN1_ETYPE_IA5_STRING); if (result < 0) { gnutls_assert(); goto cleanup; } } else if (policy->qualifier[i].type == GNUTLS_X509_QUALIFIER_NOTICE) { tmpd.data = (void *) policy->qualifier[i].data; tmpd.size = policy->qualifier[i].size; if (tmpd.size > 200) { gnutls_assert(); result = GNUTLS_E_INVALID_REQUEST; goto cleanup; } result = encode_user_notice(&tmpd, &der_data); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_write_value(c2, "?LAST.policyQualifiers.?LAST.qualifier", &der_data); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); goto cleanup; } } } result = _gnutls_x509_der_encode(c2, "", &der_data, 0); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_crt_set_extension(crt, "2.5.29.32", &der_data, 0); _gnutls_free_datum(&der_data); crt->use_extensions = 1; cleanup: asn1_delete_structure(&c2); _gnutls_free_datum(&prev_der_data); return result; }
int _pkcs12_encode_crt_bag(gnutls_pkcs12_bag_type_t type, const gnutls_datum_t * raw, 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_write_value(c2, "certId", X509_CERT_OID, 1); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_write_string(c2, "certValue", raw, ASN1_ETYPE_OCTET_STRING); 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_write_value(c2, "crlId", X509_CRL_OID, 1); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_write_string(c2, "crlValue", raw, ASN1_ETYPE_OCTET_STRING); 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_write_value(c2, "secretTypeId", RANDOM_NONCE_OID, 1); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_write_string(c2, "secretValue", raw, ASN1_ETYPE_OCTET_STRING); if (ret < 0) { gnutls_assert(); goto cleanup; } break; default: gnutls_assert(); asn1_delete_structure(&c2); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } ret = _gnutls_x509_der_encode(c2, "", out, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } asn1_delete_structure(&c2); return 0; cleanup: asn1_delete_structure(&c2); return ret; }