how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Lisa Matias
With OpenSSL version 1.1.1, my previously working code is now failing with this error:

error: dereferencing pointer to incomplete type ‘X509_NAME_ENTRY {aka struct X509_name_entry_st}’

Basically, I am trying to do the following...

X509_NAME_ENTRY *nameEntry;
nameEntry = X509_NAME_ENTRY_create_by_NID (&nameEntry, nid,
                        derTagToVType (tag), buffer, bufferLength);
nameEntry->value->flags = specifiedFlags;

And the error occurs at the last line above only with this newer version of OpenSSL 1.1.1 and not with any of the older versions I have been using for many years.

Unfortunately, I do not see any function in the openssl include files such as "X509_NAME_ENTRY_set_flags(...)" which are available to use instead.

Does anyone know if there any alternative generic method in OpenSSL 1.1.1 to set flags for a X509_NAME_ENTRY, which is independent of the ASN.1 type of the X509_NAME_ENTRY?

Thanks.

Lisa.


Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Viktor Dukhovni
On Mon, Jun 17, 2019 at 09:19:41PM -0700, Lisa Matias wrote:

> X509_NAME_ENTRY *nameEntry;
> nameEntry = X509_NAME_ENTRY_create_by_NID (&nameEntry, nid,
>                         derTagToVType (tag), buffer, bufferLength);
> *nameEntry->value->flags = specifiedFlags;*

Can you be a bit more explicit about why you need to do this?
What flags do you intend to set and why?

That said, you can use:

    ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne);

to get the ASN1_STRING holding the value, and since ASN1_STRINGs
are not opaque types, you can just use:

        value->flags = ...

asuming that's a sensible thing to do.  You may however be straying
into undocumented behaviour, and so it might be good to know whether
perhaps there's a better way of getting the result you actually want.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Lisa Matias
If you look here:
It states:
X509_NAME_ENTRY_get_data() retrieves the field value of ne in and ASN1_STRING structure.

Unfortunately this does not work for any non-string X.500 attributes such as x500UniqueIdentifer which is defined as an ASN.1 BIT STRING.

I am only looking to fix in OpenSSL 1.1.1, what was previously working in all older versions of OpenSSL all the way back to 0.9.7 which included a way to support non-string attributes in X509_NAME_ENTRY.

Thanks.

Lisa.



On Mon, 17 Jun 2019 at 22:37, Viktor Dukhovni <[hidden email]> wrote:
On Mon, Jun 17, 2019 at 09:19:41PM -0700, Lisa Matias wrote:

> X509_NAME_ENTRY *nameEntry;
> nameEntry = X509_NAME_ENTRY_create_by_NID (&nameEntry, nid,
>                         derTagToVType (tag), buffer, bufferLength);
> *nameEntry->value->flags = specifiedFlags;*

Can you be a bit more explicit about why you need to do this?
What flags do you intend to set and why?

That said, you can use:

    ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne);

to get the ASN1_STRING holding the value, and since ASN1_STRINGs
are not opaque types, you can just use:

        value->flags = ...

asuming that's a sensible thing to do.  You may however be straying
into undocumented behaviour, and so it might be good to know whether
perhaps there's a better way of getting the result you actually want.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Viktor Dukhovni
On Tue, Jun 18, 2019 at 07:16:46AM -0700, Lisa Matias wrote:

> If you look here:
>
> https://www.openssl.org/docs/man1.1.0/man3/X509_NAME_ENTRY_get_data.html
>
> It states:
>
> *X509_NAME_ENTRY_get_data() retrieves the field value of ne in
> and ASN1_STRING structure.*

Regardless of the entry type, the underlying value is always stored
as an ASN.1 string.

    struct X509_name_entry_st {
        ASN1_OBJECT *object;        /* AttributeType */
        ASN1_STRING *value;         /* AttributeValue */
        int set;                    /* index of RDNSequence for this entry */
        int size;                   /* temp variable */
    };

The flags you're looking for are associated with the ASN.1 string.
To indicate that it is a bit-string you set:

    value->flags |= ASN1_STRING_FLAG_BITS_LEFT | i

where "i" is the number of unused bits in the final octet.

> Unfortunately this does not work for any non-string X.500 attributes such
> as x500UniqueIdentifer which is defined as an ASN.1 BIT STRING.

Actually, it does.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Lisa Matias
Sorry, I was just frustrated that the changes to OpenSSL 1.1.1 broke code which worked for nearly 15 years, by denying access to previously accessible C structs.

I was able to use OpenSSL to generate a certificate with a subject containing the x500UniqueIdentifier attribute as a pure ASN.1 BIT STRING, as you can see with the following snippet from OpenSSL asn1parse.

  ___:d=5  hl=2 l=   3 prim: OBJECT            :x500UniqueIdentifier
  ___:d=5  hl=2 l=  16 prim: BIT STRING
        

Are you sure that the ASN.1 BIT STRING value is really stored as an ASN.1 STRING in a X500_NAME_ENTRY, when it is a binary value and not a text value?

Regardless, I did try this as you helpfully suggested:

(X509_NAME_ENTRY_get_data (nameEntry)->flags) |= (ASN1_STRING_FLAG_BITS_LEFT | i);

And it seems to be working properly for x500UniqueIdentifer attribute, without any errors I can find during compile or in the content of the resulting certificates.

Thank you very much for your assistance.

Lisa.


On Tue, 18 Jun 2019 at 12:30, Viktor Dukhovni <[hidden email]> wrote:
On Tue, Jun 18, 2019 at 07:16:46AM -0700, Lisa Matias wrote:

