From 98907b68f107936e83fa2b24ba4e4a6d536bd0e2 Mon Sep 17 00:00:00 2001 From: okir Date: Wed, 16 Apr 2003 20:52:26 +0000 Subject: [PATCH] - fixed endianness problem with encoding/deconding of bit fields git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1034 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/asn1.c | 58 +++++++++++++++++++++++++++++++++-- src/libopensc/asn1.h | 1 + src/libopensc/pkcs15-pin.c | 4 +-- src/libopensc/pkcs15-prkey.c | 8 ++--- src/libopensc/pkcs15-pubkey.c | 8 ++--- src/libopensc/pkcs15.c | 4 +-- 6 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 72a21e5d..d6ade8a9 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -469,6 +469,52 @@ static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf, return 0; } +/* + * 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) +{ + u8 data[sizeof(unsigned int)]; + unsigned int field = 0; + int i, n; + + if (outlen != sizeof(data)) + return SC_ERROR_BUFFER_TOO_SMALL; + + n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1); + if (n < 0) + return n; + + for (i = 0; i < n; i += 8) { + field |= (data[i/8] << i); + } + memcpy(outbuf, &field, outlen); + return 0; +} + +static int encode_bit_field(const u8 *inbuf, size_t inlen, + u8 **outbuf, size_t *outlen) +{ + u8 data[sizeof(unsigned int)]; + unsigned int field = 0; + int i, bits; + + if (inlen != sizeof(data)) + return SC_ERROR_BUFFER_TOO_SMALL; + + /* count the bits */ + memcpy(&field, inbuf, inlen); + for (bits = 0; field; bits++) + field >>= 1; + + memcpy(&field, inbuf, inlen); + for (i = 0; i < bits; i += 8) + data[i/8] = field >> i; + + return encode_bit_string(data, bits, outbuf, outlen, 1); +} + int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out) { int i, a = 0; @@ -763,15 +809,15 @@ static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_asn1_p int r; const struct sc_pkcs15_object *p15_obj = obj->p15_obj; struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5]; - size_t flags_len; size_t label_len = strlen(p15_obj->label); + size_t flags_len; sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr); sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj); if (label_len != 0) sc_format_asn1_entry(asn1_c_attr + 0, (void *) p15_obj->label, &label_len, 1); if (p15_obj->flags) { - flags_len = _sc_count_bit_string_size(&p15_obj->flags, sizeof(p15_obj->flags)); + flags_len = sizeof(p15_obj->flags); sc_format_asn1_entry(asn1_c_attr + 1, (void *) &p15_obj->flags, &flags_len, 1); } if (p15_obj->auth_id.len) @@ -860,6 +906,10 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry } } break; + case SC_ASN1_BIT_FIELD: + if (parm != NULL) + r = decode_bit_field(obj, objlen, (u8 *) parm, *len); + break; case SC_ASN1_OCTET_STRING: if (parm != NULL) { int c; @@ -1113,6 +1163,10 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry else r = encode_bit_string((const u8 *) parm, *len, &buf, &buflen, 0); break; + case SC_ASN1_BIT_FIELD: + assert(len != NULL); + r = encode_bit_field((const u8 *) parm, *len, &buf, &buflen); + break; case SC_ASN1_OCTET_STRING: case SC_ASN1_UTF8STRING: assert(len != NULL); diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index c4d59a44..3f981b0c 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -141,6 +141,7 @@ void sc_asn1_clear_algorithm_id(struct sc_algorithm_id *); /* internal structures */ #define SC_ASN1_STRUCT 129 #define SC_ASN1_CHOICE 130 +#define SC_ASN1_BIT_FIELD 131 /* bit string as integer */ /* 'complex' structures */ #define SC_ASN1_PATH 256 diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index a6a8d2f7..c68c679c 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -32,7 +32,7 @@ static const struct sc_asn1_entry c_asn1_com_ao_attr[] = { { NULL } }; static const struct sc_asn1_entry c_asn1_pin_attr[] = { - { "pinFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, + { "pinFlags", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, 0, NULL }, { "pinType", SC_ASN1_ENUMERATED, ASN1_ENUMERATED, 0, NULL }, { "minLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, NULL }, { "storedLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, NULL }, @@ -136,7 +136,7 @@ int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1); - flags_len = _sc_count_bit_string_size(&pin->flags, sizeof(pin->flags)); + flags_len = sizeof(pin->flags); sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 1); sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 1); sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 1); diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 75d92d0a..c7f67c0a 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -29,9 +29,9 @@ static const struct sc_asn1_entry c_asn1_com_key_attr[] = { { "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL }, - { "usage", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, + { "usage", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, 0, NULL }, { "native", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, NULL }, - { "accessFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL }, + { "accessFlags", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL }, { "keyReference",SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, { NULL } }; @@ -219,12 +219,12 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, break; } sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1); - usage_len = _sc_count_bit_string_size(&prkey->usage, sizeof(prkey->usage)); + usage_len = sizeof(prkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1); if (prkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1); if (prkey->access_flags) { - af_len = _sc_count_bit_string_size(&prkey->access_flags, sizeof(prkey->access_flags)); + af_len = sizeof(prkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1); } if (prkey->key_reference >= 0) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 5684b7e6..847bd51c 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -29,9 +29,9 @@ static const struct sc_asn1_entry c_asn1_com_key_attr[] = { { "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL }, - { "usage", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, + { "usage", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, 0, NULL }, { "native", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, NULL }, - { "accessFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL }, + { "accessFlags", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL }, { "keyReference",SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, { NULL } }; @@ -185,12 +185,12 @@ int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, } sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1); - usage_len = _sc_count_bit_string_size(&pubkey->usage, sizeof(pubkey->usage)); + usage_len = sizeof(pubkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1); if (pubkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1); if (pubkey->access_flags) { - af_len = _sc_count_bit_string_size(&pubkey->access_flags, sizeof(pubkey->access_flags)); + af_len = sizeof(pubkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1); } if (pubkey->key_reference >= 0) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index e75a54de..149353a7 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -63,7 +63,7 @@ static const struct sc_asn1_entry c_asn1_toki[] = { { "serialNumber", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, NULL }, { "manufacturerID", SC_ASN1_UTF8STRING, ASN1_UTF8STRING, SC_ASN1_OPTIONAL, NULL }, { "label", SC_ASN1_UTF8STRING, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL }, - { "tokenflags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, + { "tokenflags", SC_ASN1_BIT_FIELD, ASN1_BIT_STRING, 0, NULL }, { "seInfo", SC_ASN1_SEQUENCE, SC_ASN1_CONS | ASN1_SEQUENCE, SC_ASN1_OPTIONAL, NULL }, { "recordInfo", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL }, { "supportedAlgorithms", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 2, SC_ASN1_OPTIONAL, NULL }, @@ -168,7 +168,7 @@ int sc_pkcs15_encode_tokeninfo(struct sc_context *ctx, sc_format_asn1_entry(asn1_toki + 3, card->label, &label_len, 1); } if (card->flags) { - flags_len = _sc_count_bit_string_size(&card->flags, sizeof(card->flags)); + flags_len = sizeof(card->flags); sc_format_asn1_entry(asn1_toki + 4, &card->flags, &flags_len, 1); } sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1);