static int iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo) { struct sc_context *ctx = card->ctx; size_t offs = 0; int rv; LOG_FUNC_CALLED(ctx); while(offs < data_len) { struct iasecc_extended_tlv tlv; rv = iasecc_parse_get_tlv(card, data + offs, &tlv); LOG_TEST_RET(ctx, rv, "iasecc_parse_get_tlv() get and parse TLV error"); sc_log(ctx, "iasecc_parse_docp() parse_get_tlv retuned %i; tag %X; size %i", rv, tlv.tag, tlv.size); if (tlv.tag == IASECC_DOCP_TAG_ACLS) { int _rv = iasecc_parse_docp(card, tlv.value, tlv.size, sdo); free(tlv.value); LOG_TEST_RET(ctx, _rv, "parse error: cannot parse DOCP"); } else if (tlv.tag == IASECC_DOCP_TAG_ACLS_CONTACT) { sdo->docp.acls_contact = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_ACLS_CONTACTLESS) { sdo->docp.acls_contactless = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_SIZE) { sdo->docp.size = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_NAME) { sdo->docp.name = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_ISSUER_DATA) { sdo->docp.issuer_data = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_NON_REPUDATION) { sdo->docp.non_repudiation = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_USAGE_REMAINING) { sdo->docp.usage_remaining = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_TRIES_MAXIMUM) { sdo->docp.tries_maximum = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_TRIES_REMAINING) { sdo->docp.tries_remaining = tlv; } else { LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "iasecc_parse_get_tlv() parse error: non DOCP tag"); } offs += rv; } rv = iasecc_parse_acls(card, &sdo->docp, 0); LOG_TEST_RET(ctx, rv, "Cannot parse ACLs in DOCP"); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_chv *chv) { struct sc_context *ctx = card->ctx; size_t offs = 0; int rv; LOG_FUNC_CALLED(ctx); while(offs < data_len) { struct iasecc_extended_tlv tlv; rv = iasecc_parse_get_tlv(card, data + offs, &tlv); LOG_TEST_RET(ctx, rv, "iasecc_parse_chv() get and parse TLV error"); sc_log(ctx, "iasecc_parse_chv() get and parse TLV returned %i; tag %X; size %i", rv, tlv.tag, tlv.size); if (tlv.tag == IASECC_SDO_CHV_TAG_SIZE_MAX) chv->size_max = tlv; else if (tlv.tag == IASECC_SDO_CHV_TAG_SIZE_MIN) chv->size_min = tlv; else if (tlv.tag == IASECC_SDO_CHV_TAG_VALUE) chv->value = tlv; else LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "parse error: non CHV SDO tag"); offs += rv; } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_keyset *keyset) { struct sc_context *ctx = card->ctx; size_t offs = 0; int rv; LOG_FUNC_CALLED(ctx); while(offs < data_len) { struct iasecc_extended_tlv tlv; rv = iasecc_parse_get_tlv(card, data + offs, &tlv); LOG_TEST_RET(ctx, rv, "iasecc_parse_keyset() get and parse TLV error"); sc_log(ctx, "iasecc_parse_prvkey() get and parse TLV returned %i; tag %X; size %i", rv, tlv.tag, tlv.size); if (tlv.tag == IASECC_SDO_KEYSET_TAG_COMPULSORY) keyset->compulsory = tlv; else LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "parse error: non KeySet SDO tag"); offs += rv; } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_pubkey *pubkey) { struct sc_context *ctx = card->ctx; size_t offs = 0; int rv; LOG_FUNC_CALLED(ctx); while(offs < data_len) { struct iasecc_extended_tlv tlv; rv = iasecc_parse_get_tlv(card, data + offs, &tlv); LOG_TEST_RET(ctx, rv, "iasecc_parse_pubkey() get and parse TLV error"); sc_log(ctx, "iasecc_parse_pubkey() get and parse TLV returned %i; tag %X; size %"SC_FORMAT_LEN_SIZE_T"u", rv, tlv.tag, tlv.size); if (tlv.tag == IASECC_SDO_PUBKEY_TAG_N) pubkey->n = tlv; else if (tlv.tag == IASECC_SDO_PUBKEY_TAG_E) pubkey->e = tlv; else if (tlv.tag == IASECC_SDO_PUBKEY_TAG_CHR) pubkey->chr = tlv; else if (tlv.tag == IASECC_SDO_PUBKEY_TAG_CHA) pubkey->cha = tlv; else if (tlv.tag == IASECC_SDO_PUBKEY_TAG_COMPULSORY) pubkey->compulsory = tlv; else LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "parse error: non PubKey SDO tag"); offs += rv; } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_sdo *sdo) { struct sc_context *ctx = card->ctx; struct iasecc_extended_tlv tlv; int tlv_size, rv; LOG_FUNC_CALLED(ctx); sc_log(ctx, "iasecc_sdo_parse_data() class %X; ref %X", sdo->sdo_class, sdo->sdo_ref); tlv_size = iasecc_parse_get_tlv(card, data, &tlv); LOG_TEST_RET(ctx, tlv_size, "parse error: get TLV"); sc_log(ctx, "iasecc_sdo_parse_data() tlv.tag 0x%X", tlv.tag); if (tlv.tag == IASECC_DOCP_TAG) { sc_log(ctx, "iasecc_sdo_parse_data() parse IASECC_DOCP_TAG: 0x%X; size %i", tlv.tag, tlv.size); rv = iasecc_parse_docp(card, tlv.value, tlv.size, sdo); sc_log(ctx, "iasecc_sdo_parse_data() parsed IASECC_DOCP_TAG rv %i", rv); free(tlv.value); LOG_TEST_RET(ctx, rv, "parse error: cannot parse DOCP"); } else if (tlv.tag == IASECC_DOCP_TAG_NON_REPUDATION) { sdo->docp.non_repudiation = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_USAGE_REMAINING) { sdo->docp.usage_remaining = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_TRIES_MAXIMUM) { sdo->docp.tries_maximum = tlv; } else if (tlv.tag == IASECC_DOCP_TAG_TRIES_REMAINING) { sdo->docp.tries_remaining = tlv; } else if (tlv.tag == IASECC_SDO_CHV_TAG) { if (sdo->sdo_class != IASECC_SDO_CLASS_CHV) LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: IASECC_SDO_CHV_TAG tag in non User CHV SDO"); rv = iasecc_parse_chv(card, tlv.value, tlv.size, &sdo->data.chv); LOG_TEST_RET(ctx, rv, "parse error: cannot parse SDO CHV data"); free(tlv.value); } else if (tlv.tag == IASECC_SDO_PUBKEY_TAG) { if (sdo->sdo_class != IASECC_SDO_CLASS_RSA_PUBLIC) LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: SDO_PUBLIC_KEY tag in non PUBLIC_KEY SDO"); rv = iasecc_parse_pubkey(card, tlv.value, tlv.size, &sdo->data.pub_key); LOG_TEST_RET(ctx, rv, "parse error: cannot parse SDO PUBLIC KEY data"); free(tlv.value); } else if (tlv.tag == IASECC_SDO_PRVKEY_TAG) { if (sdo->sdo_class != IASECC_SDO_CLASS_RSA_PRIVATE) LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: SDO_PRIVATE_KEY tag in non PRIVATE_KEY SDO"); rv = iasecc_parse_prvkey(card, tlv.value, tlv.size, &sdo->data.prv_key); LOG_TEST_RET(ctx, rv, "parse error: cannot parse SDO PRIVATE KEY data"); free(tlv.value); } else if (tlv.tag == IASECC_SDO_KEYSET_TAG) { if (sdo->sdo_class != IASECC_SDO_CLASS_KEYSET) LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: SDO_KEYSET tag in non KEYSET SDO"); rv = iasecc_parse_keyset(card, tlv.value, tlv.size, &sdo->data.keyset); LOG_TEST_RET(ctx, rv, "parse error: cannot parse SDO KEYSET data"); free(tlv.value); } else { sc_log(ctx, "iasecc_sdo_parse_data() non supported tag 0x%X", tlv.tag); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } return tlv_size; }