botan icon indicating copy to clipboard operation
botan copied to clipboard

Can we decode BER encoded using botan?

Open ra185148 opened this issue 2 years ago • 16 comments

Can you please help us understand how we can decode the multiple hierarchies

for example, if we have the following

SEQUENCE : SEQUENCE : SET : SEQUENCE : OBJECT IDENTIFIER : countryName [2.5.4.6] PRINTABLE STRING : 'US' SET : SEQUENCE : OBJECT IDENTIFIER : organizationName [2.5.4.10] PRINTABLE STRING : 'ABCD' SET : SEQUENCE : OBJECT IDENTIFIER : commonName [2.5.4.3] PRINTABLE STRING : 'ABCD Root' INTEGER : 223338299393

Can we do decode this using Botan? Also, if we encode the sample mentioned in https://github.com/randombit/botan/issues/1684 Can we decode using botan?

ra185148 avatar Feb 14 '22 05:02 ra185148

You can use BER_Decoder for decoding and you can see multiple examples of how it's used to decode X.509 objects here.

On that note, what you want to decode there looks a bit like X.509. Have you seen Botan's API for that? Maybe you don't have to implement custom decoding logic.

hrantzsch avatar Feb 14 '22 08:02 hrantzsch

Actually tried using the BER_DECODER but couldn't succeed

Let's take an example here... I am generating a random number and encoding it with an OID. Same random number to be decoded back

Following is sample:

_std::vector<uint8_t> randomNewNumber(16);

Botan::AutoSeeded_RNG rngl;
rngl.randomize(randomNewNumber.data(), 16);

Botan::secure_vector<uint8_t> signedData = Botan::DER_Encoder()
    .start_cons(Botan::ASN1_Tag::SEQUENCE)
    .encode(Botan::OID("1.2.840.113549.1.9.25.3"))
    .start_cons(Botan::ASN1_Tag::SET)
    .encode(randomNewNumber, Botan::ASN1_Tag::OCTET_STRING)
    .end_cons()
    .end_cons()
    .get_contents();

std::vector<uint8_t> randomNumberDEREncoded = Botan::unlock(signedData);

Botan::BER_Decoder dec(randomNumberDEREncoded);
dec.decode(randomNumberDEREncoded,Botan::SEQUENCE);_

Here decoding failed with Bad_Tag, I understand that SEQUENCE would not be the correct input here in decode. Can you please guide how can we decode this?

ra185148 avatar Feb 14 '22 09:02 ra185148

You can use the decoder analogously to the encoder. For your example above:

  // ...
  std::vector<uint8_t> randomNumberDEREncoded = Botan::unlock(signedData);

  Botan::OID oid;
  std::vector<uint8_t> rand;

  Botan::BER_Decoder(randomNumberDEREncoded)
      .start_cons(Botan::ASN1_Tag::SEQUENCE)
      .decode(oid)
      .start_cons(Botan::ASN1_Tag::SET)
      .decode(rand, Botan::ASN1_Tag::OCTET_STRING)
      .end_cons()
      .end_cons();

  assert(randomNewNumber == rand);

hrantzsch avatar Feb 14 '22 10:02 hrantzsch

Thank you for sharing the sample code.

Can you please share the sample example link as well which you mentioned above? Also, do we have any example to use the CONTEXT_SPECIFIC as well?

ra185148 avatar Feb 14 '22 14:02 ra185148

you please share the sample example link as well which you mentioned above

I'm not sure which link you are referring to. I linked https://github.com/randombit/botan/blob/a19627a2b76e7f1b9b7e19fbaf2ef464ac220ce6/src/lib/x509/x509_obj.cpp above.

example to use the CONTEXT_SPECIFIC as well

You can look for uses of ASN1_Class::ContextSpecific in the code base.

Side note: are you absolutely sure that the existing X.509 API in Botan is not what you need? What is it you're trying to encode/decode?

hrantzsch avatar Feb 14 '22 16:02 hrantzsch

As per my requirement, I have a few keys and other data appended along with the certificate data which is to be decoded.

Further tried using the sample but faced Invalid Argument while encoding and Bad_Tag issue while decoding one sample.

Tried the following to Encode:

std::vector<uint8_t> CountryCode = Botan::hex_decode("5553"); Botan::secure_vector<uint8_t> signedDataSample = Botan::DER_Encoder() .start_cons(Botan::ASN1_Tag::SEQUENCE) .start_cons(Botan::ASN1_Tag::SEQUENCE) .start_cons(Botan::ASN1_Tag::SET) .start_cons(Botan::ASN1_Tag::SEQUENCE) .encode(Botan::OID("2.5.4.6")) .encode( CountryCode, Botan::ASN1_Tag::PRINTABLE_STRING) .end_cons() .end_cons() .end_cons() .end_cons() .get_contents();

But it gives an invalid argument exception. Can you please mention, what wrong we are doing here.

I have a sample encoded string "3048303F310B300906035504061302555331153013060355040A130C555555555553616D706C65733119301706035504031310555555552053616D706C6520526F6F7402053400000006"

For which I am trying to use the below

