# Whether attribute certificates can be used in the public\_key module.

**URL:** <https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930>\
**Category:** Questions / Help\
**Tags:** erlang-otp, public-key\
**Created:** [October 4, 2023, 12:18pm UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930 "2023-10-04T12:18:59Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tanaka](https://erlangforums.com/letter_avatar_proxy/v4/letter/t/ecae2f/32.png) [@tanaka](https://erlangforums.com/u/tanaka)\
**Post date:** [October 4, 2023, 12:18pm UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930/1 "2023-10-04T12:18:59Z")

</div>

We are trying to implement a feature for issuing attribute certificates using records such as AttributeCertificate, which are defined in public\_key.hrl

We checked if a certificate generated by the public\_key module could be read/parsed correctly by a modified OpenSSL 3 implementation with the attribute certificates.

Since I could confirm that the record was defined in the header, I obtained a test acert.pem that was included in the pull request to make openssl3 support attribute certificates, and tried to see if I could parse it.

> <https://github.com/openssl/openssl/pull/15857/files#diff-8884a003f7452a5083c9e9732684ef59d09537a46f42674f03968f6de73ddc0b>
>
> Closes #14648 
> 
> Please see the checklist below for sub-task completion status.…
> 
> Right now I've split this implementation over several patches to try to keep the sizes a little more manageable,
> but I can squash them if that makes more sense.
> 
> Some of the areas of concern regarding this patch series are listed below. Any feedback related to these (or anything else)
> would be greatly appreciated
> 
> \### Attribute values
> 
> RFC 5755 defines several Attribute types that have ASN.1 SEQUENCEs as their value fields. E.g. \[group\](https://datatracker.ietf.org/doc/html/rfc5755#section-4.4.4) and \[role\](https://datatracker.ietf.org/doc/html/rfc5755#section-4.4.5). As far as I can tell, there is no nice way to handle Attributes that don't have string (or similar) values for printing or parsing. The current code just uses the output of \`ANS1\_item\_print()\` for printing, and parses from the config file using \`ASN1\_generate\_nconf()\`.
> Maybe some framework, similar to the \`X509V3\_EXT\_METHOD\` used for extensions might be useful for X509\_ATTRIBUTEs?
> 
> \### public API
> 
> RFC 5755 defines the attribute certificate format using several new ASN.1 sequence types that don't seem to be used in any other profiles. I've tried to find a good balance of what to expose in the public API, but if there are any opinions on whether I should be exposing more or less, I would be happy to hear them.
> 
> \### file separation
> I'm not 100% sure that all of the function implementations are in the right location (correct function in correct file). I've tried to 
> follow the way that the X509, X509\_REQ and X509\_CRL implementation is divided, but maybe there is some room for improvement there.
> 
> \<!--
> Thank you for your pull request. Please review these requirements:
> 
> Contributors guide: https://github.com/openssl/openssl/blob/master/CONTRIBUTING.md
> 
> Other than that, provide a description above this comment if there isn't one already
> 
> If this fixes a GitHub issue, make sure to have a line saying 'Fixes #XXXX' (without quotes) in the commit message.
> \--\>
> 
> \#### Checklist
> \- \[x\] file / BIO input output for attribute certificates (AC)
> \- \[x\] setters / getters for AC fields
> \- \[x\] read AC attribute values from config file
> \- \[x\] documentation is added or updated
> \- \[x\] tests are added or updated

I tried to see if I could expand it with public\_key:pem\_decode/1, but it only returned an empty list.

```erlang
1> {ok, Bin} = file:read_file("acert.pem").
<<"-----BEGIN ATTRIBUTE CERTIFICATE-----\nMIICPTCCASUCAQEwN6AWMBGkDzANMQswCQYDVQQDDAJDQQIBAqEdpBswGTEXMBUG\nA1UEAwwOc2Vyd"...>>
2> public_key:pem_decode(Bin).
[]

```

After removing the header and footer listed in the PEM format and changing it to DER format with base64 decoding, we confirmed that it could be read with public\_key:der\_decode/2.

```erlang
1> {ok, Bin} = file:read_file("acert.der").
{ok,<<48,130,2,61,48,130,1,37,2,1,1,48,55,160,22,48,17,
      164,15,48,13,49,11,48,9,6,3,...>>}
2> public_key:der_decode('AttributeCertificate', Bin).
{'AttributeCertificate',{'AttributeCertificateInfo',v2,
                                                    {'Holder',{'IssuerSerial',[{directoryName,{rdnSequence,[[{'AttributeTypeAndValue',{2,
                                                                                                                                       5,4,3},
                                                                                                                                      <<12,2,67,65>>}]]}}],
                                                                              2,asn1_NOVALUE},
                                                              [{directoryName,{rdnSequence,[[{'AttributeTypeAndValue',{2,
                                                                                                                       5,4,3},
                                                                                                                      <<12,14,115,101,114,118,101,114,46,101,120,...>>}]]}}],
                                                              asn1_NOVALUE},
                                                    {v2Form,{'V2Form',[{directoryName,{rdnSequence,[[{'AttributeTypeAndValue',{2,
                                                                                                                               5,4,3},
                                                                                                                              <<12,28,65,116,116,114,105,98,117,...>>}]]}}],
                                                                      asn1_NOVALUE,asn1_NOVALUE}},
                                                    {'AlgorithmIdentifier',{1,2,840,113549,1,1,11},<<5,0>>},
                                                    21175981651213461252787528108986572854611892162,
                                                    {'AttCertValidityPeriod',"20210615123500Z",
                                                                             "20310613123500Z"},
                                                    [{'Attribute',{1,3,6,1,5,5,7,10,4},
                                                                  [<<48,21,160,9,134,7,84,101,115,116,118,97,108,48,...>>]},
                                                     {'Attribute',{2,5,4,72},
                                                                  [<<48,17,161,15,131,13,97,100,109,105,110,105,115,...>>]}],
                                                    asn1_NOVALUE,
                                                    [{'Extension',{2,5,29,35},
                                                                  false,
                                                                  <<48,22,128,20,98,110,201,104,103,108,100,187,...>>},
                                                     {'Extension',{2,5,29,56},false,<<5,0>>}]},
                        {'AlgorithmIdentifier',{1,2,840,113549,1,1,11},<<5,0>>},
                        <<69,138,69,18,58,43,116,222,188,53,116,139,152,54,158,
                          186,187,177,135,15,153,178,191,70,174,...>>}

```

The current functionality that has already been implemented in public\_key module is sufficient for our objective of handling the certificate in DER format.

We would like to use the public\_key module functionality for issuing a platform certificate defined by TCG.

[https://trustedcomputinggroup.org/resource/tcg-platform-certificate-profile/](https://trustedcomputinggroup.org/resource/tcg-platform-certificate-profile/)

I would like to confirm that the handling of attribute certificates in the public\_key module of Erlang/OTP will not be deprecated and will remain supported.

Are the attribute certificates defined in RFC5755 and the related RFCs currently supported in the public\_key module?

> **[RFC 5755: An Internet Attribute Certificate Profile for Authorization](https://datatracker.ietf.org/doc/html/rfc5755)**
>
> This specification defines a profile for the use of X.509 Attribute Certificates in Internet Protocols. Attribute certificates may be used in a wide range of applications and environments covering a broad spectrum of interoperability goals and a...

---

<div class="post-metadata">

**Author:** ![jimdigriz](https://erlangforums.com/user_avatar/erlangforums.com/jimdigriz/32/1885_2.png) [@jimdigriz](https://erlangforums.com/u/jimdigriz)\
**Post date:** [October 8, 2023, 8:07am UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930/2 "2023-10-08T08:07:31Z")

</div>

My understanding is that the support, as it is for general X.509 work, is this support is mostly incidental as this is all just pure ASN.1 decoding.

Lurking in [https://github.com/erlang/otp/tree/master/lib/public\_key/asn1](https://github.com/erlang/otp/tree/master/lib/public_key/asn1) is a list of `.asn1` files that tend to be just verbatim extracted from IETF materials and elsewhere.

During the building of OTP, these get converted into records that represent the underlying ASN.1 form. `public_key` then provides some functions to work with these records (typically outputting DER).

Anything not in there I suspect would just appear as raw non-human readable objects…plus nothing stops anyone just using their own ASN.1 definitions.

So probably not a question of ‘support’ as all this needs is an ASN.1 decoder which OTP has built in.

To actually work with `AttributeCertificate` you still need to do the hard coding part which not even OpenSSL does 🙂

---

<div class="post-metadata">

**Author:** ![tanaka](https://erlangforums.com/letter_avatar_proxy/v4/letter/t/ecae2f/32.png) [@tanaka](https://erlangforums.com/u/tanaka)\
**Post date:** [December 5, 2023, 6:03am UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930/3 "2023-12-05T06:03:31Z")

</div>

AttributeCertificate is decoded/encoded using code generated from ASN.1, so I recognized that it can be used regardless of whether or not documentation is available.

Therefore, we tried to generate a module that reads ASN.1 of PlatformCertificate, which is currently being developed by TCG, and performs encode and decode.

ASN.1 of PlatformCertificate defines the following SEQUENCE in which the encoding and decoding process is already provided in the public\_key module (OTP-PUB-KEY.erl) ` AlgorithmIdentifier`.

```erlang
IMPORTS
    AlgorithmIdentifier
        FROM PKIX1Explicit88 {
            iso(1)
            identified-organization(3)
            dod(6)
            internet(1)
            security(5)
            mechanisms(5)
            pkix(7)
            id-mod(0)
            id-pkix1-explicit(18)
        };
URIReference ::= SEQUENCE {
    uniformResourceIdentifier IA5String (SIZE (1..urimax)),
    hashAlgorithm AlgorithmIdentifier OPTIONAL,
    hashValue BIT STRING OPTIONAL
}

```

When an Erlang module is generated from the ASN.1 definition of PlatformCertificate, I want the encoding and decoding process for AlgorithmIdentifier to invoke the ‘OTP-PUB-KEY’:‘enc\_AlgorithmIdentifier’/2 function defined in OTP-PUB-KEY.erl.

We are currently creating an Erlang module by executing `erlc -bber +der +noobj PlatformCertificate.set.asn` with an ASN.1 file named PlatformCertificate.asn1. The PlatformCertificate.set.asn file contains only the description of PlatformCertificate.asn1.

The replacement of `OTP-PUB-KEY` is carried out on the generated Erlang module by using sed for substitution.

```sh
sed -i -e "s/PKIX1Explicit88/OTP-PUB-KEY/g" PlatformCertificate.erl

```

Is it possible to specify the use of `OTP-PUB-KEY` in the decoding or encoding process of an AlgorithmIdentifier imported from ASN.1 via the erlc options, such as through a configuration file?

---

<div class="post-metadata">

**Author:** ![ingela](https://erlangforums.com/letter_avatar_proxy/v4/letter/i/53a042/32.png) [@ingela](https://erlangforums.com/u/ingela)\
**Post date:** [December 5, 2023, 7:23am UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930/4 "2023-12-05T07:23:59Z")

</div>

Would it perhaps be easier to use `public_key:der_decode(<Asn1Type>, DER)`

In your case` public_key:der_decode('AlgorithmIdentifier', DER).` in your erlang module.

---

<div class="post-metadata">

**Author:** ![tanaka](https://erlangforums.com/letter_avatar_proxy/v4/letter/t/ecae2f/32.png) [@tanaka](https://erlangforums.com/u/tanaka)\
**Post date:** [December 19, 2023, 12:52pm UTC](https://erlangforums.com/t/whether-attribute-certificates-can-be-used-in-the-public-key-module/2930/5 "2023-12-19T12:52:27Z")

</div>

Thanks for the idea.

The following is an excerpt of the URIReference encoding process from the erlang code generated from the ASN.1 definition.

```erlang
%%================================
%% URIReference
%%================================
enc_URIReference(Val) ->
    enc_URIReference(Val, [<<48>>]).

enc_URIReference(Val, TagIn) ->
    {_, Cindex1, Cindex2, Cindex3} = Val,

    %%-------------------------------------------------
    %% attribute uniformResourceIdentifier(1) with type IA5String
    %%-------------------------------------------------
    {EncBytes1, EncLen1} = encode_restricted_string(Cindex1, [<<22>>]),

    %%-------------------------------------------------
    %% attribute hashAlgorithm(2) External PKIX1Explicit88:AlgorithmIdentifier OPTIONAL
    %%-------------------------------------------------
    {EncBytes2, EncLen2} =
        case Cindex2 of
            asn1_NOVALUE ->
                {<<>>, 0};
            _ ->
                'PKIX1Explicit88':'enc_AlgorithmIdentifier'(Cindex2, [<<48>>])
        end,

    %%-------------------------------------------------
    %% attribute hashValue(3) with type BIT STRING OPTIONAL
    %%-------------------------------------------------
    {EncBytes3, EncLen3} =
        case Cindex3 of
            asn1_NOVALUE ->
                {<<>>, 0};
            _ ->
                encode_unnamed_bit_string(Cindex3, [<<3>>])
        end,

    BytesSoFar = [EncBytes1, EncBytes2, EncBytes3],
    LenSoFar = EncLen1 + EncLen2 + EncLen3,
    encode_tags(TagIn, BytesSoFar, LenSoFar).

```

This shows that `'PKIX1Explicit88':'enc_AlgorithmIdentifier'(Cindex2, [<<48>>])` is called as an encoding process for AlgorithmIdentifier.

The definition of AlgorithmIdentifier actually exists in [PKIX1Explicit88.asn1](https://www.itu.int/wftp3/Public/t/fl/ietf/rfc/rfc3280/PKIX1Explicit88.html).  
In erlang/otp, it is named `OTP-PUB-KEY` and is grouped together with other ASN.1 definitions.

The following is the process of calling AlgorithmIdentifier in `OTP-PUB-KEY.erl`, which is actually called by public\_key.

```erlang
%%================================
%% AlgorithmIdentifier
%%================================
enc_AlgorithmIdentifier(Val) ->
    enc_AlgorithmIdentifier(Val, [<<48>>]).

enc_AlgorithmIdentifier(Val, TagIn) ->
    {_, Cindex1, Cindex2} = Val,

    %%-------------------------------------------------
    %% attribute algorithm(1) with type OBJECT IDENTIFIER
    %%-------------------------------------------------
    {EncBytes1, EncLen1} = encode_object_identifier(Cindex1, [<<6>>]),

    %%-------------------------------------------------
    %% attribute parameters(2) with type ASN1_OPEN_TYPE OPTIONAL
    %%-------------------------------------------------
    {EncBytes2, EncLen2} =
        case Cindex2 of
            asn1_NOVALUE ->
                {<<>>, 0};
            _ ->
                encode_open_type(Cindex2, [])
        end,

    BytesSoFar = [EncBytes1, EncBytes2],
    LenSoFar = EncLen1 + EncLen2,
    encode_tags(TagIn, BytesSoFar, LenSoFar).

```

Checking the [Erlang User’s Guide ASN.1](https://www.erlang.org/doc/apps/asn1/asn1_getting_started#multi-file-compilation), it is introduced that erlang code can be generated with any module name by specifying `MyModule.set.asn`.

Even if you make use of public\_key:der\_encode/2 and public\_key:der\_decode/2, you will have to change the code generated from ASN.1.

Is there a better way to do this in erlc settings?
