lpac/euicc/es10c_ex.c
2024-04-19 11:58:50 +08:00

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));
}