diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c index 353226ce..006dfa11 100644 --- a/src/libopensc/pkcs15-skey.c +++ b/src/libopensc/pkcs15-skey.c @@ -26,13 +26,30 @@ #include #include -#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; iname; 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; ialgo_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); } diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index a31abb45..2ce34b6c 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -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: diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 5352f9fb..dd46d242 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -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);