/** * gnutls_x509_crt_set_crl_dist_points2: * @crt: a certificate of type #gnutls_x509_crt_t * @type: is one of the gnutls_x509_subject_alt_name_t enumerations * @data: The data to be set * @data_size: The data size * @reason_flags: revocation reasons * * This function will set the CRL distribution points certificate extension. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.6.0 **/ int gnutls_x509_crt_set_crl_dist_points2(gnutls_x509_crt_t crt, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size, unsigned int reason_flags) { int result; gnutls_datum_t der_data = { NULL, 0 }; gnutls_datum_t oldname = { NULL, 0 }; unsigned int critical; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* Check if the extension already exists. */ result = _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &oldname, &critical); _gnutls_free_datum(&oldname); if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* generate the extension. */ result = _gnutls_x509_ext_gen_crl_dist_points(type, data, data_size, reason_flags, &der_data); if (result < 0) { gnutls_assert(); return result; } result = _gnutls_x509_crt_set_extension(crt, "2.5.29.31", &der_data, 0); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); return result; } crt->use_extensions = 1; return 0; }
/** * gnutls_x509_crt_set_subject_key_id: * @cert: a certificate of type #gnutls_x509_crt_t * @id: The key ID * @id_size: Holds the size of the subject key ID field. * * This function will set the X.509 certificate's subject key ID * extension. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt_t cert, const void *id, size_t id_size) { int result; gnutls_datum_t old_id, der_data; gnutls_datum_t d_id; unsigned int critical; if (cert == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* Check if the extension already exists. */ result = _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &old_id, &critical); if (result >= 0) _gnutls_free_datum(&old_id); if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* generate the extension. */ d_id.data = (void*)id; d_id.size = id_size; result = gnutls_x509_ext_export_subject_key_id(&d_id, &der_data); if (result < 0) { gnutls_assert(); return result; } result = _gnutls_x509_crt_set_extension(cert, "2.5.29.14", &der_data, 0); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); return result; } cert->use_extensions = 1; return 0; }
/** * gnutls_x509_crt_cpy_crl_dist_points: * @dst: a certificate of type #gnutls_x509_crt_t * @src: the certificate where the dist points will be copied from * * This function will copy the CRL distribution points certificate * extension, from the source to the destination certificate. * This may be useful to copy from a CA certificate to issued ones. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt_t dst, gnutls_x509_crt_t src) { int result; gnutls_datum_t der_data; unsigned int critical; if (dst == NULL || src == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* Check if the extension already exists. */ result = _gnutls_x509_crt_get_extension(src, "2.5.29.31", 0, &der_data, &critical); if (result < 0) { gnutls_assert(); return result; } result = _gnutls_x509_crt_set_extension(dst, "2.5.29.31", &der_data, critical); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); return result; } dst->use_extensions = 1; return 0; }
/** * gnutls_x509_crt_get_name_constraints: * @crt: should contain a #gnutls_x509_crt_t type * @nc: The nameconstraints intermediate type * @flags: zero or %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND * @critical: the extension status * * This function will return an intermediate type containing * the name constraints of the provided CA certificate. That * structure can be used in combination with gnutls_x509_name_constraints_check() * to verify whether a server's name is in accordance with the constraints. * * When the @flags is set to %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, then if * the @nc structure is empty * this function will behave identically as if the flag was not set. * Otherwise if there are elements in the @nc structure then only the * excluded constraints will be appended to the constraints. * * Note that @nc must be initialized prior to calling this function. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * if the extension is not present, otherwise a negative error value. * * Since: 3.3.0 **/ int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt, gnutls_x509_name_constraints_t nc, unsigned int flags, unsigned int *critical) { int ret; gnutls_datum_t der = { NULL, 0 }; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_x509_crt_get_extension(crt, "2.5.29.30", 0, &der, critical); if (ret < 0) return gnutls_assert_val(ret); if (der.size == 0 || der.data == NULL) return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); ret = gnutls_x509_ext_import_name_constraints(&der, nc, flags); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum(&der); return ret; }
/** * gnutls_x509_crt_set_issuer_alt_name: * @crt: a certificate of type #gnutls_x509_crt_t * @type: is one of the gnutls_x509_subject_alt_name_t enumerations * @data: The data to be set * @data_size: The size of data to be set * @flags: GNUTLS_FSAN_SET to clear previous data or GNUTLS_FSAN_APPEND to append. * * This function will set the issuer alternative name certificate * extension. It can set the same types as gnutls_x509_crt_set_subject_alt_name(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.3.0 **/ int gnutls_x509_crt_set_issuer_alt_name(gnutls_x509_crt_t crt, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size, unsigned int flags) { int result; gnutls_datum_t der_data = { NULL, 0 }; gnutls_datum_t prev_der_data = { NULL, 0 }; unsigned int critical = 0; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* Check if the extension already exists. */ if (flags == GNUTLS_FSAN_APPEND) { result = _gnutls_x509_crt_get_extension(crt, "2.5.29.18", 0, &prev_der_data, &critical); if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_assert(); return result; } } /* generate the extension. */ result = _gnutls_x509_ext_gen_subject_alt_name(type, data, data_size, &prev_der_data, &der_data); if (flags == GNUTLS_FSAN_APPEND) _gnutls_free_datum(&prev_der_data); if (result < 0) { gnutls_assert(); goto finish; } result = _gnutls_x509_crt_set_extension(crt, "2.5.29.18", &der_data, critical); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); return result; } crt->use_extensions = 1; return 0; finish: _gnutls_free_datum(&prev_der_data); return result; }
/** * gnutls_x509_crt_set_policy: * @crt: 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, const struct gnutls_x509_policy_st *policy, unsigned int critical) { int ret; gnutls_datum_t der_data = {NULL, 0}, prev_der_data = { NULL, 0 }; gnutls_x509_policies_t policies = NULL; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = gnutls_x509_policies_init(&policies); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_x509_crt_get_extension(crt, "2.5.29.32", 0, &prev_der_data, NULL); if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_assert(); goto cleanup; } if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { ret = gnutls_x509_ext_import_policies(&prev_der_data, policies, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = gnutls_x509_policies_set(policies, policy); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_ext_export_policies(policies, &der_data); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.32", &der_data, 0); crt->use_extensions = 1; cleanup: if (policies != NULL) gnutls_x509_policies_deinit(policies); _gnutls_free_datum(&prev_der_data); _gnutls_free_datum(&der_data); return ret; }
/** * gnutls_x509_crt_set_authority_info_access: * @crt: Holds the certificate * @what: what data to get, a #gnutls_info_access_what_t type. * @data: output data to be freed with gnutls_free(). * * This function sets the Authority Information Access (AIA) * extension, see RFC 5280 section 4.2.2.1 for more information. * * The type of data stored in @data is specified via @what which * should be #gnutls_info_access_what_t values. * * If @what is %GNUTLS_IA_OCSP_URI, @data will hold the OCSP URI. * If @what is %GNUTLS_IA_CAISSUERS_URI, @data will hold the caIssuers * URI. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_x509_crt_set_authority_info_access(gnutls_x509_crt_t crt, int what, gnutls_datum_t * data) { int ret; gnutls_datum_t der = { NULL, 0 }; gnutls_datum_t new_der = { NULL, 0 }; gnutls_x509_aia_t aia_ctx = NULL; const char *oid; unsigned int c; if (crt == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = gnutls_x509_aia_init(&aia_ctx); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_x509_crt_get_extension(crt, GNUTLS_OID_AIA, 0, &der, &c); if (ret >= 0) { /* decode it */ ret = gnutls_x509_ext_import_aia(&der, aia_ctx, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } if (what == GNUTLS_IA_OCSP_URI) oid = GNUTLS_OID_AD_OCSP; else if (what == GNUTLS_IA_CAISSUERS_URI) oid = GNUTLS_OID_AD_CAISSUERS; else return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = gnutls_x509_aia_set(aia_ctx, oid, GNUTLS_SAN_URI, data); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_ext_export_aia(aia_ctx, &new_der); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crt_set_extension(crt, GNUTLS_OID_AIA, &new_der, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } crt->use_extensions = 1; cleanup: if (aia_ctx != NULL) gnutls_x509_aia_deinit(aia_ctx); _gnutls_free_datum(&new_der); _gnutls_free_datum(&der); return ret; }
/** * gnutls_x509_crt_set_key_purpose_oid: * @cert: a certificate of type #gnutls_x509_crt_t * @oid: a pointer to a null terminated string that holds the OID * @critical: Whether this extension will be critical or not * * This function will set the key purpose OIDs of the Certificate. * These are stored in the Extended Key Usage extension (2.5.29.37) * See the GNUTLS_KP_* definitions for human readable names. * * Subsequent calls to this function will append OIDs to the OID list. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_x509_crt_set_key_purpose_oid(gnutls_x509_crt_t cert, const void *oid, unsigned int critical) { int ret; gnutls_datum_t old_id = {NULL,0}; gnutls_datum_t der = {NULL,0}; gnutls_x509_key_purposes_t p = NULL; if (cert == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = gnutls_x509_key_purpose_init(&p); if (ret < 0) return gnutls_assert_val(ret); /* Check if the extension already exists. */ ret = _gnutls_x509_crt_get_extension(cert, "2.5.29.37", 0, &old_id, NULL); if (ret >= 0) { ret = gnutls_x509_ext_import_key_purposes(&old_id, p, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = gnutls_x509_key_purpose_set(p, oid); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_ext_export_key_purposes(p, &der); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crt_set_extension(cert, "2.5.29.37", &der, critical); if (ret < 0) { gnutls_assert(); goto cleanup; } cert->use_extensions = 1; ret = 0; cleanup: _gnutls_free_datum(&der); _gnutls_free_datum(&old_id); if (p != NULL) gnutls_x509_key_purpose_deinit(p); return ret; }
/** * gnutls_x509_crt_set_crl_dist_points2: * @crt: a certificate of type #gnutls_x509_crt_t * @type: is one of the gnutls_x509_subject_alt_name_t enumerations * @data: The data to be set * @data_size: The data size * @reason_flags: revocation reasons * * This function will set the CRL distribution points certificate extension. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.6.0 **/ int gnutls_x509_crt_set_crl_dist_points2(gnutls_x509_crt_t crt, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size, unsigned int reason_flags) { int ret; gnutls_datum_t der_data = { NULL, 0 }; gnutls_datum_t old_der = { NULL, 0 }; unsigned int critical; gnutls_x509_crl_dist_points_t cdp = NULL; gnutls_datum_t san; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = gnutls_x509_crl_dist_points_init(&cdp); if (ret < 0) return gnutls_assert_val(ret); /* Check if the extension already exists. */ ret = _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &old_der, &critical); if (ret >= 0 && old_der.data != NULL) { ret = gnutls_x509_ext_import_crl_dist_points(&old_der, cdp, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } san.data = (void*)data; san.size = data_size; ret = gnutls_x509_crl_dist_points_set(cdp, type, &san, reason_flags); if (ret < 0) { gnutls_assert(); goto cleanup; } /* generate the extension. */ ret = gnutls_x509_ext_export_crl_dist_points(cdp, &der_data); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.31", &der_data, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } crt->use_extensions = 1; ret = 0; cleanup: _gnutls_free_datum(&der_data); _gnutls_free_datum(&old_der); if (cdp != NULL) gnutls_x509_crl_dist_points_deinit(cdp); return ret; }
/** * 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; }
/** * gnutls_x509_crt_set_authority_info_access: * @crt: Holds the certificate * @what: what data to get, a #gnutls_info_access_what_t type. * @data: output data to be freed with gnutls_free(). * * This function sets the Authority Information Access (AIA) * extension, see RFC 5280 section 4.2.2.1 for more information. * * The type of data stored in @data is specified via @what which * should be #gnutls_info_access_what_t values. * * If @what is %GNUTLS_IA_OCSP_URI, @data will hold the OCSP URI. * If @what is %GNUTLS_IA_CAISSUERS_URI, @data will hold the caIssuers * URI. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_x509_crt_set_authority_info_access(gnutls_x509_crt_t crt, int what, gnutls_datum_t * data) { int ret, result; gnutls_datum_t aia = { NULL, 0 }; gnutls_datum_t der_data = { NULL, 0 }; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; const char *oid; unsigned int c; if (crt == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); oid = what_to_oid(what); if (oid == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.AuthorityInfoAccessSyntax", &c2); if (ret != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(ret); } ret = _gnutls_x509_crt_get_extension(crt, GNUTLS_OID_AIA, 0, &aia, &c); if (ret >= 0) { /* decode it */ ret = asn1_der_decoding(&c2, aia.data, aia.size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } } /* generate the extension. */ /* 1. create a new element. */ result = asn1_write_value(c2, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } /* 2. Add the OID. */ result = asn1_write_value(c2, "?LAST.accessMethod", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } /* accessLocation is a choice */ result = asn1_write_value(c2, "?LAST.accessLocation", "uniformResourceIdentifier", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } result = asn1_write_value(c2, "?LAST.accessLocation.uniformResourceIdentifier", data->data, data->size); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } ret = _gnutls_x509_der_encode(c2, "", &der_data, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crt_set_extension(crt, GNUTLS_OID_AIA, &der_data, 0); if (ret < 0) gnutls_assert(); crt->use_extensions = 1; cleanup: _gnutls_free_datum(&der_data); _gnutls_free_datum(&aia); asn1_delete_structure(&c2); return ret; }
/** * gnutls_x509_crt_set_key_purpose_oid: * @cert: a certificate of type #gnutls_x509_crt_t * @oid: a pointer to a null terminated string that holds the OID * @critical: Whether this extension will be critical or not * * This function will set the key purpose OIDs of the Certificate. * These are stored in the Extended Key Usage extension (2.5.29.37) * See the GNUTLS_KP_* definitions for human readable names. * * Subsequent calls to this function will append OIDs to the OID list. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_x509_crt_set_key_purpose_oid(gnutls_x509_crt_t cert, const void *oid, unsigned int critical) { int result; gnutls_datum_t old_id, der_data; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; if (cert == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = asn1_create_element (_gnutls_get_pkix(), "PKIX1.ExtKeyUsageSyntax", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* Check if the extension already exists. */ result = _gnutls_x509_crt_get_extension(cert, "2.5.29.37", 0, &old_id, NULL); if (result >= 0) { /* decode it. */ result = asn1_der_decoding(&c2, old_id.data, old_id.size, NULL); _gnutls_free_datum(&old_id); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } } /* generate the extension. */ /* 1. create a new element. */ result = asn1_write_value(c2, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } /* 2. Add the OID. */ result = asn1_write_value(c2, "?LAST", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } result = _gnutls_x509_der_encode(c2, "", &der_data, 0); asn1_delete_structure(&c2); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = _gnutls_x509_crt_set_extension(cert, "2.5.29.37", &der_data, critical); _gnutls_free_datum(&der_data); if (result < 0) { gnutls_assert(); return result; } cert->use_extensions = 1; return 0; }