views:

52

answers:

2

Greetings,

How can I simply encode some binary data into an ASN.1 DER-encoded blob? I'm using C/C++, and I figure it should be possible to simply prefix the binary blob with some appropriate bytes that signify that the data is of type octet string and is of a given length (and in a sequence of length 1 I guess).

Background if you're interested:

Why do I want to abuse ASN.1 in this way? For a research project, I need to embed some data in a digital signature that has an associated an X.509 certificate. (I'm using createSignatureEx in Peter Gutmann's cryptlib library to create CMS / S/MIME-2/3 / PKCS-#7 compliant signatures if it matters. I'm not signing the data I want to encode, just adding it as metadata to the signature to enrich it.) According to my understanding, serious signatures with arbitrary extension data require the extension data to be encoded using ASN.1 DER. My data is a binary blob and is only useful to my application, so there's no real value in doing proper ASN.1 encoding of each part of my data. I figure with some work I could learn to use asn1c to do this, but it looks pretty complicated and I'm on deadline. Equally importantly, it seems unnecessary and it seems like this information could be useful to other developers who want to avoid the pain of proper ASN.1 encoding.

Thanks!

+1  A: 

I would use the ASN.1 Compiler.

People abuse ASN.1 because it is a way to encode data structures. Any time you have a C/C++ program working with a data structure that the attacker controls problems like; buffer overflows and integer overflows, come into play. ASN.1 is no more insecure than lets say XML or JSON or bencode, as these are all likely points of failure. There can be problems with the encoding library its self, like this nasty Microsoft vulnerability. But this statement is true regardless of the encoding method you use. ASN.1 is a great choice because the resulting message is extremely small and it is the most efficient use of space of any encoding method that I know of.

Rook
Interesting. I can see the protective value afforded by proper encoding. But this is just a research project, and I need to have this done yesterday. Doing all the boilerplate code etc to use asn1c is exactly what I'm trying to avoid if I can. If I use asn1c, I'll just encode it as a binary blob (octet string) anyway. Please don't fall over in shock; I'm a security researcher but this just needs to be done.
Paul
@Paul as a security researcher I have no idea what you are trying to accomplish.
Rook
@Paul, it sounds like you are trying to write an ASN.1 fuzzer, good luck doing that in a day. If your attacking an application than you need to know all of the ASN.1 structs, like specifically targeting the processing of X.509.
Rook
Ah. No, I'm not trying to attack something. I'm just trying to enhance digital signatures with some extra data that I'm claiming provides security value (more than that I cannot say). Fuzzing would probably work to discover valid inputs, but I took a quick spin at the compiler earlier today and I think I'm going to do that. Originally I'll just encode as a single octet string, then maybe later I'll get fancy and encode my struct properly. Any advice on how to clean up the asn1c output for subversion? It's generating 60 files, and I hope to not check them all in.
Paul
BTW, using asn1c (exactly what I was asking how to avoid doing :) ) is the path I ended up choosing, and it was easier than I expected but still took a few hours (and then a few more when I did something more elaborate). So if no better answers show up, I will accept this one.
Paul
+1  A: 

You can't just append a blob of ASN.1 to an X.509 certificate and expect it to become part of the certificate. The certificate is an ASN.1 SEQUENCE of values, and as such it starts with a SEQUENCE tag and a length, which encompasses all of the certificate.

If you want to add a field to the certificate structure (which will probably mean that it is no longer a valid certificate, but it could still be a valid ASN.1 structure) then you will have to change the length of that enclosing sequence as well as appending your data.

Yes, 04 08 01 23 45 67 89 ab cd ef is a valid DER encoding of an octet string. The 04 at the beginning is the tag for OCTET STRING and the 08 is the length of the string. Note that lengths up to 127 are encoded in one byte and that larger lengths use a longer encoding.

For a good introduction to ASN.1 -- and especially to its use in cryptographic messages -- see "A Layman's Guide to a Subset of ASN.1, BER and DER", which you should be able to find on the rsa.com site.

dajames
Ah, I think I see what you're thinking. I'm not just suffixing some ASN.1 encoded bits on a digital signature. I'm using the crypto library cryptlib, which allows me to specify arbitrary certificate extensions given that they are an ASN.1 formatted object, using a function as follows:int cryptAddCertExtension( const CRYPT_CERTIFICATE certificate, const char *oid, const intcriticalFlag, const void *extension, const int extensionLength );
Paul
My ASN.1 gets accepted and my oid (1 2 3 4 5 or 1 2 3 4 6, both from their test code) gets accepted, but when actually creating the bits of the signature the library segfaults on me. The add function does reject at least some OID's, but I don't know thorough the check is (nor whether it can be). Do you think an invalid OID would be likely to cause a crash? (It seems plausible to me. I have already sent email to Peter Gutmann, the library author). How can I determine a valid OID to use? This is just a research project; I don't need it to interoperate with anything. Thanks so much.
Paul
OK, you're adding something to a certificate that you're creating yourself. That should make things a little easier. The OID 1.2.3.4.5 is legitimate and should be safe (1.2 means "ISO member body" and there doesn't seem to be an ISO body #3. I haven't used Cryptlib, but it looks like you need to pass your OID encoded as an ASN.1 OBJECT ID (Hex: 06 04 2A 03 04 05) - Note the odd way the first two bytes of the OID value are combined in ASN.1. Peter Gutmann's X.509 Style Guide is a great reference for the format of certificates.
dajames
If anyone else needs to know this, note cryptlib doesn't appear to actually need the OID included in the ASN.1; it's just specified as an argument to the function for adding the ASN.1.
Paul