summaryrefslogtreecommitdiffstats
path: root/crypto/asn1/a_bitstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asn1/a_bitstr.c')
-rw-r--r--crypto/asn1/a_bitstr.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index 2c10120651..275de43eb6 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -68,27 +68,50 @@ int i2d_ASN1_BIT_STRING(a,pp)
ASN1_BIT_STRING *a;
unsigned char **pp;
{
- int ret,j,r,bits;
+ int ret,j,r,bits,len;
unsigned char *p,*d;
if (a == NULL) return(0);
- /* our bit strings are always a multiple of 8 :-) */
- bits=0;
- ret=1+a->length;
+ len=a->length;
+
+ if (len > 0)
+ {
+ if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
+ {
+ bits=(int)a->flags&0x07;
+ }
+ else
+ {
+ for ( ; len > 0; len--)
+ {
+ if (a->data[len-1]) break;
+ }
+ j=a->data[len-1];
+ if (j & 0x01) bits=0;
+ else if (j & 0x02) bits=1;
+ else if (j & 0x04) bits=2;
+ else if (j & 0x08) bits=3;
+ else if (j & 0x10) bits=4;
+ else if (j & 0x20) bits=5;
+ else if (j & 0x40) bits=6;
+ else if (j & 0x80) bits=7;
+ else bits=0; /* should not happen */
+ }
+ }
+ else
+ bits=0;
+ ret=1+len;
r=ASN1_object_size(0,ret,V_ASN1_BIT_STRING);
if (pp == NULL) return(r);
p= *pp;
ASN1_put_object(&p,0,ret,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL);
- if (bits == 0)
- j=0;
- else j=8-bits;
- *(p++)=(unsigned char)j;
+ *(p++)=(unsigned char)bits;
d=a->data;
- memcpy(p,d,a->length);
- p+=a->length;
- if (a->length > 0) p[-1]&=(0xff<<j);
+ memcpy(p,d,len);
+ p+=len;
+ if (len > 0) p[-1]&=(0xff<<bits);
*pp=p;
return(r);
}
@@ -127,6 +150,12 @@ long length;
if (len < 1) { i=ASN1_R_STRING_TOO_SHORT; goto err; }
i= *(p++);
+ /* We do this to preserve the settings. If we modify
+ * the settings, via the _set_bit function, we will recalculate
+ * on output */
+ ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
+ ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|(i&0x07)); /* set */
+
if (len-- > 1) /* using one because of the bits left byte */
{
s=(unsigned char *)Malloc((int)len);
@@ -170,6 +199,8 @@ int value;
v=1<<(7-(n&0x07));
iv= ~v;
+ a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
+
if (a == NULL) return(0);
if ((a->length < (w+1)) || (a->data == NULL))
{