diff --git a/CHANGES.md b/CHANGES.md index aaa47976a2b99..28e1c0ae4d88f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -47,6 +47,12 @@ OpenSSL 3.4 *Tim Perry* + * Added Attribute Certificate (RFC 5755) support. Attribute + Certificates can be created, parsed, modified and printed via the + public API. There is no command-line tool support at this time. + + *Damian Hobson-Garcia* + OpenSSL 3.3 ----------- diff --git a/NEWS.md b/NEWS.md index 7af4eabb2c3d3..3196a06254184 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,6 +28,8 @@ OpenSSL. This release is in development. + * Added initial Attribute Certificate (RFC 5755) support. + OpenSSL 3.3 ----------- diff --git a/build.info b/build.info index fdab98c103d6f..51d9184045bf5 100644 --- a/build.info +++ b/build.info @@ -44,6 +44,7 @@ DEPEND[]=include/openssl/asn1.h \ include/openssl/ui.h \ include/openssl/x509.h \ include/openssl/x509v3.h \ + include/openssl/x509_acert.h \ include/openssl/x509_vfy.h \ include/crypto/bn_conf.h include/crypto/dso_conf.h \ include/internal/param_names.h crypto/params_idx.c @@ -75,6 +76,7 @@ GENERATE[include/openssl/ssl.h]=include/openssl/ssl.h.in GENERATE[include/openssl/ui.h]=include/openssl/ui.h.in GENERATE[include/openssl/x509.h]=include/openssl/x509.h.in GENERATE[include/openssl/x509v3.h]=include/openssl/x509v3.h.in +GENERATE[include/openssl/x509_acert.h]=include/openssl/x509_acert.h.in GENERATE[include/openssl/x509_vfy.h]=include/openssl/x509_vfy.h.in GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in diff --git a/crypto/asn1/asn1_item_list.c b/crypto/asn1/asn1_item_list.c index b5a83ba8914b9..ab0d500d650b0 100644 --- a/crypto/asn1/asn1_item_list.c +++ b/crypto/asn1/asn1_item_list.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "asn1_item_list.h" diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h index 72299a7b6b3de..fc59c2cdbaba6 100644 --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -150,6 +150,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = { ASN1_ITEM_ref(SXNET), ASN1_ITEM_ref(ISSUER_SIGN_TOOL), ASN1_ITEM_ref(USERNOTICE), + ASN1_ITEM_ref(X509_ACERT), ASN1_ITEM_ref(X509_ALGORS), ASN1_ITEM_ref(X509_ALGOR), ASN1_ITEM_ref(X509_ATTRIBUTE), diff --git a/crypto/x509/build.info b/crypto/x509/build.info index 3f70f3ff36dfb..6cebadea77296 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -15,7 +15,8 @@ SOURCE[../../libcrypto]=\ v3_pcia.c v3_pci.c v3_ist.c \ 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 + v3_soa_id.c v3_no_ass.c v3_group_ac.c v3_single_use.c v3_ind_iss.c \ + x509_acert.c x509aset.c t_acert.c x_ietfatt.c IF[{- !$disabled{'deprecated-3.0'} -}] SOURCE[../../libcrypto]=x509type.c diff --git a/crypto/x509/t_acert.c b/crypto/x509/t_acert.c new file mode 100644 index 0000000000000..0b5ab313115cd --- /dev/null +++ b/crypto/x509/t_acert.c @@ -0,0 +1,285 @@ +/* + * 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include + +static int print_attribute(BIO *bp, X509_ATTRIBUTE *a) +{ + ASN1_OBJECT *aobj; + int i, j, count; + int ret = 0; + + aobj = X509_ATTRIBUTE_get0_object(a); + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + + if ((j = i2a_ASN1_OBJECT(bp, aobj)) <= 0) + goto err; + + count = X509_ATTRIBUTE_count(a); + if (count == 0) { + ERR_raise(ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES); + goto err; + } + + if (j < 25 && (BIO_printf(bp, "%*s", 25 - j, " ") <= 0)) + goto err; + + if (BIO_puts(bp, ":") <= 0) + goto err; + + for (i = 0; i < count; i++) { + ASN1_TYPE *at; + int type; + ASN1_BIT_STRING *bs; + + at = X509_ATTRIBUTE_get0_type(a, i); + type = at->type; + + switch (type) { + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_IA5STRING: + bs = at->value.asn1_string; + if (BIO_write(bp, (char *)bs->data, bs->length) != bs->length) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + break; + case V_ASN1_SEQUENCE: + if (BIO_puts(bp, "\n") <= 0) + goto err; + ASN1_parse_dump(bp, at->value.sequence->data, + at->value.sequence->length, i, 1); + break; + default: + if (BIO_printf(bp, "unable to print attribute of type 0x%X\n", + type) < 0) + goto err; + break; + } + } + ret = 1; +err: + return ret; +} + +int X509_ACERT_print_ex(BIO *bp, X509_ACERT *x, unsigned long nmflags, + unsigned long cflag) +{ + int i; + char mlch = ' '; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + } + + if ((cflag & X509_FLAG_NO_HEADER) == 0) { + if (BIO_printf(bp, "Attribute Certificate:\n") <= 0) + goto err; + if (BIO_printf(bp, "%4sData:\n", "") <= 0) + goto err; + } + + if ((cflag & X509_FLAG_NO_VERSION) == 0) { + long l; + + l = X509_ACERT_get_version(x); + if (l == X509_ACERT_VERSION_2) { + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, + (unsigned long)l) <= 0) + goto err; + } else { + if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) + goto err; + } + } + + if ((cflag & X509_FLAG_NO_SERIAL) == 0) { + const ASN1_INTEGER *serial; + + serial = X509_ACERT_get0_serialNumber(x); + + if (BIO_printf(bp, "%8sSerial Number: ", "") <= 0) + goto err; + + if (i2a_ASN1_INTEGER(bp, serial) <= 0) + goto err; + + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + + if ((cflag & X509_FLAG_NO_SUBJECT) == 0) { + const GENERAL_NAMES *holderEntities; + const OSSL_ISSUER_SERIAL *holder_bcid; + const X509_NAME *holderIssuer = NULL; + + if (BIO_printf(bp, "%8sHolder:\n", "") <= 0) + goto err; + + holderEntities = X509_ACERT_get0_holder_entityName(x); + if (holderEntities != NULL) { + for (i = 0; i < sk_GENERAL_NAME_num(holderEntities); i++) { + GENERAL_NAME *entity; + + entity = sk_GENERAL_NAME_value(holderEntities, i); + + if (BIO_printf(bp, "%12sName:%c", "", mlch) <= 0) + goto err; + if (GENERAL_NAME_print(bp, entity) <= 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + } + + if ((holder_bcid = X509_ACERT_get0_holder_baseCertId(x)) != NULL) + holderIssuer = OSSL_ISSUER_SERIAL_get0_issuer(holder_bcid); + + if (holderIssuer != NULL) { + const ASN1_INTEGER *holder_serial; + const ASN1_BIT_STRING *iuid; + + if (BIO_printf(bp, "%12sIssuer:%c", "", mlch) <= 0) + goto err; + + if (X509_NAME_print_ex(bp, holderIssuer, 0, nmflags) <= 0) + goto err; + + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + + if (BIO_printf(bp, "%12sSerial: ", "") <= 0) + goto err; + + holder_serial = OSSL_ISSUER_SERIAL_get0_serial(holder_bcid); + + if (i2a_ASN1_INTEGER(bp, holder_serial) <= 0) + goto err; + + iuid = OSSL_ISSUER_SERIAL_get0_issuerUID(holder_bcid); + if (iuid != NULL) { + if (BIO_printf(bp, "%12sIssuer UID: ", "") <= 0) + goto err; + if (X509_signature_dump(bp, iuid, 24) <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + } + + if ((cflag & X509_FLAG_NO_ISSUER) == 0) { + const X509_NAME *issuer; + + if (BIO_printf(bp, "%8sIssuer:%c", "", mlch) <= 0) + goto err; + issuer = X509_ACERT_get0_issuerName(x); + if (issuer) { + if (X509_NAME_print_ex(bp, issuer, 0, nmflags) < 0) + goto err; + } else { + if (BIO_printf(bp, "Unsupported Issuer Type") <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + + if ((cflag & X509_FLAG_NO_VALIDITY) == 0) { + if (BIO_printf(bp, "%8sValidity\n", "") <= 0) + goto err; + if (BIO_printf(bp, "%12sNot Before: ", "") <= 0) + goto err; + if (ASN1_GENERALIZEDTIME_print(bp, X509_ACERT_get0_notBefore(x)) == 0) + goto err; + if (BIO_printf(bp, "\n%12sNot After : ", "") <= 0) + goto err; + if (ASN1_GENERALIZEDTIME_print(bp, X509_ACERT_get0_notAfter(x)) == 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + + if ((cflag & X509_FLAG_NO_ATTRIBUTES) == 0) { + if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0) + goto err; + + if (X509_ACERT_get_attr_count(x) == 0) { + if (BIO_printf(bp, "%12s(none)\n", "") <= 0) + goto err; + } else { + for (i = 0; i < X509_ACERT_get_attr_count(x); i++) { + if (print_attribute(bp, X509_ACERT_get_attr(x, i)) == 0) + goto err; + } + } + } + + if ((cflag & X509_FLAG_NO_EXTENSIONS) == 0) { + const STACK_OF(X509_EXTENSION) *exts; + + exts = X509_ACERT_get0_extensions(x); + if (exts != NULL) { + if (BIO_printf(bp, "%8sExtensions:\n", "") <= 0) + goto err; + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + int critical; + + ex = sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + obj = X509_EXTENSION_get_object(ex); + if (i2a_ASN1_OBJECT(bp, obj) <= 0) + goto err; + critical = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0) + goto err; + if (X509V3_EXT_print(bp, ex, cflag, 20) <= 0) { + if (BIO_printf(bp, "%16s", "") <= 0) + goto err; + if (ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)) <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + } + } + + if ((cflag & X509_FLAG_NO_SIGDUMP) == 0) { + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + + X509_ACERT_get0_signature(x, &sig, &sig_alg); + if (X509_signature_print(bp, sig_alg, sig) <= 0) + return 0; + } + + return 1; + +err: + ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB); + return 0; +} + +int X509_ACERT_print(BIO *bp, X509_ACERT *x) +{ + return X509_ACERT_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} diff --git a/crypto/x509/x509_acert.c b/crypto/x509/x509_acert.c new file mode 100644 index 0000000000000..a3c894636339e --- /dev/null +++ b/crypto/x509/x509_acert.c @@ -0,0 +1,328 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include "x509_acert.h" + +/* + * OpenSSL ASN.1 template translation of RFC 5755 4.1. + */ + +ASN1_SEQUENCE(OSSL_OBJECT_DIGEST_INFO) = { + ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, digestedObjectType, ASN1_ENUMERATED), + ASN1_OPT(OSSL_OBJECT_DIGEST_INFO, otherObjectTypeID, ASN1_OBJECT), + ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, digestAlgorithm, X509_ALGOR), + ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, objectDigest, ASN1_BIT_STRING), +} ASN1_SEQUENCE_END(OSSL_OBJECT_DIGEST_INFO) + +ASN1_SEQUENCE(OSSL_ISSUER_SERIAL) = { + ASN1_SEQUENCE_OF(OSSL_ISSUER_SERIAL, issuer, GENERAL_NAME), + ASN1_EMBED(OSSL_ISSUER_SERIAL, serial, ASN1_INTEGER), + ASN1_OPT(OSSL_ISSUER_SERIAL, issuerUID, ASN1_BIT_STRING), +} ASN1_SEQUENCE_END(OSSL_ISSUER_SERIAL) + +ASN1_SEQUENCE(X509_ACERT_ISSUER_V2FORM) = { + ASN1_SEQUENCE_OF_OPT(X509_ACERT_ISSUER_V2FORM, issuerName, GENERAL_NAME), + ASN1_IMP_OPT(X509_ACERT_ISSUER_V2FORM, baseCertificateId, OSSL_ISSUER_SERIAL, 0), + ASN1_IMP_OPT(X509_ACERT_ISSUER_V2FORM, objectDigestInfo, OSSL_OBJECT_DIGEST_INFO, 1), +} ASN1_SEQUENCE_END(X509_ACERT_ISSUER_V2FORM) + +ASN1_CHOICE(X509_ACERT_ISSUER) = { + ASN1_SEQUENCE_OF(X509_ACERT_ISSUER, u.v1Form, GENERAL_NAME), + ASN1_IMP(X509_ACERT_ISSUER, u.v2Form, X509_ACERT_ISSUER_V2FORM, 0), +} ASN1_CHOICE_END(X509_ACERT_ISSUER) + +ASN1_SEQUENCE(X509_HOLDER) = { + ASN1_IMP_OPT(X509_HOLDER, baseCertificateID, OSSL_ISSUER_SERIAL, 0), + ASN1_IMP_SEQUENCE_OF_OPT(X509_HOLDER, entityName, GENERAL_NAME, 1), + ASN1_IMP_OPT(X509_HOLDER, objectDigestInfo, OSSL_OBJECT_DIGEST_INFO, 2), +} ASN1_SEQUENCE_END(X509_HOLDER) + +ASN1_SEQUENCE(X509_ACERT_INFO) = { + ASN1_EMBED(X509_ACERT_INFO, version, ASN1_INTEGER), + ASN1_EMBED(X509_ACERT_INFO, holder, X509_HOLDER), + ASN1_EMBED(X509_ACERT_INFO, issuer, X509_ACERT_ISSUER), + ASN1_EMBED(X509_ACERT_INFO, signature, X509_ALGOR), + ASN1_EMBED(X509_ACERT_INFO, serialNumber, ASN1_INTEGER), + ASN1_EMBED(X509_ACERT_INFO, validityPeriod, X509_VAL), + ASN1_SEQUENCE_OF(X509_ACERT_INFO, attributes, X509_ATTRIBUTE), + ASN1_OPT(X509_ACERT_INFO, issuerUID, ASN1_BIT_STRING), + ASN1_SEQUENCE_OF_OPT(X509_ACERT_INFO, extensions, X509_EXTENSION), +} ASN1_SEQUENCE_END(X509_ACERT_INFO) + +ASN1_SEQUENCE(X509_ACERT) = { + ASN1_SIMPLE(X509_ACERT, acinfo, X509_ACERT_INFO), + ASN1_EMBED(X509_ACERT, sig_alg, X509_ALGOR), + ASN1_EMBED(X509_ACERT, signature, ASN1_BIT_STRING), +} ASN1_SEQUENCE_END(X509_ACERT) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ACERT) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ACERT) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X509_ACERT_INFO) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_ISSUER_SERIAL) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_OBJECT_DIGEST_INFO) +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; +} + +/* Attribute management functions */ + +int X509_ACERT_get_attr_count(const X509_ACERT *x) +{ + return X509at_get_attr_count(x->acinfo->attributes); +} + +int X509_ACERT_get_attr_by_NID(const X509_ACERT *x, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(x->acinfo->attributes, nid, lastpos); +} + +int X509_ACERT_get_attr_by_OBJ(const X509_ACERT *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(x->acinfo->attributes, obj, lastpos); +} + +X509_ATTRIBUTE *X509_ACERT_get_attr(const X509_ACERT *x, int loc) +{ + return X509at_get_attr(x->acinfo->attributes, loc); +} + +X509_ATTRIBUTE *X509_ACERT_delete_attr(X509_ACERT *x, int loc) +{ + return X509at_delete_attr(x->acinfo->attributes, loc); +} + +int X509_ACERT_add1_attr(X509_ACERT *x, X509_ATTRIBUTE *attr) +{ + STACK_OF(X509_ATTRIBUTE) **attrs = &x->acinfo->attributes; + + return X509at_add1_attr(attrs, attr) != NULL; +} + +int X509_ACERT_add1_attr_by_OBJ(X509_ACERT *x, const ASN1_OBJECT *obj, + int type, const void *bytes, int len) +{ + STACK_OF(X509_ATTRIBUTE) **attrs = &x->acinfo->attributes; + + return X509at_add1_attr_by_OBJ(attrs, obj, type, bytes, len) != NULL; +} + +int X509_ACERT_add1_attr_by_NID(X509_ACERT *x, int nid, int type, + const void *bytes, int len) +{ + STACK_OF(X509_ATTRIBUTE) **attrs = &x->acinfo->attributes; + + return X509at_add1_attr_by_NID(attrs, nid, type, bytes, len) != NULL; +} + +int X509_ACERT_add1_attr_by_txt(X509_ACERT *x, const char *attrname, int type, + const unsigned char *bytes, int len) +{ + STACK_OF(X509_ATTRIBUTE) **attrs = &x->acinfo->attributes; + + return X509at_add1_attr_by_txt(attrs, attrname, type, bytes, len) != NULL; +} + +static int check_asn1_attribute(const char **value) +{ + const char *p = *value; + + if (strncmp(p, "ASN1:", 5) != 0) + return 0; + + p += 5; + while (ossl_isspace(*p)) + p++; + + *value = p; + return 1; +} + +int X509_ACERT_add_attr_nconf(CONF *conf, const char *section, + X509_ACERT *acert) +{ + int ret = 0, i; + STACK_OF(CONF_VALUE) *attr_sk = NCONF_get_section(conf, section); + + if (attr_sk == NULL) + goto err; + + for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { + CONF_VALUE *v = sk_CONF_VALUE_value(attr_sk, i); + const char *value = v->value; + + if (value == NULL) { + ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES, + "name=%s,section=%s",v->name, section); + goto err; + } + + if (check_asn1_attribute(&value) == 1) { + int att_len; + unsigned char *att_data = NULL; + ASN1_TYPE *asn1 = ASN1_generate_nconf(value, conf); + + if (asn1 == NULL) + goto err; + + att_len = i2d_ASN1_TYPE(asn1, &att_data); + + ret = X509_ACERT_add1_attr_by_txt(acert, v->name, V_ASN1_SEQUENCE, + att_data, att_len); + OPENSSL_free(att_data); + ASN1_TYPE_free(asn1); + + if (!ret) + goto err; + } else { + ret = X509_ACERT_add1_attr_by_txt(acert, v->name, + V_ASN1_OCTET_STRING, + (unsigned char *)value, + strlen(value)); + if (!ret) + goto err; + } + } + ret = 1; +err: + return ret; +} + +void *X509_ACERT_get_ext_d2i(const X509_ACERT *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->acinfo->extensions, nid, crit, idx); +} + +int X509_ACERT_add1_ext_i2d(X509_ACERT *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->acinfo->extensions, nid, value, crit, flags); +} + +const STACK_OF(X509_EXTENSION) *X509_ACERT_get0_extensions(const X509_ACERT *x) +{ + return x->acinfo->extensions; +} diff --git a/crypto/x509/x509_acert.h b/crypto/x509/x509_acert.h new file mode 100644 index 0000000000000..e2680d329739d --- /dev/null +++ b/crypto/x509/x509_acert.h @@ -0,0 +1,22 @@ +/* + * 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 + */ + +#ifndef OSSL_CRYPTO_X509_X509_ACERT_H +# define OSSL_CRYPTO_X509_X509_ACERT_H + +#include + +# define X509_ACERT_ISSUER_V2 1 + +DECLARE_ASN1_ITEM(OSSL_OBJECT_DIGEST_INFO) +DECLARE_ASN1_ITEM(OSSL_ISSUER_SERIAL) +DECLARE_ASN1_ITEM(X509_ACERT_ISSUER_V2FORM) +DECLARE_ASN1_ITEM(X509_ACERT_ISSUER) +DECLARE_ASN1_ITEM(X509_HOLDER) +#endif diff --git a/crypto/x509/x509aset.c b/crypto/x509/x509aset.c new file mode 100644 index 0000000000000..3d7e5fbb21dc8 --- /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 +#include +#include +#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/crypto/x509/x_all.c b/crypto/x509/x_all.c index 3e4c852b70a10..3083eb1dca9b7 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "internal/asn1.h" #include "crypto/pkcs7.h" #include "crypto/x509.h" +#include "crypto/x509_acert.h" #include "crypto/rsa.h" int X509_verify(X509 *a, EVP_PKEY *r) @@ -51,6 +53,16 @@ int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) return X509_REQ_verify_ex(a, r, NULL, NULL); } +int X509_ACERT_verify(X509_ACERT *a, EVP_PKEY *r) +{ + if (X509_ALGOR_cmp(&a->sig_alg, &a->acinfo->signature) != 0) + return 0; + + return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_ACERT_INFO), &a->sig_alg, + &a->signature, a->acinfo, + NULL, r, NULL, NULL); +} + int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) { return ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), @@ -173,6 +185,21 @@ X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) ASN1_ITEM_rptr(X509_CRL)); } +int X509_ACERT_sign(X509_ACERT *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_ACERT_INFO), &x->sig_alg, + &x->acinfo->signature, + &x->signature, x->acinfo, NULL, + pkey, md, NULL, NULL); +} + +int X509_ACERT_sign_ctx(X509_ACERT *x, EVP_MD_CTX *ctx) +{ + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_ACERT_INFO), + &x->sig_alg, &x->acinfo->signature, &x->signature, + &x->acinfo, ctx); +} + int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { return @@ -824,3 +851,25 @@ EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) { return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); } + +#ifndef OPENSSL_NO_STDIO +X509_ACERT *d2i_X509_ACERT_fp(FILE *fp, X509_ACERT **acert) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_ACERT), fp, acert); +} + +int i2d_X509_ACERT_fp(FILE *fp, const X509_ACERT *acert) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_ACERT), fp, acert); +} +#endif + +X509_ACERT *d2i_X509_ACERT_bio(BIO *bp, X509_ACERT **acert) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_ACERT), bp, acert); +} + +int i2d_X509_ACERT_bio(BIO *bp, const X509_ACERT *acert) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_ACERT), bp, acert); +} diff --git a/crypto/x509/x_ietfatt.c b/crypto/x509/x_ietfatt.c new file mode 100644 index 0000000000000..08db0bafc7200 --- /dev/null +++ b/crypto/x509/x_ietfatt.c @@ -0,0 +1,240 @@ +/* + * 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 +#include +#include + +/*- + * Definition of IetfAttrSyntax from RFC 5755 4.4 + * + * IetfAttrSyntax ::= SEQUENCE { + * policyAuthority [0] GeneralNames OPTIONAL, + * values SEQUENCE OF CHOICE { + * octets OCTET STRING, + * oid OBJECT IDENTIFIER, + * string UTF8String + * } + * } + * + * Section 4.4.2 states that all values in the sequence MUST use the + * same choice of value (octet, oid or string). + */ + +struct OSSL_IETF_ATTR_SYNTAX_VALUE_st { + int type; + union { + ASN1_OCTET_STRING *octets; + ASN1_OBJECT *oid; + ASN1_UTF8STRING *string; + } u; +}; + +struct OSSL_IETF_ATTR_SYNTAX_st { + GENERAL_NAMES *policyAuthority; + int type; + STACK_OF(OSSL_IETF_ATTR_SYNTAX_VALUE) *values; +}; + +ASN1_CHOICE(OSSL_IETF_ATTR_SYNTAX_VALUE) = { + ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.octets, ASN1_OCTET_STRING), + ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.oid, ASN1_OBJECT), + ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.string, ASN1_UTF8STRING), +} ASN1_CHOICE_END(OSSL_IETF_ATTR_SYNTAX_VALUE) + +ASN1_SEQUENCE(OSSL_IETF_ATTR_SYNTAX) = { + ASN1_IMP_SEQUENCE_OF_OPT(OSSL_IETF_ATTR_SYNTAX, policyAuthority, GENERAL_NAME, 0), + ASN1_SEQUENCE_OF(OSSL_IETF_ATTR_SYNTAX, values, OSSL_IETF_ATTR_SYNTAX_VALUE), +} ASN1_SEQUENCE_END(OSSL_IETF_ATTR_SYNTAX) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX_VALUE) + +OSSL_IETF_ATTR_SYNTAX *d2i_OSSL_IETF_ATTR_SYNTAX (OSSL_IETF_ATTR_SYNTAX **a, + const unsigned char **in, + long len) +{ + OSSL_IETF_ATTR_SYNTAX *ias; + int i; + + ias = (OSSL_IETF_ATTR_SYNTAX *) ASN1_item_d2i((ASN1_VALUE **)a, in, len, + OSSL_IETF_ATTR_SYNTAX_it()); + if (ias == NULL) + return ias; + + for (i = 0; i < sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(ias->values); i++) + { + OSSL_IETF_ATTR_SYNTAX_VALUE *val; + + val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(ias->values, i); + if (i == 0) + ias->type = val->type; + else if (val->type != ias->type) + goto invalid_types; + } + + return ias; + +invalid_types: + OSSL_IETF_ATTR_SYNTAX_free(ias); + if (a) + *a = NULL; + ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; +} + +int i2d_OSSL_IETF_ATTR_SYNTAX (const OSSL_IETF_ATTR_SYNTAX *a, + unsigned char **out) +{ + return ASN1_item_i2d((const ASN1_VALUE *)a, out, OSSL_IETF_ATTR_SYNTAX_it()); +} + +int OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX *a) +{ + if (a->values == NULL) + return 0; + + return sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(a->values); +} + +const GENERAL_NAMES * +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX *a) +{ + return a->policyAuthority; +} + +void OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX *a, + GENERAL_NAMES *names) +{ + GENERAL_NAMES_free(a->policyAuthority); + a->policyAuthority = names; +} + +void *OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX *a, + int ind, int *type) +{ + OSSL_IETF_ATTR_SYNTAX_VALUE *val; + + val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(a->values, ind); + if (val == NULL) + return NULL; + + if (type != NULL) + *type = val->type; + + switch (val->type) { + case OSSL_IETFAS_OCTETS: + return val->u.octets; + case OSSL_IETFAS_OID: + return val->u.oid; + case OSSL_IETFAS_STRING: + return val->u.string; + } + + return NULL; +} + +int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type, + void *data) +{ + OSSL_IETF_ATTR_SYNTAX_VALUE *val; + + if (data == NULL) + return 0; + + if (a->values == NULL) { + if ((a->values = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_new_null()) == NULL) + goto err; + a->type = type; + } + + if (type != a->type) { + ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + if ((val = OSSL_IETF_ATTR_SYNTAX_VALUE_new()) == NULL) + goto err; + + val->type = type; + switch (type) { + case OSSL_IETFAS_OCTETS: + val->u.octets = data; + break; + case OSSL_IETFAS_OID: + val->u.oid = data; + break; + case OSSL_IETFAS_STRING: + val->u.string = data; + break; + default: + ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + if (sk_OSSL_IETF_ATTR_SYNTAX_VALUE_push(a->values, val) <= 0) { + OSSL_IETF_ATTR_SYNTAX_VALUE_free(val); + return 0; + } + + return 1; + +err: + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + return 0; +} + +int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, int indent) +{ + int i; + + if (a->policyAuthority != NULL) { + for (i = 0; i < sk_GENERAL_NAME_num(a->policyAuthority); i++) { + if (BIO_printf(bp, "%*s", indent, "") <= 0) + goto err; + + if (GENERAL_NAME_print(bp, sk_GENERAL_NAME_value(a->policyAuthority, + i)) <= 0) + goto err; + + if (BIO_printf(bp, "\n") <= 0) + goto err; + } + } + + for (i = 0; i < OSSL_IETF_ATTR_SYNTAX_get_value_num(a); i++) { + char oidstr[80]; + int ietf_type; + void *attr_value = OSSL_IETF_ATTR_SYNTAX_get0_value(a, i, &ietf_type); + + if (attr_value == NULL) + goto err; + + if (BIO_printf(bp, "%*s", indent, "") <= 0) + goto err; + + switch (ietf_type) { + case OSSL_IETFAS_OID: + OBJ_obj2txt(oidstr, sizeof(oidstr), attr_value, 0); + BIO_printf(bp, "%.*s", (int) sizeof(oidstr), oidstr); + break; + case OSSL_IETFAS_OCTETS: + case OSSL_IETFAS_STRING: + ASN1_STRING_print(bp, attr_value); + break; + } + } + if (BIO_printf(bp, "\n") <= 0) + goto err; + + return 1; + +err: + return 0; +} diff --git a/doc/build.info b/doc/build.info index 326c4ea34bbf2..c7cb6d5d4fb3e 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1719,6 +1719,14 @@ DEPEND[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod GENERATE[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod DEPEND[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod GENERATE[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod +DEPEND[html/man3/OSSL_IETF_ATTR_SYNTAX.html]=man3/OSSL_IETF_ATTR_SYNTAX.pod +GENERATE[html/man3/OSSL_IETF_ATTR_SYNTAX.html]=man3/OSSL_IETF_ATTR_SYNTAX.pod +DEPEND[man/man3/OSSL_IETF_ATTR_SYNTAX.3]=man3/OSSL_IETF_ATTR_SYNTAX.pod +GENERATE[man/man3/OSSL_IETF_ATTR_SYNTAX.3]=man3/OSSL_IETF_ATTR_SYNTAX.pod +DEPEND[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +GENERATE[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +DEPEND[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +GENERATE[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod DEPEND[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod GENERATE[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod DEPEND[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod @@ -2799,6 +2807,26 @@ 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_add1_attr.html]=man3/X509_ACERT_add1_attr.pod +GENERATE[html/man3/X509_ACERT_add1_attr.html]=man3/X509_ACERT_add1_attr.pod +DEPEND[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod +GENERATE[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod +DEPEND[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod +GENERATE[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod +DEPEND[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.pod +GENERATE[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.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_ACERT_get_attr.html]=man3/X509_ACERT_get_attr.pod +GENERATE[html/man3/X509_ACERT_get_attr.html]=man3/X509_ACERT_get_attr.pod +DEPEND[man/man3/X509_ACERT_get_attr.3]=man3/X509_ACERT_get_attr.pod +GENERATE[man/man3/X509_ACERT_get_attr.3]=man3/X509_ACERT_get_attr.pod +DEPEND[html/man3/X509_ACERT_print_ex.html]=man3/X509_ACERT_print_ex.pod +GENERATE[html/man3/X509_ACERT_print_ex.html]=man3/X509_ACERT_print_ex.pod +DEPEND[man/man3/X509_ACERT_print_ex.3]=man3/X509_ACERT_print_ex.pod +GENERATE[man/man3/X509_ACERT_print_ex.3]=man3/X509_ACERT_print_ex.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 @@ -3361,6 +3389,8 @@ html/man3/OSSL_HPKE_CTX_new.html \ html/man3/OSSL_HTTP_REQ_CTX.html \ html/man3/OSSL_HTTP_parse_url.html \ html/man3/OSSL_HTTP_transfer.html \ +html/man3/OSSL_IETF_ATTR_SYNTAX.html \ +html/man3/OSSL_IETF_ATTR_SYNTAX_print.html \ html/man3/OSSL_ITEM.html \ html/man3/OSSL_LIB_CTX.html \ html/man3/OSSL_PARAM.html \ @@ -3631,6 +3661,11 @@ 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_add1_attr.html \ +html/man3/X509_ACERT_add_attr_nconf.html \ +html/man3/X509_ACERT_get0_holder_baseCertId.html \ +html/man3/X509_ACERT_get_attr.html \ +html/man3/X509_ACERT_print_ex.html \ html/man3/X509_ALGOR_dup.html \ html/man3/X509_ATTRIBUTE.html \ html/man3/X509_CRL_get0_by_serial.html \ @@ -4006,6 +4041,8 @@ man/man3/OSSL_HPKE_CTX_new.3 \ man/man3/OSSL_HTTP_REQ_CTX.3 \ man/man3/OSSL_HTTP_parse_url.3 \ man/man3/OSSL_HTTP_transfer.3 \ +man/man3/OSSL_IETF_ATTR_SYNTAX.3 \ +man/man3/OSSL_IETF_ATTR_SYNTAX_print.3 \ man/man3/OSSL_ITEM.3 \ man/man3/OSSL_LIB_CTX.3 \ man/man3/OSSL_PARAM.3 \ @@ -4276,6 +4313,11 @@ 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_add1_attr.3 \ +man/man3/X509_ACERT_add_attr_nconf.3 \ +man/man3/X509_ACERT_get0_holder_baseCertId.3 \ +man/man3/X509_ACERT_get_attr.3 \ +man/man3/X509_ACERT_print_ex.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/OSSL_IETF_ATTR_SYNTAX.pod b/doc/man3/OSSL_IETF_ATTR_SYNTAX.pod new file mode 100644 index 0000000000000..816ad799b0cd0 --- /dev/null +++ b/doc/man3/OSSL_IETF_ATTR_SYNTAX.pod @@ -0,0 +1,97 @@ +=pod + +=head1 NAME + +OSSL_IETF_ATTR_SYNTAX, +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority, +OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority, +OSSL_IETF_ATTR_SYNTAX_get_value_num, +OSSL_IETF_ATTR_SYNTAX_get0_value, +OSSL_IETF_ATTR_SYNTAX_add1_value +- Accessors and setters for OSSL_IETF_ATTR_SYNTAX + +=head1 SYNOPSIS + + #include + + typedef struct OSSL_IETF_ATTR_SYNTAX_st OSSL_IETF_ATTR_SYNTAX; + + const GENERAL_NAMES * + OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX *a); + void OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX *a, + GENERAL_NAMES *names); + + int OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX *a); + void *OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX *a, + int ind, int *type); + int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type, + void *data); + +=head1 DESCRIPTION + +B is an opaque structure that represents the +IetfAttrSyntax type defined in RFC 5755 (Section 4.4) for use +as an AttributeValue. + +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority() and OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority() +get and set the policyAuthority field of the structure. Both routines act on +internal pointers of the structure and must not be freed by the application. + +An B object also holds a sequence of values. +OSSL_IETF_ATTR_SYNTAX_get_value_num() returns the number of values in the +sequence. OSSL_IETF_ATTR_SYNTAX_add1_value(), adds a copy of I of a specified +I to the sequence. The caller should free the I after use. + +OSSL_IETF_ATTR_SYNTAX_get0_value() will return the value and a specific index I +in the sequence or NULL on error. If I is not NULL, the type of the +value will be written to this location. + +The I of the values stored in the B value sequence is +one of the following: + +=over 4 + +=item OSSL_IETFAS_OCTETS + +A pointer to an ASN1_OCTET_STRING + +=item OSSL_IETFAS_OID + +A pointer to an ASN1_OBJECT + +=item OSSL_IETFAS_STRING + +A pointer to an ASN1_UTF8STRING + +=back + +=head1 RETURN VALUES + +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority() returns an pointer to a +B structure or B if the policy authority has not been +set. + +OSSL_IETF_ATTR_SYNTAX_get_value_num() returns the number of entries in the value +sequence or -1 on error. + +OSSL_IETF_ATTR_SYNTAX_get0_value() returns a pointer to the value at the given index +or NULL if the index is out of range. + +OSSL_IETF_ATTR_SYNTAX_add1_value() returns 1 on success and 0 on failure. + +=head1 HISTORY + +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(), OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(), +OSSL_IETF_ATTR_SYNTAX_get_value_num(), OSSL_IETF_ATTR_SYNTAX_get0_value(), and +OSSL_IETF_ATTR_SYNTAX_add1_value() were added in OpenSSL 3.4. + +=head1 COPYRIGHT + +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 +L. + +=cut diff --git a/doc/man3/OSSL_IETF_ATTR_SYNTAX_print.pod b/doc/man3/OSSL_IETF_ATTR_SYNTAX_print.pod new file mode 100644 index 0000000000000..6fa0ddae5e015 --- /dev/null +++ b/doc/man3/OSSL_IETF_ATTR_SYNTAX_print.pod @@ -0,0 +1,41 @@ +=pod + +=head1 NAME + +OSSL_IETF_ATTR_SYNTAX_print - OSSL_IETF_ATTR_SYNTAX printing + +=head1 SYNOPSIS + + #include + + int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, + int indent); + +=head1 DESCRIPTION + +OSSL_IETF_ATTR_SYNTAX_print() prints a human readable version of I to +BIO I. +Each line of the output is indented by I spaces. + +=head1 RETURN VALUES + +OSSL_IETF_ATTR_SYNTAX_print() return 1 on success or 0 on failure. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +OSSL_IETF_ATTR_SYNTAX_print() was added in OpenSSL 3.4. + +=head1 COPYRIGHT + +Copyright 2021-2022 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. + +=cut diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod index ac93920addec3..6e521b268f0db 100644 --- a/doc/man3/PEM_read_bio_PrivateKey.pod +++ b/doc/man3/PEM_read_bio_PrivateKey.pod @@ -26,6 +26,8 @@ PEM_write_bio_Parameters, PEM_read_bio_DSAparams, PEM_read_DSAparams, PEM_write_bio_DSAparams, PEM_write_DSAparams, PEM_read_bio_DHparams, PEM_read_DHparams, PEM_write_bio_DHparams, PEM_write_DHparams, PEM_read_bio_X509, PEM_read_X509, PEM_write_bio_X509, PEM_write_X509, +PEM_read_bio_X509_ACERT, PEM_read_X509_ACERT, +PEM_write_bio_X509_ACERT, PEM_write_X509_ACERT, PEM_read_bio_X509_AUX, PEM_read_X509_AUX, PEM_write_bio_X509_AUX, PEM_write_X509_AUX, PEM_read_bio_X509_REQ, PEM_read_X509_REQ, PEM_write_bio_X509_REQ, PEM_write_X509_REQ, PEM_write_bio_X509_REQ_NEW, @@ -108,6 +110,13 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines int PEM_write_bio_X509(BIO *bp, X509 *x); int PEM_write_X509(FILE *fp, X509 *x); + X509_ACERT *PEM_read_bio_X509_ACERT(BIO *bp, X509_ACERT **x, + pem_password_cb *cb, void *u); + X509_ACERT *PEM_read_X509_ACERT(FILE *fp, X509_ACERT **x, + pem_password_cb *cb, void *u); + int PEM_write_bio_X509_ACERT(BIO *bp, X509_ACERT *x); + int PEM_write_X509_ACERT(FILE *fp, X509_ACERT *x); + X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u); X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u); int PEM_write_bio_X509_AUX(BIO *bp, X509 *x); @@ -287,6 +296,9 @@ The B functions process an X509 certificate using an X509 structure. They will also process a trusted X509 certificate but any trust settings are discarded. +The B functions process an X509 attribute certificate using +an X509_ACERT structure. + The B functions process a trusted X509 certificate using an X509 structure. diff --git a/doc/man3/X509V3_get_d2i.pod b/doc/man3/X509V3_get_d2i.pod index 4a2e81b0dbdff..b5abd2ff28c85 100644 --- a/doc/man3/X509V3_get_d2i.pod +++ b/doc/man3/X509V3_get_d2i.pod @@ -4,9 +4,10 @@ X509V3_get_d2i, X509V3_add1_i2d, X509V3_EXT_d2i, X509V3_EXT_i2d, X509_get_ext_d2i, X509_add1_ext_i2d, +X509_ACERT_get_ext_d2i, X509_ACERT_add1_ext_i2d, X509_CRL_get_ext_d2i, X509_CRL_add1_ext_i2d, X509_REVOKED_get_ext_d2i, X509_REVOKED_add1_ext_i2d, -X509_get0_extensions, X509_CRL_get0_extensions, +X509_get0_extensions, X509_ACERT_get0_extensions, X509_CRL_get0_extensions, X509_REVOKED_get0_extensions - X509 extension decode and encode functions =head1 SYNOPSIS @@ -25,6 +26,10 @@ X509_REVOKED_get0_extensions - X509 extension decode and encode functions int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags); + void *X509_ACERT_get_ext_d2i(const X509_ACERT *x, int nid, int *crit, int *idx); + int X509_ACERT_add1_ext_i2d(X509_ACERT *x, int nid, void *value, int crit, + unsigned long flags); + void *X509_CRL_get_ext_d2i(const X509_CRL *crl, int nid, int *crit, int *idx); int X509_CRL_add1_ext_i2d(X509_CRL *crl, int nid, void *value, int crit, unsigned long flags); @@ -34,6 +39,7 @@ X509_REVOKED_get0_extensions - X509 extension decode and encode functions unsigned long flags); const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); + const STACK_OF(X509_EXTENSION) *X509_ACERT_get0_extensions(const X509 *x); const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r); @@ -64,6 +70,10 @@ X509_get_ext_d2i() and X509_add1_ext_i2d() operate on the extensions of certificate I. They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). +X509_ACERT_get_ext_d2i() and X509_ACERT_add1_ext_i2d() operate on the extensions +of B structure I. They are otherwise identical to X509V3_get_d2i() +and X509V3_add1_i2d(). + X509_CRL_get_ext_d2i() and X509_CRL_add1_ext_i2d() operate on the extensions of CRL I. They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). @@ -72,9 +82,10 @@ X509_REVOKED_get_ext_d2i() and X509_REVOKED_add1_ext_i2d() operate on the extensions of B structure I (i.e for CRL entry extensions). They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). -X509_get0_extensions(), X509_CRL_get0_extensions() and -X509_REVOKED_get0_extensions() return a STACK of all the extensions -of a certificate, a CRL or a CRL entry respectively. +X509_get0_extensions(), X509_ACERT_get0_extensions(), +X509_CRL_get0_extensions() and X509_REVOKED_get0_extensions() return a +STACK of all the extensions of a certificate, an attribute certificate, +a CRL or a CRL entry respectively. =head1 NOTES diff --git a/doc/man3/X509_ACERT_add1_attr.pod b/doc/man3/X509_ACERT_add1_attr.pod new file mode 100644 index 0000000000000..ab6a25667048f --- /dev/null +++ b/doc/man3/X509_ACERT_add1_attr.pod @@ -0,0 +1,67 @@ +=pod + +=head1 NAME + +X509_ACERT_add1_attr, +X509_ACERT_add1_attr_by_NID, +X509_ACERT_add1_attr_by_OBJ, +X509_ACERT_add1_attr_by_txt, +X509_ACERT_delete_attr +- X509_ACERT attribute functions + +=head1 SYNOPSIS + + #include + + int X509_ACERT_add1_attr(X509_ACERT *x, X509_ATTRIBUTE *attr); + int X509_ACERT_add1_attr_by_NID(X509_ACERT *x, int nid, int type, + const void *bytes, int len); + int X509_ACERT_add1_attr_by_OBJ(X509_ACERT *x, const ASN1_OBJECT *obj, + int type, const void *bytes, int len); + int X509_ACERT_add1_attr_by_txt(X509_ACERT *x, const char *attrname, int type, + const unsigned char *bytes, int len); + X509_ATTRIBUTE *X509_ACERT_delete_attr(X509_ACERT *x, int loc); + +=head1 DESCRIPTION + +X509_ACERT_add1_attr() adds a constructed X509_ATTRIBUTE B to the +existing X509_ACERT structure B. + +X509_ACERT_add1_attr_by_NID() and X509_ACERT_add1_attr_by_OBJ() +add an attribute of type I or I with a value of ASN1 +type I constructed using I bytes from I. + +X509_ACERT_add1_attr_by_txt() adds an attribute of type I with a value of +ASN1 type I constructed using I bytes from I. + +X509_ACERT_delete_attr() will delete the Ith attribute from I and +return a pointer to it or NULL if there are fewer than I attributes +contained in I. + +=head1 RETURN VALUES + +X509_ACERT_add1_attr(), X509_ACERT_add1_attr_by_NID(), and +X509_ACERT_add1_attr_by_OBJ() return 1 for success and 0 for failure. + +X509_ACERT_delete_attr() returns a B pointer on +success or NULL on failure. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +X509_ACERT_add1_attr(), X509_ACERT_add1_attr_by_NID(), X509_ACERT_add1_attr_by_OBJ(), +X509_ACERT_add1_attr_by_txt() and X509_ACERT_delete_attr() 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. + +=cut diff --git a/doc/man3/X509_ACERT_add_attr_nconf.pod b/doc/man3/X509_ACERT_add_attr_nconf.pod new file mode 100644 index 0000000000000..a16d31c3f3698 --- /dev/null +++ b/doc/man3/X509_ACERT_add_attr_nconf.pod @@ -0,0 +1,63 @@ +=pod + +=head1 NAME + +X509_ACERT_add_attr_nconf +- Add attributes to X509_ACERT from configuration section + +=head1 SYNOPSIS + + #include + + int X509_ACERT_add_attr_nconf(CONF *conf, const char *section, + X509_ACERT *acert); + +=head1 DESCRIPTION + +X509_ACERT_add_attr_nconf() adds one or more Bs to the +existing B structure I. The attributes are read +from a I
of the I object. + +The give I
of the configuration should contain attribute +descriptions of the form: + + attribute_name = value + +The format of B will vary depending on the B. +B can either be a string value or an B +object. + +To encode an B object, use the prefix "ASN1:" followed by +the object description that uses the same syntax as L. +For example: + + id-aca-group = ASN1:SEQUENCE:ietfattr + + [ietfattr] + values = SEQUENCE:groups + + [groups] + 1.string = UTF8:mygroup1 + +=head1 RETURN VALUES + +X509_ACERT_add_attr_nconf() returns 1 for success and 0 for failure. + +=head1 SEE ALSO + +L. + +=head1 HISTORY + +The function X509_ACERT_add_attr_nconf() was 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. + +=cut 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 0000000000000..7741f286d3cd3 --- /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 + + 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 +I, X509_ACERT_set0_holder_baseCertId() sets the identity based on the +issuer and serial number of a certificate detailed in I and +X509_ACERT_set0_holder_digest() sets the holder entity based on digest +information I. 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, 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 can be retrieved with +X509_ACERT_get0_holder_entityName(), X509_ACERT_get0_holder_baseCertId(), and +X509_ACERT_get0_holder_digest(). + +A B 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 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 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 information is given +by I 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 indicates the algorithm used to compute I. + +=head1 RETURN VALUES + +All I/I routines return 1 for success and 0 for failure. +All I 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 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. + +=cut diff --git a/doc/man3/X509_ACERT_get_attr.pod b/doc/man3/X509_ACERT_get_attr.pod new file mode 100644 index 0000000000000..b61cc2510bff7 --- /dev/null +++ b/doc/man3/X509_ACERT_get_attr.pod @@ -0,0 +1,59 @@ +=pod + +=head1 NAME + +X509_ACERT_get_attr, +X509_ACERT_get_attr_by_NID, +X509_ACERT_get_attr_by_OBJ, +X509_ACERT_get_attr_count +- Retrieve attributes from an X509_ACERT structure + +=head1 SYNOPSIS + + #include + + X509_ATTRIBUTE *X509_ACERT_get_attr(const X509_ACERT *x, int loc); + int X509_ACERT_get_attr_by_NID(const X509_ACERT *x, int nid, int lastpos); + int X509_ACERT_get_attr_by_OBJ(const X509_ACERT *x, const ASN1_OBJECT *obj, + int lastpos); + int X509_ACERT_get_attr_count(const X509_ACERT *x); + +=head1 DESCRIPTION + +X509_ACERT_get0_attr() retrieves the Ith B from an +B I. X509_ACERT_get_attr_count() returns the total number +of attributes in the B. + +X509_ACERT_get_attr_by_NID() and X509_ACERT_get_attr_by_OBJ() retrieve the next +attribute location matching I or I after I. I +should initially be set to -1. +If there are no more entries -1 is returned. If I is invalid +(doesn't correspond to a valid OID) then -2 is returned. + +=head1 RETURN VALUES + +X509_ACERT_get0_attr() return a B from an attribute +certificate, or NULL if the specified attribute is not found. + +X509_ACERT_get_attr_by_NID() and X509_ACERT_get_attr_by_OBJ() return +the location of the next attribute requested or -1 if not found. +X509_ACERT_get_attr_by_NID() can also return -2 if the supplied NID is invalid. + +X509_ACERT_get_attr_count() returns the number of attributes in the given +attribute certificate. + +=head1 HISTORY + +X509_ACERT_get0_attr(), X509_ACERT_get_attr_by_NID(), X509_ACERT_get_attr_by_OBJ() and +X509_ACERT_get_attr_count() 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. + +=cut diff --git a/doc/man3/X509_ACERT_print_ex.pod b/doc/man3/X509_ACERT_print_ex.pod new file mode 100644 index 0000000000000..3a5e0c7a518df --- /dev/null +++ b/doc/man3/X509_ACERT_print_ex.pod @@ -0,0 +1,112 @@ +=pod + +=head1 NAME + +X509_ACERT_print_ex, X509_ACERT_print +- X509_ACERT printing routines + +=head1 SYNOPSIS + + #include + + int X509_ACERT_print(BIO *bp, X509_ACERT *acert); + int X509_ACERT_print_ex(BIO *bp, X509_ACERT *acert, unsigned long nmflags, + unsigned long cflag); + +=head1 DESCRIPTION + +X509_ACERT_print_ex() prints a human readable version of the attribute +certificate I to BIO I. + +The following data contained in the attribute certificate is printed +in order: + +=over 4 + +=item * + +The header text "Attribute certificate:" and "Data:" (X509_FLAG_NO_HEADER) + += item * + +The attribute certificate version number as defined by the standard, +followed in parentheses by the value contained in the version field in +hexadecimal notation. If the version number is not a valid value according +to the specification, only the raw value is printed. +See X509_ACERT_get_version(3) for details. (X509_FLAG_NO_VERSION) + += item * + +The serial number of the attribute certificate (X509_FLAG_NO_SERIAL) + += item * + +The identity of the holder of the attribute certificate. If the +holder issuer name is present, the first GENERAL_NAME +returned by X509_ACERT_get0_holder_entityName() is printed. +If the holder baseCertificateId is present, the issuer name +(printed with X509_NAME_print_ex) and serial number of the +holder's certificate are displayed. (X509_FLAG_NO_SUBJECT) + += item * + +The name of the attribute certificate issuer as returned from +X509_ACERT_get0_issuerName() and printed using X509_NAME_print_ex(). +(X509_FLAG_NO_ISSUER) + += item * + +The period of validity between the times returned from X509_ACERT_get0_notBefore() +and X509_ACERT_get0_notAfter(). The values are printed as a generalized times +using ASN1_GENERALIZEDTIME_print(). (X509_FLAG_NO_VALIDITY) + += item * + +The list of attributes contained in the attribute certificate. +The attribute type is printed with i2a_ASN1_OBJECT(). String valued +attributes are printed as raw string data. ASN1 encoded values are +printed with ASN1_parse_dump(). (X509_FLAG_NO_ATTRIBUTES) + += item * + +All X.509 extensions contained in the attribute certificate. (X509_FLAG_NO_EXTENSIONS) + += item * + +The signature is printed with X509_signature_print(). (X509_FLAG_NO_SIGDUMP) + +If I is specifies as X509_FLAG_COMPAT, all of the above data in the +attribute certificate will be printed. + +The I flag determines the format used to output all fields printed using +X509_NAME_print_ex(). See L for details. + +X509_ACERT_print() is equivalent to calling X509_ACERT_print_ex() with the +I and I set to XN_FLAG_COMPAT and X509_FLAG_COMPAT +respectively. + +=back + +=head1 RETURN VALUES + +X509_ACERT_print_ex() X509_ACERT_print() return 1 for +success and 0 for failure. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +X509_ACERT_print() and X509_ACERT_print_ex() 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. + +=cut diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod index 86a259f025f11..4ecd5c0830c9f 100644 --- a/doc/man3/X509_dup.pod +++ b/doc/man3/X509_dup.pod @@ -79,6 +79,9 @@ GENERAL_NAME_free, GENERAL_NAME_new, GENERAL_SUBTREE_free, GENERAL_SUBTREE_new, +OSSL_IETF_ATTR_SYNTAX_free, +OSSL_IETF_ATTR_SYNTAX_it, +OSSL_IETF_ATTR_SYNTAX_new, IPAddressChoice_free, IPAddressChoice_new, IPAddressFamily_free, @@ -171,6 +174,13 @@ OSSL_CRMF_PKIPUBLICATIONINFO_new, OSSL_CRMF_SINGLEPUBINFO_free, OSSL_CRMF_SINGLEPUBINFO_it, OSSL_CRMF_SINGLEPUBINFO_new, +OSSL_IETF_ATTR_SYNTAX_VALUE_free, +OSSL_IETF_ATTR_SYNTAX_VALUE_it, +OSSL_IETF_ATTR_SYNTAX_VALUE_new, +OSSL_ISSUER_SERIAL_free, +OSSL_ISSUER_SERIAL_new, +OSSL_OBJECT_DIGEST_INFO_free, +OSSL_OBJECT_DIGEST_INFO_new, OTHERNAME_free, OTHERNAME_new, PBE2PARAM_free, @@ -265,6 +275,15 @@ TS_TST_INFO_free, TS_TST_INFO_new, USERNOTICE_free, USERNOTICE_new, +X509_ACERT_dup, +X509_ACERT_free, +X509_ACERT_it, +X509_ACERT_new, +X509_ACERT_INFO_free, +X509_ACERT_INFO_it, +X509_ACERT_INFO_new, +X509_ACERT_ISSUER_V2FORM_free, +X509_ACERT_ISSUER_V2FORM_new, X509_ALGOR_free, X509_ALGOR_it, X509_ALGOR_new, diff --git a/doc/man3/X509_get0_notBefore.pod b/doc/man3/X509_get0_notBefore.pod index 1ca0a1b128aa8..84dee91850c2d 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 fields of I to I. Ownership of the passed parameter I 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 and B fields of certificate B 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 +and B fields of B to B. Ownership of the passed +parameter B 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 and B fields of I. The value returned is an internal pointer which must not be freed up after @@ -67,9 +85,16 @@ or NULL if the B 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 and B routines, the B routines +use the ASN1_GENERALIZEDTIME format instead of ASN1_TIME for holding time +data. + =head1 SEE ALSO L, +L L, L, L, diff --git a/doc/man3/X509_get0_signature.pod b/doc/man3/X509_get0_signature.pod index a49a70038e31f..485d39bf25125 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 + + 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 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. 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 48ae5afc4243a..c265ce09bcff4 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 + + 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 or NULL if the fields are not present. +X509_ACERT_get0_issuerUID() returns the issuer unique identifier of the +attribute certificate B 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, @@ -45,6 +55,12 @@ L, L, L +=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 5594c8a284b06..ac93a33b8f266 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 + + 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 as an @@ -28,12 +35,19 @@ X509_set_serialNumber() sets the serial number of certificate B to B. A copy of the serial number is used internally so B 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 -structure. +X509_get_serialNumber(), X509_get0_serialNumber() and +X509_ACERT_get0_serialNumber() return a pointer to an B 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 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 64659de6ab6a7..2f392ad7a2e6c 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 + + 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 with a suitable version value, see L: @@ -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. 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. + =head1 RETURN VALUES X509_get_subject_name(), X509_get_issuer_name(), X509_REQ_get_subject_name() -and X509_CRL_get_issuer() return an B pointer. +X509_ACERT_get0_issuerName() and X509_CRL_get_issuer() return +an B 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 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 c5db26c5790ce..d6b11e454fd35 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 + + 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 to I. 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, B, and B. +B, B, B, +and B. =head1 NOTES diff --git a/doc/man3/X509_sign.pod b/doc/man3/X509_sign.pod index 7ca8a1a55ecf8..75c968b1146f8 100644 --- a/doc/man3/X509_sign.pod +++ b/doc/man3/X509_sign.pod @@ -4,6 +4,7 @@ X509_sign, X509_sign_ctx, X509_REQ_sign, X509_REQ_sign_ctx, +X509_ACERT_sign, X509_ACERT_sign_ctx, X509_CRL_sign, X509_CRL_sign_ctx - sign certificate, certificate request, or CRL signature @@ -20,6 +21,11 @@ sign certificate, certificate request, or CRL signature int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); + #include + + int X509_ACERT_sign(X509_ACERT *x, EVP_PKEY *pkey, const EVP_MD *md); + int X509_ACERT_sign_ctx(X509_ACERT *x, EVP_MD_CTX *ctx); + =head1 DESCRIPTION X509_sign() signs certificate I using private key I and message @@ -29,6 +35,7 @@ If the certificate information includes X.509 extensions, these two functions make sure that the certificate bears X.509 version 3. X509_REQ_sign(), X509_REQ_sign_ctx(), +X509_ACERT_sign(), X509_ACERT_sign_ctx(), X509_CRL_sign(), and X509_CRL_sign_ctx() sign certificate requests and CRLs, respectively. @@ -68,6 +75,9 @@ available in all versions of OpenSSL. The X509_sign_ctx(), X509_REQ_sign_ctx() and X509_CRL_sign_ctx() functions were added in OpenSSL 1.0.1. +The X509_ACERT_sign() and X509_ACERT_sign_ctx() functions were added +in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/X509_verify.pod b/doc/man3/X509_verify.pod index 8cdb2154ae511..e6c35675f80c7 100644 --- a/doc/man3/X509_verify.pod +++ b/doc/man3/X509_verify.pod @@ -4,7 +4,7 @@ X509_verify, X509_self_signed, X509_REQ_verify_ex, X509_REQ_verify, -X509_CRL_verify - +X509_CRL_verify, X509_ACERT_verify - verify certificate, certificate request, or CRL signature =head1 SYNOPSIS @@ -19,6 +19,9 @@ verify certificate, certificate request, or CRL signature int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); + #include + int X509_ACERT_verify(X509_CRL *a, EVP_PKEY *r); + =head1 DESCRIPTION X509_verify() verifies the signature of certificate I using public key @@ -31,8 +34,9 @@ authority key identifier (if present) must match the subject key identifier etc. The signature itself is actually verified only if B is 1, as for explicitly trusted certificates this verification is not worth the effort. -X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify() -verify the signatures of certificate requests and CRLs, respectively. +X509_REQ_verify_ex(), X509_REQ_verify(), X509_CRL_verify() and X509_ACERT_verify() +verify the signatures of certificate requests, CRLs and attribute certificates +respectively. =head1 RETURN VALUES @@ -71,6 +75,8 @@ functions are available in all versions of OpenSSL. X509_REQ_verify_ex(), and X509_self_signed() were added in OpenSSL 3.0. +X509_ACERT_verify() was added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod index 00efb60358166..06f764ef8bb8c 100644 --- a/doc/man3/d2i_X509.pod +++ b/doc/man3/d2i_X509.pod @@ -100,6 +100,7 @@ d2i_OSSL_CRMF_MSGS, d2i_OSSL_CRMF_PBMPARAMETER, d2i_OSSL_CRMF_PKIPUBLICATIONINFO, d2i_OSSL_CRMF_SINGLEPUBINFO, +d2i_OSSL_IETF_ATTR_SYNTAX, d2i_OTHERNAME, d2i_PBE2PARAM, d2i_PBEPARAM, @@ -157,6 +158,9 @@ d2i_USERNOTICE, d2i_X509, d2i_X509_bio, d2i_X509_fp, +d2i_X509_ACERT, +d2i_X509_ACERT_bio, +d2i_X509_ACERT_fp, d2i_X509_ALGOR, d2i_X509_ALGORS, d2i_X509_ATTRIBUTE, @@ -271,6 +275,7 @@ i2d_OSSL_CRMF_MSGS, i2d_OSSL_CRMF_PBMPARAMETER, i2d_OSSL_CRMF_PKIPUBLICATIONINFO, i2d_OSSL_CRMF_SINGLEPUBINFO, +i2d_OSSL_IETF_ATTR_SYNTAX, i2d_OTHERNAME, i2d_PBE2PARAM, i2d_PBEPARAM, @@ -331,6 +336,9 @@ i2d_USERNOTICE, i2d_X509, i2d_X509_bio, i2d_X509_fp, +i2d_X509_ACERT, +i2d_X509_ACERT_bio, +i2d_X509_ACERT_fp, i2d_X509_ALGOR, i2d_X509_ALGORS, i2d_X509_ATTRIBUTE, diff --git a/fuzz/acert.c b/fuzz/acert.c new file mode 100644 index 0000000000000..542e793f9fb46 --- /dev/null +++ b/fuzz/acert.c @@ -0,0 +1,48 @@ +/* + * 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 may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include +#include +#include +#include +#include "fuzzer.h" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_clear_error(); + CRYPTO_free_ex_index(0, -1); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + const unsigned char *p = buf; + unsigned char *der = NULL; + + X509_ACERT *acert = d2i_X509_ACERT(NULL, &p, len); + if (acert != NULL) { + BIO *bio = BIO_new(BIO_s_null()); + + X509_ACERT_print(bio, acert); + BIO_free(bio); + + i2d_X509_ACERT(acert, &der); + OPENSSL_free(der); + + X509_ACERT_free(acert); + } + ERR_clear_error(); + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/fuzz/build.info b/fuzz/build.info index f31178a52462b..21686f980c783 100644 --- a/fuzz/build.info +++ b/fuzz/build.info @@ -10,7 +10,7 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] PROGRAMS{noinst}=asn1 asn1parse bignum bndiv client conf crl server smime - PROGRAMS{noinst}=punycode pem decoder + PROGRAMS{noinst}=punycode pem decoder acert PROGRAMS{noinst}=v3name IF[{- !$disabled{"cmp"} -}] @@ -93,6 +93,10 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] INCLUDE[decoder]=../include {- $ex_inc -} DEPEND[decoder]=../libcrypto {- $ex_lib -} + SOURCE[acert]=acert.c driver.c + INCLUDE[acert]=../include {- $ex_inc -} + DEPEND[acert]=../libcrypto {- $ex_lib -} + SOURCE[punycode]=punycode.c driver.c INCLUDE[punycode]=../include {- $ex_inc -} DEPEND[punycode]=../libcrypto.a {- $ex_lib -} @@ -133,6 +137,7 @@ ENDIF IF[{- !$disabled{tests} -}] PROGRAMS{noinst}=asn1-test asn1parse-test bignum-test bndiv-test client-test conf-test crl-test server-test smime-test PROGRAMS{noinst}=punycode-test pem-test decoder-test + PROGRAMS{noinst}=punycode-test pem-test decoder-test acert-test PROGRAMS{noinst}=v3name-test IF[{- !$disabled{"cmp"} -}] @@ -217,6 +222,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[decoder-test]=../include DEPEND[decoder-test]=../libcrypto + SOURCE[acert-test]=acert.c test-corpus.c + INCLUDE[acert-test]=../include + DEPEND[acert-test]=../libcrypto + SOURCE[punycode-test]=punycode.c test-corpus.c INCLUDE[punycode-test]=../include DEPEND[punycode-test]=../libcrypto.a diff --git a/fuzz/corpora b/fuzz/corpora index 3e7b9b6d1dfa2..9f7667061314e 160000 --- a/fuzz/corpora +++ b/fuzz/corpora @@ -1 +1 @@ -Subproject commit 3e7b9b6d1dfa28b54e8e4206be1bf59338c14c46 +Subproject commit 9f7667061314ecf9a287ce1c9702073ca1e345e3 diff --git a/include/crypto/x509_acert.h b/include/crypto/x509_acert.h new file mode 100644 index 0000000000000..3223bf623447f --- /dev/null +++ b/include/crypto/x509_acert.h @@ -0,0 +1,66 @@ +/* + * 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 + */ + +#ifndef OSSL_CRYPTO_X509_ACERT_H +# define OSSL_CRYPTO_X509_ACERT_H +# pragma once + +# include + +struct ossl_object_digest_info_st { + ASN1_ENUMERATED digestedObjectType; + ASN1_OBJECT *otherObjectTypeID; + X509_ALGOR digestAlgorithm; + ASN1_BIT_STRING objectDigest; +}; + +struct ossl_issuer_serial_st { + STACK_OF(GENERAL_NAME) *issuer; + ASN1_INTEGER serial; + ASN1_BIT_STRING *issuerUID; +}; + +struct X509_acert_issuer_v2form_st { + STACK_OF(GENERAL_NAME) *issuerName; + OSSL_ISSUER_SERIAL *baseCertificateId; + OSSL_OBJECT_DIGEST_INFO *objectDigestInfo; +}; + +typedef struct X509_acert_issuer_st { + int type; + union { + STACK_OF(GENERAL_NAME) *v1Form; + X509_ACERT_ISSUER_V2FORM *v2Form; + } u; +} X509_ACERT_ISSUER; + +typedef struct X509_holder_st { + OSSL_ISSUER_SERIAL *baseCertificateID; + STACK_OF(GENERAL_NAME) *entityName; + OSSL_OBJECT_DIGEST_INFO *objectDigestInfo; +} X509_HOLDER; + +struct X509_acert_info_st { + ASN1_INTEGER version; /* default of v2 */ + X509_HOLDER holder; + X509_ACERT_ISSUER issuer; + X509_ALGOR signature; + ASN1_INTEGER serialNumber; + X509_VAL validityPeriod; + STACK_OF(X509_ATTRIBUTE) *attributes; + ASN1_BIT_STRING *issuerUID; + X509_EXTENSIONS *extensions; +}; + +struct X509_acert_st { + X509_ACERT_INFO *acinfo; + X509_ALGOR sig_alg; + ASN1_BIT_STRING signature; +}; +#endif diff --git a/include/openssl/pem.h b/include/openssl/pem.h index 0446c77019ab8..6ea1a49a69445 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h @@ -58,6 +58,7 @@ extern "C" { # define PEM_STRING_PARAMETERS "PARAMETERS" # define PEM_STRING_CMS "CMS" # define PEM_STRING_SM2PARAMETERS "SM2 PARAMETERS" +# define PEM_STRING_ACERT "ATTRIBUTE CERTIFICATE" # define PEM_TYPE_ENCRYPTED 10 # define PEM_TYPE_MIC_ONLY 20 diff --git a/include/openssl/x509_acert.h.in b/include/openssl/x509_acert.h.in new file mode 100644 index 0000000000000..42376a6cb763e --- /dev/null +++ b/include/openssl/x509_acert.h.in @@ -0,0 +1,156 @@ +/* + * {- join("\n * ", @autowarntext) -} + * + * Copyright 2022 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 + */ + +{- +use OpenSSL::stackhash qw(generate_stack_macros); +-} + +#ifndef OPENSSL_X509_ACERT_H +# define OPENSSL_X509_ACERT_H +# pragma once + +# include +# include +# include + +typedef struct X509_acert_st X509_ACERT; +typedef struct X509_acert_info_st X509_ACERT_INFO; +typedef struct ossl_object_digest_info_st OSSL_OBJECT_DIGEST_INFO; +typedef struct ossl_issuer_serial_st OSSL_ISSUER_SERIAL; +typedef struct X509_acert_issuer_v2form_st X509_ACERT_ISSUER_V2FORM; + +DECLARE_ASN1_FUNCTIONS(X509_ACERT) +DECLARE_ASN1_DUP_FUNCTION(X509_ACERT) +DECLARE_ASN1_ITEM(X509_ACERT_INFO) +DECLARE_ASN1_ALLOC_FUNCTIONS(X509_ACERT_INFO) +DECLARE_ASN1_ALLOC_FUNCTIONS(OSSL_OBJECT_DIGEST_INFO) +DECLARE_ASN1_ALLOC_FUNCTIONS(OSSL_ISSUER_SERIAL) +DECLARE_ASN1_ALLOC_FUNCTIONS(X509_ACERT_ISSUER_V2FORM) + +# ifndef OPENSSL_NO_STDIO +X509_ACERT *d2i_X509_ACERT_fp(FILE *fp, X509_ACERT **acert); +int i2d_X509_ACERT_fp(FILE *fp, const X509_ACERT *acert); +# endif + +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); + +int X509_ACERT_sign(X509_ACERT *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_ACERT_sign_ctx(X509_ACERT *x, EVP_MD_CTX *ctx); +int X509_ACERT_verify(X509_ACERT *a, EVP_PKEY *r); + +# 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); + +int X509_ACERT_print(BIO *bp, X509_ACERT *x); +int X509_ACERT_print_ex(BIO *bp, X509_ACERT *x, unsigned long nmflags, + unsigned long cflag); + +int X509_ACERT_get_attr_count(const X509_ACERT *x); +int X509_ACERT_get_attr_by_NID(const X509_ACERT *x, int nid, int lastpos); +int X509_ACERT_get_attr_by_OBJ(const X509_ACERT *x, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_ACERT_get_attr(const X509_ACERT *x, int loc); +X509_ATTRIBUTE *X509_ACERT_delete_attr(X509_ACERT *x, int loc); + +void *X509_ACERT_get_ext_d2i(const X509_ACERT *x, int nid, int *crit, int *idx); +int X509_ACERT_add1_ext_i2d(X509_ACERT *x, int nid, void *value, int crit, + unsigned long flags); +const STACK_OF(X509_EXTENSION) *X509_ACERT_get0_extensions(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_add1_attr(X509_ACERT *x, X509_ATTRIBUTE *attr); +int X509_ACERT_add1_attr_by_OBJ(X509_ACERT *x, const ASN1_OBJECT *obj, + int type, const void *bytes, int len); +int X509_ACERT_add1_attr_by_NID(X509_ACERT *x, int nid, int type, + const void *bytes, int len); +int X509_ACERT_add1_attr_by_txt(X509_ACERT *x, const char *attrname, int type, + const unsigned char *bytes, int len); +int X509_ACERT_add_attr_nconf(CONF *conf, const char *section, + X509_ACERT *acert); + +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); + +# define OSSL_IETFAS_OCTETS 0 +# define OSSL_IETFAS_OID 1 +# define OSSL_IETFAS_STRING 2 + +typedef struct OSSL_IETF_ATTR_SYNTAX_VALUE_st OSSL_IETF_ATTR_SYNTAX_VALUE; +typedef struct OSSL_IETF_ATTR_SYNTAX_st OSSL_IETF_ATTR_SYNTAX; +{- + generate_stack_macros("OSSL_IETF_ATTR_SYNTAX_VALUE"); +-} + +DECLARE_ASN1_ITEM(OSSL_IETF_ATTR_SYNTAX_VALUE) +DECLARE_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX_VALUE) +DECLARE_ASN1_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX) + +const GENERAL_NAMES * +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX *a); +void OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX *a, + GENERAL_NAMES *names); + +int OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX *a); +void *OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX *a, + int ind, int *type); +int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type, + void *data); +int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, int indent); + +#endif diff --git a/test/build.info b/test/build.info index 52bc392f1206e..b51e0f895e785 100644 --- a/test/build.info +++ b/test/build.info @@ -63,7 +63,8 @@ IF[{- !$disabled{tests} -}] provfetchtest prov_config_test rand_test \ ca_internals_test bio_tfo_test membio_test bio_dgram_test list_test \ fips_version_test x509_test hpke_test pairwise_fail_test \ - nodefltctxtest evp_xof_test x509_load_cert_file_test bio_meth_test + nodefltctxtest evp_xof_test x509_load_cert_file_test bio_meth_test \ + x509_acert_test IF[{- !$disabled{'rpk'} -}] PROGRAMS{noinst}=rpktest @@ -1206,6 +1207,10 @@ ENDIF INCLUDE[cert_comp_test]=../include ../apps/include .. DEPEND[cert_comp_test]=../libcrypto ../libssl libtestutil.a + SOURCE[x509_acert_test]=x509_acert_test.c + INCLUDE[x509_acert_test]=../include ../apps/include + DEPEND[x509_acert_test]=../libcrypto libtestutil.a + {- use File::Spec::Functions; use File::Basename; diff --git a/test/certs/acert.pem b/test/certs/acert.pem new file mode 100644 index 0000000000000..efd2a05dc6e94 --- /dev/null +++ b/test/certs/acert.pem @@ -0,0 +1,5 @@ +Generated with paccor (https://github.com/nsacyber/paccor) + +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIID4zCCAssCAQEwOaA3MB+kHTAbMRkwFwYDVQQDDBBUUE0gTWFudWZhY3R1cmVyAhRADHoGLYO7i9GfV2Yz2rrlRFDPSqA6MDikNjA0MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLZXhhbXBsZS5jb20xDzANBgNVBAsMBlBDVGVzdDANBgkqhkiG9w0BAQsFAAIBATAiGA8yMDE4MDEwMTA1MDAwMFoYDzIwMjgwMTAxMDUwMDAwWjCB7TALBgVngQUCEzECMAAwHAYFZ4EFAhExEzARMAkCAQECAQMCARYEBAAAAAEwEgYFZ4EFAhkxCTAHBgVngQUIAjCBlQYHZ4EFBQEHAjGBiTCBhqBkMC8wDgYGZ4EFEgMBBAQAAgABDBJYWVogQ29tcHV0aW5nIEluYy4MATGABkFCQzEyMzAxMA4GBmeBBRIDAQQEAAcAAgwNTm90IFNwZWNpZmllZAwDSEQxgAgxMjM0QUJDRIMB/6IeMBwMCHVuYW1lIC1yDBA2LjUuMC0xNS1nZW5lcmljMBQGBWeBBQIXMQswCQIBAQIBAQIBETCCAScwbwYDVR0jBGgwZoAUl46DRCrPD3GZndkBbbNDngf6ZHChOKQ2MDQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtleGFtcGxlLmNvbTEPMA0GA1UECwwGUENUZXN0ghRmuv6Ey2JadCAOFysMNOn9CiH45zBBBgNVHSAEOjA4MDYGAioDMDAwLgYIKwYBBQUHAgIwIgwgVENHIFRydXN0ZWQgUGxhdGZvcm0gRW5kb3JzZW1lbnQwcQYDVR0RBGowaKRmMGQxEzARBgZngQUFAQQMB01vZGVsIEExHjAcBgZngQUFAQEMElhZWiBDb21wdXRpbmcgSW5jLjEZMBcGBmeBBQUBBQwNTm90IFNwZWNpZmllZDESMBAGBmeBBQUBBgwGQUJDMTIzMA0GCSqGSIb3DQEBCwUAA4IBAQBKj3TsMcVSu8zFLPwMX5f8SHelruSr0Oi4QCNLwAylo9Oi3loIaIwCRf95+z4SUJjGhyuBBooWP6Io0uWJ43tI7IFHdZ5vMtRIdemD3te+2iYH7OHMzMucsQ3L63n+XHHxhNrMgBOGI9+7Q4Rnvnm7OFFVqSKt5rX0sZFrR12XVD67CA3VC+khyXy1cV/3v95DwWFSHOG2VkiKjDdO2B4WRrK0Cy2J7ZFo0TYtaLNEONABL5nfa9MIXUAgo4hDwhxNSXfirJPgVt8HQNaoQPepHDiZbmRZc38Q1LAUpTxMYDePH0pQDkmI9Tdk+4/CMYhU0CIq6jzRHrOaUwfgNGp9 +-----END ATTRIBUTE CERTIFICATE----- diff --git a/test/certs/acert_bc1.pem b/test/certs/acert_bc1.pem new file mode 100644 index 0000000000000..78e25d65f0ef1 --- /dev/null +++ b/test/certs/acert_bc1.pem @@ -0,0 +1,46 @@ +Extracted from bouncycastle test case +Source: pkix/src/test/j2me/org/bouncycastle/cert/test/AttrCertTest.java +Copyright (c) 2000-2023 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) +SPDX-License-Identifier: MIT + +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2 +dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS +VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2 +dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0 +LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn +aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw +CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY +DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs +ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K +IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0 +TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j +dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw +ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg +ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl +Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt +ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0 +dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8 +L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl +c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ +ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct +ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3 +dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1 +bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy +aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6 +eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov +L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz +b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0 +aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46 +b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+ +CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y +Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv +QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0 +dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph +Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj +aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+ +CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA +A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr +6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3 +Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv +-----END ATTRIBUTE CERTIFICATE----- diff --git a/test/certs/acert_bc2.pem b/test/certs/acert_bc2.pem new file mode 100644 index 0000000000000..4276949f14619 --- /dev/null +++ b/test/certs/acert_bc2.pem @@ -0,0 +1,17 @@ +Extracted from bouncycastle test case +Source: pkix/src/test/java/org/bouncycastle/cert/test/PEMData.java +Copyright (c) 2000-2023 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) +SPDX-License-Identifier: MIT + +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl +IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy +aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV +BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv +dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw +MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV +MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI +NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7 +eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G +odUBlSsJwPPQjZSU +-----END ATTRIBUTE CERTIFICATE----- diff --git a/test/certs/acert_ietf.pem b/test/certs/acert_ietf.pem new file mode 100644 index 0000000000000..fdb6e1114ebe2 --- /dev/null +++ b/test/certs/acert_ietf.pem @@ -0,0 +1,15 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIICPTCCASUCAQEwN6AWMBGkDzANMQswCQYDVQQDDAJDQQIBAqEdpBswGTEXMBUG +A1UEAwwOc2VydmVyLmV4YW1wbGWgLTArpCkwJzElMCMGA1UEAwwcQXR0cmlidXRl +IENlcnRpZmljYXRlIElzc3VlcjANBgkqhkiG9w0BAQsFAAIUA7WQWQKiqrVAIUS4 +LE/ZgBtfV8IwIhgPMjAyMTA2MTUxMjM1MDBaGA8yMDMxMDYxMzEyMzUwMFowQTAj +BggrBgEFBQcKBDEXMBWgCYYHVGVzdHZhbDAIDAZncm91cDEwGgYDVQRIMRMwEaEP +gw1hZG1pbmlzdHJhdG9yMCwwHwYDVR0jBBgwFoAUYm7JaGdsZLtTgt0tqoCK2MrI +i10wCQYDVR04BAIFADANBgkqhkiG9w0BAQsFAAOCAQEARYpFEjordN68NXSLmDae +uruxhw+Zsr9Grom4mqYy/2lAuu58os4xA4Cez9OdkfCZmU9baDBVfMWys7GlCJdg +wn5uO5Kk2eiEWsujO/EV4c5eyXSrsUghQZQKfIVsgeut+7WfmDy/+j8ibbxJxJp/ +KMIoDjBAaMDhhxaCYclm8dJRT9DPba/bCNjuPGeTXslDQSXIfzFDgQkRZ0+Z7s9i +enYBmnH4rvW+SX8v5MzfGOu8VtHAKKBEcCbs2qGwYBEUUsCA/LYKSnOwn655wsd9 +k6KifIGOCVS4ZbK9pDyYcH/6/OmD1eSUwDZsd8CrJYDC31gAu7xqhOsBzR9DL3oD +4Q== +-----END ATTRIBUTE CERTIFICATE----- diff --git a/test/recipes/60-test_x509_acert.t b/test/recipes/60-test_x509_acert.t new file mode 100644 index 0000000000000..2bf58d6a6f75a --- /dev/null +++ b/test/recipes/60-test_x509_acert.t @@ -0,0 +1,24 @@ +#! /usr/bin/env perl +# 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 + +use OpenSSL::Test::Utils; +use OpenSSL::Test qw/:DEFAULT srctop_file/; + +setup("test_x509_acert"); + +plan skip_all => "test_x509_acert uses ec which is not supported by this build" + if disabled("ec"); + +plan tests => 1; + +ok(run(test(["x509_acert_test", srctop_file("test", "certs", "acert.pem"), + srctop_file("test", "certs", "acert_ietf.pem"), + srctop_file("test", "certs", "acert_bc1.pem"), + srctop_file("test", "certs", "acert_bc2.pem")])), + "running x509_acert_test"); + diff --git a/test/recipes/99-test_fuzz_acert.t b/test/recipes/99-test_fuzz_acert.t new file mode 100644 index 0000000000000..f62be1ec69002 --- /dev/null +++ b/test/recipes/99-test_fuzz_acert.t @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +# 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 +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +use OpenSSL::Test qw/:DEFAULT srctop_file/; +use OpenSSL::Test::Utils; + +my $fuzzer = "acert"; +setup("test_fuzz_${fuzzer}"); + +plan tests => 2; # one more due to below require_ok(...) + +require_ok(srctop_file('test','recipes','fuzz.pl')); + +fuzz_ok($fuzzer); diff --git a/test/x509_acert_test.c b/test/x509_acert_test.c new file mode 100644 index 0000000000000..0099d4629e15b --- /dev/null +++ b/test/x509_acert_test.c @@ -0,0 +1,174 @@ +/* + * 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 +#include +#include + +#include "testutil.h" + +static int test_print_acert(int idx) +{ + int ret = 0; + const char *acert_file; + X509_ACERT *acert = NULL; + BIO *bp, *bout; + + if (!TEST_ptr(acert_file = test_get_argument(idx))) + return 0; + + if (!TEST_ptr(bp = BIO_new_file(acert_file, "r"))) + return 0; + + if (!TEST_ptr(bout = BIO_new_fp(stderr, BIO_NOCLOSE))) + goto err; + + if (!TEST_ptr(acert = PEM_read_bio_X509_ACERT(bp, NULL, NULL, NULL))) + goto err; + + if (!TEST_int_eq(X509_ACERT_print(bout, acert), 1)) { + goto err; + } + + ret = 1; + +err: + BIO_free(bp); + BIO_free(bout); + X509_ACERT_free(acert); + return ret; +} + +static int test_acert_sign(void) +{ + int ret = 0; + const char *acert_file; + EVP_PKEY *pkey; + BIO *bp = NULL; + X509_ACERT *acert = NULL; + + if (!TEST_ptr(acert_file = test_get_argument(0))) + return 0; + + if (!TEST_ptr(pkey = EVP_RSA_gen(2048))) + return 0; + + if (!TEST_ptr(bp = BIO_new_file(acert_file, "r"))) + goto err; + + if (!TEST_ptr(acert = PEM_read_bio_X509_ACERT(bp, NULL, NULL, NULL))) + goto err; + + if (!TEST_int_gt(X509_ACERT_sign(acert, pkey, EVP_sha256()), 0) || + !TEST_int_eq(X509_ACERT_verify(acert, pkey), 1)) + goto err; + + ret = 1; + +err: + BIO_free(bp); + X509_ACERT_free(acert); + EVP_PKEY_free(pkey); + return ret; +} + +/* IetfAttrSyntax structure with one value */ +static const unsigned char attr_syntax_single[] = { + 0x30, 0x15, 0xa0, 0x09, 0x86, 0x07, 0x54, 0x65, 0x73, 0x74, 0x76, 0x61, + 0x6c, 0x30, 0x08, 0x0c, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x31 +}; + +/* IetfAttrSyntax structure with multiple values of the same type */ +static const unsigned char attr_syntax_multiple[] = { + 0x30, 0x1d, 0x30, 0x1b, 0x0c, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, + 0x31, 0x0c, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x32, 0x0c, 0x07, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x33 +}; + +/* IetfAttrSyntax structure with multiple values of different types */ +static const unsigned char attr_syntax_diff_type[] = { + 0x30, 0x11, 0x30, 0x0f, 0x04, 0x08, 0x64, 0x65, 0x61, 0x64, 0x63, 0x6f, + 0x64, 0x65, 0x0c, 0x03, 0x61, 0x61, 0x61 +}; + +/* IetfAttrSyntax structure with an invalid/unsupported value type */ +static const unsigned char attr_syntax_invalid_type[] = { + 0x30, 0x05, 0x30, 0x03, 0x02, 0x01, 0x0a +}; + +#define ADD_TEST_DATA(x, valid) {x, sizeof(x), valid} + +struct ietf_type_test_data { + const unsigned char *data; + size_t len; + int valid; +}; + +static const struct ietf_type_test_data ietf_syntax_tests[] = { + ADD_TEST_DATA(attr_syntax_single, 1), + ADD_TEST_DATA(attr_syntax_multiple, 1), + ADD_TEST_DATA(attr_syntax_diff_type, 0), + ADD_TEST_DATA(attr_syntax_invalid_type, 0), +}; + +static int test_object_group_attr(int idx) +{ + int ret = 0; + OSSL_IETF_ATTR_SYNTAX *ias = NULL; + BIO *bout = NULL; + const unsigned char *p; + const struct ietf_type_test_data *test = &ietf_syntax_tests[idx]; + + if (!TEST_ptr(bout = BIO_new_fp(stderr, BIO_NOCLOSE))) + goto done; + + p = test->data; + + ias = d2i_OSSL_IETF_ATTR_SYNTAX(NULL, &p, test->len); + + if ((test->valid && !TEST_ptr(ias)) + || (!test->valid && !TEST_ptr_null(ias))) + goto done; + + if (ias != NULL + && !TEST_int_eq(OSSL_IETF_ATTR_SYNTAX_print(bout, ias, 4), 1)) { + OSSL_IETF_ATTR_SYNTAX_free(ias); + goto done; + } + + ret = 1; + +done: + OSSL_IETF_ATTR_SYNTAX_free(ias); + BIO_free(bout); + return ret; +} + +OPT_TEST_DECLARE_USAGE("[...]\n") +int setup_tests(void) +{ + int cnt; + + if (!test_skip_common_options()) { + TEST_error("Error parsing test options\n"); + return 0; + } + + cnt = test_get_argument_count(); + if (cnt < 1) { + TEST_error("Must specify at least 1 attribute certificate file\n"); + return 0; + } + + ADD_ALL_TESTS(test_print_acert, cnt); + ADD_TEST(test_acert_sign); + ADD_ALL_TESTS(test_object_group_attr, OSSL_NELEM(ietf_syntax_tests)); + + return 1; +} diff --git a/util/libcrypto.num b/util/libcrypto.num index 75813690dcefe..903ca8f899ef6 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5548,3 +5548,86 @@ X509_STORE_get1_objects 5675 3_3_0 EXIST::FUNCTION: OPENSSL_LH_set_thunks 5676 3_3_0 EXIST::FUNCTION: OPENSSL_LH_doall_arg_thunk 5677 3_3_0 EXIST::FUNCTION: OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines 5678 3_3_0 EXIST::FUNCTION:HTTP +d2i_X509_ACERT ? 3_4_0 EXIST::FUNCTION: +i2d_X509_ACERT ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_free ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_new ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_it ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_dup ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_INFO_it ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_INFO_free ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_INFO_new ? 3_4_0 EXIST::FUNCTION: +OSSL_OBJECT_DIGEST_INFO_free ? 3_4_0 EXIST::FUNCTION: +OSSL_OBJECT_DIGEST_INFO_new ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_free ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_new ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_ISSUER_V2FORM_free ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_ISSUER_V2FORM_new ? 3_4_0 EXIST::FUNCTION: +d2i_X509_ACERT_fp ? 3_4_0 EXIST::FUNCTION:STDIO +i2d_X509_ACERT_fp ? 3_4_0 EXIST::FUNCTION:STDIO +PEM_read_X509_ACERT ? 3_4_0 EXIST::FUNCTION:STDIO +PEM_write_X509_ACERT ? 3_4_0 EXIST::FUNCTION:STDIO +PEM_read_bio_X509_ACERT ? 3_4_0 EXIST::FUNCTION: +PEM_write_bio_X509_ACERT ? 3_4_0 EXIST::FUNCTION: +d2i_X509_ACERT_bio ? 3_4_0 EXIST::FUNCTION: +i2d_X509_ACERT_bio ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_holder_entityName ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_holder_baseCertId ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_holder_digest ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_issuerName ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_version ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_signature ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_signature_nid ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_info_sigalg ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_serialNumber ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_notBefore ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_notAfter ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_issuerUID ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set_version ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set0_holder_entityName ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set0_holder_baseCertId ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set0_holder_digest ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set1_issuerName ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set1_serialNumber ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set1_notBefore ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_set1_notAfter ? 3_4_0 EXIST::FUNCTION: +OSSL_OBJECT_DIGEST_INFO_get0_digest ? 3_4_0 EXIST::FUNCTION: +OSSL_OBJECT_DIGEST_INFO_set1_digest ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_get0_issuer ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_get0_serial ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_get0_issuerUID ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_set1_issuer ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_set1_serial ? 3_4_0 EXIST::FUNCTION: +OSSL_ISSUER_SERIAL_set1_issuerUID ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_print ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_print_ex ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_attr_count ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_attr_by_NID ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_attr_by_OBJ ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_attr ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_delete_attr ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add1_attr ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add1_attr_by_OBJ ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add1_attr_by_NID ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add1_attr_by_txt ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_sign ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_sign_ctx ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_verify ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get_ext_d2i ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add1_ext_i2d ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_get0_extensions ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_VALUE_it ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_VALUE_free ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_VALUE_new ? 3_4_0 EXIST::FUNCTION: +d2i_OSSL_IETF_ATTR_SYNTAX ? 3_4_0 EXIST::FUNCTION: +i2d_OSSL_IETF_ATTR_SYNTAX ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_free ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_new ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_it ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_get_value_num ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_get0_value ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_add1_value ? 3_4_0 EXIST::FUNCTION: +OSSL_IETF_ATTR_SYNTAX_print ? 3_4_0 EXIST::FUNCTION: +X509_ACERT_add_attr_nconf ? 3_4_0 EXIST::FUNCTION: diff --git a/util/other.syms b/util/other.syms index 84e6bb6ba3efe..f3fb800d06579 100644 --- a/util/other.syms +++ b/util/other.syms @@ -70,6 +70,7 @@ OSSL_ENCODER_CLEANUP datatype OSSL_ENCODER_INSTANCE datatype OSSL_HTTP_bio_cb_t datatype OSSL_HTTP_REQ_CTX datatype +OSSL_IETF_ATTR_SYNTAX datatype OSSL_ITEM datatype OSSL_LIB_CTX datatype OSSL_PARAM datatype