[erlang-bugs] bug decoding AuthorityKeyIdentifier in certificate?

Warren Smith <>
Tue Aug 14 21:29:27 CEST 2012


Thanks for taking a look at this.

Your explanation makes sense and it may be that other implementations ignore the problem because that information isn't needed. I believed the certificate was generated using OpenSSL, but I don't know what sort of configuration was used. I'll see if we can generate a new certificate that does the right thing.

Thanks again,


Warren


-----Original Message-----
From: Kenneth Lundin [mailto:] 
Sent: Monday, August 13, 2012 7:59 AM
To: Warren Smith
Cc: 
Subject: Re: [erlang-bugs] bug decoding AuthorityKeyIdentifier in certificate?

Hi Warren,

I have looked at this and suspect that the certificate you have does not follow the standard correctly when it comes to the extension of type AuthorityKeyIdentifier.

AuthorityKeyIdentifier is specified as this:

AuthorityKeyIdentifier ::= SEQUENCE {
    keyIdentifier                     [0] KeyIdentifier            OPTIONAL,
    authorityCertIssuer            [1] GeneralNames             OPTIONAL,
    authorityCertSerialNumber [2] CertificateSerialNumber  OPTIONAL }
    -- authorityCertIssuer and authorityCertSerialNumber MUST both
    -- be present or both be absent

On the TLV level of decoding your data decodes to:
{16,
  [{131072,
    <<24,108,58,144,28,124,144,19,105,161,199,17,225,187,125,
      255,122,178,251,182>>},
   {131073,
    [{17,[{16,[{6,<<85,4,10>>},{19,<<"Auto">>}]}]},
     {17,[{16,[{6,<<85,4,11>>},{19,<<"FutureGridNimbus">>}]}]},
     {17,[{16,[{6,<<85,4,3>>},{19,<<"CA">>}]}]}]},
   {131074,<<0>>}]},

