Kaarle Ritvanen via RT
10 years ago
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);
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 openssl-***@openssl.org
Automated List Manager ***@openssl.org
1.8.3.1
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org