Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: [openssl-users] Help finding replacement for ASN1_seq_unpack_X509

73 views
Skip to first unread message

Dr. Stephen Henson

unread,
Jul 19, 2016, 6:10:37 PM7/19/16
to
On Tue, Jul 19, 2016, Jim Carroll wrote:

> OpenSSL 1.1.0 has upgraded the safestack.h macro system, but I'm having
> difficulty understanding the changes. I'm porting a piece of code from
> OpenSSL 0.9.8 that uses ASN1_seq_unpack_X509. In 0.9.8, safestack.h had this
> definition.
>
> #define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \
>
> SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func))
>
> Could anyone point me in the right direction and how this needs to be
> adapted?
>
>

Ah, that uses some ancient stuff which is originally from OpenSSL 0.9.6. For
1.1.0 this has changed. You need to create a typedef for a STACK_OF(X509) and
then define ASN.1 functions for it for a SEQUENCE OF X509. That is a lot
easier than it sounds. This should do it:

#include <openssl/x509.h>
#include <openssl/asn1t.h>

typedef STACK_OF(X509) SEQ_CERT;

ASN1_ITEM_TEMPLATE(SEQ_CERT) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, SeqCert, X509)
ASN1_ITEM_TEMPLATE_END(SEQ_CERT)

IMPLEMENT_ASN1_FUNCTIONS(SEQ_CERT)

This defines a function d2i_SEQ_CERT() which replaces the original macro.

Note that this construct should also work in earlier versions of OpenSSL too
including 0.9.8.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users

Salz, Rich

unread,
Jul 21, 2016, 4:35:58 AM7/21/16
to
> Would it be acceptable to just iterate the stack elements, passing each X509
> through i2d_X509 and appending the results -- would that generate valid
> DER?

Maybe. It depends on what the receiver is expecting. If it's willing to read a set of certs until it hits EOF (or equivalent) that's fine. But if you're sending a SEQUENCE OF certificates then you need to wrap it in an ASN1/DER container. For example, Netscape Cert Sequence

Can you post a code snippet?

Salz, Rich

unread,
Jul 21, 2016, 8:57:55 AM7/21/16
to

> STACK_OF(X509)* stack = sk_x509_new_null();
> sk_x509_push(stack, cert);
> sk_x509_push(stack, ca);
>
> return ASN1_seq_pack_X509(stack, i2d_X509, NULL, len_out);

Okay, so your just pushing two DER-format blobs one after the other.
Yes, what you thought to do is fine. :)

Salz, Rich

unread,
Jul 21, 2016, 9:17:08 AM7/21/16
to
> Thanks Rich!

You're welcome. Getting M2Crypto moved to 1.1 is a *great* project. Thanks.

--
Senior Architect, Akamai Technologies
IM: rich...@jabber.at Twitter: RichSalz

Dr. Stephen Henson

unread,
Jul 21, 2016, 9:53:27 AM7/21/16
to
On Wed, Jul 20, 2016, Jim Carroll wrote:

> Thanks much....I have a corollary question if you don't mind. In OpenSSL
> 1.1.0, what is the accepted procedure to convert a STACK_OF(X509) to DER?
>

It depends on what you mean by "to DER" and what the other ends is expecting.

The code snipped I suggested will do that: if you call i2d_SEQ_CERT (or
whatever you called it) that will work. That wraps the whole lot in a SEQUENCE
header which is the same as the original. That is it is a SEQUENCE OF X509.

> Would it be acceptable to just iterate the stack elements, passing each X509
> through i2d_X509 and appending the results -- would that generate valid DER?
> Is there a better way?
>

It depends on what the other side expects. If you just do that that and EOF
signals the and of the last certificate you'll be fine. If you append
additional data afterwards then you need to mark the last certificate somehow.
The certificate sequence version prepends the data with the length of all the
certificates so it automatically handles that.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org

Dr. Stephen Henson

