/* This function will attempt to set the requested extension in * the given X509v3 certificate. * * Critical will be either 0 or 1. */ static int add_extension(ASN1_TYPE asn, const char *root, const char *extension_id, const gnutls_datum_t * ext_data, unsigned int critical) { int result; const char *str; char name[ASN1_MAX_NAME_SIZE]; snprintf(name, sizeof(name), "%s", root); /* Add a new extension in the list. */ result = asn1_write_value(asn, name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (root[0] != 0) snprintf(name, sizeof(name), "%s.?LAST.extnID", root); else snprintf(name, sizeof(name), "?LAST.extnID"); result = asn1_write_value(asn, name, extension_id, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (critical == 0) str = "FALSE"; else str = "TRUE"; if (root[0] != 0) snprintf(name, sizeof(name), "%s.?LAST.critical", root); else snprintf(name, sizeof(name), "?LAST.critical"); result = asn1_write_value(asn, name, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (root[0] != 0) snprintf(name, sizeof(name), "%s.?LAST.extnValue", root); else snprintf(name, sizeof(name), "?LAST.extnValue"); result = _gnutls_x509_write_value(asn, name, ext_data); if (result < 0) { gnutls_assert(); return result; } return 0; }
/* Overwrite the given extension (using the index) * index here starts from one. */ static int overwrite_extension (ASN1_TYPE asn, const char *root, unsigned int indx, const gnutls_datum_t * ext_data, unsigned int critical) { char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; const char *str; int result; if (root[0] != 0) snprintf (name, sizeof (name), "%s.?%u", root, indx); else snprintf (name, sizeof (name), "?%u", indx); if (critical == 0) str = "FALSE"; else str = "TRUE"; _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".critical"); result = asn1_write_value (asn, name2, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); result = _gnutls_x509_write_value (asn, name2, ext_data); if (result < 0) { gnutls_assert (); return result; } return 0; }
/* Encodes the bag into a SafeContents structure, and puts the output in * the given datum. Enc is set to non zero if the data are encrypted; */ int _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents, int *enc) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result; int i; const char *oid; if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) { *enc = 1; return 0; /* ENCRYPTED BAG, do nothing. */ } else if (enc) *enc = 0; /* Step 1. Create 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; } for (i = 0; i < bag->bag_elements; i++) { oid = bag_to_oid (bag->element[i].type); if (oid == NULL) { gnutls_assert (); continue; } result = asn1_write_value (c2, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Copy the bag type. */ result = asn1_write_value (c2, "?LAST.bagId", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Set empty attributes */ result = write_attributes (bag, i, c2, "?LAST.bagAttributes"); if (result < 0) { gnutls_assert (); goto cleanup; } /* Copy the Bag Value */ if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE || bag->element[i].type == GNUTLS_BAG_SECRET || bag->element[i].type == GNUTLS_BAG_CRL) { gnutls_datum_t tmp; /* in that case encode it to a CertBag or * a CrlBag. */ result = _pkcs12_encode_crt_bag (bag->element[i].type, &bag->element[i].data, &tmp); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0); _gnutls_free_datum (&tmp); } else { result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &bag->element[i].data, 0); } if (result < 0) { gnutls_assert (); goto cleanup; } } /* Encode the data and copy them into the datum */ *contents = c2; return 0; cleanup: if (c2) asn1_delete_structure (&c2); 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; if (type == 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_value (c2, "certValue", raw, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } } else { /* 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_value (c2, "crlValue", raw, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } } 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; }