diff options
author | Ralf S. Engelschall <rse@openssl.org> | 1998-12-21 11:00:56 +0000 |
---|---|---|
committer | Ralf S. Engelschall <rse@openssl.org> | 1998-12-21 11:00:56 +0000 |
commit | dfeab0689f69c0b4bd3480ffd37a9cacc2f17d9c (patch) | |
tree | 2f74e0cfd76a9e092548a9bf52e579aef984299b /crypto/asn1/a_bitstr.c | |
parent | 58964a492275ca9a59a0cd9c8155cb2491b4b909 (diff) | |
download | openssl-new-dfeab0689f69c0b4bd3480ffd37a9cacc2f17d9c.tar.gz |
Import of old SSLeay release: SSLeay 0.9.1b (unreleased)SSLeay
Diffstat (limited to 'crypto/asn1/a_bitstr.c')
-rw-r--r-- | crypto/asn1/a_bitstr.c | 53 |
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)) { |