diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index ca45890d..d74f0090 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -59,6 +59,9 @@ #define MYEID_CARD_CAP_GRIDPIN 0x10 #define MYEID_CARD_CAP_PIV_EMU 0x20 +#define MYEID_MAX_APDU_DATA_LEN 0xFF +#define MYEID_MAX_RSA_KEY_LEN 2048 + static const char *myeid_card_name = "MyEID"; static char card_name_buf[MYEID_CARD_NAME_MAX_LEN]; @@ -677,25 +680,29 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t * } for (i = 0; i < SC_SEC_ENV_MAX_PARAMS; i++) if (env->params[i].param_type == SC_SEC_ENV_PARAM_TARGET_FILE) { - target_file = (sc_path_t*) env->params[i].value; - if (env->params[i].value_len < sizeof(sc_path_t) || target_file->len != 2) { - sc_log(card->ctx, "wrong length of target file reference.\n"); - return SC_ERROR_WRONG_LENGTH; - } - *p++ = 0x83; - *p++ = 2; - memcpy(p, target_file->value, 2); - p+= 2; - break; + target_file = (sc_path_t*) env->params[i].value; + if (env->params[i].value_len < sizeof(sc_path_t) || target_file->len != 2) { + sc_log(card->ctx, "wrong length of target file reference.\n"); + return SC_ERROR_WRONG_LENGTH; + } + *p++ = 0x83; + *p++ = 2; + memcpy(p, target_file->value, 2); + p+= 2; + break; } - if (env->operation == SC_SEC_OPERATION_UNWRAP || env->operation == SC_SEC_OPERATION_WRAP) /* & SC_SEC_ENV_IV_PRESENT*/ + if (env->operation == SC_SEC_OPERATION_UNWRAP || env->operation == SC_SEC_OPERATION_WRAP) { /* add IV if present */ for (i = 0; i < SC_SEC_ENV_MAX_PARAMS; i++) if (env->params[i].param_type == SC_SEC_ENV_PARAM_IV) { *p++ = 0x87; *p++ = (unsigned char) env->params[i].value_len; + if (p + env->params[i].value_len >= sbuf + SC_MAX_APDU_BUFFER_SIZE) { + sc_log(card->ctx, "IV too long.\n"); + return SC_ERROR_WRONG_LENGTH; + } memcpy(p, env->params[i].value, env->params[i].value_len); p+=(unsigned char) env->params[i].value_len; break; @@ -1288,20 +1295,21 @@ static int myeid_wrap_key(struct sc_card *card, u8 *out, size_t outlen) static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgram_len) { int r; - u8 out[512]; - size_t outlen = 512; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - u8 p2 = 0x86; + u8 p2 = 0x86; /* init P2 for asymmetric crypto by default.*/ myeid_private_data_t* priv; + int symmetric_operation = 0; LOG_FUNC_CALLED(card->ctx); SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); - assert(card != NULL && crgram != NULL && out != NULL); + if (card == NULL || crgram == NULL) { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "One or more of required arguments was null.\n"); + } - if (crgram_len > 256) + if (crgram_len > MYEID_MAX_RSA_KEY_LEN / 8) LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); if (card->drv_data) @@ -1313,40 +1321,56 @@ static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgra if (priv->sec_env->algorithm == SC_ALGORITHM_AES || priv->sec_env->algorithm == SC_ALGORITHM_3DES || priv->sec_env->algorithm == SC_ALGORITHM_DES) - p2 = 0x84; /* Set correct P2 for symmetric crypto */ + symmetric_operation = 1; + } + } + + if (symmetric_operation) + { + p2 = 0x84; /* Set correct P2 for symmetric crypto */ + if (crgram_len > MYEID_MAX_APDU_DATA_LEN) + { + LOG_TEST_RET(card->ctx, SC_ERROR_WRONG_LENGTH, "Unwrapping symmetric data longer that 255 bytes is not supported\n"); } } /* INS: 0x2A PERFORM SECURITY OPERATION * P1: 0x00 Do not expect response - the deciphered data will be placed into the target key EF. * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram - * P2: 0x84 Cmd: AES/3DES Cryptogram (plain value encoded in BER-TLV DO, but not including SM DOs) */ + * P2: 0x84 Cmd: AES/3DES Cryptogram (plain value encoded in BER-TLV DO, but not including SM DOs) + If crgram_len == 256 (2048 bit RSA), we split the cryptogram in two and send two APDUs. + */ sc_format_apdu(card, &apdu, - (crgram_len < 256) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT, + SC_APDU_CASE_3_SHORT, 0x2A, 0x00, p2); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); - apdu.le = crgram_len; + apdu.le = 0; - if (crgram_len == 256 && p2 == 0x86) + if (symmetric_operation) { - apdu.le = 0; - /* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */ - sbuf[0] = 0x81; - memcpy(sbuf + 1, crgram, crgram_len / 2); - apdu.lc = crgram_len / 2 + 1; + /* symmetric crypto, no padding indicator byte */ + { + memcpy(sbuf, crgram, crgram_len); + apdu.lc = crgram_len; + } } - else if (p2 == 0x86) + else { - sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */ - memcpy(sbuf + 1, crgram, crgram_len); - apdu.lc = crgram_len + 1; - } - else /* symmetric crypto, no padding indicator byte */ - { - memcpy(sbuf, crgram, crgram_len); - apdu.lc = crgram_len; + if (crgram_len > MYEID_MAX_APDU_DATA_LEN) + { + /* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */ + sbuf[0] = 0x81; + memcpy(sbuf + 1, crgram, crgram_len / 2); + apdu.lc = crgram_len / 2 + 1; + } + else + { + sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */ + memcpy(sbuf + 1, crgram, crgram_len); + apdu.lc = crgram_len + 1; + } } apdu.datalen = apdu.lc; @@ -1356,15 +1380,15 @@ static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgra LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { - if (crgram_len == 256 && p2 == 0x86) /* with symmetric crypto, we support only single apdu unwrap for now */ + if (crgram_len > MYEID_MAX_APDU_DATA_LEN) { - sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x00, p2); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); - apdu.le = crgram_len; + apdu.le = 0; /* padding indicator byte, - * 0x82 = Second half of 2048 bit cryptogram */ + * 0x82 = Second half of 2048 bit cryptogram */ sbuf[0] = 0x82; memcpy(sbuf + 1, crgram + crgram_len / 2, crgram_len / 2); apdu.lc = crgram_len / 2 + 1; @@ -1374,18 +1398,6 @@ static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgra r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) - { - LOG_FUNC_RETURN(card->ctx, r); - } - } - else - { - int len = apdu.resplen > outlen ? outlen : apdu.resplen; - - memcpy(out, apdu.resp, len); - LOG_FUNC_RETURN(card->ctx, r); } } LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 75099bb8..a25d95cb 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -227,7 +227,7 @@ struct sc_supported_algo_info { typedef struct sc_sec_env_param { unsigned int param_type; - unsigned char* value; + void* value; unsigned int value_len; } sc_sec_env_param_t; diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index d69a18ca..47e8e3ad 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -53,22 +53,24 @@ static int sec_env_add_param(sc_security_env_t* se, const sc_sec_env_param_t* p) } -static sc_path_t get_file_path(const struct sc_pkcs15_object* obj) +static int get_file_path(const struct sc_pkcs15_object* obj, sc_path_t* path) { - sc_path_t path; + if (!path) + return SC_ERROR_INCORRECT_PARAMETERS; + const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; const struct sc_pkcs15_skey_info *skey = (const struct sc_pkcs15_skey_info *) obj->data; - memset (&path, 0, sizeof(path)); - if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) { - path = prkey->path; + *path = prkey->path; } else if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY) { - path = skey->path; + *path = skey->path; } + else + return SC_ERROR_INCORRECT_PARAMETERS; - return path; + return SC_SUCCESS; } @@ -83,7 +85,7 @@ static int select_key_file(struct sc_pkcs15_card *p15card, LOG_FUNC_CALLED(ctx); - orig_path = get_file_path(key); + LOG_TEST_RET(ctx, get_file_path(key, &orig_path), "Could not get key file path."); memset(&path, 0, sizeof(sc_path_t)); memset(&file_id, 0, sizeof(sc_path_t)); @@ -131,7 +133,8 @@ static int use_key(struct sc_pkcs15_card *p15card, { int r = SC_SUCCESS; int revalidated_cached_pin = 0; - sc_path_t path = get_file_path(obj); + sc_path_t path; + LOG_TEST_RET(p15card->card->ctx, get_file_path(obj, &path), "Failed to get key file path."); r = sc_lock(p15card->card); LOG_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); @@ -419,7 +422,7 @@ int sc_pkcs15_unwrap(struct sc_pkcs15_card *p15card, LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid unwrapping target key path"); } - senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, (u8*) &target_file_id, sizeof(target_file_id)}; + senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, &target_file_id, sizeof(target_file_id)}; LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add target file path to security environment"); r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); @@ -427,7 +430,7 @@ int sc_pkcs15_unwrap(struct sc_pkcs15_card *p15card, senv.algorithm_flags = sec_flags; if ((sec_flags & (SC_ALGORITHM_AES_CBC | SC_ALGORITHM_AES_CBC_PAD)) > 0) { - senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (u8*) param, paramlen }; + senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (void*) param, paramlen }; LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add IV to security environment"); } @@ -498,11 +501,11 @@ int sc_pkcs15_wrap(struct sc_pkcs15_card *p15card, switch (target_key->type) { case SC_PKCS15_TYPE_PRKEY_RSA: - tkey_path = target_prkey->path; - break; - default: /* we already know it is a secret key */ - tkey_path = target_skey->path; - break; + tkey_path = target_prkey->path; + break; + default: /* we already know it is a secret key */ + tkey_path = target_skey->path; + break; } if (!tkey_path.len && tkey_path.aid.len) { @@ -523,7 +526,7 @@ int sc_pkcs15_wrap(struct sc_pkcs15_card *p15card, else { LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid unwrapping target key path"); } - senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, (u8*) &target_file_id, sizeof(target_file_id)}; + senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, &target_file_id, sizeof(target_file_id)}; LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add target file path to security environment"); r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); @@ -531,7 +534,7 @@ int sc_pkcs15_wrap(struct sc_pkcs15_card *p15card, senv.algorithm_flags = sec_flags; if ((sec_flags & (SC_ALGORITHM_AES_CBC | SC_ALGORITHM_AES_CBC_PAD)) > 0) { - senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (u8*) param, paramlen }; + senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (void*) param, paramlen }; LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add IV to security environment"); } diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c index f715e4a8..be19f3d7 100644 --- a/src/libopensc/pkcs15-skey.c +++ b/src/libopensc/pkcs15-skey.c @@ -164,10 +164,10 @@ sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_obj temp_oid.value[8] = -1; /* strip off AES subtype octet*/ if (sc_compare_oid(&id_aes, &temp_oid)) - if (info.key_type == 0) { - info.key_type = CKK_AES; - break; - } + if (info.key_type == 0) { + info.key_type = CKK_AES; + break; + } } } } diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index b4ec6204..ba63b25a 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2353,7 +2353,7 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile skey_info->key_type = key_type; /* PKCS#11 CKK_* */ skey_info->data.value = args.key.data; skey_info->data.len = args.key.data_len; - skey_info->value_len = args.value_len; /* callers preferred length */ + skey_info->value_len = args.value_len * 8; /* key length comes in number of bytes, use length in bits in PKCS#15. */ args.key.data = NULL; key_obj->session_object = 1; } @@ -2361,7 +2361,8 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile if(_token == FALSE) args.session_object = 1; /* store the object on card for duration of the session. */ - rc = sc_pkcs15init_store_secret_key(fw_data->p15_card, profile, &args, &key_obj); + args.value_len = args.value_len * 8; /* CKA_VALUE_LEN is number of bytes, PKCS#15 needs key length in bits */ + rc = sc_pkcs15init_store_secret_key(fw_data->p15_card, profile, &args, &key_obj); if (rc < 0) { rv = sc_to_cryptoki_error(rc, "C_CreateObject"); goto out; @@ -3521,7 +3522,7 @@ struct sc_pkcs11_object_ops pkcs15_cert_ops = { NULL, /* decrypt */ NULL, /* derive */ NULL, /* can_do */ - NULL /* init_params */ + NULL, /* init_params */ NULL /* wrap_key */ }; @@ -3971,11 +3972,10 @@ pkcs15_prkey_unwrap(struct sc_pkcs11_session *session, void *obj, if (!fw_data) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_UnwrapKey"); - sc_log(context, "unwrapping %p %p %p %p %lu %p", session, obj, - pMechanism, pWrappedKey, ulWrappedKeyLen, targetKeyObj); - - if (pMechanism == NULL || pWrappedKey == NULL || ulWrappedKeyLen == 0 || targetKeyObj == NULL) + if (pMechanism == NULL || pWrappedKey == NULL || ulWrappedKeyLen == 0 || targetKeyObj == NULL) { + sc_log(context, "One or more of mandatory arguments were NULL."); return CKR_ARGUMENTS_BAD; + } /* See which of the alternative keys supports unwrap */ while (prkey && !(prkey->prv_info->usage & SC_PKCS15_PRKEY_USAGE_UNWRAP)) @@ -3984,6 +3984,8 @@ pkcs15_prkey_unwrap(struct sc_pkcs11_session *session, void *obj, if (prkey == NULL) return CKR_KEY_FUNCTION_NOT_PERMITTED; + sc_log(context, "Using mechanism %lx.", pMechanism->mechanism); + /* Select the proper padding mechanism */ switch (pMechanism->mechanism) { case CKM_RSA_PKCS: @@ -4529,7 +4531,7 @@ struct sc_pkcs11_object_ops pkcs15_pubkey_ops = { NULL, /* decrypt */ NULL, /* derive */ NULL, /* can_do */ - NULL /* init_params */ + NULL, /* init_params */ NULL /* wrap_key */ }; @@ -4709,7 +4711,7 @@ struct sc_pkcs11_object_ops pkcs15_dobj_ops = { NULL, /* decrypt */ NULL, /* derive */ NULL, /* can_do */ - NULL /* init_params */ + NULL, /* init_params */ NULL /* wrap_key */ }; @@ -4847,11 +4849,10 @@ pkcs15_skey_unwrap(struct sc_pkcs11_session *session, void *obj, if (!fw_data) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_UnwrapKey"); - sc_log(context, "unwrapping %p %p %p %p %lu %p", session, obj, - pMechanism, pWrappedKey, ulWrappedKeyLen, targetKeyObj); - - if (pMechanism == NULL || pWrappedKey == NULL || ulWrappedKeyLen == 0 || targetKeyObj == NULL) - return CKR_ARGUMENTS_BAD; + if (pMechanism == NULL || pWrappedKey == NULL || ulWrappedKeyLen == 0 || targetKeyObj == NULL) { + sc_log(context, "One or more of mandatory arguments were NULL."); + return CKR_ARGUMENTS_BAD; + } /* Check whether this key supports unwrap */ if (skey && !(skey->info->usage & SC_PKCS15_PRKEY_USAGE_UNWRAP)) @@ -4863,6 +4864,7 @@ pkcs15_skey_unwrap(struct sc_pkcs11_session *session, void *obj, if (skey == NULL) return CKR_KEY_FUNCTION_NOT_PERMITTED; + sc_log(context, "Using mechanism %lx.", pMechanism->mechanism); /* Select the proper padding mechanism */ switch (pMechanism->mechanism) { case CKM_AES_ECB: @@ -4920,21 +4922,21 @@ pkcs15_skey_wrap(struct sc_pkcs11_session *session, void *obj, if (!fw_data) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_WrapKey"); - sc_log(context, "wrapping %p %p %p %p %p %p, %lu", session, obj, - pMechanism, targetKey, pData, pulDataLen, pulDataLen == NULL ? 0 : *pulDataLen); - - if (session == NULL || pMechanism == NULL || obj == NULL || targetKey == NULL) - return CKR_ARGUMENTS_BAD; + if (session == NULL || pMechanism == NULL || obj == NULL || targetKey == NULL) { + sc_log(context, "One or more of mandatory arguments were NULL."); + return CKR_ARGUMENTS_BAD; + } /* Verify that the key supports wrapping */ if (skey && !(skey->info->usage & SC_PKCS15_PRKEY_USAGE_WRAP)) skey = NULL; /* TODO: browse for a key that supports, like other similar funcs */ - if (skey == NULL) return CKR_KEY_FUNCTION_NOT_PERMITTED; + sc_log(context, "Using mechanism %lx.", pMechanism->mechanism); + /* Select the proper padding mechanism */ switch (pMechanism->mechanism) { case CKM_AES_ECB: @@ -4983,7 +4985,7 @@ struct sc_pkcs11_object_ops pkcs15_skey_ops = { NULL, /* decrypt */ NULL, /* derive */ NULL, /* can_do */ - NULL /* init_params */ + NULL, /* init_params */ pkcs15_skey_wrap /* wrap_key */ }; diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 76268a9d..48551120 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -1097,6 +1097,9 @@ sc_pkcs11_wrap_operation(sc_pkcs11_operation_t *operation, struct sc_pkcs11_object *targetKey, CK_BYTE_PTR pWrappedData, CK_ULONG_PTR ulWrappedDataLen) { + if (!operation || !wrappingKey || !wrappingKey->ops || !wrappingKey->ops->wrap_key) + return CKR_ARGUMENTS_BAD; + return wrappingKey->ops->wrap_key(operation->session, wrappingKey, &operation->mechanism, @@ -1110,6 +1113,9 @@ sc_pkcs11_unwrap_operation(sc_pkcs11_operation_t *operation, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, struct sc_pkcs11_object *targetKey) { + if (!operation || !unwrappingKey || !unwrappingKey->ops || !unwrappingKey->ops->unwrap_key) + return CKR_ARGUMENTS_BAD; + return unwrappingKey->ops->unwrap_key(operation->session, unwrappingKey, &operation->mechanism, diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 1255d47f..8dc5b544 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -83,6 +83,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha224_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ + NULL, /* wrap */ + NULL, /* unwrap */ NULL, /* mech_data */ NULL, /* free_mech_data */ }; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index ea9b07e6..eda7071e 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1295,7 +1295,7 @@ sc_pkcs15init_init_skdf(struct sc_pkcs15_card *p15card, struct sc_profile *profi struct sc_pkcs15_object *object = NULL; const char *label; unsigned int usage; - unsigned int keybits = keyargs->value_len * 8; + unsigned int keybits = keyargs->value_len; int r = 0, key_type; LOG_FUNC_CALLED(ctx);