summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/x509/build.info2
-rw-r--r--crypto/x509/x509_acert.c110
-rw-r--r--crypto/x509/x509aset.c177
-rw-r--r--doc/build.info6
-rw-r--r--doc/man3/X509_ACERT_get0_holder_baseCertId.pod122
-rw-r--r--doc/man3/X509_get0_notBefore.pod25
-rw-r--r--doc/man3/X509_get0_signature.pod19
-rw-r--r--doc/man3/X509_get0_uids.pod18
-rw-r--r--doc/man3/X509_get_serialNumber.pod24
-rw-r--r--doc/man3/X509_get_subject_name.pod19
-rw-r--r--doc/man3/X509_get_version.pod12
-rw-r--r--include/openssl/x509_acert.h.in51
-rw-r--r--util/libcrypto.num28
13 files changed, 601 insertions, 12 deletions
diff --git a/crypto/x509/build.info b/crypto/x509/build.info
index 2976b37e0f..b580d2b4f8 100644
--- a/crypto/x509/build.info
+++ b/crypto/x509/build.info
@@ -16,7 +16,7 @@ SOURCE[../../libcrypto]=\
pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \
v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c v3_no_rev_avail.c \
v3_soa_id.c v3_no_ass.c v3_group_ac.c v3_single_use.c v3_ind_iss.c \
- x509_acert.c
+ x509_acert.c x509aset.c
IF[{- !$disabled{'deprecated-3.0'} -}]
SOURCE[../../libcrypto]=x509type.c
diff --git a/crypto/x509/x509_acert.c b/crypto/x509/x509_acert.c
index 9a1c298d7a..d6b78bfc7c 100644
--- a/crypto/x509/x509_acert.c
+++ b/crypto/x509/x509_acert.c
@@ -73,3 +73,113 @@ IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X509_ACERT_ISSUER_V2FORM)
IMPLEMENT_PEM_rw(X509_ACERT, X509_ACERT, PEM_STRING_ACERT, X509_ACERT)
+static X509_NAME *get_dirName(const GENERAL_NAMES *names)
+{
+ GENERAL_NAME *dirName;
+
+ if (sk_GENERAL_NAME_num(names) != 1)
+ return NULL;
+
+ dirName = sk_GENERAL_NAME_value(names, 0);
+ if (dirName->type != GEN_DIRNAME)
+ return NULL;
+
+ return dirName->d.directoryName;
+}
+
+void OSSL_OBJECT_DIGEST_INFO_get0_digest(const OSSL_OBJECT_DIGEST_INFO *o,
+ int *digestedObjectType,
+ const X509_ALGOR **digestAlgorithm,
+ const ASN1_BIT_STRING **digest)
+{
+ if (digestedObjectType != NULL)
+ *digestedObjectType = ASN1_ENUMERATED_get(&o->digestedObjectType);
+ if (digestAlgorithm != NULL)
+ *digestAlgorithm = &o->digestAlgorithm;
+ if (digest != NULL)
+ *digest = &o->objectDigest;
+}
+
+const X509_NAME *OSSL_ISSUER_SERIAL_get0_issuer(const OSSL_ISSUER_SERIAL *isss)
+{
+ return get_dirName(isss->issuer);
+}
+
+const ASN1_INTEGER *OSSL_ISSUER_SERIAL_get0_serial(const OSSL_ISSUER_SERIAL *isss)
+{
+ return &isss->serial;
+}
+
+const ASN1_BIT_STRING *OSSL_ISSUER_SERIAL_get0_issuerUID(const OSSL_ISSUER_SERIAL *isss)
+{
+ return isss->issuerUID;
+}
+
+long X509_ACERT_get_version(const X509_ACERT *x)
+{
+ return ASN1_INTEGER_get(&x->acinfo->version);
+}
+
+void X509_ACERT_get0_signature(const X509_ACERT *x,
+ const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg)
+{
+ if (psig != NULL)
+ *psig = &x->signature;
+ if (palg != NULL)
+ *palg = &x->sig_alg;
+}
+
+int X509_ACERT_get_signature_nid(const X509_ACERT *x)
+{
+ return OBJ_obj2nid(x->sig_alg.algorithm);
+}
+
+const GENERAL_NAMES *X509_ACERT_get0_holder_entityName(const X509_ACERT *x)
+{
+ return x->acinfo->holder.entityName;
+}
+
+const OSSL_ISSUER_SERIAL *X509_ACERT_get0_holder_baseCertId(const X509_ACERT *x)
+{
+ return x->acinfo->holder.baseCertificateID;
+}
+
+const OSSL_OBJECT_DIGEST_INFO *X509_ACERT_get0_holder_digest(const X509_ACERT *x)
+{
+ return x->acinfo->holder.objectDigestInfo;
+}
+
+const X509_NAME *X509_ACERT_get0_issuerName(const X509_ACERT *x)
+{
+ if (x->acinfo->issuer.type != X509_ACERT_ISSUER_V2
+ || x->acinfo->issuer.u.v2Form == NULL)
+ return NULL;
+
+ return get_dirName(x->acinfo->issuer.u.v2Form->issuerName);
+}
+
+const ASN1_BIT_STRING *X509_ACERT_get0_issuerUID(const X509_ACERT *x)
+{
+ return x->acinfo->issuerUID;
+}
+
+const X509_ALGOR *X509_ACERT_get0_info_sigalg(const X509_ACERT *x)
+{
+ return &x->acinfo->signature;
+}
+
+const ASN1_INTEGER *X509_ACERT_get0_serialNumber(const X509_ACERT *x)
+{
+ return &x->acinfo->serialNumber;
+}
+
+const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notBefore(const X509_ACERT *x)
+{
+ return x->acinfo->validityPeriod.notBefore;
+}
+
+const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notAfter(const X509_ACERT *x)
+{
+ return x->acinfo->validityPeriod.notAfter;
+}
diff --git a/crypto/x509/x509aset.c b/crypto/x509/x509aset.c
new file mode 100644
index 0000000000..3d7e5fbb21
--- /dev/null
+++ b/crypto/x509/x509aset.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2021 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include "x509_acert.h"
+
+static int replace_gentime(ASN1_STRING **dest, const ASN1_GENERALIZEDTIME *src)
+{
+ ASN1_STRING *s;
+
+ if (src->type != V_ASN1_GENERALIZEDTIME)
+ return 0;
+
+ if (*dest == src)
+ return 1;
+
+ s = ASN1_STRING_dup(src);
+ if (s == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ASN1_STRING_free(*dest);
+ *dest = s;
+
+ return 1;
+}
+
+static int replace_dirName(GENERAL_NAMES **names, const X509_NAME *dirName)
+{
+ GENERAL_NAME *gen_name = NULL;
+ STACK_OF(GENERAL_NAME) *new_names = NULL;
+ X509_NAME *name_copy;
+
+ if ((name_copy = X509_NAME_dup(dirName)) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ if ((new_names = sk_GENERAL_NAME_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ if ((gen_name = GENERAL_NAME_new()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ if (sk_GENERAL_NAME_push(new_names, gen_name) <= 0) {
+ ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
+ goto err;
+ }
+
+ GENERAL_NAME_set0_value(gen_name, GEN_DIRNAME, name_copy);
+
+ GENERAL_NAMES_free(*names);
+ *names = new_names;
+
+ return 1;
+
+err:
+ GENERAL_NAME_free(gen_name);
+ sk_GENERAL_NAME_free(new_names);
+ X509_NAME_free(name_copy);
+ return 0;
+}
+
+int OSSL_OBJECT_DIGEST_INFO_set1_digest(OSSL_OBJECT_DIGEST_INFO *o,
+ int digestedObjectType,
+ X509_ALGOR *digestAlgorithm,
+ ASN1_BIT_STRING *digest)
+{
+
+ if (ASN1_ENUMERATED_set(&o->digestedObjectType, digestedObjectType) <= 0)
+ return 0;
+
+ if (X509_ALGOR_copy(&o->digestAlgorithm, digestAlgorithm) <= 0)
+ return 0;
+
+ if (ASN1_STRING_copy(&o->objectDigest, digest) <= 0)
+ return 0;
+
+ return 1;
+}
+
+int OSSL_ISSUER_SERIAL_set1_issuer(OSSL_ISSUER_SERIAL *isss,
+ const X509_NAME *issuer)
+{
+ return replace_dirName(&isss->issuer, issuer);
+}
+
+int OSSL_ISSUER_SERIAL_set1_serial(OSSL_ISSUER_SERIAL *isss,
+ const ASN1_INTEGER *serial)
+{
+ return ASN1_STRING_copy(&isss->serial, serial);
+}
+
+int OSSL_ISSUER_SERIAL_set1_issuerUID(OSSL_ISSUER_SERIAL *isss,
+ const ASN1_BIT_STRING *uid)
+{
+ ASN1_BIT_STRING_free(isss->issuerUID);
+ isss->issuerUID = ASN1_STRING_dup(uid);
+ if (isss->issuerUID == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ return 0;
+ }
+ return 1;
+}
+
+int X509_ACERT_set_version(X509_ACERT *x, long version)
+{
+ return ASN1_INTEGER_set(&x->acinfo->version, version);
+}
+
+void X509_ACERT_set0_holder_entityName(X509_ACERT *x, GENERAL_NAMES *names)
+{
+ GENERAL_NAMES_free(x->acinfo->holder.entityName);
+ x->acinfo->holder.entityName = names;
+}
+
+void X509_ACERT_set0_holder_baseCertId(X509_ACERT *x,
+ OSSL_ISSUER_SERIAL *isss)
+{
+ OSSL_ISSUER_SERIAL_free(x->acinfo->holder.baseCertificateID);
+ x->acinfo->holder.baseCertificateID = isss;
+}
+
+void X509_ACERT_set0_holder_digest(X509_ACERT *x,
+ OSSL_OBJECT_DIGEST_INFO *dinfo)
+{
+ OSSL_OBJECT_DIGEST_INFO_free(x->acinfo->holder.objectDigestInfo);
+ x->acinfo->holder.objectDigestInfo = dinfo;
+}
+
+int X509_ACERT_set1_issuerName(X509_ACERT *x, const X509_NAME *name)
+{
+ X509_ACERT_ISSUER_V2FORM *v2Form;
+
+ v2Form = x->acinfo->issuer.u.v2Form;
+
+ /* only v2Form is supported, so always create that version */
+ if (v2Form == NULL) {
+ v2Form = X509_ACERT_ISSUER_V2FORM_new();
+ if (v2Form == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
+ return 0;
+ }
+ x->acinfo->issuer.u.v2Form = v2Form;
+ x->acinfo->issuer.type = X509_ACERT_ISSUER_V2;
+ }
+
+ return replace_dirName(&v2Form->issuerName, name);
+}
+
+int X509_ACERT_set1_serialNumber(X509_ACERT *x, const ASN1_INTEGER *serial)
+{
+ return ASN1_STRING_copy(&x->acinfo->serialNumber, serial);
+}
+
+int X509_ACERT_set1_notBefore(X509_ACERT *x, const ASN1_GENERALIZEDTIME *time)
+{
+ return replace_gentime(&x->acinfo->validityPeriod.notBefore, time);
+}
+
+int X509_ACERT_set1_notAfter(X509_ACERT *x, const ASN1_GENERALIZEDTIME *time)
+{
+ return replace_gentime(&x->acinfo->validityPeriod.notAfter, time);
+}
diff --git a/doc/build.info b/doc/build.info
index 326c4ea34b..da0e7a637f 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -2799,6 +2799,10 @@ DEPEND[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
GENERATE[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
DEPEND[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
GENERATE[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
+DEPEND[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod
+GENERATE[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod
+DEPEND[man/man3/X509_ACERT_get0_holder_baseCertId.3]=man3/X509_ACERT_get0_holder_baseCertId.pod
+GENERATE[man/man3/X509_ACERT_get0_holder_baseCertId.3]=man3/X509_ACERT_get0_holder_baseCertId.pod
DEPEND[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
GENERATE[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
DEPEND[man/man3/X509_ALGOR_dup.3]=man3/X509_ALGOR_dup.pod
@@ -3631,6 +3635,7 @@ html/man3/UI_create_method.html \
html/man3/UI_new.html \
html/man3/X509V3_get_d2i.html \
html/man3/X509V3_set_ctx.html \
+html/man3/X509_ACERT_get0_holder_baseCertId.html \
html/man3/X509_ALGOR_dup.html \
html/man3/X509_ATTRIBUTE.html \
html/man3/X509_CRL_get0_by_serial.html \
@@ -4276,6 +4281,7 @@ man/man3/UI_create_method.3 \
man/man3/UI_new.3 \
man/man3/X509V3_get_d2i.3 \
man/man3/X509V3_set_ctx.3 \
+man/man3/X509_ACERT_get0_holder_baseCertId.3 \
man/man3/X509_ALGOR_dup.3 \
man/man3/X509_ATTRIBUTE.3 \
man/man3/X509_CRL_get0_by_serial.3 \
diff --git a/doc/man3/X509_ACERT_get0_holder_baseCertId.pod b/doc/man3/X509_ACERT_get0_holder_baseCertId.pod
new file mode 100644
index 0000000000..7741f286d3
--- /dev/null
+++ b/doc/man3/X509_ACERT_get0_holder_baseCertId.pod
@@ -0,0 +1,122 @@
+=pod
+
+=head1 NAME
+
+X509_ACERT_get0_holder_baseCertId,
+X509_ACERT_get0_holder_digest,
+X509_ACERT_get0_holder_entityName,
+X509_ACERT_set0_holder_baseCertId,
+X509_ACERT_set0_holder_digest,
+X509_ACERT_set0_holder_entityName,
+OSSL_ISSUER_SERIAL_get0_issuer,
+OSSL_ISSUER_SERIAL_get0_issuerUID,
+OSSL_ISSUER_SERIAL_get0_serial,
+OSSL_ISSUER_SERIAL_set1_issuer,
+OSSL_ISSUER_SERIAL_set1_issuerUID,
+OSSL_ISSUER_SERIAL_set1_serial,
+OSSL_OBJECT_DIGEST_INFO_get0_digest,
+OSSL_OBJECT_DIGEST_INFO_set1_digest - get and set Attribute Certificate holder fields
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509_acert.h>
+
+ const GENERAL_NAMES *X509_ACERT_get0_holder_entityName(const X509_ACERT *x);
+ OSSL_ISSUER_SERIAL *X509_ACERT_get0_holder_baseCertId(const X509_ACERT *x);
+ OSSL_OBJECT_DIGEST_INFO * X509_ACERT_get0_holder_digest(const X509_ACERT *x);
+ void X509_ACERT_set0_holder_entityName(X509_ACERT *x, GENERAL_NAMES *name);
+ void X509_ACERT_set0_holder_baseCertId(X509_ACERT *x, OSSL_ISSUER_SERIAL *isss);
+ void X509_ACERT_set0_holder_digest(X509_ACERT *x,
+ OSSL_OBJECT_DIGEST_INFO *dinfo);
+
+ X509_NAME *OSSL_ISSUER_SERIAL_get0_issuer(OSSL_ISSUER_SERIAL *isss);
+ ASN1_INTEGER *OSSL_ISSUER_SERIAL_get0_serial(OSSL_ISSUER_SERIAL *isss);
+ ASN1_BIT_STRING *OSSL_ISSUER_SERIAL_get0_issuerUID(OSSL_ISSUER_SERIAL *isss);
+ int OSSL_ISSUER_SERIAL_set1_issuer(OSSL_ISSUER_SERIAL *isss, X509_NAME *issuer);
+ int OSSL_ISSUER_SERIAL_set1_serial(OSSL_ISSUER_SERIAL *isss, ASN1_INTEGER *serial);
+ int OSSL_ISSUER_SERIAL_set1_issuerUID(OSSL_ISSUER_SERIAL *isss, ASN1_BIT_STRING *uid);
+
+ void OSSL_OBJECT_DIGEST_INFO_get0_digest(OSSL_OBJECT_DIGEST_INFO *o,
+ ASN1_ENUMERATED **digestedObjectType,
+ X509_ALGOR **digestAlgorithm,
+ ASN1_BIT_STRING **digest);
+ void OSSL_OBJECT_DIGEST_INFO_set1_digest(OSSL_OBJECT_DIGEST_INFO *o,
+ ASN1_ENUMERATED *digestedObjectType,
+ X509_ALGOR *digestAlgorithm,
+ ASN1_BIT_STRING *digest);
+
+=head1 DESCRIPTION
+
+These routines set and get the holder identity of an X509 attribute certificate.
+
+X509_ACERT_set0_holder_entityName() sets the identity as a B<GENERAL_NAME>
+I<name>, X509_ACERT_set0_holder_baseCertId() sets the identity based on the
+issuer and serial number of a certificate detailed in I<isss> and
+X509_ACERT_set0_holder_digest() sets the holder entity based on digest
+information I<dinfo>. Although RFC 5755 section 4.2.2 recommends that only
+one of the above methods be used to set the holder identity for a given
+attribute certificate I<x>, setting multiple methods at the same time is
+possible. It is up to the application to handle cases when conflicting
+identity information is specified using different methods.
+
+Pointers to the internal structures describing the holder identity of
+attribute certificate I<x> can be retrieved with
+X509_ACERT_get0_holder_entityName(), X509_ACERT_get0_holder_baseCertId(), and
+X509_ACERT_get0_holder_digest().
+
+A B<OSSL_ISSUER_SERIAL> object holds the subject name and UID of a certificate
+issuer and a certificate's serial number. OSSL_ISSUER_SERIAL_set1_issuer(),
+OSSL_ISSUER_SERIAL_set1_issuerUID(), and OSSL_ISSUER_SERIAL_set1_serial()
+respectively copy these values into the B<OSSL_ISSUER_SERIAL> structure.
+The application is responsible for freeing its own copy of these values after
+use. OSSL_ISSUER_SERIAL_get0_issuer(), OSSL_ISSUER_SERIAL_get0_issuerUID(),
+and OSSL_ISSUER_SERIAL_get0_serial() return pointers to these values in the object.
+
+An B<OSSL_OBJECT_DIGEST_INFO> object holds a digest of data to identify the
+attribute certificate holder. OSSL_OBJECT_DIGEST_INFO_set1_digest() sets the
+digest information of the object. The type of I<digest> information is given
+by I<digestedObjectType> and can be one of:
+
+=over 4
+
+=item OSSL_OBJECT_DIGEST_INFO_PUBLIC_KEY
+
+Hash of a public key
+
+=item OSSL_OBJECT_DIGEST_INFO_PUBLIC_KEY_CERT
+
+Hash of a public key certificate
+
+=item OSSL_OBJECT_DIGEST_INFO_OTHER
+
+Hash of another object. See NOTES below.
+
+=back
+
+I<digestAlgorithm> indicates the algorithm used to compute I<digest>.
+
+=head1 RETURN VALUES
+
+All I<set0>/I<set1> routines return 1 for success and 0 for failure.
+All I<get0> functions return a pointer to the object's inner structure. These
+pointers must not be freed after use.
+
+=head1 NOTES
+
+Although the value of B<OSSL_OBJECT_DIGEST_INFO_OTHER> is defined in RFC 5755,
+its use is prohibited for conformant attribute certificates.
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.4.
+
+=head1 COPYRIGHT
+
+Copyright 2023 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>.
+
+=cut
diff --git a/doc/man3/X509_get0_notBefore.pod b/doc/man3/X509_get0_notBefore.pod
index 1ca0a1b128..84dee91850 100644
--- a/doc/man3/X509_get0_notBefore.pod
+++ b/doc/man3/X509_get0_notBefore.pod
@@ -4,6 +4,8 @@
X509_get0_notBefore, X509_getm_notBefore, X509_get0_notAfter,
X509_getm_notAfter, X509_set1_notBefore, X509_set1_notAfter,
+X509_ACERT_get0_notBefore, X509_ACERT_get0_notAfter,
+X509_ACERT_set1_notBefore, X509_ACERT_set1_notAfter,
X509_CRL_get0_lastUpdate, X509_CRL_get0_nextUpdate, X509_CRL_set1_lastUpdate,
X509_CRL_set1_nextUpdate - get or set certificate or CRL dates
@@ -20,6 +22,12 @@ X509_CRL_set1_nextUpdate - get or set certificate or CRL dates
int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm);
int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm);
+ const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notBefore(const X509 *x);
+ const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notAfter(const X509 *x);
+
+ int X509_ACERT_set1_notBefore(X509_ACERT *x, const ASN1_GENERALIZEDTIME *tm);
+ int X509_ACERT_set1_notAfter(X509_ACERT *x, const ASN1_GENERALIZEDTIME *tm);
+
const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl);
const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl);
@@ -43,6 +51,16 @@ and B<notAfter> fields of I<x> to I<tm>. Ownership of the passed
parameter I<tm> is not transferred by these functions so it must
be freed up after the call.
+X509_ACERT_get0_notBefore() and X509_ACERT_get0_notAfter() return
+the B<notBefore> and B<notAfter> fields of certificate B<x> respectively.
+returned is an internal pointer which must not be freed up after
+the call.
+
+X509_ACERT_set1_notBefore() and X509_ACERT_set1_notAfter() set the B<notBefore>
+and B<notAfter> fields of B<x> to B<tm>. Ownership of the passed
+parameter B<tm> is not transferred by these functions so it must
+be freed up after the call.
+
X509_CRL_get0_lastUpdate() and X509_CRL_get0_nextUpdate() return the
B<lastUpdate> and B<nextUpdate> fields of I<crl>. The value
returned is an internal pointer which must not be freed up after
@@ -67,9 +85,16 @@ or NULL if the B<lastUpdate> field is absent.
X509_set1_notBefore(), X509_set1_notAfter(), X509_CRL_set1_lastUpdate() and
X509_CRL_set1_nextUpdate() return 1 for success or 0 for failure.
+=head1 NOTES
+
+Unlike the B<X509> and B<X509_CRL> routines, the B<X509_ACERT> routines
+use the ASN1_GENERALIZEDTIME format instead of ASN1_TIME for holding time
+data.
+
=head1 SEE ALSO
L<d2i_X509(3)>,
+L<ASN1_GENERALIZEDTIME_check(3)>
L<ERR_get_error(3)>,
L<X509_CRL_get0_by_serial(3)>,
L<X509_get0_signature(3)>,
diff --git a/doc/man3/X509_get0_signature.pod b/doc/man3/X509_get0_signature.pod
index a49a70038e..485d39bf25 100644
--- a/doc/man3/X509_get0_signature.pod
+++ b/doc/man3/X509_get0_signature.pod
@@ -5,7 +5,9 @@
X509_get0_signature, X509_REQ_set0_signature, X509_REQ_set1_signature_algo,
X509_get_signature_nid, X509_get0_tbs_sigalg, X509_REQ_get0_signature,
X509_REQ_get_signature_nid, X509_CRL_get0_signature, X509_CRL_get_signature_nid,
-X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature information
+X509_ACERT_get0_signature, X509_ACERT_get0_info_sigalg,
+X509_ACERT_get_signature_nid, X509_get_signature_info,
+X509_SIG_INFO_get, X509_SIG_INFO_set - signature information
=head1 SYNOPSIS
@@ -24,6 +26,8 @@ X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature inform
const X509_ALGOR **palg);
int X509_REQ_get_signature_nid(const X509_REQ *crl);
+ const X509_ALGOR *X509_ACERT_get0_info_sigalg(const X509_ACERT *x);
+
void X509_CRL_get0_signature(const X509_CRL *crl,
const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg);
@@ -37,6 +41,12 @@ X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature inform
void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
int secbits, uint32_t flags);
+ #include <openssl/x509_acert.h>
+
+ void X509_ACERT_get0_signature(const X509_ACERT *x,
+ const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg);
+ int X509_ACERT_get_signature_nid(const X509_ACERT *x);
=head1 DESCRIPTION
X509_get0_signature() sets B<*psig> to the signature of B<x> and B<*palg>
@@ -56,6 +66,10 @@ X509_REQ_get0_signature(), X509_REQ_get_signature_nid()
X509_CRL_get0_signature() and X509_CRL_get_signature_nid() perform the
same function for certificate requests and CRLs.
+X509_ACERT_get0_signature(), X509_ACERT_get_signature_nid() and
+X509_ACERT_get0_info_sigalg() perform the same function for attribute
+certificates.
+
X509_get_signature_info() retrieves information about the signature of
certificate B<x>. The NID of the signing digest is written to B<*mdnid>,
the public key algorithm to B<*pknid>, the effective security bits to
@@ -130,6 +144,9 @@ added in OpenSSL 1.1.0.
The X509_REQ_set0_signature() and X509_REQ_set1_signature_algo()
were added in OpenSSL 1.1.1e.
+The X509_ACERT_get0_signature(), X509_ACERT_get0_info_sigalg() and
+X509_ACERT_get_signature_nid() functions were added in OpenSSL 3.4.
+
=head1 COPYRIGHT
Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_get0_uids.pod b/doc/man3/X509_get0_uids.pod
index 48ae5afc42..c265ce09bc 100644
--- a/doc/man3/X509_get0_uids.pod
+++ b/doc/man3/X509_get0_uids.pod
@@ -2,7 +2,8 @@
=head1 NAME
-X509_get0_uids - get certificate unique identifiers
+X509_get0_uids, X509_ACERT_get0_issuerUID
+- get certificate and attribute certificate unique identifiers
=head1 SYNOPSIS
@@ -11,11 +12,17 @@ X509_get0_uids - get certificate unique identifiers
void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid,
const ASN1_BIT_STRING **psuid);
+ #include <openssl/x509_acert.h>
+
+ ASN1_BIT_STRING *X509_ACERT_get0_issuerUID(X509_ACERT *x);
=head1 DESCRIPTION
X509_get0_uids() sets B<*piuid> and B<*psuid> to the issuer and subject unique
identifiers of certificate B<x> or NULL if the fields are not present.
+X509_ACERT_get0_issuerUID() returns the issuer unique identifier of the
+attribute certificate B<x> or NULL if the field is not present.
+
=head1 NOTES
The issuer and subject unique identifier fields are very rarely encountered in
@@ -25,6 +32,9 @@ practice outside test cases.
X509_get0_uids() does not return a value.
+X509_ACERT_get0_issuerUID() returns a unique identifier on success or NULL
+on failure.
+
=head1 SEE ALSO
L<d2i_X509(3)>,
@@ -45,6 +55,12 @@ L<X509_sign(3)>,
L<X509V3_get_d2i(3)>,
L<X509_verify_cert(3)>
+=head1 HISTORY
+
+X509_get0_uids() was added in OpenSSL 1.1.0.
+
+X509_ACERT_get0_issuerUID() was added in OpenSSL 3.4.
+
=head1 COPYRIGHT
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_get_serialNumber.pod b/doc/man3/X509_get_serialNumber.pod
index 5594c8a284..ac93a33b8f 100644
--- a/doc/man3/X509_get_serialNumber.pod
+++ b/doc/man3/X509_get_serialNumber.pod
@@ -4,7 +4,9 @@
X509_get_serialNumber,
X509_get0_serialNumber,
-X509_set_serialNumber
+X509_set_serialNumber,
+X509_ACERT_get0_serialNumber,
+X509_ACERT_set1_serialNumber
- get or set certificate serial number
=head1 SYNOPSIS
@@ -15,6 +17,11 @@ X509_set_serialNumber
const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x);
int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+ #include <openssl/x509_acert.h>
+
+ ASN1_INTEGER *X509_ACERT_get0_serialNumber(X509_ACERT *x);
+ int X509_ACERT_set1_serialNumber(X509_ACERT *x, ASN1_INTEGER *serial);
+
=head1 DESCRIPTION
X509_get_serialNumber() returns the serial number of certificate B<x> as an
@@ -28,12 +35,19 @@ X509_set_serialNumber() sets the serial number of certificate B<x> to
B<serial>. A copy of the serial number is used internally so B<serial> should
be freed up after use.
+X509_ACERT_get0_serialNumber() performs the same operation as
+X509_get_serialNumber() for attribute certificates.
+
+X509_ACERT_set1_serialNumber() performs the same operation as
+X509_set_serialNumber() for attribute certificates.
+
=head1 RETURN VALUES
-X509_get_serialNumber() and X509_get0_serialNumber() return an B<ASN1_INTEGER>
-structure.
+X509_get_serialNumber(), X509_get0_serialNumber() and
+X509_ACERT_get0_serialNumber() return a pointer to an B<ASN1_INTEGER> structure.
-X509_set_serialNumber() returns 1 for success and 0 for failure.
+X509_set_serialNumber() and X509_ACERT_set1_serialNumber() return 1 for success
+and 0 for failure.
=head1 SEE ALSO
@@ -59,6 +73,8 @@ L<X509_verify_cert(3)>
The X509_get_serialNumber() and X509_set_serialNumber() functions are
available in all versions of OpenSSL.
The X509_get0_serialNumber() function was added in OpenSSL 1.1.0.
+The X509_ACERT_get0_serialNumber() and X509_ACERT_set1_serialNumber()
+functions were added in OpenSSL 3.4.
=head1 COPYRIGHT
diff --git a/doc/man3/X509_get_subject_name.pod b/doc/man3/X509_get_subject_name.pod
index 64659de6ab..2f392ad7a2 100644
--- a/doc/man3/X509_get_subject_name.pod
+++ b/doc/man3/X509_get_subject_name.pod
@@ -6,6 +6,7 @@ X509_NAME_hash_ex, X509_NAME_hash,
X509_get_subject_name, X509_set_subject_name, X509_subject_name_hash,
X509_get_issuer_name, X509_set_issuer_name, X509_issuer_name_hash,
X509_REQ_get_subject_name, X509_REQ_set_subject_name,
+X509_ACERT_get0_issuerName, X509_ACERT_set1_issuerName,
X509_CRL_get_issuer, X509_CRL_set_issuer_name -
get X509_NAME hashes or get and set issuer or subject names
@@ -30,6 +31,11 @@ get X509_NAME hashes or get and set issuer or subject names
X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl);
int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name);
+ #include <openssl/x509_acert.h>
+
+ X509_NAME *X509_ACERT_get0_issuerName(const X509_ACERT *x);
+ int X509_ACERT_set1_issuerName(X509_ACERT *x, const X509_NAME *name);
+
The following macro has been deprecated since OpenSSL 3.0, and can be
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
see L<openssl_user_macros(7)>:
@@ -63,13 +69,19 @@ X509_get_subject_name(), X509_set_subject_name(), and X509_subject_name_hash()
except they relate to the issuer name of I<x>.
Similarly X509_REQ_get_subject_name(), X509_REQ_set_subject_name(),
+X509_ACERT_get0_issuerName(), X509_ACERT_set1_issuerName(),
X509_CRL_get_issuer() and X509_CRL_set_issuer_name() get or set the subject
or issuer names of certificate requests of CRLs respectively.
+Since attribute certificates do not have a subject name, only the issuer name
+can be set. For details on setting X509_ACERT holder identities, see
+L<X509_ACERT_set0_holder_entityName(3)>.
+
=head1 RETURN VALUES
X509_get_subject_name(), X509_get_issuer_name(), X509_REQ_get_subject_name()
-and X509_CRL_get_issuer() return an B<X509_NAME> pointer.
+X509_ACERT_get0_issuerName() and X509_CRL_get_issuer() return
+an B<X509_NAME> pointer.
X509_NAME_hash_ex(), X509_NAME_hash(),
X509_subject_name_hash() and X509_issuer_name_hash()
@@ -77,8 +89,9 @@ return the first four bytes of the SHA1 hash value,
converted to B<unsigned long> in little endian order,
or 0 on failure.
-X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name()
-and X509_CRL_set_issuer_name() return 1 for success and 0 for failure.
+X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name(),
+X509_ACERT_get0_issuerName() and X509_CRL_set_issuer_name() return 1 for
+success and 0 for failure.
=head1 BUGS
diff --git a/doc/man3/X509_get_version.pod b/doc/man3/X509_get_version.pod
index c5db26c579..d6b11e454f 100644
--- a/doc/man3/X509_get_version.pod
+++ b/doc/man3/X509_get_version.pod
@@ -3,7 +3,8 @@
=head1 NAME
X509_get_version, X509_set_version, X509_REQ_get_version, X509_REQ_set_version,
-X509_CRL_get_version, X509_CRL_set_version - get or set certificate,
+X509_ACERT_get_version, X509_ACERT_set_version, X509_CRL_get_version,
+X509_CRL_set_version - get or set certificate,
certificate request or CRL version
=head1 SYNOPSIS
@@ -19,6 +20,11 @@ certificate request or CRL version
long X509_CRL_get_version(const X509_CRL *crl);
int X509_CRL_set_version(X509_CRL *x, long version);
+ #include <openssl/x509_acert.h>
+
+ int X509_ACERT_set_version(X509_ACERT *x, long version);
+ long X509_ACERT_get_version(const X509_ACERT *x);
+
=head1 DESCRIPTION
X509_get_version() returns the numerical value of the version field of
@@ -31,9 +37,11 @@ X509_set_version() sets the numerical value of the version field of certificate
I<x> to I<version>.
Similarly X509_REQ_get_version(), X509_REQ_set_version(),
+X509_ACERT_get_version(), X509_ACERT_set_version(),
X509_CRL_get_version() and X509_CRL_set_version() get and set the version
number of certificate requests and CRLs. They use constants
-B<X509_REQ_VERSION_1>, B<X509_CRL_VERSION_1>, and B<X509_CRL_VERSION_2>.
+B<X509_REQ_VERSION_1>, B<X509_ACERT_VERSION_2>, B<X509_CRL_VERSION_1>,
+and B<X509_CRL_VERSION_2>.
=head1 NOTES
diff --git a/include/openssl/x509_acert.h.in b/include/openssl/x509_acert.h.in
index 1d66af9545..826f39d423 100644
--- a/include/openssl/x509_acert.h.in
+++ b/include/openssl/x509_acert.h.in
@@ -45,4 +45,55 @@ DECLARE_PEM_rw(X509_ACERT, X509_ACERT)
X509_ACERT *d2i_X509_ACERT_bio(BIO *bp, X509_ACERT **acert);
int i2d_X509_ACERT_bio(BIO *bp, const X509_ACERT *acert);
+# define X509_ACERT_VERSION_2 1
+
+const GENERAL_NAMES *X509_ACERT_get0_holder_entityName(const X509_ACERT *x);
+const OSSL_ISSUER_SERIAL *X509_ACERT_get0_holder_baseCertId(const X509_ACERT *x);
+const OSSL_OBJECT_DIGEST_INFO * X509_ACERT_get0_holder_digest(const X509_ACERT *x);
+const X509_NAME *X509_ACERT_get0_issuerName(const X509_ACERT *x);
+long X509_ACERT_get_version(const X509_ACERT *x);
+void X509_ACERT_get0_signature(const X509_ACERT *x,
+ const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg);
+int X509_ACERT_get_signature_nid(const X509_ACERT *x);
+const X509_ALGOR *X509_ACERT_get0_info_sigalg(const X509_ACERT *x);
+const ASN1_INTEGER *X509_ACERT_get0_serialNumber(const X509_ACERT *x);
+const ASN1_TIME *X509_ACERT_get0_notBefore(const X509_ACERT *x);
+const ASN1_TIME *X509_ACERT_get0_notAfter(const X509_ACERT *x);
+const ASN1_BIT_STRING *X509_ACERT_get0_issuerUID(const X509_ACERT *x);
+
+# define OSSL_OBJECT_DIGEST_INFO_PUBLIC_KEY 0
+# define OSSL_OBJECT_DIGEST_INFO_PUBLIC_KEY_CERT 1
+# define OSSL_OBJECT_DIGEST_INFO_OTHER 2 /* must not be used in RFC 5755 profile */
+int X509_ACERT_set_version(X509_ACERT *x, long version);
+void X509_ACERT_set0_holder_entityName(X509_ACERT *x, GENERAL_NAMES *name);
+void X509_ACERT_set0_holder_baseCertId(X509_ACERT *x, OSSL_ISSUER_SERIAL *isss);
+void X509_ACERT_set0_holder_digest(X509_ACERT *x,
+ OSSL_OBJECT_DIGEST_INFO *dinfo);
+
+int X509_ACERT_set1_issuerName(X509_ACERT *x, const X509_NAME *name);
+int X509_ACERT_set1_serialNumber(X509_ACERT *x, const ASN1_INTEGER *serial);
+int X509_ACERT_set1_notBefore(X509_ACERT *x, const ASN1_GENERALIZEDTIME *time);
+int X509_ACERT_set1_notAfter(X509_ACERT *x, const ASN1_GENERALIZEDTIME *time);
+
+void OSSL_OBJECT_DIGEST_INFO_get0_digest(const OSSL_OBJECT_DIGEST_INFO *o,
+ int *digestedObjectType,
+ const X509_ALGOR **digestAlgorithm,
+ const ASN1_BIT_STRING **digest);
+
+int OSSL_OBJECT_DIGEST_INFO_set1_digest(OSSL_OBJECT_DIGEST_INFO *o,
+ int digestedObjectType,
+ X509_ALGOR *digestAlgorithm,
+ ASN1_BIT_STRING *digest);
+
+const X509_NAME *OSSL_ISSUER_SERIAL_get0_issuer(const OSSL_ISSUER_SERIAL *isss);
+const ASN1_INTEGER *OSSL_ISSUER_SERIAL_get0_serial(const OSSL_ISSUER_SERIAL *isss);
+const ASN1_BIT_STRING *OSSL_ISSUER_SERIAL_get0_issuerUID(const OSSL_ISSUER_SERIAL *isss);
+
+int OSSL_ISSUER_SERIAL_set1_issuer(OSSL_ISSUER_SERIAL *isss,
+ const X509_NAME *issuer);
+int OSSL_ISSUER_SERIAL_set1_serial(OSSL_ISSUER_SERIAL *isss,
+ const ASN1_INTEGER *serial);
+int OSSL_ISSUER_SERIAL_set1_issuerUID(OSSL_ISSUER_SERIAL *isss,
+ const ASN1_BIT_STRING *uid);
#endif
diff --git a/util/libcrypto.num b/util/libcrypto.num
index dbba798a3b..57dee34ec0 100644
--- a/util/libcrypto.num
+++ b/