2017-09-13 10:21:59 +00:00
|
|
|
/*
|
|
|
|
* ef-atr.c: Stuff for handling EF(GDO)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "asn1.h"
|
2017-08-02 21:12:58 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include <stdlib.h>
|
2018-02-23 22:15:03 +00:00
|
|
|
#include <string.h>
|
2017-09-13 10:21:59 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
2018-02-23 22:15:03 +00:00
|
|
|
unsigned char *iccsn, size_t *iccsn_len,
|
|
|
|
unsigned char *chn, size_t *chn_len)
|
2017-09-13 10:21:59 +00:00
|
|
|
{
|
2018-02-23 22:15:03 +00:00
|
|
|
int r = SC_SUCCESS, iccsn_found = 0, chn_found = 0;
|
2017-09-13 10:21:59 +00:00
|
|
|
const unsigned char *p = gdo;
|
|
|
|
size_t left = gdo_len;
|
|
|
|
|
|
|
|
while (left >= 2) {
|
|
|
|
unsigned int cla, tag;
|
|
|
|
size_t tag_len;
|
|
|
|
|
|
|
|
r = sc_asn1_read_tag(&p, left, &cla, &tag, &tag_len);
|
|
|
|
if (r != SC_SUCCESS) {
|
|
|
|
if (r == SC_ERROR_ASN1_END_OF_CONTENTS) {
|
|
|
|
/* not enough data */
|
|
|
|
r = SC_SUCCESS;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-03-19 14:25:14 +00:00
|
|
|
if (p == NULL) {
|
2017-09-13 10:21:59 +00:00
|
|
|
/* done parsing */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cla == SC_ASN1_TAG_APPLICATION) {
|
|
|
|
switch (tag) {
|
|
|
|
case 0x1A:
|
2018-02-23 22:15:03 +00:00
|
|
|
iccsn_found = 1;
|
|
|
|
if (iccsn && iccsn_len) {
|
|
|
|
memcpy(iccsn, p, MIN(tag_len, *iccsn_len));
|
|
|
|
*iccsn_len = MIN(tag_len, *iccsn_len);
|
|
|
|
}
|
2017-09-13 10:21:59 +00:00
|
|
|
break;
|
|
|
|
case 0x1F20:
|
2018-02-23 22:15:03 +00:00
|
|
|
chn_found = 1;
|
|
|
|
if (chn && chn_len) {
|
|
|
|
memcpy(chn, p, MIN(tag_len, *chn_len));
|
|
|
|
*chn_len = MIN(tag_len, *chn_len);
|
|
|
|
}
|
2017-09-13 10:21:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p += tag_len;
|
2018-05-25 12:54:47 +00:00
|
|
|
left = gdo_len - (p - gdo);
|
2017-09-13 10:21:59 +00:00
|
|
|
}
|
|
|
|
|
2018-02-23 22:15:03 +00:00
|
|
|
if (!iccsn_found && iccsn_len)
|
|
|
|
*iccsn_len = 0;
|
|
|
|
if (!chn_found && chn_len)
|
|
|
|
*chn_len = 0;
|
|
|
|
|
2017-09-13 10:21:59 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
sc_parse_ef_gdo(struct sc_card *card,
|
2018-02-23 22:15:03 +00:00
|
|
|
unsigned char *iccsn, size_t *iccsn_len,
|
|
|
|
unsigned char *chn, size_t *chn_len)
|
2017-09-13 10:21:59 +00:00
|
|
|
{
|
|
|
|
struct sc_context *ctx;
|
|
|
|
struct sc_path path;
|
|
|
|
struct sc_file *file;
|
|
|
|
unsigned char *gdo = NULL;
|
|
|
|
size_t gdo_len = 0;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (!card)
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
ctx = card->ctx;
|
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
|
|
|
|
sc_format_path("3F002F02", &path);
|
|
|
|
r = sc_select_file(card, &path, &file);
|
|
|
|
LOG_TEST_GOTO_ERR(ctx, r, "Cannot select EF(GDO) file");
|
|
|
|
|
|
|
|
if (file->size) {
|
|
|
|
gdo_len = file->size;
|
|
|
|
} else {
|
|
|
|
gdo_len = 64;
|
|
|
|
}
|
|
|
|
gdo = malloc(gdo_len);
|
|
|
|
if (!gdo) {
|
|
|
|
r = SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sc_read_binary(card, 0, gdo, gdo_len, 0);
|
|
|
|
LOG_TEST_GOTO_ERR(ctx, r, "Cannot read EF(GDO) file");
|
|
|
|
|
|
|
|
r = sc_parse_ef_gdo_content(gdo, r, iccsn, iccsn_len, chn, chn_len);
|
|
|
|
|
|
|
|
err:
|
|
|
|
sc_file_free(file);
|
|
|
|
free(gdo);
|
|
|
|
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|