unread,
Jul 21, 2016, 9:54:51 AM7/21/16
to
On Thu, Jul 21, 2016, Salz, Rich wrote:

>
> > STACK_OF(X509)* stack = sk_x509_new_null();
> > sk_x509_push(stack, cert);
> > sk_x509_push(stack, ca);
> >
> > return ASN1_seq_pack_X509(stack, i2d_X509, NULL, len_out);
>
> Okay, so your just pushing two DER-format blobs one after the other.
> Yes, what you thought to do is fine. :)

Actually that is including a SEQUENCE header and not just the DER blobs. So if
the result must be compatible with the original format the snippet I suggested
would be appropriate here.

Salz, Rich

unread,
Jul 21, 2016, 10:29:55 AM7/21/16
to

> Actually that is including a SEQUENCE header and not just the DER blobs. So if
> the result must be compatible with the original format the snippet I
> suggested would be appropriate here.

Thanks for the correction.

Dr. Stephen Henson

unread,
Jul 21, 2016, 2:41:46 PM7/21/16
to
On Thu, Jul 21, 2016, Jim Carroll wrote:

>
> I ran into problems with swig when I tried to deploy you suggestion. Your
> solution was slick pre-processor magic's and I was having difficulty
> reversing the magic to troubleshoot swig (and I was a little shy about
> admitting I didn't understand your suggestion).
>
> I've spent more time reading ASN1 headers since then, and I'm starting to
> get a glimmer of understanding of whats/what. I'm now circling back to your
> solution and I think I'm getting on top of the swig issue.
>

I'd be interested in knowing more details of the swig problems you had. If it
helps you can just include my code snippet in a separate C source file and
then just use the i2d/d2i functions in the swig wrapper itself.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org

Dr. Stephen Henson

unread,
Jul 21, 2016, 3:00:59 PM7/21/16
to
On Thu, Jul 21, 2016, Jim Carroll wrote:

> Steve,
>
> I ran into problems with swig when I tried to deploy you suggestion. Your
> solution was slick pre-processor magic's and I was having difficulty
> reversing the magic to troubleshoot swig (and I was a little shy about
> admitting I didn't understand your suggestion).
>

Well there are various things going on underneath which can be hard to follow
if you aren't used to them. Here's a bit more detail about what is going on.

Initially we just include the necessary headers:

#include <openssl/x509.h>
#include <openssl/asn1t.h>

ASN.1 encode/decode routines generally use a structure name. We have
STACK_OF(X509) but no name for that so we can make one up which I call
SEQ_CERT:

typedef STACK_OF(X509) SEQ_CERT;

The next bit defines an ASN.1 module structure which says the SEQ_CERT is
a SEQUENCE OF X509:

ASN1_ITEM_TEMPLATE(SEQ_CERT) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, SeqCert, X509)
ASN1_ITEM_TEMPLATE_END(SEQ_CERT)

Here SEQ_CERT is the structure name which that macro defines as a SEQUENCE OF
X509. The "SeqCert" is just a string that is used as a name in the definition:
it can be anything.

Now that's all very well but it doesn't actually define any functions. The bit
that does that is this:

IMPLEMENT_ASN1_FUNCTIONS(SEQ_CERT)

This implements four functions but we're only interested in the encode and
decode ones which look like this:

int i2d_SEQ_CERT(SEQ_CERT *a, unsigned char **pp);
TYPE *d2i_SEQ_CERT(SEQ_CERT **a, unsigned char **pp, long length);

These behave like regular ASN.1 functions you pass in SEQ_CERT: which is
STACK_OF(X509) to the i2d_SEQ_CERT and it encodes the result as a SEQUENCE
OF X509 which is the same format as the original.

Similarly you can decode using d2i_SEQ_CERT() and get back a STACK_OF(X509).

If you have this in a separate module you can declare the new functions (e.g.
in a header file) with:

DECLARE_ASN1_FUNCTIONS(SEQ_CERT)

Hope that helps. If you have any further problems let me know.
0 new messages