1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2004-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
12e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
13e1051a39Sopenharmony_ci#include <openssl/crypto.h>
14e1051a39Sopenharmony_ci#include <openssl/buffer.h>
15e1051a39Sopenharmony_ci#include <openssl/x509.h>
16e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
17e1051a39Sopenharmony_ci#include "crypto/x509.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci#include "x509_local.h"
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ci/* X509_VERIFY_PARAM functions */
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ci#define SET_HOST 0
24e1051a39Sopenharmony_ci#define ADD_HOST 1
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_cistatic char *str_copy(const char *s)
27e1051a39Sopenharmony_ci{
28e1051a39Sopenharmony_ci    return OPENSSL_strdup(s);
29e1051a39Sopenharmony_ci}
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistatic void str_free(char *s)
32e1051a39Sopenharmony_ci{
33e1051a39Sopenharmony_ci    OPENSSL_free(s);
34e1051a39Sopenharmony_ci}
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cistatic int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode,
37e1051a39Sopenharmony_ci                                    const char *name, size_t namelen)
38e1051a39Sopenharmony_ci{
39e1051a39Sopenharmony_ci    char *copy;
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci    /*
42e1051a39Sopenharmony_ci     * Refuse names with embedded NUL bytes, except perhaps as final byte.
43e1051a39Sopenharmony_ci     * XXX: Do we need to push an error onto the error stack?
44e1051a39Sopenharmony_ci     */
45e1051a39Sopenharmony_ci    if (namelen == 0 || name == NULL)
46e1051a39Sopenharmony_ci        namelen = name ? strlen(name) : 0;
47e1051a39Sopenharmony_ci    else if (name != NULL
48e1051a39Sopenharmony_ci             && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen) != NULL)
49e1051a39Sopenharmony_ci        return 0;
50e1051a39Sopenharmony_ci    if (namelen > 0 && name[namelen - 1] == '\0')
51e1051a39Sopenharmony_ci        --namelen;
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci    if (mode == SET_HOST) {
54e1051a39Sopenharmony_ci        sk_OPENSSL_STRING_pop_free(vpm->hosts, str_free);
55e1051a39Sopenharmony_ci        vpm->hosts = NULL;
56e1051a39Sopenharmony_ci    }
57e1051a39Sopenharmony_ci    if (name == NULL || namelen == 0)
58e1051a39Sopenharmony_ci        return 1;
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_ci    copy = OPENSSL_strndup(name, namelen);
61e1051a39Sopenharmony_ci    if (copy == NULL)
62e1051a39Sopenharmony_ci        return 0;
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    if (vpm->hosts == NULL &&
65e1051a39Sopenharmony_ci        (vpm->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
66e1051a39Sopenharmony_ci        OPENSSL_free(copy);
67e1051a39Sopenharmony_ci        return 0;
68e1051a39Sopenharmony_ci    }
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci    if (!sk_OPENSSL_STRING_push(vpm->hosts, copy)) {
71e1051a39Sopenharmony_ci        OPENSSL_free(copy);
72e1051a39Sopenharmony_ci        if (sk_OPENSSL_STRING_num(vpm->hosts) == 0) {
73e1051a39Sopenharmony_ci            sk_OPENSSL_STRING_free(vpm->hosts);
74e1051a39Sopenharmony_ci            vpm->hosts = NULL;
75e1051a39Sopenharmony_ci        }
76e1051a39Sopenharmony_ci        return 0;
77e1051a39Sopenharmony_ci    }
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    return 1;
80e1051a39Sopenharmony_ci}
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ciX509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    X509_VERIFY_PARAM *param;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    param = OPENSSL_zalloc(sizeof(*param));
87e1051a39Sopenharmony_ci    if (param == NULL) {
88e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
89e1051a39Sopenharmony_ci        return NULL;
90e1051a39Sopenharmony_ci    }
91e1051a39Sopenharmony_ci    param->trust = X509_TRUST_DEFAULT;
92e1051a39Sopenharmony_ci    /* param->inh_flags = X509_VP_FLAG_DEFAULT; */
93e1051a39Sopenharmony_ci    param->depth = -1;
94e1051a39Sopenharmony_ci    param->auth_level = -1; /* -1 means unset, 0 is explicit */
95e1051a39Sopenharmony_ci    return param;
96e1051a39Sopenharmony_ci}
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    if (param == NULL)
101e1051a39Sopenharmony_ci        return;
102e1051a39Sopenharmony_ci    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
103e1051a39Sopenharmony_ci    sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
104e1051a39Sopenharmony_ci    OPENSSL_free(param->peername);
105e1051a39Sopenharmony_ci    OPENSSL_free(param->email);
106e1051a39Sopenharmony_ci    OPENSSL_free(param->ip);
107e1051a39Sopenharmony_ci    OPENSSL_free(param);
108e1051a39Sopenharmony_ci}
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci/*-
111e1051a39Sopenharmony_ci * This function determines how parameters are "inherited" from one structure
112e1051a39Sopenharmony_ci * to another. There are several different ways this can happen.
113e1051a39Sopenharmony_ci *
114e1051a39Sopenharmony_ci * 1. If a child structure needs to have its values initialized from a parent
115e1051a39Sopenharmony_ci *    they are simply copied across. For example SSL_CTX copied to SSL.
116e1051a39Sopenharmony_ci * 2. If the structure should take on values only if they are currently unset.
117e1051a39Sopenharmony_ci *    For example the values in an SSL structure will take appropriate value
118e1051a39Sopenharmony_ci *    for SSL servers or clients but only if the application has not set new
119e1051a39Sopenharmony_ci *    ones.
120e1051a39Sopenharmony_ci *
121e1051a39Sopenharmony_ci * The "inh_flags" field determines how this function behaves.
122e1051a39Sopenharmony_ci *
123e1051a39Sopenharmony_ci * Normally any values which are set in the default are not copied from the
124e1051a39Sopenharmony_ci * destination and verify flags are ORed together.
125e1051a39Sopenharmony_ci *
126e1051a39Sopenharmony_ci * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
127e1051a39Sopenharmony_ci * to the destination. Effectively the values in "to" become default values
128e1051a39Sopenharmony_ci * which will be used only if nothing new is set in "from".
129e1051a39Sopenharmony_ci *
130e1051a39Sopenharmony_ci * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
131e1051a39Sopenharmony_ci * they are set or not. Flags is still Ored though.
132e1051a39Sopenharmony_ci *
133e1051a39Sopenharmony_ci * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
134e1051a39Sopenharmony_ci * of ORed.
135e1051a39Sopenharmony_ci *
136e1051a39Sopenharmony_ci * If X509_VP_FLAG_LOCKED is set then no values are copied.
137e1051a39Sopenharmony_ci *
138e1051a39Sopenharmony_ci * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
139e1051a39Sopenharmony_ci * after the next call.
140e1051a39Sopenharmony_ci */
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci/* Macro to test if a field should be copied from src to dest */
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci#define test_x509_verify_param_copy(field, def) \
145e1051a39Sopenharmony_ci    (to_overwrite || (src->field != def && (to_default || dest->field == def)))
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci/* Macro to test and copy a field if necessary */
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci#define x509_verify_param_copy(field, def) \
150e1051a39Sopenharmony_ci    if (test_x509_verify_param_copy(field, def)) \
151e1051a39Sopenharmony_ci        dest->field = src->field;
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
154e1051a39Sopenharmony_ci                              const X509_VERIFY_PARAM *src)
155e1051a39Sopenharmony_ci{
156e1051a39Sopenharmony_ci    unsigned long inh_flags;
157e1051a39Sopenharmony_ci    int to_default, to_overwrite;
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci    if (src == NULL)
160e1051a39Sopenharmony_ci        return 1;
161e1051a39Sopenharmony_ci    inh_flags = dest->inh_flags | src->inh_flags;
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ci    if ((inh_flags & X509_VP_FLAG_ONCE) != 0)
164e1051a39Sopenharmony_ci        dest->inh_flags = 0;
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_ci    if ((inh_flags & X509_VP_FLAG_LOCKED) != 0)
167e1051a39Sopenharmony_ci        return 1;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    to_default = (inh_flags & X509_VP_FLAG_DEFAULT) != 0;
170e1051a39Sopenharmony_ci    to_overwrite = (inh_flags & X509_VP_FLAG_OVERWRITE) != 0;
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    x509_verify_param_copy(purpose, 0);
173e1051a39Sopenharmony_ci    x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
174e1051a39Sopenharmony_ci    x509_verify_param_copy(depth, -1);
175e1051a39Sopenharmony_ci    x509_verify_param_copy(auth_level, -1);
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    /* If overwrite or check time not set, copy across */
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    if (to_overwrite || (dest->flags & X509_V_FLAG_USE_CHECK_TIME) == 0) {
180e1051a39Sopenharmony_ci        dest->check_time = src->check_time;
181e1051a39Sopenharmony_ci        dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
182e1051a39Sopenharmony_ci        /* Don't need to copy flag: that is done below */
183e1051a39Sopenharmony_ci    }
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci    if ((inh_flags & X509_VP_FLAG_RESET_FLAGS) != 0)
186e1051a39Sopenharmony_ci        dest->flags = 0;
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci    dest->flags |= src->flags;
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci    if (test_x509_verify_param_copy(policies, NULL)) {
191e1051a39Sopenharmony_ci        if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
192e1051a39Sopenharmony_ci            return 0;
193e1051a39Sopenharmony_ci    }
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    x509_verify_param_copy(hostflags, 0);
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    if (test_x509_verify_param_copy(hosts, NULL)) {
198e1051a39Sopenharmony_ci        sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
199e1051a39Sopenharmony_ci        dest->hosts = NULL;
200e1051a39Sopenharmony_ci        if (src->hosts != NULL) {
201e1051a39Sopenharmony_ci            dest->hosts =
202e1051a39Sopenharmony_ci                sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free);
203e1051a39Sopenharmony_ci            if (dest->hosts == NULL)
204e1051a39Sopenharmony_ci                return 0;
205e1051a39Sopenharmony_ci        }
206e1051a39Sopenharmony_ci    }
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_ci    if (test_x509_verify_param_copy(email, NULL)) {
209e1051a39Sopenharmony_ci        if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen))
210e1051a39Sopenharmony_ci            return 0;
211e1051a39Sopenharmony_ci    }
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci    if (test_x509_verify_param_copy(ip, NULL)) {
214e1051a39Sopenharmony_ci        if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen))
215e1051a39Sopenharmony_ci            return 0;
216e1051a39Sopenharmony_ci    }
217e1051a39Sopenharmony_ci
218e1051a39Sopenharmony_ci    return 1;
219e1051a39Sopenharmony_ci}
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
222e1051a39Sopenharmony_ci                           const X509_VERIFY_PARAM *from)
223e1051a39Sopenharmony_ci{
224e1051a39Sopenharmony_ci    unsigned long save_flags;
225e1051a39Sopenharmony_ci    int ret;
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci    if (to == NULL) {
228e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
229e1051a39Sopenharmony_ci        return 0;
230e1051a39Sopenharmony_ci    }
231e1051a39Sopenharmony_ci    save_flags = to->inh_flags;
232e1051a39Sopenharmony_ci    to->inh_flags |= X509_VP_FLAG_DEFAULT;
233e1051a39Sopenharmony_ci    ret = X509_VERIFY_PARAM_inherit(to, from);
234e1051a39Sopenharmony_ci    to->inh_flags = save_flags;
235e1051a39Sopenharmony_ci    return ret;
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_cistatic int int_x509_param_set1(char **pdest, size_t *pdestlen,
239e1051a39Sopenharmony_ci                               const char *src, size_t srclen)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    char *tmp;
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ci    if (src != NULL) {
244e1051a39Sopenharmony_ci        if (srclen == 0)
245e1051a39Sopenharmony_ci            srclen = strlen(src);
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_ci        tmp = OPENSSL_malloc(srclen + 1);
248e1051a39Sopenharmony_ci        if (tmp == NULL)
249e1051a39Sopenharmony_ci            return 0;
250e1051a39Sopenharmony_ci        memcpy(tmp, src, srclen);
251e1051a39Sopenharmony_ci        tmp[srclen] = '\0'; /* enforce NUL termination */
252e1051a39Sopenharmony_ci    } else {
253e1051a39Sopenharmony_ci        tmp = NULL;
254e1051a39Sopenharmony_ci        srclen = 0;
255e1051a39Sopenharmony_ci    }
256e1051a39Sopenharmony_ci    OPENSSL_free(*pdest);
257e1051a39Sopenharmony_ci    *pdest = tmp;
258e1051a39Sopenharmony_ci    if (pdestlen != NULL)
259e1051a39Sopenharmony_ci        *pdestlen = srclen;
260e1051a39Sopenharmony_ci    return 1;
261e1051a39Sopenharmony_ci}
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
264e1051a39Sopenharmony_ci{
265e1051a39Sopenharmony_ci    OPENSSL_free(param->name);
266e1051a39Sopenharmony_ci    param->name = OPENSSL_strdup(name);
267e1051a39Sopenharmony_ci    return param->name != NULL;
268e1051a39Sopenharmony_ci}
269e1051a39Sopenharmony_ci
270e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
271e1051a39Sopenharmony_ci{
272e1051a39Sopenharmony_ci    param->flags |= flags;
273e1051a39Sopenharmony_ci    if ((flags & X509_V_FLAG_POLICY_MASK) != 0)
274e1051a39Sopenharmony_ci        param->flags |= X509_V_FLAG_POLICY_CHECK;
275e1051a39Sopenharmony_ci    return 1;
276e1051a39Sopenharmony_ci}
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
279e1051a39Sopenharmony_ci                                  unsigned long flags)
280e1051a39Sopenharmony_ci{
281e1051a39Sopenharmony_ci    param->flags &= ~flags;
282e1051a39Sopenharmony_ci    return 1;
283e1051a39Sopenharmony_ci}
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ciunsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param)
286e1051a39Sopenharmony_ci{
287e1051a39Sopenharmony_ci    return param->flags;
288e1051a39Sopenharmony_ci}
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ciuint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param)
291e1051a39Sopenharmony_ci{
292e1051a39Sopenharmony_ci    return param->inh_flags;
293e1051a39Sopenharmony_ci}
294e1051a39Sopenharmony_ci
295e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags)
296e1051a39Sopenharmony_ci{
297e1051a39Sopenharmony_ci    param->inh_flags = flags;
298e1051a39Sopenharmony_ci    return 1;
299e1051a39Sopenharmony_ci}
300e1051a39Sopenharmony_ci
301e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
302e1051a39Sopenharmony_ci{
303e1051a39Sopenharmony_ci    return X509_PURPOSE_set(&param->purpose, purpose);
304e1051a39Sopenharmony_ci}
305e1051a39Sopenharmony_ci
306e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
307e1051a39Sopenharmony_ci{
308e1051a39Sopenharmony_ci    return X509_TRUST_set(&param->trust, trust);
309e1051a39Sopenharmony_ci}
310e1051a39Sopenharmony_ci
311e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
312e1051a39Sopenharmony_ci{
313e1051a39Sopenharmony_ci    param->depth = depth;
314e1051a39Sopenharmony_ci}
315e1051a39Sopenharmony_ci
316e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
317e1051a39Sopenharmony_ci{
318e1051a39Sopenharmony_ci    param->auth_level = auth_level;
319e1051a39Sopenharmony_ci}
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_citime_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
322e1051a39Sopenharmony_ci{
323e1051a39Sopenharmony_ci    return param->check_time;
324e1051a39Sopenharmony_ci}
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
327e1051a39Sopenharmony_ci{
328e1051a39Sopenharmony_ci    param->check_time = t;
329e1051a39Sopenharmony_ci    param->flags |= X509_V_FLAG_USE_CHECK_TIME;
330e1051a39Sopenharmony_ci}
331e1051a39Sopenharmony_ci
332e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
333e1051a39Sopenharmony_ci                                  ASN1_OBJECT *policy)
334e1051a39Sopenharmony_ci{
335e1051a39Sopenharmony_ci    if (param->policies == NULL) {
336e1051a39Sopenharmony_ci        param->policies = sk_ASN1_OBJECT_new_null();
337e1051a39Sopenharmony_ci        if (param->policies == NULL)
338e1051a39Sopenharmony_ci            return 0;
339e1051a39Sopenharmony_ci    }
340e1051a39Sopenharmony_ci    return sk_ASN1_OBJECT_push(param->policies, policy);
341e1051a39Sopenharmony_ci}
342e1051a39Sopenharmony_ci
343e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
344e1051a39Sopenharmony_ci                                    STACK_OF(ASN1_OBJECT) *policies)
345e1051a39Sopenharmony_ci{
346e1051a39Sopenharmony_ci    int i;
347e1051a39Sopenharmony_ci    ASN1_OBJECT *oid, *doid;
348e1051a39Sopenharmony_ci
349e1051a39Sopenharmony_ci    if (param == NULL) {
350e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
351e1051a39Sopenharmony_ci        return 0;
352e1051a39Sopenharmony_ci    }
353e1051a39Sopenharmony_ci    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
354e1051a39Sopenharmony_ci
355e1051a39Sopenharmony_ci    if (policies == NULL) {
356e1051a39Sopenharmony_ci        param->policies = NULL;
357e1051a39Sopenharmony_ci        return 1;
358e1051a39Sopenharmony_ci    }
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci    param->policies = sk_ASN1_OBJECT_new_null();
361e1051a39Sopenharmony_ci    if (param->policies == NULL)
362e1051a39Sopenharmony_ci        return 0;
363e1051a39Sopenharmony_ci
364e1051a39Sopenharmony_ci    for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
365e1051a39Sopenharmony_ci        oid = sk_ASN1_OBJECT_value(policies, i);
366e1051a39Sopenharmony_ci        doid = OBJ_dup(oid);
367e1051a39Sopenharmony_ci        if (doid == NULL)
368e1051a39Sopenharmony_ci            return 0;
369e1051a39Sopenharmony_ci        if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
370e1051a39Sopenharmony_ci            ASN1_OBJECT_free(doid);
371e1051a39Sopenharmony_ci            return 0;
372e1051a39Sopenharmony_ci        }
373e1051a39Sopenharmony_ci    }
374e1051a39Sopenharmony_ci    param->flags |= X509_V_FLAG_POLICY_CHECK;
375e1051a39Sopenharmony_ci    return 1;
376e1051a39Sopenharmony_ci}
377e1051a39Sopenharmony_ci
378e1051a39Sopenharmony_cichar *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx)
379e1051a39Sopenharmony_ci{
380e1051a39Sopenharmony_ci    return sk_OPENSSL_STRING_value(param->hosts, idx);
381e1051a39Sopenharmony_ci}
382e1051a39Sopenharmony_ci
383e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
384e1051a39Sopenharmony_ci                                const char *name, size_t namelen)
385e1051a39Sopenharmony_ci{
386e1051a39Sopenharmony_ci    return int_x509_param_set_hosts(param, SET_HOST, name, namelen);
387e1051a39Sopenharmony_ci}
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
390e1051a39Sopenharmony_ci                                const char *name, size_t namelen)
391e1051a39Sopenharmony_ci{
392e1051a39Sopenharmony_ci    return int_x509_param_set_hosts(param, ADD_HOST, name, namelen);
393e1051a39Sopenharmony_ci}
394e1051a39Sopenharmony_ci
395e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
396e1051a39Sopenharmony_ci                                     unsigned int flags)
397e1051a39Sopenharmony_ci{
398e1051a39Sopenharmony_ci    param->hostflags = flags;
399e1051a39Sopenharmony_ci}
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ciunsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param)
402e1051a39Sopenharmony_ci{
403e1051a39Sopenharmony_ci    return param->hostflags;
404e1051a39Sopenharmony_ci}
405e1051a39Sopenharmony_ci
406e1051a39Sopenharmony_cichar *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param)
407e1051a39Sopenharmony_ci{
408e1051a39Sopenharmony_ci    return param->peername;
409e1051a39Sopenharmony_ci}
410e1051a39Sopenharmony_ci
411e1051a39Sopenharmony_ci/*
412e1051a39Sopenharmony_ci * Move peername from one param structure to another, freeing any name present
413e1051a39Sopenharmony_ci * at the target.  If the source is a NULL parameter structure, free and zero
414e1051a39Sopenharmony_ci * the target peername.
415e1051a39Sopenharmony_ci */
416e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
417e1051a39Sopenharmony_ci                                     X509_VERIFY_PARAM *from)
418e1051a39Sopenharmony_ci{
419e1051a39Sopenharmony_ci    char *peername = (from != NULL) ? from->peername : NULL;
420e1051a39Sopenharmony_ci
421e1051a39Sopenharmony_ci    if (to->peername != peername) {
422e1051a39Sopenharmony_ci        OPENSSL_free(to->peername);
423e1051a39Sopenharmony_ci        to->peername = peername;
424e1051a39Sopenharmony_ci    }
425e1051a39Sopenharmony_ci    if (from != NULL)
426e1051a39Sopenharmony_ci        from->peername = NULL;
427e1051a39Sopenharmony_ci}
428e1051a39Sopenharmony_ci
429e1051a39Sopenharmony_cichar *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param)
430e1051a39Sopenharmony_ci{
431e1051a39Sopenharmony_ci    return param->email;
432e1051a39Sopenharmony_ci}
433e1051a39Sopenharmony_ci
434e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
435e1051a39Sopenharmony_ci                                 const char *email, size_t emaillen)
436e1051a39Sopenharmony_ci{
437e1051a39Sopenharmony_ci    return int_x509_param_set1(&param->email, &param->emaillen,
438e1051a39Sopenharmony_ci                               email, emaillen);
439e1051a39Sopenharmony_ci}
440e1051a39Sopenharmony_ci
441e1051a39Sopenharmony_cistatic unsigned char
442e1051a39Sopenharmony_ci*int_X509_VERIFY_PARAM_get0_ip(X509_VERIFY_PARAM *param, size_t *plen)
443e1051a39Sopenharmony_ci{
444e1051a39Sopenharmony_ci    if (param == NULL || param->ip == NULL) {
445e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
446e1051a39Sopenharmony_ci        return NULL;
447e1051a39Sopenharmony_ci    }
448e1051a39Sopenharmony_ci    if (plen != NULL)
449e1051a39Sopenharmony_ci        *plen = param->iplen;
450e1051a39Sopenharmony_ci    return param->ip;
451e1051a39Sopenharmony_ci}
452e1051a39Sopenharmony_ci
453e1051a39Sopenharmony_cichar *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param)
454e1051a39Sopenharmony_ci{
455e1051a39Sopenharmony_ci    size_t iplen;
456e1051a39Sopenharmony_ci    unsigned char *ip = int_X509_VERIFY_PARAM_get0_ip(param, &iplen);
457e1051a39Sopenharmony_ci
458e1051a39Sopenharmony_ci    return ip == NULL ? NULL : ossl_ipaddr_to_asc(ip, iplen);
459e1051a39Sopenharmony_ci}
460e1051a39Sopenharmony_ci
461e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
462e1051a39Sopenharmony_ci                              const unsigned char *ip, size_t iplen)
463e1051a39Sopenharmony_ci{
464e1051a39Sopenharmony_ci    if (iplen != 0 && iplen != 4 && iplen != 16) {
465e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT);
466e1051a39Sopenharmony_ci        return 0;
467e1051a39Sopenharmony_ci    }
468e1051a39Sopenharmony_ci    return int_x509_param_set1((char **)&param->ip, &param->iplen,
469e1051a39Sopenharmony_ci                               (char *)ip, iplen);
470e1051a39Sopenharmony_ci}
471e1051a39Sopenharmony_ci
472e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
473e1051a39Sopenharmony_ci{
474e1051a39Sopenharmony_ci    unsigned char ipout[16];
475e1051a39Sopenharmony_ci    size_t iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc);
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci    if (iplen == 0)
478e1051a39Sopenharmony_ci        return 0;
479e1051a39Sopenharmony_ci    return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
480e1051a39Sopenharmony_ci}
481e1051a39Sopenharmony_ci
482e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
483e1051a39Sopenharmony_ci{
484e1051a39Sopenharmony_ci    return param->depth;
485e1051a39Sopenharmony_ci}
486e1051a39Sopenharmony_ci
487e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param)
488e1051a39Sopenharmony_ci{
489e1051a39Sopenharmony_ci    return param->auth_level;
490e1051a39Sopenharmony_ci}
491e1051a39Sopenharmony_ci
492e1051a39Sopenharmony_ciconst char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
493e1051a39Sopenharmony_ci{
494e1051a39Sopenharmony_ci    return param->name;
495e1051a39Sopenharmony_ci}
496e1051a39Sopenharmony_ci
497e1051a39Sopenharmony_ci#define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_ci/*
500e1051a39Sopenharmony_ci * Default verify parameters: these are used for various applications and can
501e1051a39Sopenharmony_ci * be overridden by the user specified table. NB: the 'name' field *must* be
502e1051a39Sopenharmony_ci * in alphabetical order because it will be searched using OBJ_search.
503e1051a39Sopenharmony_ci */
504e1051a39Sopenharmony_ci
505e1051a39Sopenharmony_cistatic const X509_VERIFY_PARAM default_table[] = {
506e1051a39Sopenharmony_ci    {
507e1051a39Sopenharmony_ci     "default",                 /* X509 default parameters */
508e1051a39Sopenharmony_ci     0,                         /* check time to use */
509e1051a39Sopenharmony_ci     0,                         /* inheritance flags */
510e1051a39Sopenharmony_ci     X509_V_FLAG_TRUSTED_FIRST, /* flags */
511e1051a39Sopenharmony_ci     0,                         /* purpose */
512e1051a39Sopenharmony_ci     0,                         /* trust */
513e1051a39Sopenharmony_ci     100,                       /* depth */
514e1051a39Sopenharmony_ci     -1,                        /* auth_level */
515e1051a39Sopenharmony_ci     NULL,                      /* policies */
516e1051a39Sopenharmony_ci     vpm_empty_id},
517e1051a39Sopenharmony_ci    {
518e1051a39Sopenharmony_ci     "pkcs7",                   /* S/MIME sign parameters */
519e1051a39Sopenharmony_ci     0,                         /* check time to use */
520e1051a39Sopenharmony_ci     0,                         /* inheritance flags */
521e1051a39Sopenharmony_ci     0,                         /* flags */
522e1051a39Sopenharmony_ci     X509_PURPOSE_SMIME_SIGN,   /* purpose */
523e1051a39Sopenharmony_ci     X509_TRUST_EMAIL,          /* trust */
524e1051a39Sopenharmony_ci     -1,                        /* depth */
525e1051a39Sopenharmony_ci     -1,                        /* auth_level */
526e1051a39Sopenharmony_ci     NULL,                      /* policies */
527e1051a39Sopenharmony_ci     vpm_empty_id},
528e1051a39Sopenharmony_ci    {
529e1051a39Sopenharmony_ci     "smime_sign",              /* S/MIME sign parameters */
530e1051a39Sopenharmony_ci     0,                         /* check time to use */
531e1051a39Sopenharmony_ci     0,                         /* inheritance flags */
532e1051a39Sopenharmony_ci     0,                         /* flags */
533e1051a39Sopenharmony_ci     X509_PURPOSE_SMIME_SIGN,   /* purpose */
534e1051a39Sopenharmony_ci     X509_TRUST_EMAIL,          /* trust */
535e1051a39Sopenharmony_ci     -1,                        /* depth */
536e1051a39Sopenharmony_ci     -1,                        /* auth_level */
537e1051a39Sopenharmony_ci     NULL,                      /* policies */
538e1051a39Sopenharmony_ci     vpm_empty_id},
539e1051a39Sopenharmony_ci    {
540e1051a39Sopenharmony_ci     "ssl_client",              /* SSL/TLS client parameters */
541e1051a39Sopenharmony_ci     0,                         /* check time to use */
542e1051a39Sopenharmony_ci     0,                         /* inheritance flags */
543e1051a39Sopenharmony_ci     0,                         /* flags */
544e1051a39Sopenharmony_ci     X509_PURPOSE_SSL_CLIENT,   /* purpose */
545e1051a39Sopenharmony_ci     X509_TRUST_SSL_CLIENT,     /* trust */
546e1051a39Sopenharmony_ci     -1,                        /* depth */
547e1051a39Sopenharmony_ci     -1,                        /* auth_level */
548e1051a39Sopenharmony_ci     NULL,                      /* policies */
549e1051a39Sopenharmony_ci     vpm_empty_id},
550e1051a39Sopenharmony_ci    {
551e1051a39Sopenharmony_ci     "ssl_server",              /* SSL/TLS server parameters */
552e1051a39Sopenharmony_ci     0,                         /* check time to use */
553e1051a39Sopenharmony_ci     0,                         /* inheritance flags */
554e1051a39Sopenharmony_ci     0,                         /* flags */
555e1051a39Sopenharmony_ci     X509_PURPOSE_SSL_SERVER,   /* purpose */
556e1051a39Sopenharmony_ci     X509_TRUST_SSL_SERVER,     /* trust */
557e1051a39Sopenharmony_ci     -1,                        /* depth */
558e1051a39Sopenharmony_ci     -1,                        /* auth_level */
559e1051a39Sopenharmony_ci     NULL,                      /* policies */
560e1051a39Sopenharmony_ci     vpm_empty_id}
561e1051a39Sopenharmony_ci};
562e1051a39Sopenharmony_ci
563e1051a39Sopenharmony_cistatic STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
564e1051a39Sopenharmony_ci
565e1051a39Sopenharmony_cistatic int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b)
566e1051a39Sopenharmony_ci{
567e1051a39Sopenharmony_ci    return strcmp(a->name, b->name);
568e1051a39Sopenharmony_ci}
569e1051a39Sopenharmony_ci
570e1051a39Sopenharmony_ciDECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
571e1051a39Sopenharmony_ciIMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
572e1051a39Sopenharmony_ci
573e1051a39Sopenharmony_cistatic int param_cmp(const X509_VERIFY_PARAM *const *a,
574e1051a39Sopenharmony_ci                     const X509_VERIFY_PARAM *const *b)
575e1051a39Sopenharmony_ci{
576e1051a39Sopenharmony_ci    return strcmp((*a)->name, (*b)->name);
577e1051a39Sopenharmony_ci}
578e1051a39Sopenharmony_ci
579e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
580e1051a39Sopenharmony_ci{
581e1051a39Sopenharmony_ci    int idx;
582e1051a39Sopenharmony_ci    X509_VERIFY_PARAM *ptmp;
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci    if (param_table == NULL) {
585e1051a39Sopenharmony_ci        param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
586e1051a39Sopenharmony_ci        if (param_table == NULL)
587e1051a39Sopenharmony_ci            return 0;
588e1051a39Sopenharmony_ci    } else {
589e1051a39Sopenharmony_ci        idx = sk_X509_VERIFY_PARAM_find(param_table, param);
590e1051a39Sopenharmony_ci        if (idx >= 0) {
591e1051a39Sopenharmony_ci            ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx);
592e1051a39Sopenharmony_ci            X509_VERIFY_PARAM_free(ptmp);
593e1051a39Sopenharmony_ci        }
594e1051a39Sopenharmony_ci    }
595e1051a39Sopenharmony_ci    return sk_X509_VERIFY_PARAM_push(param_table, param);
596e1051a39Sopenharmony_ci}
597e1051a39Sopenharmony_ci
598e1051a39Sopenharmony_ciint X509_VERIFY_PARAM_get_count(void)
599e1051a39Sopenharmony_ci{
600e1051a39Sopenharmony_ci    int num = OSSL_NELEM(default_table);
601e1051a39Sopenharmony_ci
602e1051a39Sopenharmony_ci    if (param_table != NULL)
603e1051a39Sopenharmony_ci        num += sk_X509_VERIFY_PARAM_num(param_table);
604e1051a39Sopenharmony_ci    return num;
605e1051a39Sopenharmony_ci}
606e1051a39Sopenharmony_ci
607e1051a39Sopenharmony_ciconst X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
608e1051a39Sopenharmony_ci{
609e1051a39Sopenharmony_ci    int num = OSSL_NELEM(default_table);
610e1051a39Sopenharmony_ci
611e1051a39Sopenharmony_ci    if (id < num)
612e1051a39Sopenharmony_ci        return default_table + id;
613e1051a39Sopenharmony_ci    return sk_X509_VERIFY_PARAM_value(param_table, id - num);
614e1051a39Sopenharmony_ci}
615e1051a39Sopenharmony_ci
616e1051a39Sopenharmony_ciconst X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
617e1051a39Sopenharmony_ci{
618e1051a39Sopenharmony_ci    int idx;
619e1051a39Sopenharmony_ci    X509_VERIFY_PARAM pm;
620e1051a39Sopenharmony_ci
621e1051a39Sopenharmony_ci    pm.name = (char *)name;
622e1051a39Sopenharmony_ci    if (param_table != NULL) {
623e1051a39Sopenharmony_ci        idx = sk_X509_VERIFY_PARAM_find(param_table, &pm);
624e1051a39Sopenharmony_ci        if (idx >= 0)
625e1051a39Sopenharmony_ci            return sk_X509_VERIFY_PARAM_value(param_table, idx);
626e1051a39Sopenharmony_ci    }
627e1051a39Sopenharmony_ci    return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table));
628e1051a39Sopenharmony_ci}
629e1051a39Sopenharmony_ci
630e1051a39Sopenharmony_civoid X509_VERIFY_PARAM_table_cleanup(void)
631e1051a39Sopenharmony_ci{
632e1051a39Sopenharmony_ci    sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
633e1051a39Sopenharmony_ci    param_table = NULL;
634e1051a39Sopenharmony_ci}
635