where {131072, ... is the keyidentifier [0]
          {131073,... is authorityCertIssuer [1] GeneralNames
          {131074, ... is authorityCertSerialNumber [2]

The tag values 131072, ... etc are decimal and not easy to understand.
But converted to hex they make more sense since 131072 in hex is #20000 The value is composed of 2 bits representing the class of the tag followed by
16 bits representing the tag-value so here we have class = 2, tagvalue = 0
131073 = #20001 = class (2), tagvalue (1) etc.

GeneralNames is defined as follows
GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

GeneralName ::= CHOICE {
     otherName                       [0]     AnotherName,
     rfc822Name                      [1]     IA5String,
     dNSName                         [2]     IA5String,
     x400Address                     [3]     ORAddress,
     directoryName                   [4]     Name,
     ediPartyName                    [5]     EDIPartyName,
     uniformResourceIdentifier       [6]     IA5String,
     iPAddress                       [7]     OCTET STRING,
     registeredID                    [8]     OBJECT IDENTIFIER }

As far as I understand the data for CHOICE level is missing in the certificate.
The data as it is now seems to be a sequence of Name instead of as it should be a sequence of GeneralName with the CHOICE-alternative directoryName (tag [4] which explains 131076 in the workaround since it corresponds to the tag [4].

I don't know why this certificate works in other implementations, maybe it is because the data in the extension AuthorityKeyIdentifier is not really necessary in the use case and therefore not decoded in the other implementations?

How is this certificate created?

/Kenneth Erlang7OTP, Ericsson

On 8/3/12, Warren Smith <> wrote:
>
> I've come across what may be a bug in the function 
> dec_AuthorityKeyIdentifier(Tlv, TagIn) in OTP-PUB-Key.erl in version 
> R15B01.
>
> A simple test program is:
>
> $ cat test_cert.erl
>
> -module(test_cert).
> -export([cert_file_to_db/1,cert_from_file/1]).
>
> cert_file_to_db(File) ->
>         Db = ssl_certificate_db:create(),
>         ssl_certificate_db:add_trusted_certs(self(), File, Db).
>
> cert_from_file(File) ->
>         {ok, PemBin} = file:read_file(File),
>
>         [PemEntry] = public_key:pem_decode(PemBin),
>         {'Certificate', Cert, not_encrypted} = PemEntry,
>
>         ErlCert = public_key:pkix_decode_cert(Cert, otp),
>         io:format("~p~n",[ErlCert]).
>
> On this certificate:
>
> $ cat 5813ea38.0
>
> -----BEGIN CERTIFICATE-----
> MIICgjCCAeugAwIBAgIBADANBgkqhkiG9w0BAQUFADA3MQ0wCwYDVQQKEwRBdXRv
> MRkwFwYDVQQLExBGdXR1cmVHcmlkTmltYnVzMQswCQYDVQQDEwJDQTAeFw0xMDA5
> MDcxNjM0NDJaFw0xNTA5MDcxNjM0NTJaMDcxDTALBgNVBAoTBEF1dG8xGTAXBgNV
> BAsTEEZ1dHVyZUdyaWROaW1idXMxCzAJBgNVBAMTAkNBMIGfMA0GCSqGSIb3DQEB
> AQUAA4GNADCBiQKBgQCyYqVUsHNqOUS+31s2zdMj7HTENnmdTxb+Ihbt50zl+L/o
> VTJkRWEw3Vy3F8KSbIHEfViDPAMBcpv2KZGZIZfCfGE9wfwEp/mcuEY/WA+jKSev
> lKFQXPWZQtP0OhwT7h2ZHYK/BA8gNvEpKmqvxm8Kb71v/HCXANYoZMwwgjNIcwID
> AQABo4GdMIGaMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFBhsOpAcfJATaaHH
> EeG7ff96svu2MFsGA1UdIwRUMFKAFBhsOpAcfJATaaHHEeG7ff96svu2oTcxDTAL
> BgNVBAoTBEF1dG8xGTAXBgNVBAsTEEZ1dHVyZUdyaWROaW1idXMxCzAJBgNVBAMT
> AkNBggEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQCuaZaw8f8AmQg4
> CiOMgR2qs1zqiXXDGJTx5mnvcDwgyWKqrsNj+8g9oh0R8fx29jUJvq82cVCk0mTR
> 6Yl/wlgFPFHveykA94AzMoHrVBdmusRJRN0B7GTCTnMCnSHhG0FBjagyqC92MZj4
> qJRQswlft8SqfOTxezAZLRXSDJYvvw==
> -----END CERTIFICATE-----
>
> Results in:
>
> $ erl -noshell -s test_cert cert_from_file 5813ea38.0 -s init stop 
> {"init terminating in
> do_boot",{{badmatch,{error,{asn1,{invalid_choice_tag,{17,[{16,[{6,<<3
> bytes>>},{19,<<4
> bytes>>}]}]}}}}},[{public_key,pkix_decode_cert,2,[{file,"public_key.er
> bytes>>l"},{line,216}]},{test_cert,cert_from_file,1,[{file,"test_cert.
> bytes>>erl"},{line,15}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
>
> Crash dump was written to: erl_crash.dump init terminating in do_boot 
> ()
>
>
> This certificate is handled ok by OpenSSL (e.g. openssl x509 -in 
> 5813ea38.0 -text -noout) and by at least one Java X.509 implementation.
>
> I haven't looked in to the process of how 
> public_key/asn1/OTP-PUB-KEY.erl is generated, but this block of code 
> in the dec_AuthorityKeyIdentifier(Tlv,
> TagIn) function:
>
>     %%-------------------------------------------------
>     %% attribute authorityCertIssuer(2)   External OTP-PUB-KEY:GeneralNames
> OPTIONAL
>     %%-------------------------------------------------
>     {Term2, Tlv3} = case Tlv2 of
>                      [{131073, V2} | TempTlv3] ->
>                          {dec_GeneralNames(V2, []), TempTlv3};
>                      _ -> {asn1_NOVALUE, Tlv2}
>                    end,
>
> Is where the problem start showing up. For the above certificate, it 
> is passing this to dec_GeneralNames(Tlv, TagIn):
>
>   Tlv: [{17,[{16,[{6,<<85,4,10>>},{19,<<"Auto">>}]}]},
>         {17,[{16,[{6,<<85,4,11>>},{19,<<"FutureGridNimbus">>}]}]},
>         {17,[{16,[{6,<<85,4,3>>},{19,<<"CA">>}]}]}]
>   TagIn: []
>
> This doesn't look like what dec_GeneralNames() expects. It is close to 
> what
> dec_Name() expects, though.
>
> There are perhaps 2 problems here. First, ({1310??, ???}, []) needs to 
> be passed to dec_GeneralNames() not just (???, []). Second, 131076 
> should be associated with the above Tlv, not 131073.
>
> So, a hack of:
>
>     %%-------------------------------------------------
>     %% attribute authorityCertIssuer(2)   External OTP-PUB-KEY:GeneralNames
> OPTIONAL
>     %%-------------------------------------------------
>     {Term2, Tlv3} = case Tlv2 of
>                       [{131073, V2} | TempTlv3] ->
>                           {dec_GeneralNames([{131076, {16, V2}}], []), 
> TempTlv3};
>                       _ -> {asn1_NOVALUE, Tlv2}
>                     end,
>
> Works around the problem for this certificate.
>
> What I haven't dug in to is why asn1rt_ber_bin_v2__decode(B, nif) is 
> picking
> 131073 instead of 131076 (see below). I don't really understand what 
> these numbers represent or where they are coming from so I'm not sure 
> if there is a problem with the code, or with this certificate. 
> However, from RFC 3280, it seems like it is valid to have a Name/RDN 
> (or any other GeneralName) as the authorityCertIssuer. Maybe there is 
> a restriction somewhere that I'm missing, though...
>
>
> decode(Type, Data)
>   Type: 'AuthorityKeyIdentifier'
>   Data:
> <<48,82,128,20,24,108,58,144,28,124,144,19,105,161,199,17,225,187,125,
>
> 255,122,178,251,182,161,55,49,13,48,11,6,3,85,4,10,19,4,65,117,116,
>
> 111,49,25,48,23,6,3,85,4,11,19,16,70,117,116,117,114,101,71,114,105,
>
> 100,78,105,109,98,117,115,49,11,48,9,6,3,85,4,3,19,2,67,65,130,1,0>>
>   element: {16,
>             [{131072,
>               <<24,108,58,144,28,124,144,19,105,161,199,17,225,187,125,255,
>                 122,178,251,182>>},
>              {131073,
>               [{17,[{16,[{6,<<85,4,10>>},{19,<<"Auto">>}]}]},
>                {17,[{16,[{6,<<85,4,11>>},{19,<<"FutureGridNimbus">>}]}]},
>                {17,[{16,[{6,<<85,4,3>>},{19,<<"CA">>}]}]}]},
>              {131074,<<0>>}]}
> _______________________________________________
> erlang-bugs mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-bugs
>


More information about the erlang-bugs mailing list