11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <stdio.h>
111cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
121cb0ef41Sopenharmony_ci#include <openssl/x509v3.h>
131cb0ef41Sopenharmony_ci#include "crypto/x509.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cistatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
161cb0ef41Sopenharmony_cistatic void trtable_free(X509_TRUST *p);
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cistatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
191cb0ef41Sopenharmony_cistatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
201cb0ef41Sopenharmony_cistatic int trust_compat(X509_TRUST *trust, X509 *x, int flags);
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cistatic int obj_trust(int id, X509 *x, int flags);
231cb0ef41Sopenharmony_cistatic int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci/*
261cb0ef41Sopenharmony_ci * WARNING: the following table should be kept in order of trust and without
271cb0ef41Sopenharmony_ci * any gaps so we can just subtract the minimum trust value to get an index
281cb0ef41Sopenharmony_ci * into the table
291cb0ef41Sopenharmony_ci */
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cistatic X509_TRUST trstandard[] = {
321cb0ef41Sopenharmony_ci    {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
331cb0ef41Sopenharmony_ci    {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
341cb0ef41Sopenharmony_ci     NULL},
351cb0ef41Sopenharmony_ci    {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
361cb0ef41Sopenharmony_ci     NULL},
371cb0ef41Sopenharmony_ci    {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
381cb0ef41Sopenharmony_ci     NULL},
391cb0ef41Sopenharmony_ci    {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
401cb0ef41Sopenharmony_ci     NULL},
411cb0ef41Sopenharmony_ci    {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
421cb0ef41Sopenharmony_ci     NULL},
431cb0ef41Sopenharmony_ci    {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
441cb0ef41Sopenharmony_ci     NULL},
451cb0ef41Sopenharmony_ci    {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
461cb0ef41Sopenharmony_ci};
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci#define X509_TRUST_COUNT        OSSL_NELEM(trstandard)
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_cistatic STACK_OF(X509_TRUST) *trtable = NULL;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cistatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
531cb0ef41Sopenharmony_ci{
541cb0ef41Sopenharmony_ci    return (*a)->trust - (*b)->trust;
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ciint (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
581cb0ef41Sopenharmony_ci                                                                int) {
591cb0ef41Sopenharmony_ci    int (*oldtrust) (int, X509 *, int);
601cb0ef41Sopenharmony_ci    oldtrust = default_trust;
611cb0ef41Sopenharmony_ci    default_trust = trust;
621cb0ef41Sopenharmony_ci    return oldtrust;
631cb0ef41Sopenharmony_ci}
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciint X509_check_trust(X509 *x, int id, int flags)
661cb0ef41Sopenharmony_ci{
671cb0ef41Sopenharmony_ci    X509_TRUST *pt;
681cb0ef41Sopenharmony_ci    int idx;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci    /* We get this as a default value */
711cb0ef41Sopenharmony_ci    if (id == X509_TRUST_DEFAULT)
721cb0ef41Sopenharmony_ci        return obj_trust(NID_anyExtendedKeyUsage, x,
731cb0ef41Sopenharmony_ci                         flags | X509_TRUST_DO_SS_COMPAT);
741cb0ef41Sopenharmony_ci    idx = X509_TRUST_get_by_id(id);
751cb0ef41Sopenharmony_ci    if (idx < 0)
761cb0ef41Sopenharmony_ci        return default_trust(id, x, flags);
771cb0ef41Sopenharmony_ci    pt = X509_TRUST_get0(idx);
781cb0ef41Sopenharmony_ci    return pt->check_trust(pt, x, flags);
791cb0ef41Sopenharmony_ci}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ciint X509_TRUST_get_count(void)
821cb0ef41Sopenharmony_ci{
831cb0ef41Sopenharmony_ci    if (!trtable)
841cb0ef41Sopenharmony_ci        return X509_TRUST_COUNT;
851cb0ef41Sopenharmony_ci    return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ciX509_TRUST *X509_TRUST_get0(int idx)
891cb0ef41Sopenharmony_ci{
901cb0ef41Sopenharmony_ci    if (idx < 0)
911cb0ef41Sopenharmony_ci        return NULL;
921cb0ef41Sopenharmony_ci    if (idx < (int)X509_TRUST_COUNT)
931cb0ef41Sopenharmony_ci        return trstandard + idx;
941cb0ef41Sopenharmony_ci    return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
951cb0ef41Sopenharmony_ci}
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ciint X509_TRUST_get_by_id(int id)
981cb0ef41Sopenharmony_ci{
991cb0ef41Sopenharmony_ci    X509_TRUST tmp;
1001cb0ef41Sopenharmony_ci    int idx;
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci    if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
1031cb0ef41Sopenharmony_ci        return id - X509_TRUST_MIN;
1041cb0ef41Sopenharmony_ci    if (trtable == NULL)
1051cb0ef41Sopenharmony_ci        return -1;
1061cb0ef41Sopenharmony_ci    tmp.trust = id;
1071cb0ef41Sopenharmony_ci    idx = sk_X509_TRUST_find(trtable, &tmp);
1081cb0ef41Sopenharmony_ci    if (idx < 0)
1091cb0ef41Sopenharmony_ci        return -1;
1101cb0ef41Sopenharmony_ci    return idx + X509_TRUST_COUNT;
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ciint X509_TRUST_set(int *t, int trust)
1141cb0ef41Sopenharmony_ci{
1151cb0ef41Sopenharmony_ci    if (X509_TRUST_get_by_id(trust) < 0) {
1161cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_INVALID_TRUST);
1171cb0ef41Sopenharmony_ci        return 0;
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci    *t = trust;
1201cb0ef41Sopenharmony_ci    return 1;
1211cb0ef41Sopenharmony_ci}
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ciint X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
1241cb0ef41Sopenharmony_ci                   const char *name, int arg1, void *arg2)
1251cb0ef41Sopenharmony_ci{
1261cb0ef41Sopenharmony_ci    int idx;
1271cb0ef41Sopenharmony_ci    X509_TRUST *trtmp;
1281cb0ef41Sopenharmony_ci    /*
1291cb0ef41Sopenharmony_ci     * This is set according to what we change: application can't set it
1301cb0ef41Sopenharmony_ci     */
1311cb0ef41Sopenharmony_ci    flags &= ~X509_TRUST_DYNAMIC;
1321cb0ef41Sopenharmony_ci    /* This will always be set for application modified trust entries */
1331cb0ef41Sopenharmony_ci    flags |= X509_TRUST_DYNAMIC_NAME;
1341cb0ef41Sopenharmony_ci    /* Get existing entry if any */
1351cb0ef41Sopenharmony_ci    idx = X509_TRUST_get_by_id(id);
1361cb0ef41Sopenharmony_ci    /* Need a new entry */
1371cb0ef41Sopenharmony_ci    if (idx < 0) {
1381cb0ef41Sopenharmony_ci        if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
1391cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
1401cb0ef41Sopenharmony_ci            return 0;
1411cb0ef41Sopenharmony_ci        }
1421cb0ef41Sopenharmony_ci        trtmp->flags = X509_TRUST_DYNAMIC;
1431cb0ef41Sopenharmony_ci    } else
1441cb0ef41Sopenharmony_ci        trtmp = X509_TRUST_get0(idx);
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci    /* OPENSSL_free existing name if dynamic */
1471cb0ef41Sopenharmony_ci    if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
1481cb0ef41Sopenharmony_ci        OPENSSL_free(trtmp->name);
1491cb0ef41Sopenharmony_ci    /* dup supplied name */
1501cb0ef41Sopenharmony_ci    if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
1511cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
1521cb0ef41Sopenharmony_ci        goto err;
1531cb0ef41Sopenharmony_ci    }
1541cb0ef41Sopenharmony_ci    /* Keep the dynamic flag of existing entry */
1551cb0ef41Sopenharmony_ci    trtmp->flags &= X509_TRUST_DYNAMIC;
1561cb0ef41Sopenharmony_ci    /* Set all other flags */
1571cb0ef41Sopenharmony_ci    trtmp->flags |= flags;
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci    trtmp->trust = id;
1601cb0ef41Sopenharmony_ci    trtmp->check_trust = ck;
1611cb0ef41Sopenharmony_ci    trtmp->arg1 = arg1;
1621cb0ef41Sopenharmony_ci    trtmp->arg2 = arg2;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci    /* If its a new entry manage the dynamic table */
1651cb0ef41Sopenharmony_ci    if (idx < 0) {
1661cb0ef41Sopenharmony_ci        if (trtable == NULL
1671cb0ef41Sopenharmony_ci            && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
1681cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
1691cb0ef41Sopenharmony_ci            goto err;;
1701cb0ef41Sopenharmony_ci        }
1711cb0ef41Sopenharmony_ci        if (!sk_X509_TRUST_push(trtable, trtmp)) {
1721cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
1731cb0ef41Sopenharmony_ci            goto err;
1741cb0ef41Sopenharmony_ci        }
1751cb0ef41Sopenharmony_ci    }
1761cb0ef41Sopenharmony_ci    return 1;
1771cb0ef41Sopenharmony_ci err:
1781cb0ef41Sopenharmony_ci    if (idx < 0) {
1791cb0ef41Sopenharmony_ci        OPENSSL_free(trtmp->name);
1801cb0ef41Sopenharmony_ci        OPENSSL_free(trtmp);
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci    return 0;
1831cb0ef41Sopenharmony_ci}
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_cistatic void trtable_free(X509_TRUST *p)
1861cb0ef41Sopenharmony_ci{
1871cb0ef41Sopenharmony_ci    if (p == NULL)
1881cb0ef41Sopenharmony_ci        return;
1891cb0ef41Sopenharmony_ci    if (p->flags & X509_TRUST_DYNAMIC) {
1901cb0ef41Sopenharmony_ci        if (p->flags & X509_TRUST_DYNAMIC_NAME)
1911cb0ef41Sopenharmony_ci            OPENSSL_free(p->name);
1921cb0ef41Sopenharmony_ci        OPENSSL_free(p);
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci}
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_civoid X509_TRUST_cleanup(void)
1971cb0ef41Sopenharmony_ci{
1981cb0ef41Sopenharmony_ci    sk_X509_TRUST_pop_free(trtable, trtable_free);
1991cb0ef41Sopenharmony_ci    trtable = NULL;
2001cb0ef41Sopenharmony_ci}
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ciint X509_TRUST_get_flags(const X509_TRUST *xp)
2031cb0ef41Sopenharmony_ci{
2041cb0ef41Sopenharmony_ci    return xp->flags;
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_cichar *X509_TRUST_get0_name(const X509_TRUST *xp)
2081cb0ef41Sopenharmony_ci{
2091cb0ef41Sopenharmony_ci    return xp->name;
2101cb0ef41Sopenharmony_ci}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ciint X509_TRUST_get_trust(const X509_TRUST *xp)
2131cb0ef41Sopenharmony_ci{
2141cb0ef41Sopenharmony_ci    return xp->trust;
2151cb0ef41Sopenharmony_ci}
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_cistatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
2181cb0ef41Sopenharmony_ci{
2191cb0ef41Sopenharmony_ci    /*
2201cb0ef41Sopenharmony_ci     * Declare the chain verified if the desired trust OID is not rejected in
2211cb0ef41Sopenharmony_ci     * any auxiliary trust info for this certificate, and the OID is either
2221cb0ef41Sopenharmony_ci     * expressly trusted, or else either "anyEKU" is trusted, or the
2231cb0ef41Sopenharmony_ci     * certificate is self-signed and X509_TRUST_NO_SS_COMPAT is not set.
2241cb0ef41Sopenharmony_ci     */
2251cb0ef41Sopenharmony_ci    flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU;
2261cb0ef41Sopenharmony_ci    return obj_trust(trust->arg1, x, flags);
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_cistatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
2301cb0ef41Sopenharmony_ci{
2311cb0ef41Sopenharmony_ci    /*
2321cb0ef41Sopenharmony_ci     * Declare the chain verified only if the desired trust OID is not
2331cb0ef41Sopenharmony_ci     * rejected and is expressly trusted.  Neither "anyEKU" nor "compat"
2341cb0ef41Sopenharmony_ci     * trust in self-signed certificates apply.
2351cb0ef41Sopenharmony_ci     */
2361cb0ef41Sopenharmony_ci    flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU);
2371cb0ef41Sopenharmony_ci    return obj_trust(trust->arg1, x, flags);
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_cistatic int trust_compat(X509_TRUST *trust, X509 *x, int flags)
2411cb0ef41Sopenharmony_ci{
2421cb0ef41Sopenharmony_ci    /* Call for side-effect of setting EXFLAG_SS for self-signed-certs */
2431cb0ef41Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
2441cb0ef41Sopenharmony_ci        return X509_TRUST_UNTRUSTED;
2451cb0ef41Sopenharmony_ci    if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS))
2461cb0ef41Sopenharmony_ci        return X509_TRUST_TRUSTED;
2471cb0ef41Sopenharmony_ci    else
2481cb0ef41Sopenharmony_ci        return X509_TRUST_UNTRUSTED;
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_cistatic int obj_trust(int id, X509 *x, int flags)
2521cb0ef41Sopenharmony_ci{
2531cb0ef41Sopenharmony_ci    X509_CERT_AUX *ax = x->aux;
2541cb0ef41Sopenharmony_ci    int i;
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    if (ax && ax->reject) {
2571cb0ef41Sopenharmony_ci        for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
2581cb0ef41Sopenharmony_ci            ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
2591cb0ef41Sopenharmony_ci            int nid = OBJ_obj2nid(obj);
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci            if (nid == id || (nid == NID_anyExtendedKeyUsage &&
2621cb0ef41Sopenharmony_ci                (flags & X509_TRUST_OK_ANY_EKU)))
2631cb0ef41Sopenharmony_ci                return X509_TRUST_REJECTED;
2641cb0ef41Sopenharmony_ci        }
2651cb0ef41Sopenharmony_ci    }
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci    if (ax && ax->trust) {
2681cb0ef41Sopenharmony_ci        for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
2691cb0ef41Sopenharmony_ci            ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
2701cb0ef41Sopenharmony_ci            int nid = OBJ_obj2nid(obj);
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci            if (nid == id || (nid == NID_anyExtendedKeyUsage &&
2731cb0ef41Sopenharmony_ci                (flags & X509_TRUST_OK_ANY_EKU)))
2741cb0ef41Sopenharmony_ci                return X509_TRUST_TRUSTED;
2751cb0ef41Sopenharmony_ci        }
2761cb0ef41Sopenharmony_ci        /*
2771cb0ef41Sopenharmony_ci         * Reject when explicit trust EKU are set and none match.
2781cb0ef41Sopenharmony_ci         *
2791cb0ef41Sopenharmony_ci         * Returning untrusted is enough for for full chains that end in
2801cb0ef41Sopenharmony_ci         * self-signed roots, because when explicit trust is specified it
2811cb0ef41Sopenharmony_ci         * suppresses the default blanket trust of self-signed objects.
2821cb0ef41Sopenharmony_ci         *
2831cb0ef41Sopenharmony_ci         * But for partial chains, this is not enough, because absent a similar
2841cb0ef41Sopenharmony_ci         * trust-self-signed policy, non matching EKUs are indistinguishable
2851cb0ef41Sopenharmony_ci         * from lack of EKU constraints.
2861cb0ef41Sopenharmony_ci         *
2871cb0ef41Sopenharmony_ci         * Therefore, failure to match any trusted purpose must trigger an
2881cb0ef41Sopenharmony_ci         * explicit reject.
2891cb0ef41Sopenharmony_ci         */
2901cb0ef41Sopenharmony_ci        return X509_TRUST_REJECTED;
2911cb0ef41Sopenharmony_ci    }
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci    if ((flags & X509_TRUST_DO_SS_COMPAT) == 0)
2941cb0ef41Sopenharmony_ci        return X509_TRUST_UNTRUSTED;
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci    /*
2971cb0ef41Sopenharmony_ci     * Not rejected, and there is no list of accepted uses, try compat.
2981cb0ef41Sopenharmony_ci     */
2991cb0ef41Sopenharmony_ci    return trust_compat(NULL, x, flags);
3001cb0ef41Sopenharmony_ci}
301