Botan::BER_Decoder(Botan::hex_decode("3048303F310B300906035504061302555331153013060355040A130C555555555553616D706C65733119301706035504031310555555552053616D706C6520526F6F7402053400000006"))
        .start_cons(Botan::ASN1_Tag::SEQUENCE)
            .start_cons(Botan::ASN1_Tag::SEQUENCE)
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid1)
                        .decode(CountryCode2, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid2)
                        .decode(Issuer, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid3)
                        .decode(SerialNum, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
            .end_cons()
            .decode_integer_type(num)
        .end_cons();

ra185148 avatar Feb 15 '22 12:02 ra185148

Hi hrantzsch

Can you please help with the above query?

ra185148 avatar Feb 16 '22 06:02 ra185148

Hi, which of the instructions above throws the exception? I assume it's one of the decodes? Maybe you can look up under which circumstances decode throws the exception you get.

hrantzsch avatar Feb 16 '22 08:02 hrantzsch

Firstly, While encoding the following,

std::vector<uint8_t> CountryCode = Botan::hex_decode("5553");
Botan::secure_vector<uint8_t> signedDataSample = Botan::DER_Encoder()
.start_cons(Botan::ASN1_Tag::SEQUENCE)
.start_cons(Botan::ASN1_Tag::SEQUENCE)
.start_cons(Botan::ASN1_Tag::SET)
.start_cons(Botan::ASN1_Tag::SEQUENCE)
.encode(Botan::OID("2.5.4.6"))
.encode( CountryCode, Botan::ASN1_Tag::PRINTABLE_STRING)
.end_cons()
.end_cons()
.end_cons()
.end_cons()
.get_contents();

getting exception : Microsoft C++ exception: Botan::Invalid_Argument on instruction .encode( CountryCode, Botan::ASN1_Tag::PRINTABLE_STRING)

Secondly, when trying to decode one available sequence i.e. "3048303F310B300906035504061302555331153013060355040A130C555555555553616D706C65733119301706035504031310555555552053616D706C6520526F6F7402053400000006"

Botan::BER_Decoder(Botan::hex_decode("3048303F310B300906035504061302555331153013060355040A130C555555555553616D706C65733119301706035504031310555555552053616D706C6520526F6F7402053400000006"))
        .start_cons(Botan::ASN1_Tag::SEQUENCE)
            .start_cons(Botan::ASN1_Tag::SEQUENCE)
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid1)
                        .decode(CountryCode2, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid2)
                        .decode(Issuer, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
                .start_cons(Botan::ASN1_Tag::SET)
                    .start_cons(Botan::ASN1_Tag::SEQUENCE)
                        .decode(oid3)
                        .decode(SerialNum, Botan::ASN1_Tag::PRINTABLE_STRING)
                    .end_cons()
                .end_cons()
            .end_cons()
            .decode_integer_type(num)
        .end_cons();

getting exception : Microsoft C++ exception: Botan::BER_Bad_Tag at instruction .decode(CountryCode2, Botan::ASN1_Tag::PRINTABLE_STRING)

ra185148 avatar Feb 16 '22 08:02 ra185148

Ah, the problem seems to be that you need to decode the printable string into a Botan::ASN1_String, rather than a plain vector.

hrantzsch avatar Feb 16 '22 08:02 hrantzsch

Hi hrantzsch

Thank you for correcting the type mentioned above. I am able to decode now.

Only one issue still persists, w.r.t context specific.

Decoding a sample - "8081885332A1F84521DE2D3B23EBE3CB2D674B16114EC598214102C3DEE175C2A669400EB039136E632E4A32140AAB5546AC478799F7B7A025335F45CCA3CD1894314FF513E3E02573ADB5135DF8B1DB3277D9DE273DC6A8B5E79D215F63B93A52137DBAFBE5CC3FF472919D86D2409762370FA80A77AED183E1ED597BF9BFDC9D286934C7C1E1E8D003FB"

I have trying to decode with the below instruction

std::vector<uint8_t> ContextString1; .decode(ContextString1, Botan::ASN1_Tag::BIT_STRING, Botan::ASN1_Tag::BIT_STRING, Botan::ASN1_Tag::CONTEXT_SPECIFIC)

Here i have tried Octet String, Bit String and plain vector, but did not helped much. Can you please mention how we can do that with Botan?

ra185148 avatar Feb 18 '22 09:02 ra185148

Botan::ASN1_String contextString;
// ...
.decode(contextString, Botan::ASN1_Tag::PRINTABLE_STRING)

~~should work :)~~

Edit: sorry, I think I misread your question. You can find example usages of CONTEXT_SPECIFIC decoding in src/lib/x509/ocsp.cpp. Can you have a look at those and see if they help you?

hrantzsch avatar Feb 18 '22 09:02 hrantzsch

Hi hrantzsch

Tried options from the above mentioned src/lib/x509/ocsp.cpp, where cotext_Specific is used in decoding the optional parameters It did not help further, If you can have a look, it will be great

Thanks

ra185148 avatar Feb 20 '22 19:02 ra185148

decode(ContextString1, Botan::OCTET_STRING, Botan::UNIVERSAL, Botan::CONTEXT_SPECIFIC);

Does this work for you?

hrantzsch avatar Feb 21 '22 09:02 hrantzsch

Yes, it worked for me. Thanks a lot. Do you have any documentation which explains all ways to use it?

ra185148 avatar Feb 21 '22 09:02 ra185148

Unfortunately not, as far as I know.

hrantzsch avatar Feb 21 '22 10:02 hrantzsch