asn1: Allow non-strict INTEGER parsing for other code paths (FCI parsing)

This commit is contained in:
Jakub Jelen 2019-11-05 13:34:07 +01:00
parent fefff2e462
commit aaa302ca35
5 changed files with 37 additions and 25 deletions

View File

@ -713,7 +713,7 @@ static int encode_bit_field(const u8 *inbuf, size_t inlen,
return encode_bit_string(data, bits, outbuf, outlen, 1);
}
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out)
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out, int strict)
{
int a = 0, is_negative = 0;
size_t i = 0;
@ -725,14 +725,14 @@ int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out)
return SC_ERROR_NOT_SUPPORTED;
}
if (inbuf[0] & 0x80) {
if (inlen > 1 && inbuf[0] == 0xff && (inbuf[1] & 0x80)) {
if (strict && inlen > 1 && inbuf[0] == 0xff && (inbuf[1] & 0x80)) {
return SC_ERROR_INVALID_ASN1_OBJECT;
}
is_negative = 1;
a |= 0xff^(*inbuf++);
i = 1;
} else {
if (inlen > 1 && inbuf[0] == 0x00 && (inbuf[1] & 0x80) == 0) {
if (strict && inlen > 1 && inbuf[0] == 0x00 && (inbuf[1] & 0x80) == 0) {
return SC_ERROR_INVALID_ASN1_OBJECT;
}
}
@ -1496,7 +1496,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
case SC_ASN1_INTEGER:
case SC_ASN1_ENUMERATED:
if (parm != NULL) {
r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm);
r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm, 1);
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "%*.*sdecoding '%s' returned %d\n", depth, depth, "",
entry->name, *((int *) entry->parm));
}

View File

