ASN1 lax bit string decoding
Some ASN1 objects stored on some smartcards (for instance the IASECC/CPX ones) do not comply strictly with the rules 8.6.2.3 and 8.6.2.3 from the ITU. Since these rules are not some strict ones, let's have a loose decoding option that can be displayed by the command: opensc-explorer asn1 7001 # for instance Fix: issue #2224
This commit is contained in:
parent
b508349010
commit
4119b2c3e7
|
@ -253,10 +253,15 @@ static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen, size_t depth
|
|||
if (buflen > sizeof(a) + 1) {
|
||||
print_hex(buf, buflen, depth);
|
||||
} else {
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a));
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 1);
|
||||
if (r < 0) {
|
||||
printf("decode error");
|
||||
return;
|
||||
printf("decode error, ");
|
||||
/* try again without the strict mode */
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 0);
|
||||
if (r < 0) {
|
||||
printf("even for lax decoding");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
for (i = r - 1; i >= 0; i--) {
|
||||
printf("%c", ((a >> i) & 1) ? '1' : '0');
|
||||
|
@ -567,7 +572,7 @@ const u8 *sc_asn1_verify_tag(sc_context_t *ctx, const u8 * buf, size_t buflen,
|
|||
}
|
||||
|
||||
static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
||||
size_t outlen, int invert)
|
||||
size_t outlen, int invert, const int strict)
|
||||
{
|
||||
const u8 *in = inbuf;
|
||||
u8 *out = (u8 *) outbuf;
|
||||
|
@ -577,13 +582,19 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
|||
|
||||
if (inlen < 1)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* 8.6.2.3 If the bitstring is empty, there shall be no subsequent octets,
|
||||
* and the initial octet shall be zero. */
|
||||
if (inlen == 1 && *in != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
|
||||
if ((*in & ~0x07) != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
|
||||
/* The formatting is only enforced by SHALL keyword so we should accept
|
||||
* by default also non-strict values. */
|
||||
if (strict) {
|
||||
/* 8.6.2.3 If the bitstring is empty, there shall be no
|
||||
* subsequent octets,and the initial octet shall be zero. */
|
||||
if (inlen == 1 && *in != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
|
||||
if ((*in & ~0x07) != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
}
|
||||
|
||||
memset(outbuf, 0, outlen);
|
||||
zero_bits = *in & 0x07;
|
||||
in++;
|
||||
|
@ -622,15 +633,15 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
|||
}
|
||||
|
||||
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen)
|
||||
void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1);
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1, strict);
|
||||
}
|
||||
|
||||
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen)
|
||||
void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0);
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0, strict);
|
||||
}
|
||||
|
||||
static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
|
||||
|
@ -675,7 +686,7 @@ static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
|
|||
* Bitfields are just bit strings, stored in an unsigned int
|
||||
* (taking endianness into account)
|
||||
*/
|
||||
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen)
|
||||
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
u8 data[sizeof(unsigned int)];
|
||||
unsigned int field = 0;
|
||||
|
@ -684,7 +695,7 @@ static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t
|
|||
if (outlen != sizeof(data))
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
|
||||
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1);
|
||||
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1, strict);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
|
@ -1538,7 +1549,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
|||
*len = objlen-1;
|
||||
parm = *buf;
|
||||
}
|
||||
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert);
|
||||
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert, 0);
|
||||
if (r >= 0) {
|
||||
*len = r;
|
||||
r = 0;
|
||||
|
@ -1547,7 +1558,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
|||
break;
|
||||
case SC_ASN1_BIT_FIELD:
|
||||
if (parm != NULL)
|
||||
r = decode_bit_field(obj, objlen, (u8 *) parm, *len);
|
||||
r = decode_bit_field(obj, objlen, (u8 *) parm, *len, 0);
|
||||
break;
|
||||
case SC_ASN1_OCTET_STRING:
|
||||
if (parm != NULL) {
|
||||
|
|
|
@ -96,10 +96,10 @@ void sc_asn1_print_tags(const u8 * buf, size_t buflen);
|
|||
int sc_asn1_utf8string_to_ascii(const u8 * buf, size_t buflen,
|
||||
u8 * outbuf, size_t outlen);
|
||||
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen);
|
||||
void *outbuf, size_t outlen, const int strict);
|
||||
/* non-inverting version */
|
||||
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen);
|
||||
void *outbuf, size_t outlen, const int strict);
|
||||
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out, int strict);
|
||||
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
||||
struct sc_object_id *id);
|
||||
|
|
|
@ -195,7 +195,7 @@ TORTURE_INTEGER(negative, "\xff\x20", -224)
|
|||
size_t value_len = sizeof(value); \
|
||||
int rv; \
|
||||
\
|
||||
rv = decode_bit_field(data, datalen, &value, value_len); \
|
||||
rv = decode_bit_field(data, datalen, &value, value_len, 1); \
|
||||
assert_int_equal(rv, SC_SUCCESS); \
|
||||
assert_int_equal(value, int_value); \
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ TORTURE_INTEGER(negative, "\xff\x20", -224)
|
|||
size_t value_len = sizeof(value); \
|
||||
int rv; \
|
||||
\
|
||||
rv = decode_bit_field(data, datalen, &value, value_len); \
|
||||
rv = decode_bit_field(data, datalen, &value, value_len, 1); \
|
||||
assert_int_equal(rv, error); \
|
||||
}
|
||||
/* Without the Tag (0x03) and Length */
|
||||
|
|
Loading…
Reference in New Issue