dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/onomondo-eim/+/43016?usp=email )
Change subject: esipa_asn1_handler_utils: clean up handling of EuiccPackageResult ......................................................................
esipa_asn1_handler_utils: clean up handling of EuiccPackageResult
The function that handles the parsing and processing of the EuiccPackageResult is written in a confusing way and also seems to be slightly wrong (we do not want to re-bind any work item to a eimTransactionId here). Let's clean it up in a way that is easier to follow.
Change-Id: Ic2f64c254f3e07ce8dfdf43af977decf3514627b Related: SYS#8100 --- M src/crypto_utils.erl M src/esipa_asn1_handler_utils.erl 2 files changed, 83 insertions(+), 84 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/onomondo-eim refs/changes/16/43016/1
diff --git a/src/crypto_utils.erl b/src/crypto_utils.erl index 21929b5..7d051a1 100644 --- a/src/crypto_utils.erl +++ b/src/crypto_utils.erl @@ -12,6 +12,7 @@ -export([ sign_euiccPackageSigned/2, verify_euiccPackageResultSigned/2, + verify_euiccPackageErrorSigned/2, store_euicc_pubkey_from_authenticateResponseOk/2, store_euicc_pubkey_from_ipaEuiccDataResponse/2 ]). @@ -107,52 +108,57 @@ error end.
-verify_euiccPackageResultSigned(EuiccPackageResult, EidValue) -> +verify_euiccPackageResultSigned(EuiccPackageResultSigned, EidValue) -> {ok, ConsumerEuicc} = mnesia_db_euicc:state_get(EidValue, consumerEuicc), case ConsumerEuicc of false -> % Read the AssociationToken {ok, AssociationToken} = mnesia_db_euicc:state_get(EidValue, associationToken),
- case EuiccPackageResult of - {euiccPackageResultSigned, EuiccPackageResultSigned} -> - EuiccPackageResultDataSigned = maps:get( - euiccPackageResultDataSigned, EuiccPackageResultSigned - ), - EuiccSignEPR = maps:get(euiccSignEPR, EuiccPackageResultSigned), - {ok, EuiccPackageResultDataSigned_enc} = 'SGP32Definitions':encode( - 'EuiccPackageResultDataSigned', - EuiccPackageResultDataSigned - ), - % "euiccSignEPR SHALL apply on the concatenated data objects euiccPackageResultDataSigned and - % eimSignature." (see also GSMA SGP.32, section 2.11.2.1) - MsgToBeVerfied = utils:join_binary_list([ - EuiccPackageResultDataSigned_enc, - enc_association_token(AssociationToken) - ]), - verify_signature(MsgToBeVerfied, EuiccSignEPR, EidValue); - {euiccPackageErrorSigned, EuiccPackageErrorSigned} -> - EuiccPackageErrorDataSigned = maps:get( - euiccPackageErrorDataSigned, EuiccPackageErrorSigned - ), - EuiccSignEPE = maps:get(euiccSignEPE, EuiccPackageErrorSigned), - {ok, EuiccPackageErrorDataSigned_enc} = 'SGP32Definitions':encode( - 'EuiccPackageErrorDataSigned', - EuiccPackageErrorDataSigned - ), - % "euiccSignEPE SHALL apply on the concatenated data objects euiccPackageErrorDataSigned and - % eimSignature." (see also GSMA SGP.32, section 2.11.2.1) - MsgToBeVerfied = utils:join_binary_list([ - EuiccPackageErrorDataSigned_enc, - enc_association_token(AssociationToken) - ]), - verify_signature(MsgToBeVerfied, EuiccSignEPE, EidValue); - {euiccPackageErrorUnsigned, _} -> - % This result has no signature - ok; - _ -> - error - end; + EuiccPackageResultDataSigned = maps:get( + euiccPackageResultDataSigned, EuiccPackageResultSigned + ), + EuiccSignEPR = maps:get(euiccSignEPR, EuiccPackageResultSigned), + {ok, EuiccPackageResultDataSigned_enc} = 'SGP32Definitions':encode( + 'EuiccPackageResultDataSigned', + EuiccPackageResultDataSigned + ), + % "euiccSignEPR SHALL apply on the concatenated data objects euiccPackageResultDataSigned and + % eimSignature." (see also GSMA SGP.32, section 2.11.2.1) + MsgToBeVerfied = utils:join_binary_list([ + EuiccPackageResultDataSigned_enc, + enc_association_token(AssociationToken) + ]), + verify_signature(MsgToBeVerfied, EuiccSignEPR, EidValue); + _ -> + logger:info( + "omitting signature check for euiccPackageResultSigned from eID ~p (consumer eUICC)~n", + [utils:binary_to_hex(EidValue)] + ), + ok + end. + +verify_euiccPackageErrorSigned(EuiccPackageErrorSigned, EidValue) -> + {ok, ConsumerEuicc} = mnesia_db_euicc:state_get(EidValue, consumerEuicc), + case ConsumerEuicc of + false -> + % Read the AssociationToken + {ok, AssociationToken} = mnesia_db_euicc:state_get(EidValue, associationToken), + EuiccPackageErrorDataSigned = maps:get( + euiccPackageErrorDataSigned, EuiccPackageErrorSigned + ), + EuiccSignEPE = maps:get(euiccSignEPE, EuiccPackageErrorSigned), + {ok, EuiccPackageErrorDataSigned_enc} = 'SGP32Definitions':encode( + 'EuiccPackageErrorDataSigned', + EuiccPackageErrorDataSigned + ), + % "euiccSignEPE SHALL apply on the concatenated data objects euiccPackageErrorDataSigned and + % eimSignature." (see also GSMA SGP.32, section 2.11.2.1) + MsgToBeVerfied = utils:join_binary_list([ + EuiccPackageErrorDataSigned_enc, + enc_association_token(AssociationToken) + ]), + verify_signature(MsgToBeVerfied, EuiccSignEPE, EidValue); _ -> logger:info( "omitting signature check for euiccPackageResultSigned from eID ~p (consumer eUICC)~n", diff --git a/src/esipa_asn1_handler_utils.erl b/src/esipa_asn1_handler_utils.erl index 8d6e59a..373922f 100644 --- a/src/esipa_asn1_handler_utils.erl +++ b/src/esipa_asn1_handler_utils.erl @@ -40,18 +40,13 @@ none end.
-process_euiccPackageResult(Pid, EuiccPackageResult, Debuginfo, EimTransactionId) -> - WorkBind = fun(Map) -> - case maps:find(eimTransactionId, Map) of - {ok, Value} -> - mnesia_db_work:bind(Pid, Value); - _ -> - ok - end - end, +% Handle an EuiccPackageResult, this includes everything from the handling of the work items in mnesia_db, down to +% signature checks and the generation of an appropriate outcome for the REST API. +handle_euiccPackageResult(Pid, EuiccPackageResult, Debuginfo) -> + EimTransactionId = eimTransactionId_from_euiccPackageResult(EuiccPackageResult), + {EidValue, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId),
CheckCounterValue = fun(Map) -> - {EidValue, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId), CounterValueIpad = maps:get(counterValue, Map), {ok, CounterValueEim} = mnesia_db_euicc:state_get(EidValue, counterValue), case CounterValueIpad of @@ -59,7 +54,7 @@ ok; _ -> logger:error( - "invalid euiccPackageResultSigned, counterValue mismatch: CounterValueIpad=~p, CounterValueEim=~p~n", + "invalid eUICC signature, counterValue mismatch: CounterValueIpad=~p, CounterValueEim=~p~n", [CounterValueIpad, CounterValueEim] ), error @@ -69,31 +64,43 @@ Outcome = case EuiccPackageResult of {euiccPackageResultSigned, EuiccPackageResultSigned} -> - EuiccPackageResultDataSigned = maps:get( - euiccPackageResultDataSigned, EuiccPackageResultSigned - ), - WorkBind(EuiccPackageResultDataSigned), - case CheckCounterValue(EuiccPackageResultDataSigned) of + case + crypto_utils:verify_euiccPackageResultSigned(EuiccPackageResultSigned, EidValue) + of ok -> - esipa_rest_utils:euiccPackageResultDataSigned_to_outcome( - EuiccPackageResultDataSigned - ); + EuiccPackageResultDataSigned = maps:get( + euiccPackageResultDataSigned, EuiccPackageResultSigned + ), + case CheckCounterValue(EuiccPackageResultDataSigned) of + ok -> + esipa_rest_utils:euiccPackageResultDataSigned_to_outcome( + EuiccPackageResultDataSigned + ); + _ -> + [{[{euiccPackageErrorCode, counterValueMismatch}]}] + end; _ -> - [{[{euiccPackageErrorCode, counterValueMismatch}]}] + [{[{procedureError, euiccSignatureInvalid}]}] end; {euiccPackageErrorSigned, EuiccPackageErrorSigned} -> - EuiccPackageErrorDataSigned = maps:get( - euiccPackageErrorDataSigned, EuiccPackageErrorSigned - ), - WorkBind(EuiccPackageErrorDataSigned), - EuiccPackageErrorCode = maps:get( - euiccPackageErrorCode, EuiccPackageErrorDataSigned - ), - case CheckCounterValue(EuiccPackageErrorDataSigned) of + case + crypto_utils:verify_euiccPackageErrorSigned(EuiccPackageErrorSigned, EidValue) + of ok -> - [{[{euiccPackageErrorCode, EuiccPackageErrorCode}]}]; + EuiccPackageErrorDataSigned = maps:get( + euiccPackageErrorDataSigned, EuiccPackageErrorSigned + ), + EuiccPackageErrorCode = maps:get( + euiccPackageErrorCode, EuiccPackageErrorDataSigned + ), + case CheckCounterValue(EuiccPackageErrorDataSigned) of + ok -> + [{[{euiccPackageErrorCode, EuiccPackageErrorCode}]}]; + _ -> + [{[{euiccPackageErrorCode, counterValueMismatch}]}] + end; _ -> - [{[{euiccPackageErrorCode, counterValueMismatch}]}] + [{[{procedureError, euiccSignatureInvalid}]}] end; {euiccPackageErrorUnsigned, _} -> [{[{euiccPackageErrorCode, undefinedError}]}] @@ -101,20 +108,6 @@
mnesia_db_work:finish(Pid, Outcome, Debuginfo).
-% Handle an EuiccPackageResult, this includes everything from the handling of the work items in mnesia_db, down to -% signature checks and the generation of an appropriate outcome for the REST API. -handle_euiccPackageResult(Pid, EuiccPackageResult, Debuginfo) -> - EimTransactionId = eimTransactionId_from_euiccPackageResult(EuiccPackageResult), - {EidValue, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId), - case crypto_utils:verify_euiccPackageResultSigned(EuiccPackageResult, EidValue) of - ok -> - process_euiccPackageResult(Pid, EuiccPackageResult, Debuginfo, EimTransactionId); - _ -> - mnesia_db_work:finish( - Pid, [{[{procedureError, euiccSignatureInvalid}]}], Debuginfo - ) - end. - % Handle an IpaEuiccDataResponse, this includes everything from the handling of the work items in mnesia_db as well % as the generation of an appropriate outcome for the REST API. In case IpaEuiccDataResponse contains an eUICC public % key, we will automatically store it so that we can use it to check the signatures of PSMOs and eCOs.