static int do_ls(int argc, char **argv) { u8 buf[256], *cur = buf; int r, count; r = sc_list_files(card, buf, sizeof(buf)); if (r < 0) { check_ret(r, SC_AC_OP_LIST_FILES, "unable to receive file listing", current_file); return -1; } count = r; printf("FileID\tType Size\n"); while (count >= 2) { sc_path_t path; sc_file_t *file = NULL; char filename[10]; int i = 0; int matches = 0; /* construct file name */ sprintf(filename, "%02X%02X", cur[0], cur[1]); /* compare file name against patterns */ for (i = 0; i < argc; i++) { if (pattern_match(argv[i], filename)) { matches = 1; break; } } /* if any filename pattern were given, filter only matching file names */ if (argc == 0 || matches) { if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; sc_append_path_id(&path, cur, 2); } else { if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, cur, 2, 0, 0) != SC_SUCCESS) { printf("unable to set path.\n"); die(1); } } r = sc_select_file(card, &path, &file); if (r) { printf(" %02X%02X unable to select file, %s\n", cur[0], cur[1], sc_strerror(r)); } else { file->id = (cur[0] << 8) | cur[1]; print_file(file); sc_file_free(file); } } cur += 2; count -= 2; select_current_path_or_die(); } return 0; }
static int arg_to_path(const char *arg, sc_path_t *path, int is_id) { memset(path, 0, sizeof(sc_path_t)); if (strncasecmp(arg, "aid:", strlen("aid:")) == 0) { /* DF aid */ const char *p = arg + strlen("aid:"); int r; path->type = SC_PATH_TYPE_DF_NAME; path->len = sizeof(path->value); if ((r = sc_hex_to_bin(p, path->value, &path->len)) < 0) { printf("Error parsing AID: %s\n", p); return r; } } else { /* file id */ unsigned int buf[2]; u8 cbuf[2]; if (strlen(arg) != 4) { printf("Wrong ID length.\n"); return -1; } if (sscanf(arg, "%02X%02X", &buf[0], &buf[1]) != 2) { printf("Invalid ID.\n"); return -1; } cbuf[0] = buf[0]; cbuf[1] = buf[1]; if ((cbuf[0] == 0x3F && cbuf[1] == 0x00) || is_id) { path->len = 2; memcpy(path->value, cbuf, 2); path->type = (is_id) ? SC_PATH_TYPE_FILE_ID : SC_PATH_TYPE_PATH; } else { *path = current_path; if (path->type == SC_PATH_TYPE_DF_NAME) { if (path->len > sizeof(path->aid.value)) { printf("Invalid length of DF_NAME path\n"); return -1; } memcpy(path->aid.value, path->value, path->len); path->aid.len = path->len; path->type = SC_PATH_TYPE_FILE_ID; path->len = 0; } sc_append_path_id(path, cbuf, 2); } } return 0; }
static int dump_unusedspace(void) { u8 *buf = NULL; size_t buf_len; sc_path_t path; sc_pkcs15_unusedspace_t *us; int r; if (p15card->file_unusedspace != NULL) path = p15card->file_unusedspace->path; else { path = p15card->file_app->path; sc_append_path_id(&path, (const u8 *) "\x50\x33", 2); } path.count = -1; sc_ctx_suppress_errors_on(p15card->card->ctx); r = sc_pkcs15_read_file(p15card, &path, &buf, &buf_len, NULL); sc_ctx_suppress_errors_off(p15card->card->ctx); if (r < 0) { if (r == SC_ERROR_FILE_NOT_FOUND) { printf("\nNo EF(UnusedSpace) file\n"); r = 0; } else printf("\nError reading file \"%s\": %s\n", sc_print_path(&path), sc_strerror(r)); goto err; } r = sc_pkcs15_parse_unusedspace(buf, buf_len, p15card); if (r != 0) { printf("\nError parsing EF(UnusedSpace): %s\n", sc_strerror(r)); goto err; } if (p15card->unusedspace_list == NULL) printf("\nEF(UnusedSpace) file is empty\n"); else { printf("\nContents of EF(UnusedSpace):\n"); for (us = p15card->unusedspace_list; us != NULL; us = us->next) printf(" - path=%s, index=%d, length=%d -- auth_id = %s\n", sc_print_path(&us->path), us->path.index, us->path.count, us->auth_id.len == 0 ? "<empty>" : sc_pkcs15_print_id(&us->auth_id)); } err: if (buf != NULL) free(buf); return r; }
static int do_ls(int argc, char **argv) { u8 buf[256], *cur = buf; int r, count; if (argc) goto usage; r = sc_list_files(card, buf, sizeof(buf)); if (r < 0) { check_ret(r, SC_AC_OP_LIST_FILES, "unable to receive file listing", current_file); return -1; } count = r; printf("FileID\tType Size\n"); while (count >= 2) { sc_path_t path; sc_file_t *file = NULL; if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; sc_append_path_id(&path, cur, 2); } else { if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, cur, 2, 0, 0) != SC_SUCCESS) { printf("unable to set path.\n"); die(1); } } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } file->id = (cur[0] << 8) | cur[1]; cur += 2; count -= 2; print_file(file); sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent DF: %s\n", sc_strerror(r)); die(1); } } return 0; usage: puts("Usage: ls"); return -1; }
/* sets a TLV encoded path as returned from GET DATA in a sc_path_t object */ static int asepcos_tlvpath_to_scpath(sc_path_t *out, const u8 *in, size_t in_len) { int r; size_t len = in_len; memset(out, 0, sizeof(sc_path_t)); while (len != 0) { if (len < 4) return SC_ERROR_INTERNAL; if (in[0] != 0x8b || in[1] != 0x02) return SC_ERROR_INVALID_ASN1_OBJECT; /* append file id to the path */ r = sc_append_path_id(out, &in[2], 2); if (r != SC_SUCCESS) return r; len -= 4; in += 4; } out->type = SC_PATH_TYPE_PATH; return SC_SUCCESS; }
static int arg_to_path(const char *arg, sc_path_t *path, int is_id) { if (strncasecmp(arg, "aid:", strlen("aid:")) == 0) { /* DF aid */ const char *p = arg + strlen("aid:"); path->len = hex2binary(path->value, sizeof(path->value), p); path->type = SC_PATH_TYPE_DF_NAME; } else { /* file id */ int buf[2]; u8 cbuf[2]; if (strlen(arg) != 4) { printf("Wrong ID length.\n"); return -1; } if (sscanf(arg, "%02X%02X", &buf[0], &buf[1]) != 2) { printf("Invalid ID.\n"); return -1; } cbuf[0] = buf[0]; cbuf[1] = buf[1]; if ((cbuf[0] == 0x3F && cbuf[1] == 0x00) || is_id) { path->len = 2; memcpy(path->value, cbuf, 2); if (is_id) path->type = SC_PATH_TYPE_FILE_ID; else path->type = SC_PATH_TYPE_PATH; } else { *path = current_path; sc_append_path_id(path, cbuf, 2); } } return 0; }
static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card) { unsigned char *buf = NULL; int err, ok = 0; size_t len; sc_path_t tmppath; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; sc_pkcs15_tokeninfo_t tokeninfo; if (ctx->debug > 4) sc_debug(ctx, "trying normal pkcs15 processing\n"); /* Enumerate apps now */ if (card->app_count < 0) { err = sc_enum_apps(card); if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) { sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err)); goto end; } } p15card->file_app = sc_file_new(); if (p15card->file_app == NULL) { err = SC_ERROR_OUT_OF_MEMORY; goto end; } sc_format_path("3F005015", &p15card->file_app->path); if (card->app_count > 0) { const sc_app_info_t *info; info = sc_find_pkcs15_app(card); if (info != NULL) { if (info->path.len) p15card->file_app->path = info->path; if (info->ddo != NULL) parse_ddo(p15card, info->ddo, info->ddo_len); } } /* Check if pkcs15 directory exists */ sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &p15card->file_app->path, NULL); #if 1 /* If the above test failed on cards without EF(DIR), * try to continue read ODF from 3F005031. -aet */ if ((err == SC_ERROR_FILE_NOT_FOUND) && (card->app_count < 1)) { sc_format_path("3F00", &p15card->file_app->path); err = SC_NO_ERROR; } #endif sc_ctx_suppress_errors_off(card->ctx); if (err < 0) goto end; if (p15card->file_odf == NULL) { /* check if an ODF is present; suppress errors as we * don't know yet whether we have a pkcs15 card */ tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2); sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &tmppath, &p15card->file_odf); sc_ctx_suppress_errors_off(card->ctx); } else { tmppath = p15card->file_odf->path; sc_file_free(p15card->file_odf); p15card->file_odf = NULL; err = sc_select_file(card, &tmppath, &p15card->file_odf); } if (err != SC_SUCCESS) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &tmppath); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(ctx, "EF(ODF) not found in '%s'\n", pbuf); goto end; } if ((len = p15card->file_odf->size) == 0) { sc_error(card->ctx, "EF(ODF) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err < 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } len = err; if (parse_odf(buf, len, p15card)) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; sc_error(card->ctx, "Unable to parse ODF\n"); goto end; } free(buf); buf = NULL; if (card->ctx->debug) { sc_pkcs15_df_t *df; sc_debug(card->ctx, "The following DFs were found:\n"); for (df = p15card->df_list; df; df = df->next) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &df->path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(card->ctx, " DF type %u, path %s, index %u, count %d\n", df->type, pbuf, df->path.index, df->path.count); } } if (p15card->file_tokeninfo == NULL) { tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x32", 2); } else { tmppath = p15card->file_tokeninfo->path; sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo); if (err) goto end; if ((len = p15card->file_tokeninfo->size) == 0) { sc_error(card->ctx, "EF(TokenInfo) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err <= 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } memset(&tokeninfo, 0, sizeof(tokeninfo)); err = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t)err); if (err != SC_SUCCESS) goto end; p15card->version = tokeninfo.version; p15card->label = tokeninfo.label; p15card->serial_number = tokeninfo.serial_number; p15card->manufacturer_id = tokeninfo.manufacturer_id; p15card->last_update = tokeninfo.last_update; p15card->flags = tokeninfo.flags; p15card->preferred_language = tokeninfo.preferred_language; p15card->seInfo = tokeninfo.seInfo; p15card->num_seInfo = tokeninfo.num_seInfo; /* for cardos cards initialized by Siemens: sign with decrypt */ if (strcmp(p15card->card->driver->short_name,"cardos") == 0 && ( strcmp(p15card->manufacturer_id,"Siemens AG (C)") == 0 || strcmp(p15card->manufacturer_id,"Prime") == 0 )) p15card->flags |= SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; ok = 1; end: if(buf != NULL) free(buf); if (!ok) { sc_pkcs15_card_clear(p15card); return err; } return SC_SUCCESS; }
static int do_find(int argc, char **argv) { u8 fid[2], end[2]; sc_path_t path; int r; fid[0] = 0; fid[1] = 0; end[0] = 0xFF; end[1] = 0xFF; switch (argc) { case 2: if (arg_to_fid(argv[1], end) != 0) return usage(do_find); /* fall through */ case 1: if (arg_to_fid(argv[0], fid) != 0) return usage(do_find); /* fall through */ case 0: break; default: return usage(do_find); } printf("FileID\tType Size\n"); while (1) { sc_file_t *file = NULL; printf("(%02X%02X)\r", fid[0], fid[1]); fflush(stdout); if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; sc_append_path_id(&path, fid, sizeof fid); } else { if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0) != SC_SUCCESS) { printf("unable to set path.\n"); die(1); } } r = sc_select_file(card, &path, &file); switch (r) { case SC_SUCCESS: file->id = (fid[0] << 8) | fid[1]; print_file(file); sc_file_free(file); select_current_path_or_die(); break; case SC_ERROR_NOT_ALLOWED: case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED: printf("(%02X%02X)\t%s\n", fid[0], fid[1], sc_strerror(r)); break; } if (fid[0] == end[0] && fid[1] == end[1]) break; fid[1] = fid[1] + 1; if (fid[1] == 0) fid[0] = fid[0] + 1; } return 0; }