#define _GNU_SOURCE #include "euicc.private.h" #include "es10c_ex.h" #include #include #include #include "derutil.h" #include "hexutil.h" static int _versiontype2str(char **out, const uint8_t *buffer, uint8_t buffer_len) { if (buffer_len != 3) { return -1; } return asprintf(out, "%d.%d.%d", buffer[0], buffer[1], buffer[2]); } int es10c_ex_get_euiccinfo2(struct euicc_ctx *ctx, struct es10c_ex_euiccinfo2 *euiccinfo2) { int fret = 0; struct euicc_derutil_node n_request = { .tag = 0xBF22, // GetEuiccInfo2Request }; uint32_t reqlen; uint8_t *respbuf = NULL; unsigned resplen; struct euicc_derutil_node tmpnode, tmpchidnode, n_EUICCInfo2; memset(euiccinfo2, 0, sizeof(struct es10c_ex_euiccinfo2)); reqlen = sizeof(ctx->apdu._internal.request_buffer.body); if (euicc_derutil_pack(ctx->apdu._internal.request_buffer.body, &reqlen, &n_request) < 0) { goto err; } if (es10x_command(ctx, &respbuf, &resplen, ctx->apdu._internal.request_buffer.body, reqlen) < 0) { goto err; } if (euicc_derutil_unpack_find_tag(&n_EUICCInfo2, n_request.tag, respbuf, resplen) < 0) { goto err; } tmpnode.self.ptr = n_EUICCInfo2.value; tmpnode.self.length = 0; while (euicc_derutil_unpack_next(&tmpnode, &tmpnode, n_EUICCInfo2.value, n_EUICCInfo2.length) == 0) { switch (tmpnode.tag) { case 0x81: // profileVersion _versiontype2str(&euiccinfo2->profileVersion, tmpnode.value, tmpnode.length); break; case 0x82: // svn _versiontype2str(&euiccinfo2->svn, tmpnode.value, tmpnode.length); break; case 0x83: // euiccFirmwareVer _versiontype2str(&euiccinfo2->euiccFirmwareVer, tmpnode.value, tmpnode.length); break; case 0x84: // extCardResource tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { switch (tmpchidnode.tag) { case 0x81: euiccinfo2->extCardResource.installedApplication = euicc_derutil_convert_bin2long(tmpchidnode.value, tmpchidnode.length); break; case 0x82: euiccinfo2->extCardResource.freeNonVolatileMemory = euicc_derutil_convert_bin2long(tmpchidnode.value, tmpchidnode.length); break; case 0x83: euiccinfo2->extCardResource.freeVolatileMemory = euicc_derutil_convert_bin2long(tmpchidnode.value, tmpchidnode.length); break; } } break; case 0x85: // uiccCapability { static const char *desc[] = {"contactlessSupport", "usimSupport", "isimSupport", "csimSupport", "akaMilenage", "akaCave", "akaTuak128", "akaTuak256", "rfu1", "rfu2", "gbaAuthenUsim", "gbaAuthenISim", "mbmsAuthenUsim", "eapClient", "javacard", "multos", "multipleUsimSupport", "multipleIsimSupport", "multipleCsimSupport", NULL}; if (euicc_derutil_convert_bin2bits_str(&euiccinfo2->uiccCapability, tmpnode.value, tmpnode.length, desc)) { goto err; } } break; case 0x86: // ts102241Version _versiontype2str(&euiccinfo2->ts102241Version, tmpnode.value, tmpnode.length); break; case 0x87: // globalplatformVersion _versiontype2str(&euiccinfo2->globalplatformVersion, tmpnode.value, tmpnode.length); break; case 0x88: // rspCapability { static const char *desc[] = {"additionalProfile", "crlSupport", "rpmSupport", "testProfileSupport", NULL}; if (euicc_derutil_convert_bin2bits_str(&euiccinfo2->rspCapability, tmpnode.value, tmpnode.length, desc)) { goto err; } } break; case 0xA9: // euiccCiPKIdListForVerification { int count; tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; count = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { count++; } euiccinfo2->euiccCiPKIdListForVerification = malloc((count + 1) * sizeof(char *)); if (!euiccinfo2->euiccCiPKIdListForVerification) { goto err; } memset(euiccinfo2->euiccCiPKIdListForVerification, 0, (count + 1) * sizeof(char *)); tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; count = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { euiccinfo2->euiccCiPKIdListForVerification[count] = malloc((tmpchidnode.length * 2 + 1) * sizeof(char)); if (!euiccinfo2->euiccCiPKIdListForVerification[count]) { goto err; } euicc_hexutil_bin2hex(euiccinfo2->euiccCiPKIdListForVerification[count], tmpchidnode.length * 2 + 1, tmpchidnode.value, tmpchidnode.length); count++; } } break; case 0xAA: // euiccCiPKIdListForSigning { int count; tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; count = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { count++; } euiccinfo2->euiccCiPKIdListForSigning = malloc((count + 1) * sizeof(char *)); if (!euiccinfo2->euiccCiPKIdListForSigning) { goto err; } memset(euiccinfo2->euiccCiPKIdListForSigning, 0, (count + 1) * sizeof(char *)); tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; count = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { euiccinfo2->euiccCiPKIdListForSigning[count] = malloc((tmpchidnode.length * 2 + 1) * sizeof(char)); if (!euiccinfo2->euiccCiPKIdListForSigning[count]) { goto err; } euicc_hexutil_bin2hex(euiccinfo2->euiccCiPKIdListForSigning[count], tmpchidnode.length * 2 + 1, tmpchidnode.value, tmpchidnode.length); count++; } } break; case 0xAB: // euiccCategory { switch (euicc_derutil_convert_bin2long(tmpnode.value, tmpnode.length)) { case 1: euiccinfo2->euiccCategory = "basicEuicc"; break; case 2: euiccinfo2->euiccCategory = "mediumEuicc"; break; case 3: euiccinfo2->euiccCategory = "contactlessEuicc"; break; case 0: default: euiccinfo2->euiccCategory = "other"; break; } } break; case 0x99: // forbiddenProfilePolicyRules { static const char *desc[] = {"pprUpdateControl", "ppr1", "ppr2", "ppr3", NULL}; if (euicc_derutil_convert_bin2bits_str(&euiccinfo2->forbiddenProfilePolicyRules, tmpnode.value, tmpnode.length, desc)) { goto err; } } break; case 0x04: // ppVersion _versiontype2str(&euiccinfo2->ppVersion, tmpnode.value, tmpnode.length); break; case 0x0C: // sasAcreditationNumber euiccinfo2->sasAcreditationNumber = malloc(tmpnode.length + 1); if (!euiccinfo2->sasAcreditationNumber) { goto err; } memcpy(euiccinfo2->sasAcreditationNumber, tmpnode.value, tmpnode.length); euiccinfo2->sasAcreditationNumber[tmpnode.length] = 0; break; case 0xAC: // certificationDataObject tmpchidnode.self.ptr = tmpnode.value; tmpchidnode.self.length = 0; while (euicc_derutil_unpack_next(&tmpchidnode, &tmpchidnode, tmpnode.value, tmpnode.length) == 0) { switch (tmpchidnode.tag) { case 0x80: euiccinfo2->certificationDataObject.platformLabel = malloc(tmpchidnode.length + 1); if (!euiccinfo2->certificationDataObject.platformLabel) { goto err; } memcpy(euiccinfo2->certificationDataObject.platformLabel, tmpchidnode.value, tmpchidnode.length); euiccinfo2->certificationDataObject.platformLabel[tmpchidnode.length] = 0; break; case 0x81: euiccinfo2->certificationDataObject.discoveryBaseURL = malloc(tmpchidnode.length + 1); if (!euiccinfo2->certificationDataObject.discoveryBaseURL) { goto err; } memcpy(euiccinfo2->certificationDataObject.discoveryBaseURL, tmpchidnode.value, tmpchidnode.length); euiccinfo2->certificationDataObject.discoveryBaseURL[tmpchidnode.length] = 0; break; } } break; } } fret = 0; goto exit; err: fret = -1; es10c_ex_euiccinfo2_free(euiccinfo2); exit: free(respbuf); respbuf = NULL; return fret; } void es10c_ex_euiccinfo2_free(struct es10c_ex_euiccinfo2 *euiccinfo2) { if (!euiccinfo2) { return; } free(euiccinfo2->profileVersion); free(euiccinfo2->svn); free(euiccinfo2->euiccFirmwareVer); free(euiccinfo2->uiccCapability); free(euiccinfo2->ts102241Version); free(euiccinfo2->globalplatformVersion); free(euiccinfo2->rspCapability); if (euiccinfo2->euiccCiPKIdListForVerification) { for (int i = 0; euiccinfo2->euiccCiPKIdListForVerification[i] != NULL; i++) { free(euiccinfo2->euiccCiPKIdListForVerification[i]); } free(euiccinfo2->euiccCiPKIdListForVerification); } if (euiccinfo2->euiccCiPKIdListForSigning) { for (int i = 0; euiccinfo2->euiccCiPKIdListForSigning[i] != NULL; i++) { free(euiccinfo2->euiccCiPKIdListForSigning[i]); } free(euiccinfo2->euiccCiPKIdListForSigning); } free(euiccinfo2->forbiddenProfilePolicyRules); free(euiccinfo2->ppVersion); free(euiccinfo2->sasAcreditationNumber); free(euiccinfo2->certificationDataObject.discoveryBaseURL); free(euiccinfo2->certificationDataObject.platformLabel); memset(euiccinfo2, 0, sizeof(struct es10c_ex_euiccinfo2)); }