*Beat Bolli*
* Added `ASN1_BIT_STRING_set1()` to set a bit string to a value including
- the length in bytes and the number of unused bits.
+ the length in bytes and the number of unused bits. Internally,
+ 'ASN1_BIT_STRING_set_bit()' has also been modified to keep the number of
+ unused bits correct when changing an ASN1_BIT_STRING.
* Bob Beck *
return ASN1_STRING_set(x, d, len);
}
-int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
+int ossl_i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp)
{
- int ret, j, bits, len;
+ int ret = 0, bits = 0, len;
unsigned char *p, *d;
if (a == NULL)
- return 0;
+ goto err;
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;
- }
-
- if (len == 0) {
- bits = 0;
- } else {
- 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;
+ if (len > INT_MAX - 1)
+ goto err;
+
+ if ((len > 0) && (a->flags & ASN1_STRING_FLAG_BITS_LEFT))
+ bits = (int)a->flags & 0x07;
- ret = 1 + len;
if (pp == NULL)
- return ret;
+ goto done;
p = *pp;
p[-1] &= (0xff << bits);
}
*pp = p;
+
+done:
+ ret = len + 1;
+
+err:
return ret;
}
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
+
while ((a->length > 0) && (a->data[a->length - 1] == 0))
a->length--;
+
+ if (a->length > 0) {
+ uint8_t u8 = a->data[a->length - 1];
+ uint8_t unused_bits = 7;
+
+ /* Only keep least significant bit; count trailing zeroes. */
+ u8 &= 0x100 - u8;
+ if ((u8 & 0x0f) != 0)
+ unused_bits -= 4;
+ if ((u8 & 0x33) != 0)
+ unused_bits -= 2;
+ if ((u8 & 0x55) != 0)
+ unused_bits -= 1;
+
+ if (!asn1_bit_string_set_unused_bits(a, unused_bits))
+ return 0;
+ }
return 1;
}
ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length);
-int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
+int ossl_i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp);
ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long length);
int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
break;
case V_ASN1_BIT_STRING:
- return ossl_i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+ return ossl_i2c_ASN1_BIT_STRING((const ASN1_BIT_STRING *)*pval,
cout ? &cout : NULL);
case V_ASN1_INTEGER: