Fix safestack issues in asn1.h
[openssl.git] / crypto / cmp / cmp_util.c
index 121b6a173a59f81aa0db5339c3f4889ce187d526..bdd876a89f215e051012061b32ab062299fcca98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -16,6 +16,8 @@
 #include <openssl/err.h> /* should be implied by cmperr.h */
 #include <openssl/x509v3.h>
 
+DEFINE_STACK_OF(X509_OBJECT)
+
 /*
  * use trace API for CMP-specific logging, prefixed by "CMP " and severity
  */
@@ -114,8 +116,9 @@ const char *ossl_cmp_log_parse_metadata(const char *buf,
  */
 static const char *improve_location_name(const char *func, const char *fallback)
 {
-    if (!ossl_assert(fallback != NULL))
-        return NULL;
+    if (fallback == NULL)
+        return func == NULL ? UNKNOWN_FUNC : func;
+
     return func == NULL || *func == '\0' || strcmp(func, UNKNOWN_FUNC) == 0
         ? fallback : func;
 }
@@ -179,62 +182,8 @@ void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn)
     }
 }
 
-/*
- * functions manipulating lists of certificates etc.
- * these functions could be generally useful.
- */
-
-int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509) *sk, X509 *cert,
-                               int no_dup, int prepend)
-{
-    if (sk == NULL) {
-        CMPerr(0, CMP_R_NULL_ARGUMENT);
-        return 0;
-    }
-    if (no_dup) {
-        /*
-         * not using sk_X509_set_cmp_func() and sk_X509_find()
-         * because this re-orders the certs on the stack
-         */
-        int i;
-
-        for (i = 0; i < sk_X509_num(sk); i++) {
-            if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
-                return 1;
-        }
-    }
-    if (!X509_up_ref(cert))
-        return 0;
-    if (!sk_X509_insert(sk, cert, prepend ? 0 : -1)) {
-        X509_free(cert);
-        return 0;
-    }
-    return 1;
-}
-
-int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
-                                int no_self_issued, int no_dups, int prepend)
-/* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
-{
-    int i;
-
-    if (sk == NULL) {
-        CMPerr(0, CMP_R_NULL_ARGUMENT);
-        return 0;
-    }
-    for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
-        X509 *cert = sk_X509_value(certs, i);
-
-        if (!no_self_issued || X509_check_issued(cert, cert) != X509_V_OK) {
-            if (!ossl_cmp_sk_X509_add1_cert(sk, cert, no_dups, prepend))
-                return 0;
-        }
-    }
-    return 1;
-}
-
 int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
-                                   int only_self_issued)
+                                   int only_self_signed)
 {
     int i;
 
@@ -247,7 +196,7 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
     for (i = 0; i < sk_X509_num(certs); i++) {
         X509 *cert = sk_X509_value(certs, i);
 
-        if (!only_self_issued || X509_check_issued(cert, cert) == X509_V_OK)
+        if (!only_self_signed || X509_self_signed(cert, 0) == 1)
             if (!X509_STORE_add_cert(store, cert)) /* ups cert ref counter */
                 return 0;
     }
@@ -255,67 +204,64 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
 }
 
 /*-
- * Builds up the certificate chain of certs as high up as possible using
- * the given list of certs containing all possible intermediate certificates and
- * optionally the (possible) trust anchor(s). See also ssl_add_cert_chain().
+ * Builds a certificate chain starting from <cert>
+ * using the optional list of intermediate CA certificates <certs>.
+ * If <store> is NULL builds the chain as far down as possible, ignoring errors.
+ * Else the chain must reach a trust anchor contained in <store>.
  *
- * Intended use of this function is to find all the certificates above the trust
- * anchor needed to verify an EE's own certificate.  Those are supposed to be
- * included in the ExtraCerts field of every first sent message of a transaction
- * when MSG_SIG_ALG is utilized.
+ * Returns NULL on error, else a pointer to a stack of (up_ref'ed) certificates
+ * starting with given EE certificate and followed by all available intermediate
+ * certificates down towards any trust anchor but without including the latter.
  *
- * NOTE: This allocates a stack and increments the reference count of each cert,
- * so when not needed any more the stack and all its elements should be freed.
- * NOTE: in case there is more than one possibility for the chain,
- * OpenSSL seems to take the first one, check X509_verify_cert() for details.
- *
- * returns a pointer to a stack of (up_ref'ed) X509 certificates containing:
- *      - the EE certificate given in the function arguments (cert)
- *      - all intermediate certificates up the chain toward the trust anchor
- *        whereas the (self-signed) trust anchor is not included
- * returns NULL on error
+ * NOTE: If a non-NULL stack is returned the caller is responsible for freeing.
+ * NOTE: In case there is more than one possibility for the chain,
+ * OpenSSL seems to take the first one; check X509_verify_cert() for details.
  */
-STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert)
+/* TODO this should be of more general interest and thus be exported. */
+STACK_OF(X509)
+    *ossl_cmp_build_cert_chain(OPENSSL_CTX *libctx, const char *propq,
+                               X509_STORE *store,
+                               STACK_OF(X509) *certs, X509 *cert)
 {
     STACK_OF(X509) *chain = NULL, *result = NULL;
-    X509_STORE *store = X509_STORE_new();
+    X509_STORE *ts = store == NULL ? X509_STORE_new() : store;
     X509_STORE_CTX *csc = NULL;
 
-    if (certs == NULL || cert == NULL || store == NULL) {
+    if (ts == NULL || cert == NULL) {
         CMPerr(0, CMP_R_NULL_ARGUMENT);
         goto err;
     }
 
-    csc = X509_STORE_CTX_new();
-    if (csc == NULL)
+    if ((csc = X509_STORE_CTX_new_with_libctx(libctx, propq)) == NULL)
         goto err;
-
-    if (!ossl_cmp_X509_STORE_add1_certs(store, certs, 0)
-            || !X509_STORE_CTX_init(csc, store, cert, NULL))
+    if (store == NULL && certs != NULL
+            && !ossl_cmp_X509_STORE_add1_certs(ts, certs, 0))
         goto err;
+    if (!X509_STORE_CTX_init(csc, ts, cert,
+                             store == NULL ? NULL : certs))
+        goto err;
+    /* disable any cert status/revocation checking etc. */
+    X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(csc),
+                                  ~(X509_V_FLAG_USE_CHECK_TIME
+                                    | X509_V_FLAG_NO_CHECK_TIME));
 
-    (void)ERR_set_mark();
-    /*
-     * ignore return value as it would fail without trust anchor given in store
-     */
-    (void)X509_verify_cert(csc);
-
-    /* don't leave any new errors in the queue */
-    (void)ERR_pop_to_mark();
-
+    if (X509_verify_cert(csc) <= 0 && store != NULL)
+        goto err;
     chain = X509_STORE_CTX_get0_chain(csc);
 
-    /* result list to store the up_ref'ed not self-issued certificates */
+    /* result list to store the up_ref'ed not self-signed certificates */
     if ((result = sk_X509_new_null()) == NULL)
         goto err;
-    if (!ossl_cmp_sk_X509_add1_certs(result, chain, 1 /* no self-issued */,
-                                     1 /* no duplicates */, 0)) {
+    if (!X509_add_certs(result, chain,
+                        X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+                        | X509_ADD_FLAG_NO_SS)) {
         sk_X509_free(result);
         result = NULL;
     }
 
  err:
-    X509_STORE_free(store);
+    if (store == NULL)
+        X509_STORE_free(ts);
     X509_STORE_CTX_free(csc);
     return result;
 }