summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2011-09-21 14:51:08 +0200
committerSimon Josefsson <simon@josefsson.org>2011-09-21 14:52:37 +0200
commit2837e8fd8f70f4f8272f381d3c15f2f8fe98ad41 (patch)
treeb28a35a7cba86b5b6e3d080320a264bbabbc5f46 /lib
parent01a6ff68bf97257a44a29e60a8cb6448bb2da328 (diff)
downloadgnutls-2837e8fd8f70f4f8272f381d3c15f2f8fe98ad41.tar.gz
Added gnutls_x509_crt_get_authority_info_access.
Diffstat (limited to 'lib')
-rw-r--r--lib/includes/gnutls/x509.h28
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/pkix.asn9
-rw-r--r--lib/pkix_asn1_tab.c6
-rw-r--r--lib/x509/x509.c206
5 files changed, 250 insertions, 0 deletions
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 67b5a1e37d..6b73f18a03 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -78,6 +78,9 @@ extern "C"
#define GNUTLS_KP_IPSEC_IKE "1.3.6.1.5.5.7.3.17"
#define GNUTLS_KP_ANY "2.5.29.37.0"
+#define GNUTLS_OID_AIA "1.3.6.1.5.5.7.1.1"
+#define GNUTLS_OID_AD_OCSP "1.3.6.1.5.5.7.48.1"
+
#define GNUTLS_FSAN_SET 0
#define GNUTLS_FSAN_APPEND 1
@@ -162,6 +165,31 @@ extern "C"
int gnutls_x509_crt_get_issuer_unique_id (gnutls_x509_crt_t crt, char *buf,
size_t * buf_size);
+ /**
+ * gnutls_info_access_what_t:
+ *
+ * Enumeration of types for the @what parameter of
+ * gnutls_x509_crt_get_authority_info_access().
+ */
+ typedef enum gnutls_info_access_what_t
+ {
+ /* get accessMethod OID */
+ GNUTLS_IA_ACCESSMETHOD_OID = 1,
+ /* get accessLocation name type */
+ GNUTLS_IA_ACCESSLOCATION_GENERALNAME_TYPE = 2,
+ /* use 100-108 for the generalName types, populate as needed */
+ /* get accessLocation URI value */
+ GNUTLS_IA_URI = 106,
+ /* quick-access variants that match both OID and name type. */
+ GNUTLS_IA_OCSP_URI = 10006
+ } gnutls_info_access_what_t;
+
+ int gnutls_x509_crt_get_authority_info_access (gnutls_x509_crt_t crt,
+ unsigned int seq,
+ int what,
+ gnutls_datum_t * data,
+ int *critical);
+
#define GNUTLS_CRL_REASON_UNUSED 128
#define GNUTLS_CRL_REASON_KEY_COMPROMISE 64
#define GNUTLS_CRL_REASON_CA_COMPROMISE 32
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 70bc8414ca..b80f7bc0f8 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -717,6 +717,7 @@ GNUTLS_3_0_0 {
gnutls_pubkey_import_ecc_raw;
gnutls_pubkey_import_ecc_raw2;
gnutls_record_get_discarded;
+ gnutls_x509_crt_get_authority_info_access;
} GNUTLS_2_12;
GNUTLS_PRIVATE {
diff --git a/lib/pkix.asn b/lib/pkix.asn
index e805fb7abf..ef1937c925 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -101,6 +101,15 @@ ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
KeyPurposeId ::= OBJECT IDENTIFIER
+-- authority info access
+
+AuthorityInfoAccessSyntax ::=
+ SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+AccessDescription ::= SEQUENCE {
+ accessMethod OBJECT IDENTIFIER,
+ accessLocation GeneralName }
+
-- CRL number extension OID and syntax
CRLNumber ::= INTEGER (0..MAX)
diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c
index d5d5cc405e..c42b155b4a 100644
--- a/lib/pkix_asn1_tab.c
+++ b/lib/pkix_asn1_tab.c
@@ -92,6 +92,12 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
{ "MAX", 1074266122, "1"},
{ NULL, 2, "KeyPurposeId"},
{ "KeyPurposeId", 1073741836, NULL },
+ { "AuthorityInfoAccessSyntax", 1612709899, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "AccessDescription"},
+ { "AccessDescription", 1610612741, NULL },
+ { "accessMethod", 1073741836, NULL },
+ { "accessLocation", 2, "GeneralName"},
{ "CRLNumber", 1611137027, NULL },
{ "0", 10, "MAX"},
{ "CertificateIssuer", 1073741826, "GeneralNames"},
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 34310721bb..c3ee568940 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -3389,3 +3389,209 @@ gnutls_x509_crt_get_issuer_unique_id (gnutls_x509_crt_t crt, char *buf,
return result;
}
+
+static int
+_gnutls_parse_aia (ASN1_TYPE src,
+ unsigned int seq,
+ int what,
+ gnutls_datum_t * data)
+{
+ int len;
+ char nptr[ASN1_MAX_NAME_SIZE];
+ int result;
+ gnutls_datum_t d;
+
+ seq++; /* 0->1, 1->2 etc */
+ switch (what)
+ {
+ case GNUTLS_IA_ACCESSMETHOD_OID:
+ snprintf (nptr, sizeof (nptr), "?%u.accessMethod", seq);
+ break;
+
+ case GNUTLS_IA_ACCESSLOCATION_GENERALNAME_TYPE:
+ snprintf (nptr, sizeof (nptr), "?%u.accessLocation", seq);
+ break;
+
+ case GNUTLS_IA_OCSP_URI:
+ {
+ char *tmpoid[20];
+ snprintf (nptr, sizeof (nptr), "?%u.accessMethod", seq);
+ len = sizeof (tmpoid);
+ result = asn1_read_value (src, nptr, tmpoid, &len);
+ if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+ if (len != sizeof (GNUTLS_OID_AD_OCSP) ||
+ memcmp (tmpoid, GNUTLS_OID_AD_OCSP, len) != 0)
+ return GNUTLS_E_UNKNOWN_ALGORITHM;
+ }
+ /* fall through */
+
+ case GNUTLS_IA_URI:
+ snprintf (nptr, sizeof (nptr),
+ "?%u.accessLocation.uniformResourceIdentifier", seq);
+ break;
+
+ default:
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ len = 0;
+ result = asn1_read_value (src, nptr, NULL, &len);
+ if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ if (result != ASN1_MEM_ERROR)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+ d.size = len;
+ d.data = gnutls_malloc (d.size);
+ if (d.data == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ result = asn1_read_value (src, nptr, d.data, &len);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ gnutls_free (d.data);
+ return _gnutls_asn2err (result);
+ }
+
+ if (data)
+ {
+ data->data = d.data;
+ data->size = d.size;
+ }
+ else
+ gnutls_free (d.data);
+
+ return GNUTLS_E_SUCCESS;
+}
+
+/**
+ * gnutls_x509_crt_get_authority_info_access:
+ * @crt: Holds the certificate
+ * @seq: specifies the sequence number of the access descriptor (0 for the first one, 1 for the second etc.)
+ * @what: what data to get, a #gnutls_info_access_what_t type.
+ * @data: output data to be freed with gnutls_free().
+ * @critical: pointer to output integer that is set to non-0 if the extension is marked as critical (may be %NULL)
+ *
+ * This function extracts the Authority Information Access (AIA)
+ * extension, see RFC 5280 section 4.2.2.1 for more information. The
+ * AIA extension holds a sequence of AccessDescription (AD) data:
+ *
+ * <informalexample><programlisting>
+ * AuthorityInfoAccessSyntax ::=
+ * SEQUENCE SIZE (1..MAX) OF AccessDescription
+ *
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ * </programlisting></informalexample>
+ *
+ * The @seq input parameter is used to indicate which member of the
+ * sequence the caller is interested in. The first member is 0, the
+ * second member 1 and so on. When the @seq value is out of bounds,
+ * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
+ *
+ * The type of data returned in @data is specified via @what which
+ * should be #gnutls_info_access_what_t values.
+ *
+ * If @what is %GNUTLS_IA_ACCESSMETHOD_OID then @data will hold the
+ * accessMethod OID (e.g., "1.3.6.1.5.5.7.48.1" for id-ad-ocsp meaning
+ * OCSP).
+ *
+ * If @what is %GNUTLS_IA_ACCESSLOCATION_GENERALNAME_TYPE, @data will
+ * hold the accessLocation GeneralName type (e.g.,
+ * "uniformResourceIdentifier").
+ *
+ * If @what is %GNUTLS_IA_URI, @data will hold the accessLocation URI
+ * data. Requesting this @what value leads to an error if the
+ * accessLocation is not of the "uniformResourceIdentifier" type.
+ *
+ * If @what is %GNUTLS_IA_OCSP_URI, @data will hold the OCSP URI.
+ * Requesting this @what value leads to an error if the accessMethod
+ * is not OSCP or accessLocation is not of the
+ * "uniformResourceIdentifier" type.
+ *
+ * More @what values may be allocated in the future as needed.
+ *
+ * If @data is NULL, the function does the same without storing the
+ * output data, that is, it will set @critical and do error checking
+ * as usual.
+ *
+ * The value of the critical flag is returned in *@critical. Supply a
+ * NULL @critical if you want the function to make sure the extension
+ * is non-critical, as required by RFC 5280.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, %GNUTLS_E_INVALID_REQUEST on
+ * invalid @crt, %GNUTLS_E_CONSTRAINT_ERROR if the extension is
+ * incorrectly marked as critical (use a non-NULL @critical to
+ * override), %GNUTLS_E_UNKNOWN_ALGORITHM if the requested OID does
+ * not match (e.g., when using %GNUTLS_IA_OCSP_URI), otherwise a
+ * negative error code.
+ **/
+int
+gnutls_x509_crt_get_authority_info_access (gnutls_x509_crt_t crt,
+ unsigned int seq,
+ int what,
+ gnutls_datum_t * data,
+ int *critical)
+{
+ int ret;
+ gnutls_datum_t aia;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ if (crt == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if ((ret = _gnutls_x509_crt_get_extension (crt, GNUTLS_OID_AIA, 0, &aia,
+ critical)) < 0)
+ return ret;
+
+ if (aia.size == 0 || aia.data == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (critical && *critical)
+ return GNUTLS_E_CONSTRAINT_ERROR;
+
+ ret = asn1_create_element (_gnutls_get_pkix (),
+ "PKIX1.AuthorityInfoAccessSyntax", &c2);
+ if (ret != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ _gnutls_free_datum (&aia);
+ return _gnutls_asn2err (ret);
+ }
+
+ ret = asn1_der_decoding (&c2, aia.data, aia.size, NULL);
+ /* asn1_print_structure (stdout, c2, "", ASN1_PRINT_ALL); */
+ _gnutls_free_datum (&aia);
+ if (ret != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&c2);
+ return _gnutls_asn2err (ret);
+ }
+
+ ret = _gnutls_parse_aia (c2, seq, what, data);
+ asn1_delete_structure (&c2);
+ if (ret < 0)
+ gnutls_assert ();
+
+ return ret;
+}