*David von Oheimb*
+ * `X509_PURPOSE_add()` has been modified
+ to take `sname` instead of `id` as the primary purpose identifier.
+ For its convenient use, `X509_PURPOSE_get_unused_id()` has been added.
+
+ This work was sponsored by Siemens AG.
+
+ *David von Oheimb*
+
* Optionally allow the FIPS provider to use the `JITTER` entropy source.
Note that using this option will require the resulting FIPS provider
to undergo entropy source validation [ESV] by the [CMVP], without this
policy path length already defined
X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY:159:\
policy when proxy language requires no policy
+X509V3_R_PURPOSE_NOT_UNIQUE:173:purpose not unique
X509V3_R_SECTION_NOT_FOUND:150:section not found
X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS:122:unable to get issuer details
X509V3_R_UNABLE_TO_GET_ISSUER_KEYID:123:unable to get issuer keyid
static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
static void xptable_free(X509_PURPOSE *p);
+/* note that the id must be unique and for the standard entries == idx + 1 */
static X509_PURPOSE xstandard[] = {
{X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
check_purpose_ssl_client, "SSL client", "sslclient", NULL},
#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard)
+/* the id must be unique, but there may be gaps and maybe table is not sorted */
static STACK_OF(X509_PURPOSE) *xptable = NULL;
static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
}
+/* find smallest identifier not yet taken - note there might be gaps */
+int X509_PURPOSE_get_unused_id(ossl_unused OSSL_LIB_CTX *libctx)
+{
+ int id = X509_PURPOSE_MAX + 1;
+
+ while (X509_PURPOSE_get_by_id(id) != -1)
+ id++;
+ return id; /* is guaranteed to be unique and > X509_PURPOSE_MAX and != 0 */
+}
+
X509_PURPOSE *X509_PURPOSE_get0(int idx)
{
if (idx < 0)
return idx + X509_PURPOSE_COUNT;
}
+/*
+ * Add purpose entry identified by |sname|. |id| must be >= X509_PURPOSE_MIN.
+ * May also be used to modify existing entry, including changing its id.
+ */
int X509_PURPOSE_add(int id, int trust, int flags,
int (*ck) (const X509_PURPOSE *, const X509 *, int),
const char *name, const char *sname, void *arg)
{
+ int old_id = 0;
int idx;
X509_PURPOSE *ptmp;
+ if (id < X509_PURPOSE_MIN) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE);
+ return 0;
+ }
+ if (trust < X509_TRUST_DEFAULT || name == NULL || sname == NULL || ck == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
/* This is set according to what we change: application can't set it */
flags &= ~X509_PURPOSE_DYNAMIC;
/* This will always be set for application modified trust entries */
flags |= X509_PURPOSE_DYNAMIC_NAME;
+
/* Get existing entry if any */
- idx = X509_PURPOSE_get_by_id(id);
- /* Need a new entry */
- if (idx == -1) {
+ idx = X509_PURPOSE_get_by_sname(sname);
+ if (idx == -1) { /* Need a new entry */
+ if (X509_PURPOSE_get_by_id(id) != -1) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE);
+ return 0;
+ }
if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL)
return 0;
ptmp->flags = X509_PURPOSE_DYNAMIC;
} else {
ptmp = X509_PURPOSE_get0(idx);
+ old_id = ptmp->purpose;
+ if (id != old_id && X509_PURPOSE_get_by_id(id) != -1) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE);
+ return 0;
+ }
}
/* OPENSSL_free existing name if dynamic */
ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
goto err;
}
+ } else if (id != old_id) {
+ /* on changing existing entry id, make sure to reset 'sorted' */
+ (void)sk_X509_PURPOSE_set(xptable, idx, ptmp);
}
return 1;
err:
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_VALUE), "bad value"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "bn dec2bn error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR),
- "bn to asn1 integer error"},
+ "bn to asn1 integer error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "dirname error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET),
- "distpoint already set"},
+ "distpoint already set"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID),
- "duplicate zone id"},
+ "duplicate zone id"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EMPTY_KEY_USAGE), "empty key usage"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE),
- "error converting zone"},
+ "error converting zone"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION),
- "error creating extension"},
+ "error creating extension"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION),
- "error in extension"},
+ "error in extension"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME),
- "expected a section name"},
+ "expected a section name"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS),
- "extension exists"},
+ "extension exists"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR),
- "extension name error"},
+ "extension name error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND),
- "extension not found"},
+ "extension not found"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED),
- "extension setting not supported"},
+ "extension setting not supported"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR),
- "extension value error"},
+ "extension value error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION),
- "illegal empty extension"},
+ "illegal empty extension"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG),
- "incorrect policy syntax tag"},
+ "incorrect policy syntax tag"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER),
- "invalid asnumber"},
+ "invalid asnumber"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING),
- "invalid boolean string"},
+ "invalid boolean string"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_CERTIFICATE),
- "invalid certificate"},
+ "invalid certificate"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EMPTY_NAME),
- "invalid empty name"},
+ "invalid empty name"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING),
- "invalid extension string"},
+ "invalid extension string"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE),
- "invalid inheritance"},
+ "invalid inheritance"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS),
- "invalid ipaddress"},
+ "invalid ipaddress"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS),
- "invalid multiple rdns"},
+ "invalid multiple rdns"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "invalid name"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT),
- "invalid null argument"},
+ "invalid null argument"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE),
- "invalid null value"},
+ "invalid null value"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "invalid number"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "invalid numbers"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER),
- "invalid object identifier"},
+ "invalid object identifier"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "invalid option"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER),
- "invalid policy identifier"},
+ "invalid policy identifier"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING),
- "invalid proxy policy setting"},
+ "invalid proxy policy setting"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "invalid purpose"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "invalid safi"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "invalid section"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "invalid syntax"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR),
- "issuer decode error"},
+ "issuer decode error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS),
- "need organization and numbers"},
+ "need organization and numbers"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEGATIVE_PATHLEN),
- "negative pathlen"},
+ "negative pathlen"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE),
- "no config database"},
+ "no config database"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE),
- "no issuer certificate"},
+ "no issuer certificate"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS),
- "no issuer details"},
+ "no issuer details"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER),
- "no policy identifier"},
+ "no policy identifier"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED),
- "no proxy cert policy language defined"},
+ "no proxy cert policy language defined"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "no public key"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS),
- "no subject details"},
+ "no subject details"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED),
- "operation not defined"},
+ "operation not defined"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "othername error"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED),
- "policy language already defined"},
+ "policy language already defined"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH),
- "policy path length"},
+ "policy path length"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED),
- "policy path length already defined"},
+ "policy path length already defined"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY),
- "policy when proxy language requires no policy"},
+ "policy when proxy language requires no policy"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_PURPOSE_NOT_UNIQUE),
+ "purpose not unique"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND),
- "section not found"},
+ "section not found"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS),
- "unable to get issuer details"},
+ "unable to get issuer details"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID),
- "unable to get issuer keyid"},
+ "unable to get issuer keyid"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT),
- "unknown bit string argument"},
+ "unknown bit string argument"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION),
- "unknown extension"},
+ "unknown extension"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME),
- "unknown extension name"},
+ "unknown extension name"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "unknown option"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_VALUE), "unknown value"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION),
- "unsupported option"},
+ "unsupported option"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE),
- "unsupported type"},
+ "unsupported type"},
{ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "user too long"},
{0, NULL}
};
=head1 NAME
-X509_check_purpose - Check the purpose of a certificate
+X509_check_purpose,
+X509_PURPOSE_get_count,
+X509_PURPOSE_get_unused_id,
+X509_PURPOSE_get_by_sname,
+X509_PURPOSE_get_by_id,
+X509_PURPOSE_add,
+X509_PURPOSE_cleanup,
+X509_PURPOSE_get0,
+X509_PURPOSE_get_id,
+X509_PURPOSE_get0_name,
+X509_PURPOSE_get0_sname,
+X509_PURPOSE_get_trust,
+X509_PURPOSE_set - functions related to checking the purpose of a certificate
=head1 SYNOPSIS
int X509_check_purpose(X509 *x, int id, int ca);
+ int X509_PURPOSE_get_count(void);
+ int X509_PURPOSE_get_unused_id(OSSL_LIB_CTX *libctx);
+ int X509_PURPOSE_get_by_sname(const char *sname);
+ int X509_PURPOSE_get_by_id(int id);
+ int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck) (const X509_PURPOSE *, const X509 *, int),
+ const char *name, const char *sname, void *arg);
+ void X509_PURPOSE_cleanup(void);
+
+ X509_PURPOSE *X509_PURPOSE_get0(int idx);
+ int X509_PURPOSE_get_id(const X509_PURPOSE *);
+ char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp);
+ char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp);
+ int X509_PURPOSE_get_trust(const X509_PURPOSE *xp);
+ int X509_PURPOSE_set(int *p, int purpose);
+
=head1 DESCRIPTION
-This function checks if certificate I<x> was created with the purpose
+X509_check_purpose() checks if certificate I<x> was created with the purpose
represented by I<id>. If I<ca> is nonzero, then certificate I<x> is
checked to determine if it's a possible CA with various levels of certainty
possibly returned. The certificate I<x> must be a complete certificate
The checks performed take into account the X.509 extensions
keyUsage, extendedKeyUsage, and basicConstraints.
+X509_PURPOSE_get_count() returns the number of currently defined purposes.
+
+X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used.
+The I<libctx> parameter should be used to provide the library context.
+It is currently ignored as the purpose mapping table is global.
+
+X509_PURPOSE_get_by_sname() returns the index of
+the purpose with the given short name or -1 if not found.
+
+X509_PURPOSE_get_by_id() returns the index of
+the purpose with the given id or -1 if not found.
+
+X509_PURPOSE_add() adds or modifies a purpose entry identified by I<sname>.
+Unless the id stays the same for an existing entry, I<id> must be fresh,
+which can be achieved by using the result of X509_PURPOSE_get_unused_id().
+The function also sets in the entry the trust id I<trust>, the given I<flags>,
+the purpose (long) name I<name>, the short name I<sname>, the purpose checking
+funktion I<ck> of type B<int (*) (const X509_PURPOSE *, const X509 *, int)>,
+and its user data I<arg> which may be retrieved via the B<X509_PURPOSE> pointer.
+
+X509_PURPOSE_cleanup() removes all purposes that are not pre-defined.
+
+X509_PURPOSE_get0() returns an B<X509_PURPOSE> pointer or NULL on error.
+
+X509_PURPOSE_get_id() returns the id of the given B<X509_PURPOSE> structure.
+
+X509_PURPOSE_get0_name() returns the (long) name of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_get0_sname() returns the short name of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_get_trust() returns the trust id of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_set() assigns the given I<purpose> id to the location pointed at by
+I<p>.
+This resets to the any purpose if I<purpose> is B<X509_PURPOSE_DEFAULT_ANY>.
+
=head1 RETURN VALUES
+X509_check_purpose() returns the following values.
For non-CA checks
=over 4
=back
+X509_PURPOSE_get_count() returns the number of currently defined purposes.
+
+X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used.
+
+X509_PURPOSE_get_by_sname() returns the index of
+the purpose with the given short name or -1 if not found.
+
+X509_PURPOSE_get_by_id() returns the index of
+the purpose with the given id or -1 if not found.
+
+int X509_PURPOSE_add() returns 1 on success, 0 on error.
+
+X509_PURPOSE_cleanup() does not return anything.
+
+X509_PURPOSE_get0() returns an B<X509_PURPOSE> pointer or NULL on error.
+
+X509_PURPOSE_get_id() returns the id of the given B<X509_PURPOSE> structure.
+
+X509_PURPOSE_get0_name() returns the (long) name of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_get0_sname() returns the short name of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_get_trust() returns the trust id of the given B<X509_PURPOSE>.
+
+X509_PURPOSE_set() returns 1 on success, 0 on error.
+
+=head1 BUGS
+
+The X509_PURPOSE implementation so far is not thread-safe.
+There may be race conditions retrieving purpose information while
+X509_PURPOSE_add() or X509_PURPOSE_cleanup(void) is being called.
+
+=head1 HISTORY
+
+X509_PURPOSE_get_unused_id() was added in OpensSL 3.5.
+
=head1 COPYRIGHT
-Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this
file except in compliance with the License. You can obtain a copy in the file
LICENSE in the source distribution or at L<https://www.openssl.org/source/license.html>.
generate_stack_macros("X509_PURPOSE");
-}
-
# define X509_PURPOSE_DEFAULT_ANY 0
# define X509_PURPOSE_SSL_CLIENT 1
# define X509_PURPOSE_SSL_SERVER 2
int X509_check_ca(X509 *x);
int X509_check_purpose(X509 *x, int id, int ca);
int X509_supported_extension(X509_EXTENSION *ex);
-int X509_PURPOSE_set(int *p, int purpose);
int X509_check_issued(X509 *issuer, X509 *subject);
int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid);
void X509_set_proxy_flag(X509 *x);
const ASN1_INTEGER *X509_get0_authority_serial(X509 *x);
int X509_PURPOSE_get_count(void);
-X509_PURPOSE *X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_unused_id(OSSL_LIB_CTX *libctx);
int X509_PURPOSE_get_by_sname(const char *sname);
int X509_PURPOSE_get_by_id(int id);
int X509_PURPOSE_add(int id, int trust, int flags,
int (*ck) (const X509_PURPOSE *, const X509 *, int),
const char *name, const char *sname, void *arg);
+void X509_PURPOSE_cleanup(void);
+
+X509_PURPOSE *X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_id(const X509_PURPOSE *);
char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp);
char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp);
int X509_PURPOSE_get_trust(const X509_PURPOSE *xp);
-void X509_PURPOSE_cleanup(void);
-int X509_PURPOSE_get_id(const X509_PURPOSE *);
+int X509_PURPOSE_set(int *p, int purpose);
STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x);
+
/* Flags for X509_check_* functions */
/*
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
# define X509V3_R_POLICY_PATH_LENGTH 156
# define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 157
# define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159
+# define X509V3_R_PURPOSE_NOT_UNIQUE 173
# define X509V3_R_SECTION_NOT_FOUND 150
# define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122
# define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123
return good;
}
+static int ck_purp(ossl_unused const X509_PURPOSE *purpose,
+ ossl_unused const X509 *x, int ca)
+{
+ return 1;
+}
+
+static int tests_X509_PURPOSE(void)
+{
+ OSSL_LIB_CTX *libctx = NULL;
+ int id, idx, *p;
+ X509_PURPOSE *xp;
+
+#undef LN
+#define LN "LN_test"
+#undef SN
+#define SN "SN_test"
+#undef ARGS
+#define ARGS(id, sn) id, X509_TRUST_MAX, 0, ck_purp, LN, sn, NULL
+ return TEST_int_gt((id = X509_PURPOSE_get_unused_id(libctx)), X509_PURPOSE_MAX)
+ && TEST_int_eq(X509_PURPOSE_get_count() + 1, id)
+ && TEST_int_eq(X509_PURPOSE_get_by_id(id), -1)
+ && TEST_int_eq(X509_PURPOSE_get_by_sname(SN), -1)
+
+ /* add new entry with fresh id and fresh sname: */
+ && TEST_int_eq(X509_PURPOSE_add(ARGS(id, SN)), 1)
+ && TEST_int_ne((idx = X509_PURPOSE_get_by_sname(SN)), -1)
+ && TEST_int_eq(X509_PURPOSE_get_by_id(id), idx)
+
+ /* overwrite same entry, should be idempotent: */
+ && TEST_int_eq(X509_PURPOSE_add(ARGS(id, SN)), 1)
+ && TEST_int_eq(X509_PURPOSE_get_by_sname(SN), idx)
+ && TEST_int_eq(X509_PURPOSE_get_by_id(id), idx)
+
+ /* fail adding entry with same sname but existing conflicting id: */
+ && TEST_int_eq(X509_PURPOSE_add(ARGS(X509_PURPOSE_MAX, SN)), 0)
+ /* fail adding entry with same existing id but conflicting sname: */
+ && TEST_int_eq(X509_PURPOSE_add(ARGS(id, SN"_different")), 0)
+
+ && TEST_ptr((xp = X509_PURPOSE_get0(idx)))
+ && TEST_int_eq(X509_PURPOSE_get_id(xp), id)
+ && TEST_str_eq(X509_PURPOSE_get0_name(xp), LN)
+ && TEST_str_eq(X509_PURPOSE_get0_sname(xp), SN)
+ && TEST_int_eq(X509_PURPOSE_get_trust(xp), X509_TRUST_MAX)
+
+ && TEST_int_eq(*(p = &xp->purpose), id)
+ && TEST_int_eq(X509_PURPOSE_set(p, X509_PURPOSE_DEFAULT_ANY), 1)
+ && TEST_int_eq(X509_PURPOSE_get_id(xp), X509_PURPOSE_DEFAULT_ANY);
+}
+
int setup_tests(void)
{
ADD_TEST(test_standard_exts);
ADD_ALL_TESTS(test_a2i_ipaddress, OSSL_NELEM(a2i_ipaddress_tests));
+ ADD_TEST(tests_X509_PURPOSE);
return 1;
}
EVP_PKEY_CTX_get_algor_params 5863 3_4_0 EXIST::FUNCTION:
EVP_PKEY_CTX_get_algor 5864 3_4_0 EXIST::FUNCTION:
EVP_get1_default_properties ? 3_5_0 EXIST::FUNCTION:
+X509_PURPOSE_get_unused_id ? 3_5_0 EXIST::FUNCTION:
d2i_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX ? 3_5_0 EXIST::FUNCTION:
i2d_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX ? 3_5_0 EXIST::FUNCTION:
OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_free ? 3_5_0 EXIST::FUNCTION:
X509_PKEY_new(3)
X509_POLICY_NODE_print(3)
X509_PUBKEY_it(3)
-X509_PURPOSE_add(3)
-X509_PURPOSE_cleanup(3)
-X509_PURPOSE_get0(3)
-X509_PURPOSE_get0_name(3)
-X509_PURPOSE_get0_sname(3)
-X509_PURPOSE_get_by_id(3)
-X509_PURPOSE_get_by_sname(3)
-X509_PURPOSE_get_count(3)
-X509_PURPOSE_get_id(3)
-X509_PURPOSE_get_trust(3)
-X509_PURPOSE_set(3)
X509_REQ_INFO_it(3)
X509_REQ_extension_nid(3)
X509_REQ_get1_email(3)