diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-11-18 19:31:54 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-11-18 19:31:54 +0100 |
commit | 9e02a17f503668551356bdd10489b93c447834e4 (patch) | |
tree | 3ab0e52f14dca48efc1d56317a4cb2a259deb456 /lib/x509 | |
parent | 96c38a6c89fe0b6f7d826c3588479ec861811054 (diff) | |
download | gnutls-9e02a17f503668551356bdd10489b93c447834e4.tar.gz |
Added functions to parse the certificate policies extention.
Added gnutls_x509_crt_get_policy() etc. In addition several updated in the
handling of strings in X.509 structures.
Diffstat (limited to 'lib/x509')
-rw-r--r-- | lib/x509/common.c | 193 | ||||
-rw-r--r-- | lib/x509/common.h | 26 | ||||
-rw-r--r-- | lib/x509/crl.c | 2 | ||||
-rw-r--r-- | lib/x509/dn.c | 6 | ||||
-rw-r--r-- | lib/x509/extensions.c | 6 | ||||
-rw-r--r-- | lib/x509/mpi.c | 4 | ||||
-rw-r--r-- | lib/x509/ocsp.c | 90 | ||||
-rw-r--r-- | lib/x509/output.c | 44 | ||||
-rw-r--r-- | lib/x509/pkcs12.c | 37 | ||||
-rw-r--r-- | lib/x509/pkcs12_bag.c | 6 | ||||
-rw-r--r-- | lib/x509/privkey.c | 2 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 8 | ||||
-rw-r--r-- | lib/x509/x509.c | 294 |
13 files changed, 522 insertions, 196 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c index d577f8ae4a..76ff429d42 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -230,8 +230,8 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, int value_size, char *res, size_t * res_size) { char str[MAX_STRING_LEN], tmpname[128]; - const char *ANAME = NULL; - int CHOICE = -1, len = -1, result; + const char *aname = NULL; + int choice = -1, len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = ""; @@ -247,17 +247,17 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, return GNUTLS_E_INTERNAL_ERROR; } - ANAME = _gnutls_x509_oid2asn_string (oid); - CHOICE = _gnutls_x509_oid_data_choice (oid); + aname = _gnutls_x509_oid2asn_string (oid); + choice = _gnutls_x509_oid_data_choice (oid); - if (ANAME == NULL) + if (aname == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if ((result = - asn1_create_element (_gnutls_get_pkix (), ANAME, + asn1_create_element (_gnutls_get_pkix (), aname, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert (); @@ -285,7 +285,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, return _gnutls_asn2err (result); } - if (CHOICE == 0) + if (choice == 0) { str[len] = 0; @@ -300,7 +300,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, asn1_delete_structure (&tmpasn); } else - { /* CHOICE */ + { /* choice */ int non_printable = 0, teletex = 0; str[len] = 0; @@ -335,7 +335,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, * characters then treat it as printable. */ for (i = 0; i < len; i++) - if (!isascii (str[i])) + if (!isprint (str[i])) ascii = 1; if (ascii == 0) @@ -664,7 +664,7 @@ _gnutls_x509_get_time (ASN1_TYPE c2, const char *when, int nochoice) { _gnutls_str_cpy (name, sizeof (name), when); - /* CHOICE */ + /* choice */ if (strcmp (ttime, "generalTime") == 0) { _gnutls_str_cat (name, sizeof (name), ".generalTime"); @@ -853,15 +853,15 @@ _gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, const char *name, * etc. */ int -_gnutls_x509_decode_octet_string (const char *string_type, - const uint8_t * der, size_t der_size, - uint8_t * output, size_t * output_size) +_gnutls_x509_decode_string (const char *string_type, + const uint8_t * der, size_t der_size, + gnutls_datum_t * output) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - int result, tmp_output_size; + int result; char strname[64]; - if (string_type == NULL) + if (string_type == NULL) /* assume octet string */ _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data"); else { @@ -885,16 +885,15 @@ _gnutls_x509_decode_octet_string (const char *string_type, goto cleanup; } - tmp_output_size = *output_size; - result = asn1_read_value (c2, "", output, &tmp_output_size); - *output_size = (size_t)tmp_output_size; - - if (result != ASN1_SUCCESS) + result = _gnutls_x509_read_value(c2, "", output); + if (result < 0) { gnutls_assert (); - result = _gnutls_asn2err (result); goto cleanup; } + + /* This is allowed since _gnutls_x509_read_value allocates one more */ + output->data[output->size] = 0; result = 0; @@ -908,13 +907,60 @@ cleanup: /* Reads a value from an ASN1 tree, and puts the output * in an allocated variable in the given datum. - * flags == 0 do nothing with the DER output - * flags == 1 parse the DER output as OCTET STRING - * flags == 2 the value is a BIT STRING + * + * Note that this function always places allocates one plus + * the required data size (to allow for a null byte). */ int _gnutls_x509_read_value (ASN1_TYPE c, const char *root, - gnutls_datum_t * ret, int flags) + gnutls_datum_t * ret) +{ + int len = 0, result; + uint8_t *tmp = NULL; + + result = asn1_read_value (c, root, NULL, &len); + if (result != ASN1_MEM_ERROR) + { + gnutls_assert (); + result = _gnutls_asn2err (result); + return result; + } + + 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; + } + + ret->data = tmp; + ret->size = (unsigned)len; + + return 0; + +cleanup: + gnutls_free (tmp); + return result; +} + +/* Reads a value from an ASN1 tree, and puts the output + * in an allocated variable in the given datum. + * + * 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, x509_string_type type) { int len = 0, result; size_t slen; @@ -928,10 +974,10 @@ _gnutls_x509_read_value (ASN1_TYPE c, const char *root, return result; } - if (flags == 2) + if (type == RV_BIT_STRING) len /= 8; - tmp = gnutls_malloc ((size_t)len); + tmp = gnutls_malloc ((size_t)len+1); if (tmp == NULL) { gnutls_assert (); @@ -947,43 +993,62 @@ _gnutls_x509_read_value (ASN1_TYPE c, const char *root, goto cleanup; } - if (flags == 2) + if (type == RV_BIT_STRING) len /= 8; - /* Extract the OCTET STRING. + /* Extract the STRING. */ - - if (flags == 1) + if (type == RV_IA5STRING || type == RV_UTF8STRING || type == RV_OCTET_STRING) { + const char* sname; slen = (size_t)len; - result = _gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen); + + if (type == RV_UTF8STRING) + sname = "UTF8String"; + else if (type == RV_IA5STRING) + sname = "IA5String"; + else + sname = NULL; + + result = _gnutls_x509_decode_string (sname, tmp, slen, ret); if (result < 0) { gnutls_assert (); goto cleanup; } - len = slen; + gnutls_free(tmp); + } + else + { + ret->data = tmp; + ret->size = (unsigned)len; } - - ret->data = tmp; - ret->size = (unsigned)len; return 0; cleanup: gnutls_free (tmp); return result; - } -int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size, - gnutls_datum_t* output) +/* The string type should be IA5String, UTF8String etc. Leave + * null for octet string */ +int _gnutls_x509_encode_string(const char* string_type, + const void* input_data, size_t input_size, + gnutls_datum_t* output) { int ret; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - + char strname[64]; + + _gnutls_str_cpy (strname, sizeof (strname), "PKIX1."); + if (string_type == NULL) + _gnutls_str_cat (strname, sizeof (strname), "pkcs-7-Data"); + else + _gnutls_str_cat (strname, sizeof (strname), string_type); + if ((ret = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS) + (_gnutls_get_pkix (), strname, &c2)) != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); @@ -1140,39 +1205,27 @@ _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const char *src_name, */ int _gnutls_x509_write_value (ASN1_TYPE c, const char *root, - const gnutls_datum_t * data, int str) + const gnutls_datum_t * data, x509_string_type type) { - int result; + int ret; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; gnutls_datum_t val = { NULL, 0 }; + const char* sname = NULL; - if (str) + if (type == RV_OCTET_STRING || type == RV_IA5STRING || type == RV_UTF8STRING) { - /* Convert it to OCTET STRING - */ - if ((result = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = asn1_write_value (c2, "", data->data, data->size); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } + + if (type == RV_IA5STRING) + sname = "IA5String"; + else if (type == RV_UTF8STRING) + sname = "UTF8String"; - result = _gnutls_x509_der_encode (c2, "", &val, 0); - if (result < 0) + ret = _gnutls_x509_encode_string(sname, data->data, data->size, &val); + if (ret < 0) { gnutls_assert (); goto cleanup; } - } else { @@ -1182,21 +1235,21 @@ _gnutls_x509_write_value (ASN1_TYPE c, const char *root, /* Write the data. */ - result = asn1_write_value (c, root, val.data, val.size); - if (result != ASN1_SUCCESS) + ret = asn1_write_value (c, root, val.data, val.size); + if (ret != ASN1_SUCCESS) { gnutls_assert (); - result = _gnutls_asn2err (result); + ret = _gnutls_asn2err (ret); goto cleanup; } - result = 0; + ret = 0; cleanup: asn1_delete_structure (&c2); if (val.data != data->data) _gnutls_free_datum (&val); - return result; + return ret; } void @@ -1443,7 +1496,7 @@ _gnutls_x509_get_signature_algorithm (ASN1_TYPE src, const char *src_name) * read. They will be read from the issuer's certificate if needed. */ result = - _gnutls_x509_read_value (src, src_name, &sa, 0); + _gnutls_x509_read_value (src, src_name, &sa); if (result < 0) { diff --git a/lib/x509/common.h b/lib/x509/common.h index 1ee919435b..4b38884434 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -66,13 +66,23 @@ #define ASN1_NULL "\x05\x00" #define ASN1_NULL_SIZE 2 +typedef enum x509_string_type { + RV_RAW, + RV_OCTET_STRING, + RV_BIT_STRING, + RV_IA5STRING, + RV_UTF8STRING +} x509_string_type; + int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim, int general); -int _gnutls_x509_decode_octet_string (const char *string_type, - const uint8_t * der, size_t der_size, - uint8_t * output, size_t * output_size); -int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size, - gnutls_datum_t* output); +int _gnutls_x509_decode_string (const char *string_type, + const uint8_t * der, size_t der_size, + gnutls_datum_t *output); + +int _gnutls_x509_encode_string(const char* string_type, + const void* input_data, size_t input_size, + gnutls_datum_t* output); int _gnutls_x509_oid_data2string (const char *OID, void *value, int value_size, char *res, @@ -112,9 +122,11 @@ int _gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, const char *name, gnutls_datum_t * out); int _gnutls_x509_read_value (ASN1_TYPE c, const char *root, - gnutls_datum_t * ret, int str); + gnutls_datum_t * ret); +int _gnutls_x509_read_string (ASN1_TYPE c, const char *root, + gnutls_datum_t * ret, x509_string_type type); int _gnutls_x509_write_value (ASN1_TYPE c, const char *root, - const gnutls_datum_t * data, int str); + const gnutls_datum_t * data, x509_string_type type); int _gnutls_x509_encode_and_write_attribute (const char *given_oid, ASN1_TYPE asn1_struct, diff --git a/lib/x509/crl.c b/lib/x509/crl.c index 8acc64ca82..f156b43132 100644 --- a/lib/x509/crl.c +++ b/lib/x509/crl.c @@ -286,7 +286,7 @@ gnutls_x509_crl_get_signature_algorithm (gnutls_x509_crl_t crl) result = _gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm", - &sa, 0); + &sa); if (result < 0) { diff --git a/lib/x509/dn.c b/lib/x509/dn.c index 9c6096193d..9506969f5a 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -834,8 +834,10 @@ _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct, if (multi) _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1"); /* .values.?1 */ - result = - _gnutls_x509_read_value (asn1_struct, tmpbuffer, value, octet_string); + if (octet_string) + result = _gnutls_x509_read_string (asn1_struct, tmpbuffer, value, RV_OCTET_STRING); + else + result = _gnutls_x509_read_value (asn1_struct, tmpbuffer, value); if (result < 0) { gnutls_assert (); diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c index a429bfea27..c251b0d727 100644 --- a/lib/x509/extensions.c +++ b/lib/x509/extensions.c @@ -122,7 +122,7 @@ get_extension (ASN1_TYPE asn, const char *root, _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); - result = _gnutls_x509_read_value (asn, name2, &value, 0); + result = _gnutls_x509_read_value (asn, name2, &value); if (result < 0) { gnutls_assert (); @@ -1254,7 +1254,7 @@ _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, } result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage", - &value, 0); + &value); if (result < 0) { gnutls_assert (); @@ -1265,7 +1265,7 @@ _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, if (policyLanguage) *policyLanguage = gnutls_strdup ((char*)value.data); - result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0); + result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) { if (policy) diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index c9d3058932..7792c588a1 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -97,7 +97,7 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, /* Read the algorithm's parameters */ _asnstr_append_name (name, sizeof (name), root, ".subjectPublicKey"); - result = _gnutls_x509_read_value (asn, name, &tmp, 2); + result = _gnutls_x509_read_string (asn, name, &tmp, RV_BIT_STRING); if (result < 0) { @@ -126,7 +126,7 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, if (pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */ { - result = _gnutls_x509_read_value (asn, name, &tmp, 0); + result = _gnutls_x509_read_value (asn, name, &tmp); if (result < 0) { gnutls_assert (); diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c index 8756431a71..87a250317c 100644 --- a/lib/x509/ocsp.c +++ b/lib/x509/ocsp.c @@ -267,7 +267,7 @@ gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp, return GNUTLS_E_SUCCESS; ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType", - &resp->response_type_oid, 0); + &resp->response_type_oid); if (ret < 0) { gnutls_assert (); @@ -296,7 +296,7 @@ gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp, } ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response", - &d, 0); + &d); if (ret < 0) { gnutls_assert (); @@ -482,7 +482,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req, snprintf (name, sizeof (name), "tbsRequest.requestList.?%u.reqCert.hashAlgorithm.algorithm", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, &sa, 0); + ret = _gnutls_x509_read_value (req->req, name, &sa); if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; else if (ret < 0) @@ -506,7 +506,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req, { snprintf (name, sizeof (name), "tbsRequest.requestList.?%u.reqCert.issuerNameHash", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash, 0); + ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -518,7 +518,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req, { snprintf (name, sizeof (name), "tbsRequest.requestList.?%u.reqCert.issuerKeyHash", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash, 0); + ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -532,7 +532,7 @@ gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req, { snprintf (name, sizeof (name), "tbsRequest.requestList.?%u.reqCert.serialNumber", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, serial_number, 0); + ret = _gnutls_x509_read_value (req->req, name, serial_number); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -718,9 +718,9 @@ gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req, inh.size = inhlen; inh.data = inh_buf; - ret = _gnutls_x509_read_value + ret = _gnutls_x509_read_string (issuer->cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", - &tmp, 2); + &tmp, RV_BIT_STRING); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -738,7 +738,7 @@ gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req, ikh.data = ikh_buf; ret = _gnutls_x509_read_value (cert->cert, "tbsCertificate.serialNumber", - &sn, 0); + &sn); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -821,7 +821,7 @@ gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req, { snprintf (name, sizeof (name), "tbsRequest.requestExtensions.?%u.extnID", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, oid, 0); + ret = _gnutls_x509_read_value (req->req, name, oid); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -833,7 +833,7 @@ gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req, { snprintf (name, sizeof (name), "tbsRequest.requestExtensions.?%u.extnValue", indx + 1); - ret = _gnutls_x509_read_value (req->req, name, data, 0); + ret = _gnutls_x509_read_value (req->req, name, data); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -896,7 +896,6 @@ gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req, gnutls_datum_t *nonce) { int ret; - size_t l = 0; gnutls_datum_t tmp; if (req == NULL || nonce == NULL) @@ -914,32 +913,16 @@ gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req, return ret; } - ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size, - NULL, &l); - if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) + ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size, + nonce); + if (ret < 0) { gnutls_assert (); gnutls_free (tmp.data); return ret; } - nonce->data = gnutls_malloc (l); - if (nonce->data == NULL) - { - gnutls_assert (); - gnutls_free (tmp.data); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size, - nonce->data, &l); gnutls_free (tmp.data); - if (ret != GNUTLS_E_SUCCESS) - { - gnutls_assert (); - return ret; - } - nonce->size = l; return GNUTLS_E_SUCCESS; } @@ -1121,7 +1104,7 @@ gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp, if (response_type_oid != NULL) { ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType", - response_type_oid, 0); + response_type_oid); if (ret < 0) { gnutls_assert (); @@ -1132,7 +1115,7 @@ gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp, if (response != NULL) { ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response", - response, 0); + response); if (ret < 0) { gnutls_assert (); @@ -1418,7 +1401,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp, snprintf (name, sizeof (name), "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm", indx + 1); - ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0); + ret = _gnutls_x509_read_value (resp->basicresp, name, &sa); if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; else if (ret < 0) @@ -1444,7 +1427,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp, "tbsResponseData.responses.?%u.certID.issuerNameHash", indx + 1); ret = _gnutls_x509_read_value (resp->basicresp, name, - issuer_name_hash, 0); + issuer_name_hash); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -1458,7 +1441,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp, "tbsResponseData.responses.?%u.certID.issuerKeyHash", indx + 1); ret = _gnutls_x509_read_value (resp->basicresp, name, - issuer_key_hash, 0); + issuer_key_hash); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -1474,7 +1457,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp, "tbsResponseData.responses.?%u.certID.serialNumber", indx + 1); ret = _gnutls_x509_read_value (resp->basicresp, name, - serial_number, 0); + serial_number); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -1491,7 +1474,7 @@ gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp, snprintf (name, sizeof (name), "tbsResponseData.responses.?%u.certStatus", indx + 1); - ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0); + ret = _gnutls_x509_read_value (resp->basicresp, name, &sa); if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; else if (ret < 0) @@ -1655,7 +1638,7 @@ gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp, { snprintf (name, sizeof (name), "tbsResponseData.responseExtensions.?%u.extnID", indx + 1); - ret = _gnutls_x509_read_value (resp->basicresp, name, oid, 0); + ret = _gnutls_x509_read_value (resp->basicresp, name, oid); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -1667,7 +1650,7 @@ gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp, { snprintf (name, sizeof (name), "tbsResponseData.responseExtensions.?%u.extnValue", indx + 1); - ret = _gnutls_x509_read_value (resp->basicresp, name, data, 0); + ret = _gnutls_x509_read_value (resp->basicresp, name, data); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); @@ -1701,7 +1684,6 @@ gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp, gnutls_datum_t *nonce) { int ret; - size_t l = 0; gnutls_datum_t tmp; ret = get_extension (resp->basicresp, "tbsResponseData.responseExtensions", @@ -1713,32 +1695,16 @@ gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp, return ret; } - ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size, - NULL, &l); - if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) + ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size, + nonce); + if (ret < 0) { gnutls_assert (); gnutls_free (tmp.data); return ret; } - nonce->data = gnutls_malloc (l); - if (nonce->data == NULL) - { - gnutls_assert (); - gnutls_free (tmp.data); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size, - nonce->data, &l); gnutls_free (tmp.data); - if (ret != GNUTLS_E_SUCCESS) - { - gnutls_assert (); - return ret; - } - nonce->size = l; return GNUTLS_E_SUCCESS; } @@ -1761,7 +1727,7 @@ gnutls_ocsp_resp_get_signature_algorithm (gnutls_ocsp_resp_t resp) gnutls_datum_t sa; ret = _gnutls_x509_read_value (resp->basicresp, - "signatureAlgorithm.algorithm", &sa, 0); + "signatureAlgorithm.algorithm", &sa); if (ret < 0) { gnutls_assert (); @@ -1797,7 +1763,7 @@ gnutls_ocsp_resp_get_signature (gnutls_ocsp_resp_t resp, return GNUTLS_E_INVALID_REQUEST; } - ret = _gnutls_x509_read_value (resp->basicresp, "signature", sig, 2); + ret = _gnutls_x509_read_string (resp->basicresp, "signature", sig, RV_BIT_STRING); if (ret != GNUTLS_E_SUCCESS) { gnutls_assert (); diff --git a/lib/x509/output.c b/lib/x509/output.c index 18db408204..a77484bae6 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -882,7 +882,8 @@ static void print_extensions (gnutls_buffer_st * str, const char *prefix, int type, cert_type_t cert) { - int i, err; + unsigned i, j; + int err; int san_idx = 0; int ian_idx = 0; int proxy_idx = 0; @@ -957,6 +958,39 @@ print_extensions (gnutls_buffer_st * str, const char *prefix, int type, ski_idx++; } + else if (strcmp (oid, "2.5.29.32") == 0) + { + struct gnutls_certificate_policy_st policy; + const char* name; + int x; + + for (x=0;;x++) + { + err = gnutls_x509_crt_get_policy (cert.crt, x, &policy, &critical); + if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + + if (err < 0) + { + addf (str, "error: certificate policy: %s\n", gnutls_strerror(err)); + break; + } + + addf (str, "%s\t\tCertificate Policies (%s):\n", prefix, critical ? _("critical") : _("not critical")); + addf (str, "%s\t\t\t%s\n", prefix, policy.policy_oid); + for (j=0;j<policy.qualifiers;j++) + { + if (policy.qualifier_type[j]==GNUTLS_X509_QUALIFIER_URI) + name = "URI"; + else if (policy.qualifier_type[j]==GNUTLS_X509_QUALIFIER_NOTICE) + name = "Note"; + else name = "Unknown qualifier"; + addf (str, "%s\t\t\t\t%s: %s\n", prefix, name, policy.qualifier_data[j]); + } + + gnutls_certificate_policy_release (&policy); + } + } else if (strcmp (oid, "2.5.29.35") == 0) { @@ -1532,11 +1566,12 @@ print_other (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned) static void print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert) { +int err; + /* Subject. */ { char *dn; size_t dn_size = 0; - int err; err = gnutls_x509_crt_get_dn (cert, NULL, &dn_size); if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) @@ -1563,7 +1598,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert) { char *dn; size_t dn_size = 0; - int err; err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &dn_size); if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) @@ -1598,8 +1632,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert) /* Signature Algorithm. */ { - int err; - err = gnutls_x509_crt_get_signature_algorithm (cert); if (err < 0) addf (str, "unknown signature algorithm (%s), ", gnutls_strerror (err)); @@ -1651,7 +1683,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert) { int pathlen; char *policyLanguage; - int err; err = gnutls_x509_crt_get_proxy (cert, NULL, &pathlen, &policyLanguage, NULL, NULL); @@ -1675,7 +1706,6 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert) { char buffer[20]; size_t size = sizeof (buffer); - int err; err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, buffer, &size); diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index 380f3fc9b0..a980ce2d75 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -68,7 +68,7 @@ _decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe, */ result = - _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1); + _gnutls_x509_read_string (pkcs12, "authSafe.content", &auth_safe, RV_OCTET_STRING); if (result < 0) { gnutls_assert (); @@ -373,8 +373,8 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * content, int len, result; int bag_type; gnutls_datum_t attr_val; + gnutls_datum_t t; int count = 0, i, attributes, j; - size_t size; /* Step 1. Extract the SEQUENCE. */ @@ -437,7 +437,7 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * content, snprintf (root, sizeof (root), "?%u.bagValue", i + 1); - result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0); + result = _gnutls_x509_read_value (c2, root, &bag->element[i].data); if (result < 0) { gnutls_assert (); @@ -495,38 +495,39 @@ _pkcs12_decode_safe_contents (const gnutls_datum_t * content, if (strcmp (oid, KEY_ID_OID) == 0) { - size = attr_val.size; - result = - _gnutls_x509_decode_octet_string (NULL, attr_val.data, size, - attr_val.data, &size); - attr_val.size = size; + _gnutls_x509_decode_string (NULL, attr_val.data, attr_val.size, &t); + _gnutls_free_datum (&attr_val); if (result < 0) { - _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_debug_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } + + attr_val.data = t.data; + attr_val.size = t.size; + bag->element[i].local_key_id = attr_val; } else if (strcmp (oid, FRIENDLY_NAME_OID) == 0) { - size = attr_val.size; result = - _gnutls_x509_decode_octet_string ("BMPString", - attr_val.data, size, - attr_val.data, &size); - attr_val.size = size; + _gnutls_x509_decode_string ("BMPString", + attr_val.data, attr_val.size, &t); + _gnutls_free_datum (&attr_val); if (result < 0) { - _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_debug_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } + + attr_val.data = t.data; + attr_val.size = t.size; + bag->element[i].friendly_name = ucs2_to_ascii ((char*)attr_val.data, attr_val.size); } @@ -566,7 +567,7 @@ _parse_safe_contents (ASN1_TYPE sc, const char *sc_name, /* Step 1. Extract the content. */ - result = _gnutls_x509_read_value (sc, sc_name, &content, 1); + result = _gnutls_x509_read_string (sc, sc_name, &content, RV_OCTET_STRING); if (result < 0) { gnutls_assert (); @@ -665,7 +666,7 @@ gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12, bag->element[0].type = GNUTLS_BAG_ENCRYPTED; bag->bag_elements = 1; - result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0); + result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data); if (result < 0) { gnutls_assert (); @@ -1048,7 +1049,7 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) /* Read the salt from the structure. */ result = - _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0); + _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt); if (result != ASN1_SUCCESS) { gnutls_assert (); diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c index 38d01e9c73..64db1bf904 100644 --- a/lib/x509/pkcs12_bag.c +++ b/lib/x509/pkcs12_bag.c @@ -195,7 +195,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type, goto cleanup; } - ret = _gnutls_x509_read_value (c2, "certValue", out, 1); + ret = _gnutls_x509_read_string (c2, "certValue", out, RV_OCTET_STRING); if (ret < 0) { gnutls_assert (); @@ -221,7 +221,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type, goto cleanup; } - ret = _gnutls_x509_read_value (c2, "crlValue", out, 1); + ret = _gnutls_x509_read_string (c2, "crlValue", out, RV_OCTET_STRING); if (ret < 0) { gnutls_assert (); @@ -247,7 +247,7 @@ _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type, goto cleanup; } - ret = _gnutls_x509_read_value (c2, "secretValue", out, 1); + ret = _gnutls_x509_read_string (c2, "secretValue", out, RV_OCTET_STRING); if (ret < 0) { gnutls_assert (); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 1a81971c3a..5e95bb4734 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -300,7 +300,7 @@ _gnutls_privkey_decode_ecc_key (const gnutls_datum_t * raw_key, } /* read the public key */ - ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2); + ret = _gnutls_x509_read_string(pkey_asn, "publicKey", &out, RV_BIT_STRING); if (ret < 0) { gnutls_assert(); diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 27c8da00cc..ae58d5a12f 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -1055,7 +1055,7 @@ _decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) int ret; gnutls_datum_t tmp; - ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); + ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert (); @@ -1084,7 +1084,7 @@ _decode_pkcs8_ecc_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) int ret; gnutls_datum_t tmp; - ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); + ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert (); @@ -1114,7 +1114,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) int ret; gnutls_datum_t tmp; - ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); + ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert (); @@ -1132,7 +1132,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) ret = _gnutls_x509_read_value (pkcs8_asn, "privateKeyAlgorithm.parameters", - &tmp, 0); + &tmp); if (ret < 0) { gnutls_assert (); diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 1549eda208..235cce7062 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -297,9 +297,10 @@ gnutls_x509_crt_get_issuer_dn (gnutls_x509_crt_t cert, char *buf, * is not specified the output is always null terminated, although the * @buf_size will not include the null character. * - * Returns: GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not - * long enough, and in that case the @buf_size will be updated - * with the required size. On success 0 is returned. + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not + * long enough, and in that case the @buf_size will be updated with + * the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there + * are no data in the current index. On success 0 is returned. **/ int gnutls_x509_crt_get_issuer_dn_by_oid (gnutls_x509_crt_t cert, @@ -332,9 +333,10 @@ gnutls_x509_crt_get_issuer_dn_by_oid (gnutls_x509_crt_t cert, * returned will be null terminated, although @oid_size will not * account for the trailing null. * - * Returns: GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not - * long enough, and in that case the @oid_size will be updated - * with the required size. On success 0 is returned. + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not + * long enough, and in that case the @buf_size will be updated with + * the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there + * are no data in the current index. On success 0 is returned. **/ int gnutls_x509_crt_get_issuer_dn_oid (gnutls_x509_crt_t cert, @@ -407,9 +409,10 @@ gnutls_x509_crt_get_dn (gnutls_x509_crt_t cert, char *buf, * is not specified the output is always null terminated, although the * @buf_size will not include the null character. * - * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is - * not long enough, and in that case the *buf_size will be updated - * with the required size. On success 0 is returned. + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not + * long enough, and in that case the @buf_size will be updated with + * the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there + * are no data in the current index. On success 0 is returned. **/ int gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t cert, const char *oid, @@ -441,9 +444,10 @@ gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t cert, const char *oid, * returned will be null terminated, although @oid_size will not * account for the trailing null. * - * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is - * not long enough, and in that case the @oid_size will be updated - * with the required size. On success 0 is returned. + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not + * long enough, and in that case the @buf_size will be updated with + * the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there + * are no data in the current index. On success 0 is returned. **/ int gnutls_x509_crt_get_dn_oid (gnutls_x509_crt_t cert, @@ -1756,6 +1760,264 @@ gnutls_x509_crt_get_proxy (gnutls_x509_crt_t cert, } /** + * gnutls_certificate_policy_release: + * @policy: a certificate policy + * + * This function will deinitialize all memory associated with the provided + * @policy. The policy is allocated using gnutls_x509_crt_get_policy(). + * + **/ +void gnutls_certificate_policy_release(struct gnutls_certificate_policy_st* policy) +{ +unsigned i; + + gnutls_free(policy->policy_oid); + for (i=0;i<policy->qualifiers;i++) + gnutls_free(policy->qualifier_data[i]); +} + +static int decode_user_notice(const void* data, size_t size, char** txt) +{ + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + int ret, len; + char choice_type[64]; + char name[128]; + gnutls_datum_t td, td2; + + ret = asn1_create_element + (_gnutls_get_pkix (), "PKIX1.UserNotice", &c2); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + + ret = asn1_der_decoding (&c2, data, size, NULL); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + + len = sizeof(choice_type); + ret = asn1_read_value(c2, "explicitText", choice_type, &len); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + + if (strcmp(choice_type, "utf8String") != 0 && strcmp(choice_type, "IA5String") != 0 && + strcmp(choice_type, "bmpString") != 0) + { + gnutls_assert(); + ret = GNUTLS_E_PARSING_ERROR; + goto cleanup; + } + + snprintf (name, sizeof (name), "explicitText.%s", choice_type); + + ret = _gnutls_x509_read_value(c2, name, &td); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + goto cleanup; + } + + if (strcmp(choice_type, "bmpString") == 0) + { /* convert to UTF-8 */ + ret = _gnutls_ucs2_to_utf8(td.data, td.size, &td2); + _gnutls_free_datum(&td); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + + td.data = td2.data; + td.size = td2.size; + } + else + { + /* _gnutls_x509_read_value allows that */ + td.data[td.size] = 0; + } + + *txt = (void*)td.data; + ret = 0; + +cleanup: + asn1_delete_structure (&c2); + return ret; + +} + +/** + * gnutls_x509_crt_get_policy: + * @cert: should contain a #gnutls_x509_crt_t structure + * @indx: This specifies which policy to return. Use (0) to get the first one. + * @policy: A pointer to a policy structure. + * @critical: will be non (0) if the extension is marked as critical + * + * This function will extract the certificate policy specified by the + * given index. + * + * If @oid is null then only the size will be filled. The @oid + * returned will be null terminated, although @oid_size will not + * account for the trailing null. + * + * 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. + **/ +int +gnutls_x509_crt_get_policy (gnutls_x509_crt_t crt, int indx, struct gnutls_certificate_policy_st* policy, unsigned int *critical) +{ + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + char tmpstr[128]; + char tmpoid[MAX_OID_SIZE]; + gnutls_datum_t tmpd = {NULL, 0}; + int ret, len; + unsigned i; + + if (crt == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + memset(policy, 0, sizeof(*policy)); + + if ((ret = + _gnutls_x509_crt_get_extension (crt, "2.5.29.32", 0, &tmpd, + critical)) < 0) + { + return ret; + } + + if (tmpd.size == 0 || tmpd .data == NULL) + { + gnutls_assert (); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + ret = asn1_create_element + (_gnutls_get_pkix (), "PKIX1.certificatePolicies", &c2); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + + ret = asn1_der_decoding (&c2, tmpd.data, tmpd.size, NULL); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + _gnutls_free_datum (&tmpd); + + indx++; + /* create a string like "?1" + */ + snprintf (tmpstr, sizeof (tmpstr), "?%u.policyIdentifier", indx); + + ret = _gnutls_x509_read_value(c2, tmpstr, &tmpd); + + if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) + ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + policy->policy_oid = (void*)tmpd.data; + tmpd.data = NULL; + + for (i=0;i<GNUTLS_MAX_QUALIFIERS;i++) + { + gnutls_datum_t td; + + snprintf (tmpstr, sizeof (tmpstr), "?%u.policyQualifiers.?%u.policyQualifierId", indx, i+1); + + len = sizeof(tmpoid); + ret = asn1_read_value(c2, tmpstr, tmpoid, &len); + + if (ret == ASN1_ELEMENT_NOT_FOUND && i > 0) + break; /* finished */ + + if (ret != ASN1_SUCCESS) + { + gnutls_assert(); + ret = _gnutls_asn2err (ret); + goto cleanup; + } + + if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.1") == 0) + { + snprintf (tmpstr, sizeof (tmpstr), "?%u.policyQualifiers.?%u.qualifier", indx, i+1); + + ret = _gnutls_x509_read_string(c2, tmpstr, &td, RV_IA5STRING); + if (ret < 0) + { + gnutls_assert(); + goto full_cleanup; + } + + policy->qualifier_data[i] = (void*)td.data; + td.data = NULL; + policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_URI; + } + else if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.2") == 0) + { + snprintf (tmpstr, sizeof (tmpstr), "?%u.policyQualifiers.?%u.qualifier", indx, i+1); + + ret = _gnutls_x509_read_string(c2, tmpstr, &td, RV_RAW); + if (ret < 0) + { + gnutls_assert(); + goto full_cleanup; + } + + ret = decode_user_notice(td.data, td.size, &policy->qualifier_data[i]); + gnutls_free(td.data); + td.data = NULL; + + if (ret < 0) + { + gnutls_assert(); + goto full_cleanup; + } + + policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_NOTICE; + } + else + policy->qualifier_type[i] = GNUTLS_X509_QUALIFIER_UNKNOWN; + + policy->qualifiers++; + + } + + + ret = 0; + goto cleanup; + +full_cleanup: + gnutls_certificate_policy_release(policy); + +cleanup: + _gnutls_free_datum (&tmpd); + asn1_delete_structure (&c2); + return ret; +} + + +/** * gnutls_x509_crt_get_extension_by_oid: * @cert: should contain a #gnutls_x509_crt_t structure * @oid: holds an Object Identified in null terminated string @@ -3443,8 +3705,8 @@ gnutls_x509_crt_get_subject_unique_id (gnutls_x509_crt_t crt, char *buf, gnutls_datum_t datum = { NULL, 0 }; result = - _gnutls_x509_read_value (crt->cert, "tbsCertificate.subjectUniqueID", - &datum, 2); + _gnutls_x509_read_string (crt->cert, "tbsCertificate.subjectUniqueID", + &datum, RV_BIT_STRING); if (datum.size > *buf_size) { /* then we're not going to fit */ @@ -3489,8 +3751,8 @@ gnutls_x509_crt_get_issuer_unique_id (gnutls_x509_crt_t crt, char *buf, gnutls_datum_t datum = { NULL, 0 }; result = - _gnutls_x509_read_value (crt->cert, "tbsCertificate.issuerUniqueID", - &datum, 2); + _gnutls_x509_read_string (crt->cert, "tbsCertificate.issuerUniqueID", + &datum, RV_BIT_STRING); if (datum.size > *buf_size) { /* then we're not going to fit */ |