static void display_data(const struct ef_name_map *map, u8 *data, size_t length) { if (map != NULL && data != NULL) { char buffer[8192]; char *value = NULL; if (opt_raw) { /* length-wise safe, but may cut off data (safe for OpenPGP cards 2.x) */ if (length > sizeof(buffer)) length = sizeof(buffer); if (map->type == TYPE_HEX) { if (exec_program) { value = prettify_hex(data, length, buffer, sizeof(buffer)); } else { sc_hex_dump(data, length, buffer, sizeof(buffer)); /* remove trailing newline */ if (*buffer != '\0' && buffer[strlen(buffer)-1] == '\n') buffer[strlen(buffer)-1] = '\0'; value = buffer; } } else { value = (char *) data; } } else { if (map->prettify_value != NULL) value = map->prettify_value(data, length); else { value = (map->type == TYPE_HEX) ? prettify_hex(data, length, buffer, sizeof(buffer)) : (char *) data; } } if (value != NULL) { if (exec_program) { char *envvar= malloc(strlen(map->env_name) + strlen(value) + 2); if (envvar != NULL) { strcpy(envvar, map->env_name); strcat(envvar, "="); strcat(envvar, value); putenv(envvar); /* envvar deliberately kept: see putenv(3) */ } } else { const char *label = map->name; int fill = (int) (INDENT - strlen(label)); printf("%s:%*s%s\n", label, fill, "", value); } } } }
/* Return the SE number from the keyD for the FID. If ref_data is not NULL the reference data is returned; this shoudl be an array of at least 2 bytes. Returns -1 on error. */ static int get_se_num_from_keyd(sc_card_t * card, unsigned short fid, u8 * ref_data) { sc_context_t *ctx = card->ctx; struct df_info_s *dfi; struct keyd_record_s *keyd; size_t len, taglen; const u8 *p, *tag; char dbgbuf[2048]; u8 fidbuf[2]; fidbuf[0] = fid >> 8; fidbuf[1] = fid; dfi = get_df_info(card); if (!dfi || !dfi->keyd_file) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "EF_keyD not loaded\n"); return -1; } for (keyd = dfi->keyd_file; keyd; keyd = keyd->next) { p = keyd->data; len = keyd->datalen; sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, p, len, dbgbuf, sizeof dbgbuf); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "keyd no %d:\n%s", keyd->recno, dbgbuf); tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); if (!tag || taglen != 4 || !(tag[2] == fidbuf[0] && tag[3] == fidbuf[1])) continue; /* Found a matching record. */ if (ref_data) { ref_data[0] = tag[0]; ref_data[1] = tag[1]; } /* Look for the SE-DO */ tag = sc_asn1_find_tag(ctx, p, len, 0x7B, &taglen); if (!tag || !taglen) continue; p = tag; len = taglen; /* And now look for the referenced SE. */ tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen); if (!tag || taglen != 1) continue; return *tag; /* found. */ } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "EF_keyD for %04hx not found\n", fid); return -1; }
void sc_apdu_log(sc_context_t *ctx, int level, const u8 *data, size_t len, int is_out) { size_t blen = len * 5 + 128; char *buf = malloc(blen); if (buf == NULL) return; sc_hex_dump(ctx, level, data, len, buf, blen); sc_debug(ctx, level, "\n%s APDU data [%5u bytes] =====================================\n" "%s" "======================================================================\n", is_out != 0 ? "Outgoing" : "Incoming", len, buf); free(buf); }
void _bin_log(sc_context_t *ctx, int type, const char *file, int line, const char *func, const char *label, const u8 *data, size_t len, FILE *f) { if (!f) { char buf[1800]; if (data) sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, data, len, buf, sizeof buf); else buf[0] = 0; sc_do_log(ctx, type, file, line, func, "\n%s (%u byte%s)%s%s", label, (unsigned int) len, len==1?"":"s", len==0?"":":\n", buf); } else { fprintf(f, "%s (%u byte%s)%s%s\n", label, (unsigned int) len, len==1?"":"s", len==0?"":":\n", sc_dump_hex(data, len)); } }
void _sc_debug_hex(sc_context_t *ctx, int type, const char *file, int line, const char *func, const char *label, const u8 *data, size_t len) { size_t blen = len * 5 + 128; char *buf = malloc(blen); if (buf == NULL) return; sc_hex_dump(ctx, type, data, len, buf, blen); if (label) sc_do_log(ctx, type, file, line, func, "\n%s (%u byte%s):\n%s", label, (unsigned int) len, len==1?"":"s", buf); else sc_do_log(ctx, type, file, line, func, "%u byte%s:\n%s", (unsigned int) len, len==1?"":"s", buf); free(buf); }
/* Process an ARR (7816-9/8.5.4) and setup the ACL. */ static void process_arr(sc_card_t * card, sc_file_t * file, const u8 * buf, size_t buflen) { sc_context_t *ctx = card->ctx; struct df_info_s *dfi; struct rule_record_s *rule; size_t left, taglen; unsigned int cla, tag; const u8 *p; int skip; char dbgbuf[2048]; /* Currently we support only the short for. */ if (buflen != 1) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "can't handle long ARRs\n"); return; } dfi = get_df_info(card); for (rule = dfi ? dfi->rule_file : NULL; rule && rule->recno != *buf; rule = rule->next) ; if (!rule) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "referenced EF_rule record %d not found\n", *buf); return; } sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, rule->data, rule->datalen, dbgbuf, sizeof dbgbuf); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "rule for record %d:\n%s", *buf, dbgbuf); p = rule->data; left = rule->datalen; skip = 1; /* Skip over initial unknown SC DOs. */ for (;;) { buf = p; if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS) break; left -= (p - buf); tag |= cla; if (tag == 0x80 && taglen != 1) { skip = 1; } else if (tag == 0x80) { /* AM byte. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " AM_DO: %02x\n", *p); skip = 0; } else if (tag >= 0x81 && tag <= 0x8f) { /* Cmd description */ sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, p, taglen, dbgbuf, sizeof dbgbuf); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " AM_DO: cmd[%s%s%s%s] %s", (tag & 8) ? "C" : "", (tag & 4) ? "I" : "", (tag & 2) ? "1" : "", (tag & 1) ? "2" : "", dbgbuf); skip = 0; } else if (tag == 0x9C) { /* Proprietary state machine descrip. */ skip = 1; } else if (!skip) { sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, p, taglen, dbgbuf, sizeof dbgbuf); switch (tag) { case 0x90: /* Always */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: always\n"); break; case 0x97: /* Never */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: never\n"); break; case 0xA4: /* Authentication, value is a CRT. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: auth %s", dbgbuf); break; case 0xB4: case 0xB6: case 0xB8: /* Cmd or resp with SM, value is a CRT. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: cmd/resp %s", dbgbuf); break; case 0x9E: /* Security Condition byte. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: condition %s", dbgbuf); break; case 0xA0: /* OR template. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: OR\n"); break; case 0xAF: /* AND template. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: AND\n"); break; } } left -= taglen; p += taglen; } }
static int sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info, unsigned char *idata, size_t idata_len) { struct sm_gp_session *gp_session = &sm_info->session.gp; struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset; unsigned char master_key[16] = { 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, }; unsigned char *keys[3] = { gp_keyset->enc, gp_keyset->mac, gp_keyset->kek }; unsigned char key_buff[16]; unsigned char *tmp; int rv = 0, ii, tmp_len; if (gp_keyset->kmc_len == 48) { for (ii=0; ii<3; ii++) memcpy(keys[ii], gp_keyset->kmc + 16*ii, 16); } else if (gp_keyset->kmc_len == 16 || gp_keyset->kmc_len == 0) { if (gp_keyset->kmc_len == 16) memcpy(master_key, gp_keyset->kmc, 16); sc_log(ctx, "KMC: %s", sc_dump_hex(master_key, sizeof(master_key))); for (ii=0; ii<3; ii++) { key_buff[0] = key_buff[8] = 0; key_buff[1] = key_buff[9] = 0; key_buff[2] = key_buff[10] = *(idata + 6); key_buff[3] = key_buff[11] = *(idata + 7); key_buff[4] = key_buff[12] = *(idata + 8); key_buff[5] = key_buff[13] = *(idata + 9); key_buff[6] = 0xF0, key_buff[14] = 0x0F; key_buff[7] = key_buff[15] = ii+1; sc_log(ctx, "key_buf:%s", sc_dump_hex(key_buff, 16)); rv = sm_encrypt_des_ecb3(master_key, key_buff, sizeof(key_buff), &tmp, &tmp_len); LOG_TEST_RET(ctx, rv, "GP init session: cannot derivate key"); memcpy(keys[ii], tmp, sizeof(gp_keyset->enc)); free(tmp); } } else { LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "GP init session: invalid KMC data"); } if (!rv && ctx) { char dump_buf[2048]; sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_session->card_challenge, sizeof(gp_session->card_challenge), dump_buf, sizeof(dump_buf)); sc_log(ctx, "Card challenge: %s", dump_buf); sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_session->host_challenge, sizeof(gp_session->host_challenge), dump_buf, sizeof(dump_buf)); sc_log(ctx, "Host challenge: %s", dump_buf); sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->enc, sizeof(gp_keyset->enc), dump_buf, sizeof(dump_buf)); sc_log(ctx, "ENC: %s", dump_buf); sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->mac, sizeof(gp_keyset->mac), dump_buf, sizeof(dump_buf)); sc_log(ctx, "MAC: %s", dump_buf); sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->kek, sizeof(gp_keyset->kek), dump_buf, sizeof(dump_buf)); sc_log(ctx, "KEK: %s", dump_buf); } return rv; }