]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added gnutls_x509_trust_list_verify_purpose_crt()
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 8 Sep 2014 14:07:40 +0000 (16:07 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 8 Sep 2014 14:52:36 +0000 (16:52 +0200)
lib/gnutls_x509.c
lib/includes/gnutls/x509.h
lib/libgnutls.map
lib/x509/verify-high.c

index 442427116e698fd65324ad7c53f3b78a01708b70..ebf019b0298a76b6988eb61de2aa54974c14e052 100644 (file)
@@ -289,9 +289,10 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session,
        /* Verify certificate 
         */
        ret =
-           gnutls_x509_trust_list_verify_crt(cred->tlist,
+           gnutls_x509_trust_list_verify_purpose_crt(cred->tlist,
                                              peer_certificate_list,
                                              peer_certificate_list_size,
+                                             purpose,
                                              verify_flags, status, NULL);
 
        if (ret < 0) {
@@ -308,33 +309,6 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session,
                        *status |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
        }
 
-       if (purpose) {
-               char oid[MAX_OID_SIZE];
-               size_t oid_size;
-
-               for (i=0;;i++) {
-                       oid_size = sizeof(oid);
-                       ret = gnutls_x509_crt_get_key_purpose_oid(peer_certificate_list[0],
-                               i, oid, &oid_size, NULL);
-                       if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
-                               if (i==0)
-                                       break;
-                               else { /* no acceptable purpose was found */
-                                       gnutls_assert();
-                                       *status |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE|GNUTLS_CERT_INVALID;
-                                       break;
-                               }
-                       } else if (ret < 0) {
-                               gnutls_assert();
-                               *status |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE|GNUTLS_CERT_INVALID;
-                               break;
-                       }
-
-                       if (strcmp(oid, purpose) == 0 || strcmp(oid, GNUTLS_KP_ANY) == 0)
-                               break;
-               }
-       }
-
        CLEAR_CERTS;
 
        *status |= ocsp_status;
index 04b4ca5ca705766755fa54a1ee2091d6e00bacef..162af447b36adb57155db29e5503d1c1bfb8c80d 100644 (file)
@@ -1278,6 +1278,15 @@ int gnutls_x509_trust_list_verify_named_crt
      const void *name, size_t name_size, unsigned int flags,
      unsigned int *verify, gnutls_verify_output_function func);
 
+int
+gnutls_x509_trust_list_verify_purpose_crt(gnutls_x509_trust_list_t list,
+                                 gnutls_x509_crt_t * cert_list,
+                                 unsigned int cert_list_size,
+                                 const char *purpose,
+                                 unsigned int flags,
+                                 unsigned int *voutput,
+                                 gnutls_verify_output_function func);
+
 int
 gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
                                  gnutls_x509_crt_t * cert_list,
index f43f1be461b473f2255dd3f45b0be04000191614..5c6173fc4697a5d07da4c709a89c897a03ce1295 100644 (file)
@@ -1023,6 +1023,7 @@ GNUTLS_3_1_0 {
        gnutls_pkcs11_obj_get_flags;
        gnutls_pkcs12_mac_info;
        gnutls_pkcs12_generate_mac2;
+       gnutls_x509_trust_list_verify_purpose_crt;
 } GNUTLS_3_0_0;
 
 GNUTLS_FIPS140 {
index f870e2d08c66f6100ca9912c8e66f238195c9d5e..f17a8559fcbdb98ee3e8d3555798eb76b7985dde 100644 (file)
@@ -31,6 +31,7 @@
 #include <hash-pjw-bare.h>
 #include "x509_int.h"
 #include <common.h>
+#include <gnutls/x509-ext.h>
 #include "verify-high.h"
 
 struct named_cert_st {
@@ -753,6 +754,91 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
                                  unsigned int flags,
                                  unsigned int *voutput,
                                  gnutls_verify_output_function func)
+{
+       return gnutls_x509_trust_list_verify_purpose_crt(list, cert_list, cert_list_size,
+                                                        NULL, flags, voutput, func);
+}
+
+static
+int check_key_purpose(gnutls_x509_crt_t crt, const gnutls_datum_t *ext_data, unsigned *voutput, 
+                     const char *purpose)
+{
+       gnutls_datum_t coid = {NULL, 0};
+       gnutls_x509_key_purposes_t p = NULL;
+       unsigned i;
+       int ret;
+
+       ret = gnutls_x509_key_purpose_init(&p);
+       if (ret < 0) {
+               gnutls_assert();
+               goto fail;
+       }
+
+       ret = gnutls_x509_ext_import_key_purposes(ext_data, p, 0);
+       if (ret < 0) {
+               gnutls_assert();
+               goto fail;
+       }
+
+       for (i=0;;i++) {
+               ret = gnutls_x509_key_purpose_get(p, i, &coid);
+               if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+                       if (i==0) {
+                               break;
+                       } else { /* no acceptable purpose was found */
+                               gnutls_assert();
+                               goto fail;
+                       }
+               } else if (ret < 0) {
+                       gnutls_assert();
+                       goto fail;
+               }
+
+               if (strcmp((char*)coid.data, purpose) == 0 || strcmp((char*)coid.data, GNUTLS_KP_ANY) == 0)
+                       break;
+       }
+
+       gnutls_x509_key_purpose_deinit(p);
+       return 0;
+ fail:
+       *voutput |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE|GNUTLS_CERT_INVALID;
+       if (p != NULL)
+               gnutls_x509_key_purpose_deinit(p);
+       return ret;
+}
+
+/**
+ * gnutls_x509_trust_list_verify_purpose_crt:
+ * @list: The structure of the list
+ * @cert_list: is the certificate list to be verified
+ * @cert_list_size: is the certificate list size
+ * @purpose: the purpose OID (GNUTLS_KP) for which the certificate must be valid (may be %NULL)
+ * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
+ * @voutput: will hold the certificate verification output.
+ * @func: If non-null will be called on each chain element verification with the output.
+ *
+ * This function will try to verify the given certificate and return
+ * its status. The @verify parameter will hold an OR'ed sequence of
+ * %gnutls_certificate_status_t flags.
+ *
+ * Additionally a certificate verification profile can be specified
+ * from the ones in %gnutls_certificate_verification_profiles_t by
+ * ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
+ * flags.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.3.8
+ **/
+int
+gnutls_x509_trust_list_verify_purpose_crt(gnutls_x509_trust_list_t list,
+                                 gnutls_x509_crt_t * cert_list,
+                                 unsigned int cert_list_size,
+                                 const char *purpose,
+                                 unsigned int flags,
+                                 unsigned int *voutput,
+                                 gnutls_verify_output_function func)
 {
        int ret;
        unsigned int i;
@@ -864,6 +950,25 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
                }
        }
 
+       /* check the purpose if given */
+       if (purpose) do {
+               gnutls_datum_t ext_data = {NULL, 0};
+
+               ret = gnutls_x509_crt_get_extension_by_oid2(cert_list[0], "2.5.29.37", 0, &ext_data, NULL);
+               if (ret < 0) {
+                       gnutls_assert();
+                       break;
+               }
+
+               ret = check_key_purpose(cert_list[0], &ext_data, voutput, purpose);
+               gnutls_free(ext_data.data);
+
+               if (ret < 0) {
+                       gnutls_assert();
+               }
+
+       } while(0);
+
        return 0;
 }