Imporve SKDF decoding and implement encoding

- fixes decoding of SecretKeyAttributes
- adds support for algorithmReferences
- adds support for algIndependentKeys (PKCS#15 Generic keys)
- implements encoding of SKDF
This commit is contained in:
Timo Teräs 2017-04-14 10:24:41 +03:00 committed by Frank Morgner
parent becd243fd6
commit 2632b616d9
3 changed files with 120 additions and 14 deletions

View File

@ -26,13 +26,30 @@
#include <stdio.h>
#include <assert.h>
#define C_ASN1_COM_KEY_ATTR_SIZE 6
/*
* in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8
*/
#define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1)
static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = {
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_COM_KEY_ATTR_SIZE 7
static const struct sc_asn1_entry c_asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE] = {
{ "iD", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL},
{ "usage", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL},
{ "native", SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, NULL, NULL },
{ "accessFlags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL, NULL, NULL},
{ "keyReference",SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
{ "algReference", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -42,18 +59,24 @@ static const struct sc_asn1_entry c_asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_COM_GENERIC_SKEY_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_generic_skey_attr[C_ASN1_COM_GENERIC_SKEY_ATTR_SIZE] = {
{ "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL},
#define C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE] = {
{ "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL},
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE 2
static const struct sc_asn1_entry c_asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE] = {
{ "secretKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL},
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_SKEY_CHOICE_SIZE 5
static const struct sc_asn1_entry c_asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE] = {
{ "genericSecretKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "desKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "des2Key", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "des3Key", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "genericSecretKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "desKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "des2Key", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ "des3Key", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
@ -70,14 +93,16 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_skey_info info;
int r;
int r, i;
size_t usage_len = sizeof(info.usage);
size_t af_len = sizeof(info.access_flags);
struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE];
struct sc_asn1_entry asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_generic_skey_attr[C_ASN1_COM_GENERIC_SKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE];
struct sc_asn1_entry asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE];
struct sc_asn1_entry asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE];
struct sc_asn1_entry asn1_skey[C_ASN1_SKEY_SIZE];
struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE];
struct sc_asn1_pkcs15_object skey_des_obj = {
obj, asn1_com_key_attr, asn1_com_skey_attr, asn1_generic_skey_attr
};
@ -86,10 +111,12 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj
sc_copy_asn1_entry(c_asn1_skey, asn1_skey);
sc_copy_asn1_entry(c_asn1_skey_choice, asn1_skey_choice);
sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_com_skey_attr, asn1_com_skey_attr);
sc_copy_asn1_entry(c_asn1_generic_skey_attr, asn1_generic_skey_attr);
sc_copy_asn1_entry(c_asn1_generic_skey_value_attr, asn1_generic_skey_value_attr);
sc_format_asn1_entry(asn1_skey + 0, asn1_skey_choice, NULL, 0);
sc_format_asn1_entry(asn1_skey_choice + 0, &skey_des_obj, NULL, 0);
@ -102,10 +129,14 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj
sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0);
sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0);
for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && (asn1_supported_algorithms + i)->name; i++)
sc_format_asn1_entry(asn1_supported_algorithms + i, &info.algo_refs[i], NULL, 0);
sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, 0);
sc_format_asn1_entry(asn1_com_skey_attr + 0, &info.value_len, NULL, 0);
sc_format_asn1_entry(asn1_generic_skey_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_generic_skey_attr + 0, asn1_generic_skey_value_attr, NULL, 0);
sc_format_asn1_entry(asn1_generic_skey_value_attr + 0, &info.path, NULL, 0);
/* Fill in defaults */
memset(&info, 0, sizeof(info));
@ -114,7 +145,9 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
return r;
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
if (asn1_skey_choice[1].flags & SC_ASN1_PRESENT)
if (asn1_skey_choice[0].flags & SC_ASN1_PRESENT)
obj->type = SC_PKCS15_TYPE_SKEY_GENERIC;
else if (asn1_skey_choice[1].flags & SC_ASN1_PRESENT)
obj->type = SC_PKCS15_TYPE_SKEY_DES;
else if (asn1_skey_choice[2].flags & SC_ASN1_PRESENT)
obj->type = SC_PKCS15_TYPE_SKEY_2DES;
@ -123,7 +156,6 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj
else
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported secret key type");
obj->data = malloc(sizeof(info));
if (obj->data == NULL)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
@ -137,5 +169,73 @@ int sc_pkcs15_encode_skdf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj,
u8 **buf, size_t *buflen)
{
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
struct sc_pkcs15_skey_info *skey = (struct sc_pkcs15_skey_info *) obj->data;
int r, i;
size_t usage_len = sizeof(skey->usage);
size_t af_len = sizeof(skey->access_flags);
struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE];
struct sc_asn1_entry asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE];
struct sc_asn1_entry asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE];
struct sc_asn1_entry asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE];
struct sc_asn1_entry asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE];
struct sc_asn1_entry asn1_skey[C_ASN1_SKEY_SIZE];
struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE];
struct sc_asn1_pkcs15_object skey_obj = {
(struct sc_pkcs15_object *) obj, asn1_com_key_attr,
asn1_com_skey_attr, asn1_generic_skey_attr
};
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_ASN1);
sc_copy_asn1_entry(c_asn1_skey, asn1_skey);
sc_copy_asn1_entry(c_asn1_skey_choice, asn1_skey_choice);
sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
sc_copy_asn1_entry(c_asn1_com_skey_attr, asn1_com_skey_attr);
sc_copy_asn1_entry(c_asn1_generic_skey_attr, asn1_generic_skey_attr);
sc_copy_asn1_entry(c_asn1_generic_skey_value_attr, asn1_generic_skey_value_attr);
sc_format_asn1_entry(asn1_skey + 0, asn1_skey_choice, NULL, 1);
switch (obj->type) {
case SC_PKCS15_TYPE_SKEY_GENERIC:
sc_format_asn1_entry(asn1_skey_choice + 0, &skey_obj, NULL, 1);
break;
case SC_PKCS15_TYPE_SKEY_DES:
sc_format_asn1_entry(asn1_skey_choice + 1, &skey_obj, NULL, 1);
break;
case SC_PKCS15_TYPE_SKEY_2DES:
sc_format_asn1_entry(asn1_skey_choice + 2, &skey_obj, NULL, 1);
break;
case SC_PKCS15_TYPE_SKEY_3DES:
sc_format_asn1_entry(asn1_skey_choice + 3, &skey_obj, NULL, 1);
break;
default:
sc_log(ctx, "Invalid secret key type: %X", obj->type);
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
break;
}
sc_format_asn1_entry(asn1_com_key_attr + 0, &skey->id, NULL, 1);
sc_format_asn1_entry(asn1_com_key_attr + 1, &skey->usage, &usage_len, 1);
if (skey->native == 0)
sc_format_asn1_entry(asn1_com_key_attr + 2, &skey->native, NULL, 1);
if (skey->access_flags)
sc_format_asn1_entry(asn1_com_key_attr + 3, &skey->access_flags, &af_len, 1);
if (skey->key_reference >= 0)
sc_format_asn1_entry(asn1_com_key_attr + 4, &skey->key_reference, NULL, 1);
for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && i<C_ASN1_SUPPORTED_ALGORITHMS_SIZE && skey->algo_refs[i]; i++)
sc_format_asn1_entry(asn1_supported_algorithms + i, &skey->algo_refs[i], NULL, 1);
sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, skey->algo_refs[0] != 0);
sc_format_asn1_entry(asn1_com_skey_attr + 0, &skey->value_len, NULL, 1);
sc_format_asn1_entry(asn1_generic_skey_attr + 0, asn1_generic_skey_value_attr, NULL, 1);
sc_format_asn1_entry(asn1_generic_skey_value_attr + 0, &skey->path, NULL, 1);
r = sc_asn1_encode(ctx, asn1_skey, buf, buflen);
sc_log(ctx, "Key path %s", sc_print_path(&skey->path));
LOG_FUNC_RETURN(ctx, r);
}

View File

@ -1955,6 +1955,9 @@ sc_pkcs15_encode_df(struct sc_context *ctx, struct sc_pkcs15_card *p15card, stru
case SC_PKCS15_PUKDF_TRUSTED:
func = sc_pkcs15_encode_pukdf_entry;
break;
case SC_PKCS15_SKDF:
func = sc_pkcs15_encode_skdf_entry;
break;
case SC_PKCS15_CDF:
case SC_PKCS15_CDF_TRUSTED:
case SC_PKCS15_CDF_USEFUL:

View File

@ -828,6 +828,9 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx,
int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_encode_skdf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *buflen);
int sc_pkcs15_encode_dodf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);