Currently, the ASN1 generation string format does not allow declaring
zero-ending bit strings unless the length is a multiple of eight. Such
non-aligned bit strings are used e.g. by an X.509 extension defined in
RFC 3779.

This patch addresses the problem by removing unnecessary assumptions
from the code handling bit strings, and introducing a new format
specifier which allows declaration of arbitrary bit strings.

---
 crypto/asn1/a_bitstr.c | 11 +++++------
 crypto/asn1/asn1.h     |  1 +
 crypto/asn1/asn1_gen.c | 19 +++++++++++++++++++
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index 0cb899f..767b4d9 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -175,22 +175,23 @@ err:
  */
 int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
        {
-       int w,v,iv;
+       int w,b,v,iv;
        unsigned char *c;
 
        w=n/8;
-       v=1<<(7-(n&0x07));
+       b=7-n&0x07;
+       v=1<<b;
        iv= ~v;
        if (!value) v=0;
 
        if (a == NULL)
                return 0;
 
-       a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
+       if (a->length <= (w+1))
+               a->flags = (a->flags & ~0x07) | ASN1_STRING_FLAG_BITS_LEFT | b;
 
        if ((a->length < (w+1)) || (a->data == NULL))
                {
-               if (!value) return(1); /* Don't need to set */
                if (a->data == NULL)
                        c=(unsigned char *)OPENSSL_malloc(w+1);
                else
@@ -207,8 +208,6 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int 
value)
                a->length=w+1;
        }
        a->data[w]=((a->data[w])&iv)|v;
-       while ((a->length > 0) && (a->data[a->length-1] == 0))
-               a->length--;
        return(1);
        }
 
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 925fdba..5c4b2ae 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -1333,6 +1333,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_FIELD_MISSING                            121
 #define ASN1_R_FIRST_NUM_TOO_LARGE                      122
 #define ASN1_R_HEADER_TOO_LONG                          123
+#define ASN1_R_ILLEGAL_BINARY                           220
 #define ASN1_R_ILLEGAL_BITSTRING_FORMAT                         175
 #define ASN1_R_ILLEGAL_BOOLEAN                          176
 #define ASN1_R_ILLEGAL_CHARACTERS                       124
diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c
index 25b270d..51caeb8 100644
--- a/crypto/asn1/asn1_gen.c
+++ b/crypto/asn1/asn1_gen.c
@@ -84,6 +84,8 @@
 #define ASN1_GEN_FORMAT_HEX    3
 /* List of bits */
 #define ASN1_GEN_FORMAT_BITLIST        4
+/* Binary */
+#define ASN1_GEN_FORMAT_BINARY 5
 
 
 struct tag_name_st
@@ -370,6 +372,8 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
                        arg->format = ASN1_GEN_FORMAT_HEX;
                else if (!strncmp(vstart, "BITLIST", 3))
                        arg->format = ASN1_GEN_FORMAT_BITLIST;
+               else if (!strncmp(vstart, "BINARY", 3))
+                       arg->format = ASN1_GEN_FORMAT_BINARY;
                else
                        {
                        ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
@@ -636,6 +640,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int 
format, int utype)
        long rdlen;
 
        int no_unused = 1;
+       int i;
 
        if (!(atmp = ASN1_TYPE_new()))
                {
@@ -793,6 +798,20 @@ static ASN1_TYPE *asn1_str2type(const char *str, int 
format, int utype)
                        no_unused = 0;
                        
                        }
+               else if ((format == ASN1_GEN_FORMAT_BINARY) && (utype == 
V_ASN1_BIT_STRING))
+                       {
+                       for (i = 0; str[i]; i++)
+                               {
+                               if (str[i] != '0' && str[i] != '1')
+                                       {
+                                       ASN1err(ASN1_F_ASN1_STR2TYPE, 
ASN1_R_ILLEGAL_BINARY);
+                                       goto bad_str;
+                                       }
+                               ASN1_BIT_STRING_set_bit(atmp->value.bit_string, 
i, str[i] - '0');
+                               }
+                       no_unused = 0;
+                       
+                       }
                else 
                        {
                        ASN1err(ASN1_F_ASN1_STR2TYPE, 
ASN1_R_ILLEGAL_BITSTRING_FORMAT);
-- 
1.8.3.1

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to