diff --git a/euicc/es10b.c b/euicc/es10b.c index 2b64173..5fa6851 100644 --- a/euicc/es10b.c +++ b/euicc/es10b.c @@ -526,7 +526,7 @@ exit: return fret; } -int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateServerResponse, struct es10b_authenticate_server_param *param, struct es10b_authenticate_server_param_user *param_user) +int es10b_authenticate_server_r(struct euicc_ctx *ctx, uint8_t **transaction_id, uint32_t *transaction_id_len, char **b64_AuthenticateServerResponse, struct es10b_authenticate_server_param *param, struct es10b_authenticate_server_param_user *param_user) { int fret = 0; uint8_t *reqbuf = NULL; @@ -537,8 +537,10 @@ int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateSe uint8_t imei[8]; uint8_t *serverSigned1 = NULL, *serverSignature1 = NULL, *euiccCiPKIdToBeUsed = NULL, *serverCertificate = NULL; int serverSigned1_len, serverSignature1_len, euiccCiPKIdToBeUsed_len, serverCertificate_len; - struct euicc_derutil_node n_request, n_serverSigned1, n_serverSignature1, n_euiccCiPKIdToBeUsed, n_serverCertificate, n_CtxParams1, n_matchingId, n_deviceInfo, n_tac, n_deviceCapabilities, n_imei; + struct euicc_derutil_node n_request, n_serverSigned1, n_transactionId, n_serverSignature1, n_euiccCiPKIdToBeUsed, n_serverCertificate, n_CtxParams1, n_matchingId, n_deviceInfo, n_tac, n_deviceCapabilities, n_imei; + *transaction_id = NULL; + *transaction_id_len = 0; *b64_AuthenticateServerResponse = NULL; memset(&n_request, 0, sizeof(n_request)); @@ -602,6 +604,11 @@ int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateSe goto err; } + if (euicc_derutil_unpack_find_tag(&n_transactionId, 0x80, n_serverSigned1.value, n_serverSigned1.length) < 0) + { + goto err; + } + if (euicc_derutil_unpack_find_tag(&n_serverSignature1, 0x5F37, serverSignature1, serverSignature1_len) < 0) { goto err; @@ -617,6 +624,14 @@ int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateSe goto err; } + *transaction_id_len = n_transactionId.length; + *transaction_id = malloc(n_transactionId.length); + if (!(*transaction_id)) + { + goto err; + } + memcpy(*transaction_id, n_transactionId.value, n_transactionId.length); + n_request.tag = 0xBF38; n_request.pack.child = &n_serverSigned1; n_serverSigned1.pack.next = &n_serverSignature1; @@ -704,6 +719,9 @@ int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateSe err: fret = -1; + free(*transaction_id); + *transaction_id = NULL; + *transaction_id_len = 0; free(*b64_AuthenticateServerResponse); *b64_AuthenticateServerResponse = NULL; exit: @@ -724,7 +742,72 @@ exit: int es10b_cancel_session_r(struct euicc_ctx *ctx, char **b64_CancelSessionResponse, struct es10b_cancel_session_param *param) { - return -1; + int fret = 0; + struct euicc_derutil_node n_request, n_transactionId, n_reason; + uint8_t reason_buf[sizeof(enum es10b_cancel_session_reason)]; + uint32_t reason_buf_len; + uint32_t reqlen; + uint8_t *respbuf = NULL; + unsigned resplen; + + struct euicc_derutil_node tmpnode; + + if (euicc_derutil_convert_long2bin(reason_buf, &reason_buf_len, param->reason) < 0) + { + goto err; + } + + memset(&n_request, 0, sizeof(n_request)); + memset(&n_transactionId, 0, sizeof(n_transactionId)); + memset(&n_reason, 0, sizeof(n_reason)); + + n_request.tag = 0xBF41; // CancelSessionRequest + n_request.pack.child = &n_transactionId; + + n_transactionId.tag = 0x80; + n_transactionId.value = (const uint8_t *)param->transactionId; + n_transactionId.length = param->transactionIdLen; + + n_reason.tag = 0x81; + n_reason.value = reason_buf; + n_reason.length = reason_buf_len; + + reqlen = sizeof(ctx->apdu._internal.request_buffer.body); + if (euicc_derutil_pack(ctx->apdu._internal.request_buffer.body, &reqlen, &n_request)) + { + goto err; + } + + if (es10x_command(ctx, &respbuf, &resplen, ctx->apdu._internal.request_buffer.body, reqlen) < 0) + { + goto err; + } + + if (euicc_derutil_unpack_find_tag(&tmpnode, n_request.tag, respbuf, resplen)) + { + goto err; + } + + *b64_CancelSessionResponse = malloc(euicc_base64_encode_len(tmpnode.self.length)); + if (!(*b64_CancelSessionResponse)) + { + goto err; + } + if (euicc_base64_encode(*b64_CancelSessionResponse, tmpnode.self.ptr, tmpnode.self.length) < 0) + { + goto err; + } + + goto exit; + +err: + fret = -1; + free(*b64_CancelSessionResponse); + *b64_CancelSessionResponse = NULL; +exit: + free(respbuf); + respbuf = NULL; + return fret; } void es10b_prepare_download_param_free(struct es10b_prepare_download_param *param) @@ -866,7 +949,7 @@ int es10b_authenticate_server(struct euicc_ctx *ctx, const char *matchingId, con return -1; } - fret = es10b_authenticate_server_r(ctx, &ctx->http._internal.b64_authenticate_server_response, ctx->http._internal.authenticate_server_param, ¶m_user); + fret = es10b_authenticate_server_r(ctx, &ctx->http._internal.transaction_id_bin, &ctx->http._internal.transaction_id_bin_len, &ctx->http._internal.b64_authenticate_server_response, ctx->http._internal.authenticate_server_param, ¶m_user); if (fret < 0) { ctx->http._internal.b64_authenticate_server_response = NULL; @@ -880,9 +963,39 @@ int es10b_authenticate_server(struct euicc_ctx *ctx, const char *matchingId, con return fret; } -int es10b_cancel_session(struct euicc_ctx *ctx) +int es10b_cancel_session(struct euicc_ctx *ctx, enum es10b_cancel_session_reason reason) { - return -1; + int fret; + + struct es10b_cancel_session_param param = { + .transactionId = ctx->http._internal.transaction_id_bin, + .transactionIdLen = ctx->http._internal.transaction_id_bin_len, + .reason = reason, + }; + + if (ctx->http._internal.transaction_id_bin == NULL) + { + return -1; + } + + if (ctx->http._internal.transaction_id_bin_len = 0) + { + return -1; + } + + if (ctx->http._internal.b64_cancel_session_response) + { + return -1; + } + + fret = es10b_cancel_session_r(ctx, &ctx->http._internal.b64_cancel_session_response, ¶m); + + if (fret < 0) + { + ctx->http._internal.b64_cancel_session_response = NULL; + } + + return fret; } int es10b_list_notification(struct euicc_ctx *ctx, struct es10b_notification_metadata_list **notificationMetadataList) diff --git a/euicc/es10b.h b/euicc/es10b.h index 0eee115..aa57bd9 100644 --- a/euicc/es10b.h +++ b/euicc/es10b.h @@ -50,8 +50,6 @@ enum es10b_cancel_session_reason ES10B_CANCEL_SESSION_REASON_POSTPONED = 1, ES10B_CANCEL_SESSION_REASON_TIMEOUT = 2, ES10B_CANCEL_SESSION_REASON_PPRNOTALLOWED = 3, - ES10B_CANCEL_SESSION_REASON_METADATAMISMATCH = 4, - ES10B_CANCEL_SESSION_REASON_LOADBPPEXECUTIONERROR = 5, ES10B_CANCEL_SESSION_REASON_UNDEFINED = 127 }; @@ -108,6 +106,7 @@ struct es10b_cancel_session_param { const uint8_t *transactionId; uint8_t transactionIdLen; + enum es10b_cancel_session_reason reason; }; struct es10b_rat @@ -132,7 +131,7 @@ int es10b_prepare_download_r(struct euicc_ctx *ctx, char **b64_PrepareDownloadRe int es10b_load_bound_profile_package_r(struct euicc_ctx *ctx, struct es10b_load_bound_profile_package_result *result, const char *b64_BoundProfilePackage); int es10b_get_euicc_challenge_r(struct euicc_ctx *ctx, char **b64_euiccChallenge); int es10b_get_euicc_info_r(struct euicc_ctx *ctx, char **b64_EUICCInfo1); -int es10b_authenticate_server_r(struct euicc_ctx *ctx, char **b64_AuthenticateServerResponse, struct es10b_authenticate_server_param *param, struct es10b_authenticate_server_param_user *param_user); +int es10b_authenticate_server_r(struct euicc_ctx *ctx, uint8_t **transaction_id, uint32_t *transaction_id_len, char **b64_AuthenticateServerResponse, struct es10b_authenticate_server_param *param, struct es10b_authenticate_server_param_user *param_user); int es10b_cancel_session_r(struct euicc_ctx *ctx, char **b64_CancelSessionResponse, struct es10b_cancel_session_param *param); void es10b_prepare_download_param_free(struct es10b_prepare_download_param *param); @@ -142,7 +141,7 @@ int es10b_prepare_download(struct euicc_ctx *ctx, const char *confirmationCode); int es10b_load_bound_profile_package(struct euicc_ctx *ctx, struct es10b_load_bound_profile_package_result *result); int es10b_get_euicc_challenge_and_info(struct euicc_ctx *ctx); int es10b_authenticate_server(struct euicc_ctx *ctx, const char *matchingId, const char *imei); -int es10b_cancel_session(struct euicc_ctx *ctx); +int es10b_cancel_session(struct euicc_ctx *ctx, enum es10b_cancel_session_reason reason); int es10b_list_notification(struct euicc_ctx *ctx, struct es10b_notification_metadata_list **notificationMetadataList); int es10b_retrieve_notifications_list(struct euicc_ctx *ctx, struct es10b_pending_notification *PendingNotification, unsigned long seqNumber); diff --git a/euicc/es9p.c b/euicc/es9p.c index 6ca0131..500bcbb 100644 --- a/euicc/es9p.c +++ b/euicc/es9p.c @@ -275,7 +275,7 @@ int es9p_initiate_authentication_r(struct euicc_ctx *ctx, char **transaction_id, const char *idata[] = {ctx->http.server_address, b64_euicc_challenge, b64_euicc_info_1, NULL}; const char *okey[] = {"transactionId", "serverSigned1", "serverSignature1", "euiccCiPKIdToBeUsed", "serverCertificate", NULL}; const char oobj[] = {0, 0, 0, 0, 0}; - void **optr[] = {(void **)&ctx->http._internal.transaction_id, (void **)&resp->b64_serverSigned1, (void **)&resp->b64_serverSignature1, (void **)&resp->b64_euiccCiPKIdToBeUsed, (void **)&resp->b64_serverCertificate, NULL}; + void **optr[] = {(void **)transaction_id, (void **)&resp->b64_serverSigned1, (void **)&resp->b64_serverSignature1, (void **)&resp->b64_euiccCiPKIdToBeUsed, (void **)&resp->b64_serverCertificate, NULL}; if (es9p_trans_json(ctx, ctx->http.server_address, "/gsma/rsp2/es9plus/initiateAuthentication", ikey, idata, okey, oobj, optr)) { @@ -293,7 +293,7 @@ int es9p_initiate_authentication_r(struct euicc_ctx *ctx, char **transaction_id, int es9p_get_bound_profile_package_r(struct euicc_ctx *ctx, char **b64_bound_profile_package, const char *server_address, const char *transaction_id, const char *b64_prepare_download_response) { const char *ikey[] = {"transactionId", "prepareDownloadResponse", NULL}; - const char *idata[] = {ctx->http._internal.transaction_id, b64_prepare_download_response, NULL}; + const char *idata[] = {transaction_id, b64_prepare_download_response, NULL}; const char *okey[] = {"boundProfilePackage", NULL}; const char oobj[] = {0}; void **optr[] = {(void **)b64_bound_profile_package, NULL}; @@ -311,7 +311,7 @@ int es9p_get_bound_profile_package_r(struct euicc_ctx *ctx, char **b64_bound_pro int es9p_authenticate_client_r(struct euicc_ctx *ctx, struct es10b_prepare_download_param *resp, const char *server_address, const char *transaction_id, const char *b64_authenticate_server_response) { const char *ikey[] = {"transactionId", "authenticateServerResponse", NULL}; - const char *idata[] = {ctx->http._internal.transaction_id, b64_authenticate_server_response, NULL}; + const char *idata[] = {transaction_id, b64_authenticate_server_response, NULL}; const char *okey[] = {"profileMetadata", "smdpSigned2", "smdpSignature2", "smdpCertificate", NULL}; const char oobj[] = {0, 0, 0, 0}; void **optr[] = {(void **)&resp->b64_profileMetadata, (void **)&resp->b64_smdpSigned2, (void **)&resp->b64_smdpSignature2, (void **)&resp->b64_smdpCertificate, NULL}; @@ -332,7 +332,7 @@ int es9p_authenticate_client_r(struct euicc_ctx *ctx, struct es10b_prepare_downl int es9p_cancel_session_r(struct euicc_ctx *ctx, const char *server_address, const char *transaction_id, const char *b64_cancel_session_response) { const char *ikey[] = {"transactionId", "cancelSessionResponse", NULL}; - const char *idata[] = {ctx->http._internal.transaction_id, b64_cancel_session_response, NULL}; + const char *idata[] = {transaction_id, b64_cancel_session_response, NULL}; if (es9p_trans_json(ctx, ctx->http.server_address, "/gsma/rsp2/es9plus/cancelSession", ikey, idata, NULL, NULL, NULL)) { @@ -348,7 +348,7 @@ int es11_authenticate_client_r(struct euicc_ctx *ctx, char ***smdp_list, const c cJSON *j_eventEntries = NULL; int j_eventEntries_size = 0; const char *ikey[] = {"transactionId", "authenticateServerResponse", NULL}; - const char *idata[] = {ctx->http._internal.transaction_id, b64_authenticate_server_response, NULL}; + const char *idata[] = {transaction_id, b64_authenticate_server_response, NULL}; const char *okey[] = {"eventEntries", NULL}; const char oobj[] = {1}; void **optr[] = {(void **)&j_eventEntries, NULL}; @@ -431,7 +431,7 @@ int es9p_initiate_authentication(struct euicc_ctx *ctx) return -1; } - fret = es9p_initiate_authentication_r(ctx, &ctx->http._internal.transaction_id, ctx->http._internal.authenticate_server_param, ctx->http.server_address, ctx->http._internal.b64_euicc_challenge, ctx->http._internal.b64_euicc_info_1); + fret = es9p_initiate_authentication_r(ctx, &ctx->http._internal.transaction_id_http, ctx->http._internal.authenticate_server_param, ctx->http.server_address, ctx->http._internal.b64_euicc_challenge, ctx->http._internal.b64_euicc_info_1); if (fret < 0) { free(ctx->http._internal.authenticate_server_param); @@ -462,7 +462,7 @@ int es9p_get_bound_profile_package(struct euicc_ctx *ctx) return -1; } - fret = es9p_get_bound_profile_package_r(ctx, &ctx->http._internal.b64_bound_profile_package, ctx->http.server_address, ctx->http._internal.transaction_id, ctx->http._internal.b64_prepare_download_response); + fret = es9p_get_bound_profile_package_r(ctx, &ctx->http._internal.b64_bound_profile_package, ctx->http.server_address, ctx->http._internal.transaction_id_http, ctx->http._internal.b64_prepare_download_response); if (fret < 0) { free(ctx->http._internal.b64_bound_profile_package); @@ -496,7 +496,7 @@ int es9p_authenticate_client(struct euicc_ctx *ctx) return -1; } - fret = es9p_authenticate_client_r(ctx, ctx->http._internal.prepare_download_param, ctx->http.server_address, ctx->http._internal.transaction_id, ctx->http._internal.b64_authenticate_server_response); + fret = es9p_authenticate_client_r(ctx, ctx->http._internal.prepare_download_param, ctx->http.server_address, ctx->http._internal.transaction_id_http, ctx->http._internal.b64_authenticate_server_response); if (fret < 0) { free(ctx->http._internal.prepare_download_param); @@ -512,7 +512,23 @@ int es9p_authenticate_client(struct euicc_ctx *ctx) int es9p_cancel_session(struct euicc_ctx *ctx) { - return -1; + int fret; + + if (ctx->http._internal.b64_cancel_session_response == NULL) + { + return -1; + } + + fret = es9p_cancel_session_r(ctx, ctx->http.server_address, ctx->http._internal.transaction_id_http, ctx->http._internal.b64_cancel_session_response); + if (fret < 0) + { + return fret; + } + + free(ctx->http._internal.b64_cancel_session_response); + ctx->http._internal.b64_cancel_session_response = NULL; + + return fret; } int es11_authenticate_client(struct euicc_ctx *ctx, char ***smdp_list) @@ -524,7 +540,7 @@ int es11_authenticate_client(struct euicc_ctx *ctx, char ***smdp_list) return -1; } - fret = es11_authenticate_client_r(ctx, smdp_list, ctx->http.server_address, ctx->http._internal.transaction_id, ctx->http._internal.b64_authenticate_server_response); + fret = es11_authenticate_client_r(ctx, smdp_list, ctx->http.server_address, ctx->http._internal.transaction_id_http, ctx->http._internal.b64_authenticate_server_response); if (fret < 0) { return fret; diff --git a/euicc/euicc.c b/euicc/euicc.c index 5f9d68c..e0f07ea 100644 --- a/euicc/euicc.c +++ b/euicc/euicc.c @@ -198,22 +198,17 @@ void euicc_fini(struct euicc_ctx *ctx) void euicc_http_cleanup(struct euicc_ctx *ctx) { - free(ctx->http._internal.transaction_id); - ctx->http._internal.transaction_id = NULL; + free(ctx->http._internal.transaction_id_http); + free(ctx->http._internal.transaction_id_bin); free(ctx->http._internal.b64_euicc_challenge); - ctx->http._internal.b64_euicc_challenge = NULL; free(ctx->http._internal.b64_euicc_info_1); - ctx->http._internal.b64_euicc_info_1 = NULL; es10b_authenticate_server_param_free(ctx->http._internal.authenticate_server_param); free(ctx->http._internal.authenticate_server_param); - ctx->http._internal.authenticate_server_param = NULL; free(ctx->http._internal.b64_authenticate_server_response); - ctx->http._internal.b64_authenticate_server_response = NULL; es10b_prepare_download_param_free(ctx->http._internal.prepare_download_param); free(ctx->http._internal.prepare_download_param); - ctx->http._internal.prepare_download_param = NULL; free(ctx->http._internal.b64_prepare_download_response); - ctx->http._internal.b64_prepare_download_response = NULL; free(ctx->http._internal.b64_bound_profile_package); - ctx->http._internal.b64_bound_profile_package = NULL; + free(ctx->http._internal.b64_cancel_session_response); + memset(&ctx->http._internal, 0, sizeof(ctx->http._internal)); } diff --git a/euicc/euicc.h b/euicc/euicc.h index f508f7c..ee1f452 100644 --- a/euicc/euicc.h +++ b/euicc/euicc.h @@ -32,7 +32,9 @@ struct euicc_ctx } status; struct { - char *transaction_id; + char *transaction_id_http; + uint8_t *transaction_id_bin; + uint32_t transaction_id_bin_len; char *b64_euicc_challenge; char *b64_euicc_info_1; struct es10b_authenticate_server_param *authenticate_server_param; @@ -40,6 +42,7 @@ struct euicc_ctx struct es10b_prepare_download_param *prepare_download_param; char *b64_prepare_download_response; char *b64_bound_profile_package; + char *b64_cancel_session_response; } _internal; } http; void *userdata;