@ -100,7 +100,7 @@ int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
/* non-inverting version */
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
void *outbuf, size_t outlen);
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out);
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);
int sc_asn1_encode_object_id(u8 **buf, size_t *buflen,

View File

@ -358,7 +358,7 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
/* fall through */
case 0x80:
/* determine the file size */
if (sc_asn1_decode_integer(p, length, &size) == 0 && size >= 0) {
if (sc_asn1_decode_integer(p, length, &size, 0) == 0 && size >= 0) {
file->size = size;
sc_log(ctx, " bytes in file: %"SC_FORMAT_LEN_SIZE_T"u",
file->size);

View File

@ -177,8 +177,8 @@ static void torture_integer(void **state)
u8 padded_zero[] = {0x00, 0x00};
u8 zero[] = {0x00};
u8 one[] = {0x01};
u8 padded_one[] = {0x00, 0x01};
u8 minus_one[] = {0xFF};
u8 padded_one[] = {0x00, 0x01};
u8 padded_minus_one[] = {0xFF, 0xFF};
u8 padded_127[] = {0x00, 0x7F};
u8 padded_128[] = {0x00, 0x80};
@ -192,22 +192,34 @@ static void torture_integer(void **state)
size_t buflen = 0;
int rv = 0;
rv = sc_asn1_decode_integer(null, sizeof(null), &value);
rv = sc_asn1_decode_integer(null, sizeof(null), &value, 1);
assert_int_equal(rv, SC_ERROR_INVALID_ASN1_OBJECT);
rv = sc_asn1_decode_integer(padded_zero, sizeof(padded_zero), &value);
rv = sc_asn1_decode_integer(padded_zero, sizeof(padded_zero), &value, 1);
assert_int_equal(rv, SC_ERROR_INVALID_ASN1_OBJECT);
rv = sc_asn1_decode_integer(padded_one, sizeof(padded_one), &value);
rv = sc_asn1_decode_integer(padded_one, sizeof(padded_one), &value, 1);
assert_int_equal(rv, SC_ERROR_INVALID_ASN1_OBJECT);
/* but we can parse them without the strict checking */
rv = sc_asn1_decode_integer(padded_one, sizeof(padded_one), &value, 0);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 1);
rv = sc_asn1_decode_integer(padded_minus_one, sizeof(padded_minus_one), &value);
rv = sc_asn1_decode_integer(padded_minus_one, sizeof(padded_minus_one), &value, 1);
assert_int_equal(rv, SC_ERROR_INVALID_ASN1_OBJECT);
/* but we can parse them without the strict checking */
rv = sc_asn1_decode_integer(padded_minus_one, sizeof(padded_minus_one), &value, 0);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, -1);
rv = sc_asn1_decode_integer(padded_127, sizeof(padded_127), &value);
rv = sc_asn1_decode_integer(padded_127, sizeof(padded_127), &value, 1);
assert_int_equal(rv, SC_ERROR_INVALID_ASN1_OBJECT);
/* but we can parse them without the strict checking */
rv = sc_asn1_decode_integer(padded_127, sizeof(padded_127), &value, 0);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 127);
rv = sc_asn1_decode_integer(padded_128, sizeof(padded_128), &value);
rv = sc_asn1_decode_integer(padded_128, sizeof(padded_128), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 128);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -216,7 +228,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, padded_128, buflen);
free(buf);
rv = sc_asn1_decode_integer(zero, sizeof(zero), &value);
rv = sc_asn1_decode_integer(zero, sizeof(zero), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 0);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -225,7 +237,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, zero, buflen);
free(buf);
rv = sc_asn1_decode_integer(one, sizeof(one), &value);
rv = sc_asn1_decode_integer(one, sizeof(one), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 1);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -234,7 +246,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, one, buflen);
free(buf);
rv = sc_asn1_decode_integer(minus_one, sizeof(minus_one), &value);
rv = sc_asn1_decode_integer(minus_one, sizeof(minus_one), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, -1);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -243,7 +255,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, minus_one, buflen);
free(buf);
rv = sc_asn1_decode_integer(max2, sizeof(max2), &value);
rv = sc_asn1_decode_integer(max2, sizeof(max2), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 32767);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -252,7 +264,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, max2, buflen);
free(buf);
rv = sc_asn1_decode_integer(min2, sizeof(min2), &value);
rv = sc_asn1_decode_integer(min2, sizeof(min2), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, -32768);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -262,7 +274,7 @@ static void torture_integer(void **state)
free(buf);
if (sizeof(int) == 4) {
rv = sc_asn1_decode_integer(max4, sizeof(max4), &value);
rv = sc_asn1_decode_integer(max4, sizeof(max4), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, 2147483647);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -271,7 +283,7 @@ static void torture_integer(void **state)
assert_memory_equal(buf, max4, buflen);
free(buf);
rv = sc_asn1_decode_integer(min4, sizeof(min4), &value);
rv = sc_asn1_decode_integer(min4, sizeof(min4), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, -2147483648);
rv = asn1_encode_integer(value, &buf, &buflen);
@ -280,14 +292,14 @@ static void torture_integer(void **state)
assert_memory_equal(buf, min4, buflen);
free(buf);
rv = sc_asn1_decode_integer(over, sizeof(over), &value);
rv = sc_asn1_decode_integer(over, sizeof(over), &value, 1);
assert_int_equal(rv, SC_ERROR_NOT_SUPPORTED);
} else {
/* On more esoteric architectures, we can have different size of int */
rv = sc_asn1_decode_integer(max4, sizeof(max4), &value);
rv = sc_asn1_decode_integer(max4, sizeof(max4), &value, 1);
assert_int_equal(rv, SC_ERROR_NOT_SUPPORTED);
rv = sc_asn1_decode_integer(min4, sizeof(min4), &value);
rv = sc_asn1_decode_integer(min4, sizeof(min4), &value, 1);
assert_int_equal(rv, SC_ERROR_NOT_SUPPORTED);
}
}
@ -308,7 +320,7 @@ static void torture_negative_int(void **state)
int value;
int rv = 0;
rv = sc_asn1_decode_integer(data1, sizeof(data1), &value);
rv = sc_asn1_decode_integer(data1, sizeof(data1), &value, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(value, -224);
}

View File

@ -154,7 +154,7 @@ soc_info(sc_context_t *ctx, sc_card_t *card)
&& cla == SC_ASN1_TAG_UNIVERSAL && tag == SC_ASN1_TAG_INTEGER) {
int applet_count = 0;
/* number of applets */
if (SC_SUCCESS == sc_asn1_decode_integer(p, length, &applet_count)) {
if (SC_SUCCESS == sc_asn1_decode_integer(p, length, &applet_count, 0)) {
printf("SoCManager knows %d applet%s%s\n", applet_count,
applet_count == 1 ? "" : "s", applet_count == 0 ? "" : ":");
/* AID of client applet #x */