> If you look here:
>
> https://www.openssl.org/docs/man1.1.0/man3/X509_NAME_ENTRY_get_data.html
>
> It states:
>
> *X509_NAME_ENTRY_get_data() retrieves the field value of ne in
> and ASN1_STRING structure.*

Regardless of the entry type, the underlying value is always stored
as an ASN.1 string.

    struct X509_name_entry_st {
        ASN1_OBJECT *object;        /* AttributeType */
        ASN1_STRING *value;         /* AttributeValue */
        int set;                    /* index of RDNSequence for this entry */
        int size;                   /* temp variable */
    };

The flags you're looking for are associated with the ASN.1 string.
To indicate that it is a bit-string you set:

    value->flags |= ASN1_STRING_FLAG_BITS_LEFT | i

where "i" is the number of unused bits in the final octet.

> Unfortunately this does not work for any non-string X.500 attributes such
> as x500UniqueIdentifer which is defined as an ASN.1 BIT STRING.

Actually, it does.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Viktor Dukhovni
On Tue, Jun 18, 2019 at 02:27:30PM -0700, Lisa Matias wrote:

> Sorry, I was just frustrated that the changes to OpenSSL 1.1.1 broke code
> which worked for nearly 15 years, by denying access to previously
> accessible C structs.

Those changes are needed to make sure that future changes in the
internals DO NOT break your code.  The internal data layout would
ideally not have been exposed the first place, but my time-machine
is out of order...

> Are you sure that the ASN.1 BIT STRING value is really stored as an ASN.1
> STRING in a X500_NAME_ENTRY, when it is a binary value and not a text value?

Yes, it is stored as ASN.1 string, which is just a buffer with a length,
but also has:

    struct asn1_string_st {
        int length;
        int type;
        unsigned char *data;
        /*
         * The value of the following field depends on the type being held.  It
         * is mostly being used for BIT_STRING so if the input data has a
         * non-zero 'unused bits' value, it will be handled correctly
         */
        long flags;
    };

a type field (the NID for the associated OID) and flags as noted
in the comment.

> Regardless, I did try this as you helpfully suggested:
>
> (X509_NAME_ENTRY_get_data (nameEntry)->flags) |=
> (ASN1_STRING_FLAG_BITS_LEFT | i);
>
> And it seems to be working properly for x500UniqueIdentifer attribute,
> without any errors I can find during compile or in the content of the
> resulting certificates.
>
> Thank you very much for your assistance.

You're welcome, that is the correct technique at present.  We should
perhaps provide getter/setter functions for the flags, or perhaps
even a specific function for indicating the value is a bitstring,
and how many bits it holds.  For now the ASN.1 string is not an
opaque structure.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Blumenthal, Uri - 0553 - MITLL
On 6/18/19, 5:44 PM, "openssl-users on behalf of Viktor Dukhovni" <[hidden email] on behalf of [hidden email]> wrote:

    We should
    perhaps provide getter/setter functions for the flags, or perhaps
    even a specific function for indicating the value is a bitstring,
    and how many bits it holds.  For now the ASN.1 string is not an
    opaque structure.

Considering how OpenSSL design evolved, I suspect that the time may come when this string would become opaque. Therefore, I suggest that getter/setter functions should be added.

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Viktor Dukhovni
On Tue, Jun 18, 2019 at 09:51:31PM +0000, Blumenthal, Uri - 0553 - MITLL wrote:

> > We should perhaps provide getter/setter functions for the flags, or
> > perhaps even a specific function for indicating the value is a bitstring,
> > and how many bits it holds.  For now the ASN.1 string is not an opaque
> > structure.
>
> Considering how OpenSSL design evolved, I suspect that the time may come
> when this string would become opaque. Therefore, I suggest that
> getter/setter functions should be added.

Any thoughts about the interface?  Some flag bits look internal,
and not necessarily ideal for applications to modify directly, so
while these might do:

    long ASN1_STRING_get_flags(ASN1_STRING *);
    void ASN1_STRING_set_flags(ASN1_STRING *, long);

Perhaps all that's needed is:

    int ASN1_BIT_STRING_set_unused(ASN1_STRING *, int);

which sets the unused bit count, checking that the ASN1_STRING type
is V_ASN1_BIT_STRING and the count is in the range [0,7].

--
        Viktor.

Reply | Threaded
Open this post in threaded view
|

Re: how to set flags in X509_NAME_ENTRY in OpenSSL 1.1.1

Blumenthal, Uri - 0553 - MITLL
    > > For now the ASN.1 string is not an opaque structure.
    >
    > Considering how OpenSSL design evolved, I suspect that the time may come
    > when this string would become opaque. Therefore, I suggest that
    > getter/setter functions should be added.
   
    Any thoughts about the interface?

Alas, since I don't have any experience actually using these flags, I don't consider myself competent suggesting the API here.

    Some flag bits look internal, and not necessarily ideal for applications to modify directly, so
    while these might do:
   
        long ASN1_STRING_get_flags(ASN1_STRING *);
        void ASN1_STRING_set_flags(ASN1_STRING *, long);
   
This makes sense. Also, if there are flags that users are likely to need - perhaps explicit getter/setter calls for those individual flags? This would lower the likelihood of erroneously affecting unintended flags by a "ricochet"...

    Perhaps all that's needed is:
   
        int ASN1_BIT_STRING_set_unused(ASN1_STRING *, int);
   
    which sets the unused bit count, checking that the ASN1_STRING type
    is V_ASN1_BIT_STRING and the count is in the range [0,7].
   
That I don't know. I can't figure how or why I would use ..._set_unused()... But as I said, my competence in this particular thing is low.

smime.p7s (7K) Download Attachment