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) {
|
if (buflen > sizeof(a) + 1) {
|
||||||
print_hex(buf, buflen, depth);
|
print_hex(buf, buflen, depth);
|
||||||
} else {
|
} 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) {
|
if (r < 0) {
|
||||||
printf("decode error");
|
printf("decode error, ");
|
||||||
return;
|
/* 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--) {
|
for (i = r - 1; i >= 0; i--) {
|
||||||
printf("%c", ((a >> i) & 1) ? '1' : '0');
|
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,
|
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;
|
const u8 *in = inbuf;
|
||||||
u8 *out = (u8 *) outbuf;
|
u8 *out = (u8 *) outbuf;
|
||||||
|
@ -577,13 +582,19 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
||||||
|
|
||||||
if (inlen < 1)
|
if (inlen < 1)
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
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. */
|
/* The formatting is only enforced by SHALL keyword so we should accept
|
||||||
if (inlen == 1 && *in != 0)
|
* by default also non-strict values. */
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
if (strict) {
|
||||||
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
|
/* 8.6.2.3 If the bitstring is empty, there shall be no
|
||||||
if ((*in & ~0x07) != 0)
|
* subsequent octets,and the initial octet shall be zero. */
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
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);
|
memset(outbuf, 0, outlen);
|
||||||
zero_bits = *in & 0x07;
|
zero_bits = *in & 0x07;
|
||||||
in++;
|
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,
|
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,
|
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,
|
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
|
* Bitfields are just bit strings, stored in an unsigned int
|
||||||
* (taking endianness into account)
|
* (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)];
|
u8 data[sizeof(unsigned int)];
|
||||||
unsigned int field = 0;
|
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))
|
if (outlen != sizeof(data))
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
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)
|
if (n < 0)
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
@ -1538,7 +1549,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
||||||
*len = objlen-1;
|
*len = objlen-1;
|
||||||
parm = *buf;
|
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) {
|
if (r >= 0) {
|
||||||
*len = r;
|
*len = r;
|
||||||
r = 0;
|
r = 0;
|
||||||
|
@ -1547,7 +1558,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
||||||
break;
|
break;
|
||||||
case SC_ASN1_BIT_FIELD:
|
case SC_ASN1_BIT_FIELD:
|
||||||
if (parm != NULL)
|
if (parm != NULL)
|
||||||
r = decode_bit_field(obj, objlen, (u8 *) parm, *len);
|
r = decode_bit_field(obj, objlen, (u8 *) parm, *len, 0);
|
||||||
break;
|
break;
|
||||||
case SC_ASN1_OCTET_STRING:
|
case SC_ASN1_OCTET_STRING:
|
||||||
if (parm != NULL) {
|
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,
|
int sc_asn1_utf8string_to_ascii(const u8 * buf, size_t buflen,
|
||||||
u8 * outbuf, size_t outlen);
|
u8 * outbuf, size_t outlen);
|
||||||
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
|
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 */
|
/* non-inverting version */
|
||||||
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
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_integer(const u8 * inbuf, size_t inlen, int *out, int strict);
|
||||||
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
||||||
struct sc_object_id *id);
|
struct sc_object_id *id);
|
||||||
|
|
|
@ -195,7 +195,7 @@ TORTURE_INTEGER(negative, "\xff\x20", -224)
|
||||||
size_t value_len = sizeof(value); \
|
size_t value_len = sizeof(value); \
|
||||||
int rv; \
|
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(rv, SC_SUCCESS); \
|
||||||
assert_int_equal(value, int_value); \
|
assert_int_equal(value, int_value); \
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ TORTURE_INTEGER(negative, "\xff\x20", -224)
|
||||||
size_t value_len = sizeof(value); \
|
size_t value_len = sizeof(value); \
|
||||||
int rv; \
|
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); \
|
assert_int_equal(rv, error); \
|
||||||
}
|
}
|
||||||
/* Without the Tag (0x03) and Length */
|
/* Without the Tag (0x03) and Length */
|
||||||
|
|
Loading…
Reference in New Issue