1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 13e1051a39Sopenharmony_ci#include "crypto/x509.h" 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_cistatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b); 16e1051a39Sopenharmony_cistatic void trtable_free(X509_TRUST *p); 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_cistatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); 19e1051a39Sopenharmony_cistatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags); 20e1051a39Sopenharmony_cistatic int trust_compat(X509_TRUST *trust, X509 *x, int flags); 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_cistatic int obj_trust(int id, X509 *x, int flags); 23e1051a39Sopenharmony_cistatic int (*default_trust) (int id, X509 *x, int flags) = obj_trust; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci/* 26e1051a39Sopenharmony_ci * WARNING: the following table should be kept in order of trust and without 27e1051a39Sopenharmony_ci * any gaps so we can just subtract the minimum trust value to get an index 28e1051a39Sopenharmony_ci * into the table 29e1051a39Sopenharmony_ci */ 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_cistatic X509_TRUST trstandard[] = { 32e1051a39Sopenharmony_ci {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL}, 33e1051a39Sopenharmony_ci {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, 34e1051a39Sopenharmony_ci NULL}, 35e1051a39Sopenharmony_ci {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth, 36e1051a39Sopenharmony_ci NULL}, 37e1051a39Sopenharmony_ci {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, 38e1051a39Sopenharmony_ci NULL}, 39e1051a39Sopenharmony_ci {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign, 40e1051a39Sopenharmony_ci NULL}, 41e1051a39Sopenharmony_ci {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, 42e1051a39Sopenharmony_ci NULL}, 43e1051a39Sopenharmony_ci {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, 44e1051a39Sopenharmony_ci NULL}, 45e1051a39Sopenharmony_ci {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL} 46e1051a39Sopenharmony_ci}; 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci#define X509_TRUST_COUNT OSSL_NELEM(trstandard) 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_cistatic STACK_OF(X509_TRUST) *trtable = NULL; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_cistatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b) 53e1051a39Sopenharmony_ci{ 54e1051a39Sopenharmony_ci return (*a)->trust - (*b)->trust; 55e1051a39Sopenharmony_ci} 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ciint (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, 58e1051a39Sopenharmony_ci int) { 59e1051a39Sopenharmony_ci int (*oldtrust) (int, X509 *, int); 60e1051a39Sopenharmony_ci oldtrust = default_trust; 61e1051a39Sopenharmony_ci default_trust = trust; 62e1051a39Sopenharmony_ci return oldtrust; 63e1051a39Sopenharmony_ci} 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ciint X509_check_trust(X509 *x, int id, int flags) 66e1051a39Sopenharmony_ci{ 67e1051a39Sopenharmony_ci X509_TRUST *pt; 68e1051a39Sopenharmony_ci int idx; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci /* We get this as a default value */ 71e1051a39Sopenharmony_ci if (id == X509_TRUST_DEFAULT) 72e1051a39Sopenharmony_ci return obj_trust(NID_anyExtendedKeyUsage, x, 73e1051a39Sopenharmony_ci flags | X509_TRUST_DO_SS_COMPAT); 74e1051a39Sopenharmony_ci idx = X509_TRUST_get_by_id(id); 75e1051a39Sopenharmony_ci if (idx < 0) 76e1051a39Sopenharmony_ci return default_trust(id, x, flags); 77e1051a39Sopenharmony_ci pt = X509_TRUST_get0(idx); 78e1051a39Sopenharmony_ci return pt->check_trust(pt, x, flags); 79e1051a39Sopenharmony_ci} 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ciint X509_TRUST_get_count(void) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci if (!trtable) 84e1051a39Sopenharmony_ci return X509_TRUST_COUNT; 85e1051a39Sopenharmony_ci return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; 86e1051a39Sopenharmony_ci} 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ciX509_TRUST *X509_TRUST_get0(int idx) 89e1051a39Sopenharmony_ci{ 90e1051a39Sopenharmony_ci if (idx < 0) 91e1051a39Sopenharmony_ci return NULL; 92e1051a39Sopenharmony_ci if (idx < (int)X509_TRUST_COUNT) 93e1051a39Sopenharmony_ci return trstandard + idx; 94e1051a39Sopenharmony_ci return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); 95e1051a39Sopenharmony_ci} 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ciint X509_TRUST_get_by_id(int id) 98e1051a39Sopenharmony_ci{ 99e1051a39Sopenharmony_ci X509_TRUST tmp; 100e1051a39Sopenharmony_ci int idx; 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) 103e1051a39Sopenharmony_ci return id - X509_TRUST_MIN; 104e1051a39Sopenharmony_ci if (trtable == NULL) 105e1051a39Sopenharmony_ci return -1; 106e1051a39Sopenharmony_ci tmp.trust = id; 107e1051a39Sopenharmony_ci idx = sk_X509_TRUST_find(trtable, &tmp); 108e1051a39Sopenharmony_ci if (idx < 0) 109e1051a39Sopenharmony_ci return -1; 110e1051a39Sopenharmony_ci return idx + X509_TRUST_COUNT; 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ciint X509_TRUST_set(int *t, int trust) 114e1051a39Sopenharmony_ci{ 115e1051a39Sopenharmony_ci if (X509_TRUST_get_by_id(trust) < 0) { 116e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_INVALID_TRUST); 117e1051a39Sopenharmony_ci return 0; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_ci *t = trust; 120e1051a39Sopenharmony_ci return 1; 121e1051a39Sopenharmony_ci} 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ciint X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), 124e1051a39Sopenharmony_ci const char *name, int arg1, void *arg2) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci int idx; 127e1051a39Sopenharmony_ci X509_TRUST *trtmp; 128e1051a39Sopenharmony_ci /* 129e1051a39Sopenharmony_ci * This is set according to what we change: application can't set it 130e1051a39Sopenharmony_ci */ 131e1051a39Sopenharmony_ci flags &= ~X509_TRUST_DYNAMIC; 132e1051a39Sopenharmony_ci /* This will always be set for application modified trust entries */ 133e1051a39Sopenharmony_ci flags |= X509_TRUST_DYNAMIC_NAME; 134e1051a39Sopenharmony_ci /* Get existing entry if any */ 135e1051a39Sopenharmony_ci idx = X509_TRUST_get_by_id(id); 136e1051a39Sopenharmony_ci /* Need a new entry */ 137e1051a39Sopenharmony_ci if (idx < 0) { 138e1051a39Sopenharmony_ci if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) { 139e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 140e1051a39Sopenharmony_ci return 0; 141e1051a39Sopenharmony_ci } 142e1051a39Sopenharmony_ci trtmp->flags = X509_TRUST_DYNAMIC; 143e1051a39Sopenharmony_ci } else 144e1051a39Sopenharmony_ci trtmp = X509_TRUST_get0(idx); 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci /* OPENSSL_free existing name if dynamic */ 147e1051a39Sopenharmony_ci if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) 148e1051a39Sopenharmony_ci OPENSSL_free(trtmp->name); 149e1051a39Sopenharmony_ci /* dup supplied name */ 150e1051a39Sopenharmony_ci if ((trtmp->name = OPENSSL_strdup(name)) == NULL) { 151e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 152e1051a39Sopenharmony_ci goto err; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci /* Keep the dynamic flag of existing entry */ 155e1051a39Sopenharmony_ci trtmp->flags &= X509_TRUST_DYNAMIC; 156e1051a39Sopenharmony_ci /* Set all other flags */ 157e1051a39Sopenharmony_ci trtmp->flags |= flags; 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci trtmp->trust = id; 160e1051a39Sopenharmony_ci trtmp->check_trust = ck; 161e1051a39Sopenharmony_ci trtmp->arg1 = arg1; 162e1051a39Sopenharmony_ci trtmp->arg2 = arg2; 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci /* If its a new entry manage the dynamic table */ 165e1051a39Sopenharmony_ci if (idx < 0) { 166e1051a39Sopenharmony_ci if (trtable == NULL 167e1051a39Sopenharmony_ci && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) { 168e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 169e1051a39Sopenharmony_ci goto err;; 170e1051a39Sopenharmony_ci } 171e1051a39Sopenharmony_ci if (!sk_X509_TRUST_push(trtable, trtmp)) { 172e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 173e1051a39Sopenharmony_ci goto err; 174e1051a39Sopenharmony_ci } 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci return 1; 177e1051a39Sopenharmony_ci err: 178e1051a39Sopenharmony_ci if (idx < 0) { 179e1051a39Sopenharmony_ci OPENSSL_free(trtmp->name); 180e1051a39Sopenharmony_ci OPENSSL_free(trtmp); 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci return 0; 183e1051a39Sopenharmony_ci} 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_cistatic void trtable_free(X509_TRUST *p) 186e1051a39Sopenharmony_ci{ 187e1051a39Sopenharmony_ci if (p == NULL) 188e1051a39Sopenharmony_ci return; 189e1051a39Sopenharmony_ci if (p->flags & X509_TRUST_DYNAMIC) { 190e1051a39Sopenharmony_ci if (p->flags & X509_TRUST_DYNAMIC_NAME) 191e1051a39Sopenharmony_ci OPENSSL_free(p->name); 192e1051a39Sopenharmony_ci OPENSSL_free(p); 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci} 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_civoid X509_TRUST_cleanup(void) 197e1051a39Sopenharmony_ci{ 198e1051a39Sopenharmony_ci sk_X509_TRUST_pop_free(trtable, trtable_free); 199e1051a39Sopenharmony_ci trtable = NULL; 200e1051a39Sopenharmony_ci} 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ciint X509_TRUST_get_flags(const X509_TRUST *xp) 203e1051a39Sopenharmony_ci{ 204e1051a39Sopenharmony_ci return xp->flags; 205e1051a39Sopenharmony_ci} 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_cichar *X509_TRUST_get0_name(const X509_TRUST *xp) 208e1051a39Sopenharmony_ci{ 209e1051a39Sopenharmony_ci return xp->name; 210e1051a39Sopenharmony_ci} 211e1051a39Sopenharmony_ci 212e1051a39Sopenharmony_ciint X509_TRUST_get_trust(const X509_TRUST *xp) 213e1051a39Sopenharmony_ci{ 214e1051a39Sopenharmony_ci return xp->trust; 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_cistatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) 218e1051a39Sopenharmony_ci{ 219e1051a39Sopenharmony_ci /* 220e1051a39Sopenharmony_ci * Declare the chain verified if the desired trust OID is not rejected in 221e1051a39Sopenharmony_ci * any auxiliary trust info for this certificate, and the OID is either 222e1051a39Sopenharmony_ci * expressly trusted, or else either "anyEKU" is trusted, or the 223e1051a39Sopenharmony_ci * certificate is self-signed and X509_TRUST_NO_SS_COMPAT is not set. 224e1051a39Sopenharmony_ci */ 225e1051a39Sopenharmony_ci flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU; 226e1051a39Sopenharmony_ci return obj_trust(trust->arg1, x, flags); 227e1051a39Sopenharmony_ci} 228e1051a39Sopenharmony_ci 229e1051a39Sopenharmony_cistatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags) 230e1051a39Sopenharmony_ci{ 231e1051a39Sopenharmony_ci /* 232e1051a39Sopenharmony_ci * Declare the chain verified only if the desired trust OID is not 233e1051a39Sopenharmony_ci * rejected and is expressly trusted. Neither "anyEKU" nor "compat" 234e1051a39Sopenharmony_ci * trust in self-signed certificates apply. 235e1051a39Sopenharmony_ci */ 236e1051a39Sopenharmony_ci flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU); 237e1051a39Sopenharmony_ci return obj_trust(trust->arg1, x, flags); 238e1051a39Sopenharmony_ci} 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_cistatic int trust_compat(X509_TRUST *trust, X509 *x, int flags) 241e1051a39Sopenharmony_ci{ 242e1051a39Sopenharmony_ci /* Call for side-effect of setting EXFLAG_SS for self-signed-certs */ 243e1051a39Sopenharmony_ci if (X509_check_purpose(x, -1, 0) != 1) 244e1051a39Sopenharmony_ci return X509_TRUST_UNTRUSTED; 245e1051a39Sopenharmony_ci if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS)) 246e1051a39Sopenharmony_ci return X509_TRUST_TRUSTED; 247e1051a39Sopenharmony_ci else 248e1051a39Sopenharmony_ci return X509_TRUST_UNTRUSTED; 249e1051a39Sopenharmony_ci} 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_cistatic int obj_trust(int id, X509 *x, int flags) 252e1051a39Sopenharmony_ci{ 253e1051a39Sopenharmony_ci X509_CERT_AUX *ax = x->aux; 254e1051a39Sopenharmony_ci int i; 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci if (ax && ax->reject) { 257e1051a39Sopenharmony_ci for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { 258e1051a39Sopenharmony_ci ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i); 259e1051a39Sopenharmony_ci int nid = OBJ_obj2nid(obj); 260e1051a39Sopenharmony_ci 261e1051a39Sopenharmony_ci if (nid == id || (nid == NID_anyExtendedKeyUsage && 262e1051a39Sopenharmony_ci (flags & X509_TRUST_OK_ANY_EKU))) 263e1051a39Sopenharmony_ci return X509_TRUST_REJECTED; 264e1051a39Sopenharmony_ci } 265e1051a39Sopenharmony_ci } 266e1051a39Sopenharmony_ci 267e1051a39Sopenharmony_ci if (ax && ax->trust) { 268e1051a39Sopenharmony_ci for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { 269e1051a39Sopenharmony_ci ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i); 270e1051a39Sopenharmony_ci int nid = OBJ_obj2nid(obj); 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci if (nid == id || (nid == NID_anyExtendedKeyUsage && 273e1051a39Sopenharmony_ci (flags & X509_TRUST_OK_ANY_EKU))) 274e1051a39Sopenharmony_ci return X509_TRUST_TRUSTED; 275e1051a39Sopenharmony_ci } 276e1051a39Sopenharmony_ci /* 277e1051a39Sopenharmony_ci * Reject when explicit trust EKU are set and none match. 278e1051a39Sopenharmony_ci * 279e1051a39Sopenharmony_ci * Returning untrusted is enough for for full chains that end in 280e1051a39Sopenharmony_ci * self-signed roots, because when explicit trust is specified it 281e1051a39Sopenharmony_ci * suppresses the default blanket trust of self-signed objects. 282e1051a39Sopenharmony_ci * 283e1051a39Sopenharmony_ci * But for partial chains, this is not enough, because absent a similar 284e1051a39Sopenharmony_ci * trust-self-signed policy, non matching EKUs are indistinguishable 285e1051a39Sopenharmony_ci * from lack of EKU constraints. 286e1051a39Sopenharmony_ci * 287e1051a39Sopenharmony_ci * Therefore, failure to match any trusted purpose must trigger an 288e1051a39Sopenharmony_ci * explicit reject. 289e1051a39Sopenharmony_ci */ 290e1051a39Sopenharmony_ci return X509_TRUST_REJECTED; 291e1051a39Sopenharmony_ci } 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ci if ((flags & X509_TRUST_DO_SS_COMPAT) == 0) 294e1051a39Sopenharmony_ci return X509_TRUST_UNTRUSTED; 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci /* 297e1051a39Sopenharmony_ci * Not rejected, and there is no list of accepted uses, try compat. 298e1051a39Sopenharmony_ci */ 299e1051a39Sopenharmony_ci return trust_compat(NULL, x, flags); 300e1051a39Sopenharmony_ci} 301