Add RFC 5755 attribute certificate support

Add support for attribute certificates (v2) as described
in RFC 5755 profile.

Attribute certificates provide a mechanism to manage authorization
information separately from the identity information provided by
public key certificates.

This initial patch adds the ASN.1 definitions
and I/O API.  Accessor functions for the certificate fields
will be added in subsequent patches.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15857)
This commit is contained in:
Damian Hobson-Garcia 2021-05-13 11:53:59 +09:00 committed by Matt Caswell
parent 0339382aba
commit 7dcee34c8f
14 changed files with 295 additions and 1 deletions

View File

@ -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

View File

@ -21,6 +21,7 @@
#include <openssl/pkcs12.h>
#include <openssl/rsa.h>
#include <openssl/x509v3.h>
#include <openssl/x509_acert.h>
#include "asn1_item_list.h"

View File

@ -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),

View File

@ -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
IF[{- !$disabled{'deprecated-3.0'} -}]
SOURCE[../../libcrypto]=x509type.c

75
crypto/x509/x509_acert.c Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#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)

22
crypto/x509/x509_acert.h Normal file
View File

@ -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 <crypto/x509_acert.h>
# 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

View File

@ -26,6 +26,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)
@ -824,3 +825,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);
}

View File

@ -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<X509> 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<X509_ACERT> functions process an X509 attribute certificate using
an X509_ACERT structure.
The B<X509_AUX> functions process a trusted X509 certificate using
an X509 structure.

View File

@ -171,6 +171,10 @@ OSSL_CRMF_PKIPUBLICATIONINFO_new,
OSSL_CRMF_SINGLEPUBINFO_free,
OSSL_CRMF_SINGLEPUBINFO_it,
OSSL_CRMF_SINGLEPUBINFO_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 +269,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,

View File

@ -157,6 +157,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,
@ -331,6 +334,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,

View File

@ -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 <openssl/x509_acert.h>
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

View File

@ -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

View File

@ -0,0 +1,48 @@
/*
* {- 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 <openssl/x509v3.h>
# include <openssl/x509.h>
# include <openssl/pem.h>
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);
#endif

View File

@ -5550,3 +5550,26 @@ 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
CRYPTO_atomic_store ? 3_4_0 EXIST::FUNCTION:
CRYPTO_aligned_alloc ? 3_4_0 EXIST::FUNCTION:
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: