[erlang-bugs] bug decoding AuthorityKeyIdentifier in certificate?
Kenneth Lundin
kenneth.lundin@REDACTED
Mon Aug 13 14:59:11 CEST 2012
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 <wsmith@REDACTED> 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.erl"},{line,216}]},{test_cert,cert_from_file,1,[{file,"test_cert.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
> erlang-bugs@REDACTED
> http://erlang.org/mailman/listinfo/erlang-bugs
>
More information about the erlang-bugs
mailing list