mirror of
https://github.com/estkme-group/lpac
synced 2024-09-17 14:30:32 +02:00
306 lines
11 KiB
C
306 lines
11 KiB
C
#define _GNU_SOURCE
|
|
#include "euicc.private.h"
|
|
#include "es10c_ex.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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));
|
|
}
|