int inSendRecvAPDU(BYTE *bSendData, int inSendLen, BYTE *bRecvData, int * inRecvLen, int inTimeOut, BOOL saved) { int inRetVal; USHORT recelen = 0; MechineStatus &= (~(Status_READER_Disconnect)); if (strcmp(gConfig.DEVICE.READER.bPORT, "Builtin") == 0) { inRetVal = BuiltinReader_CMDSendReceive(bSendData, inSendLen, bRecvData, inRecvLen); } else { CTOS_RS232FlushTxBuffer(gREADERPORT.Portnum); CTOS_RS232FlushRxBuffer(gREADERPORT.Portnum); if(saved==TRUE) myDebugFileHex2Str((char*)__FUNCTION__,__LINE__,"send:",bSendData,inSendLen); if ((inRetVal = send_apdu(gREADERPORT.Portnum, bSendData, inSendLen)) != SUCCESS) { //SystemLogInt("inSendRecvAPDU", inRetVal, "send_apdu Fail"); MechineStatus |= Status_READER_Disconnect; printf("[%s,%d] d_ERR_SendAPDU_ERROR \n",__FUNCTION__,__LINE__); return d_ERR_SendAPDU_ERROR; } // CTOS_Delay(500); if ((inRetVal = recv_apdu(gREADERPORT.Portnum, bRecvData, inTimeOut)) == 0) { MechineStatus |= Status_READER_Disconnect; printf("[%s,%d] d_ERR_RecvAPDU_ERROR \n",__FUNCTION__,__LINE__); return d_ERR_RecvAPDU_ERROR; } if(saved==TRUE) myDebugFileHex2Str((char*)__FUNCTION__,__LINE__,"recv:",bRecvData, inRetVal); CTOS_RS232FlushTxBuffer(gREADERPORT.Portnum); CTOS_RS232FlushRxBuffer(gREADERPORT.Portnum); } // ShowSystemMemoryStatus("inSendRecvAPDU2 "); inRetVal = SUCCESS; return (inRetVal); }
static u2fh_rc _u2fh_register (u2fh_devs * devs, const char *challenge, const char *origin, char **response, size_t * response_len, u2fh_cmdflags flags) { unsigned char data[V2CHALLEN + HOSIZE]; unsigned char buf[MAXDATASIZE]; char bd[2048]; size_t bdlen = sizeof (bd); size_t len; int rc = U2FH_JSON_ERROR; char chalb64[256]; size_t challen = sizeof (chalb64); int iterations = 0; rc = get_fixed_json_data (challenge, "challenge", chalb64, &challen); if (rc != U2FH_OK) { return rc; } rc = prepare_browserdata (chalb64, origin, REGISTER_TYP, bd, &bdlen); if (rc != U2FH_OK) return rc; sha256_buffer (bd, bdlen, data); prepare_origin (challenge, data + V2CHALLEN); /* FIXME: Support asynchronous usage, through a new u2fh_cmdflags flag. */ do { struct u2fdevice *dev; if (iterations++ > 15) { return U2FH_TIMEOUT_ERROR; } for (dev = devs->first; dev != NULL; dev = dev->next) { len = MAXDATASIZE; rc = send_apdu (devs, dev->id, U2F_REGISTER, data, sizeof (data), flags & U2FH_REQUEST_USER_PRESENCE ? 3 : 0, buf, &len); if (rc != U2FH_OK) { return rc; } else if (len != 2) { break; } } if (len != 2) { break; } Sleep (1000); } while ((flags & U2FH_REQUEST_USER_PRESENCE) && len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0); if (len != 2) { prepare_response (buf, len - 2, bd, response, response_len); return U2FH_OK; } return U2FH_TRANSPORT_ERROR; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int do_list_readers = 0; int do_list_drivers = 0; int do_list_rdrivers = 0; int do_list_files = 0; int do_send_apdu = 0; int do_print_atr = 0; int do_print_serial = 0; int do_print_name = 0; int action_count = 0; const char *opt_driver = NULL; sc_context_param_t ctx_param; setbuf(stderr, NULL); setbuf(stdout, NULL); while (1) { c = getopt_long(argc, argv, "nlfr:vs:DRc:aw", options, &long_optind); if (c == -1) break; if (c == '?') print_usage_and_die(app_name, options, option_help); switch (c) { case 'l': do_list_readers = 1; action_count++; break; case 'D': do_list_drivers = 1; action_count++; break; case 'R': do_list_rdrivers = 1; action_count++; break; case 'f': do_list_files = 1; action_count++; break; case 's': opt_apdus = (char **) realloc(opt_apdus, (opt_apdu_count + 1) * sizeof(char *)); opt_apdus[opt_apdu_count] = optarg; do_send_apdu++; if (opt_apdu_count == 0) action_count++; opt_apdu_count++; break; case 'a': do_print_atr = 1; action_count++; break; case 'n': do_print_name = 1; action_count++; break; case 'r': opt_reader = atoi(optarg); break; case 'v': verbose++; break; case 'c': opt_driver = optarg; break; case 'w': opt_wait = 1; break; case OPT_SERIAL: do_print_serial = 1; action_count++; break; } } if (action_count == 0) print_usage_and_die(app_name, options, option_help); memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 0; ctx_param.app_name = app_name; r = sc_context_create(&ctx, &ctx_param); if (r) { fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } if (verbose > 1) ctx->debug = verbose-1; if (do_list_rdrivers) { if ((err = list_reader_drivers())) goto end; action_count--; } if (do_list_readers) { if ((err = list_readers())) goto end; action_count--; } if (do_list_drivers) { if ((err = list_drivers())) goto end; action_count--; } if (action_count <= 0) goto end; if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); err = 1; goto end; } } err = connect_card(ctx, &card, opt_reader, 0, opt_wait, verbose); if (err) goto end; if (do_print_atr) { if (verbose) { printf("Card ATR:\n"); hex_dump_asc(stdout, card->atr, card->atr_len, -1); } else { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':'); fprintf(stdout,"%s\n",tmp); } action_count--; } if (do_print_serial) { if (verbose) printf("Card serial number:"); print_serial(card); action_count--; } if (do_print_name) { if (verbose) printf("Card name: "); printf("%s\n", card->name); action_count--; } if (do_send_apdu) { if ((err = send_apdu())) goto end; action_count--; } if (do_list_files) { if ((err = list_files())) goto end; action_count--; } end: if (card) { sc_unlock(card); sc_disconnect_card(card, 0); } if (ctx) sc_release_context(ctx); return err; }
/** * u2fh_authenticate: * @devs: a device handle, from u2fh_devs_init() and u2fh_devs_discover(). * @challenge: string with JSON data containing the challenge. * @origin: U2F origin URL. * @response: pointer to output string with JSON data. * @flags: set of ORed #u2fh_cmdflags values. * * Perform the U2F Authenticate operation. * * Returns: On success %U2FH_OK (integer 0) is returned, and on errors * an #u2fh_rc error code. */ u2fh_rc u2fh_authenticate (u2fh_devs * devs, const char *challenge, const char *origin, char **response, u2fh_cmdflags flags) { unsigned char data[CHALLBINLEN + HOSIZE + MAXKHLEN + 1]; unsigned char buf[MAXDATASIZE]; char bd[2048]; size_t bdlen = sizeof (bd); size_t len; int rc; char chalb64[256]; size_t challen = sizeof (chalb64); char khb64[256]; size_t kh64len = sizeof (khb64); base64_decodestate b64; size_t khlen; int skip_devices[devs->num_devices]; int skipped = 0; int iterations = 0; memset (skip_devices, 0, sizeof (skip_devices)); rc = get_fixed_json_data (challenge, "challenge", chalb64, &challen); if (rc != U2FH_OK) return rc; rc = prepare_browserdata (chalb64, origin, AUTHENTICATE_TYP, bd, &bdlen); if (rc != U2FH_OK) return rc; sha256_buffer (bd, bdlen, data); prepare_origin (challenge, data + CHALLBINLEN); /* confusion between key_handle and keyHandle */ rc = get_fixed_json_data (challenge, "keyHandle", khb64, &kh64len); if (rc != U2FH_OK) return rc; base64_init_decodestate (&b64); khlen = base64_decode_block (khb64, kh64len, data + HOSIZE + CHALLBINLEN + 1, &b64); data[HOSIZE + CHALLBINLEN] = khlen; /* FIXME: Support asynchronous usage, through a new u2fh_cmdflags flag. */ do { int i; if (iterations++ > 15) { return U2FH_TIMEOUT_ERROR; } for (i = 0; i < devs->num_devices; i++) { unsigned char tmp_buf[MAXDATASIZE]; if (skip_devices[i] != 0) { continue; } if (!devs->devs[i].is_alive) { skipped++; skip_devices[i] = 1; continue; } len = MAXDATASIZE; rc = send_apdu (devs, i, U2F_AUTHENTICATE, data, HOSIZE + CHALLBINLEN + khlen + 1, flags & U2FH_REQUEST_USER_PRESENCE ? 3 : 7, tmp_buf, &len); if (rc != U2FH_OK) { return rc; } else if (len != 2) { memcpy (buf, tmp_buf, len); break; } else if (memcmp (tmp_buf, NOTSATISFIED, 2) != 0) { skipped++; skip_devices[i] = 2; continue; } memcpy (buf, tmp_buf, len); } if (len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0) { Sleep (1000); } } while ((flags & U2FH_REQUEST_USER_PRESENCE) && len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0); if (len == 2 && memcmp (buf, NOTSATISFIED, 2) != 0) { return U2FH_AUTHENTICATOR_ERROR; } if (len != 2) { prepare_response (buf, len - 2, bd, challenge, response); } return U2FH_OK; }
int main(int argc, char *argv[]) { init_signals(); if(init_terminal(&hContext,&hCard)) return -1; else { if(open_tunnel(&tunnel) !=-1) { int output_len; raw_packet packet; short sw = 0x9000 ; printf("SCARD host adapter is now ready to accept connections\n"); /* main loop */ while((output_len = utun_read(&tunnel, packet.raw, MTU)) >= 0) { LONG card_status = 0; int select_ret; BYTE *packet_ptr; if(output_len == 0) continue; select_ret = utun_select(&tunnel); /* send the last tun input to the card */ printf("send %d bytes\n",output_len); packet_ptr = packet.raw; do { unsigned char curr_len = output_len > 255 ? 255 : output_len; sw = send_apdu(hContext,hCard,packet_ptr,curr_len,&card_status,select_ret); if(SW1(sw) < 0x90) { printf("Error: %02x%02x\n",SW1(sw),SW2(sw)); break; } packet_ptr += curr_len; output_len -= curr_len; } while(output_len > 0); /* if there is something else to send, do it now */ if(select_ret>0) { memset(&packet,0,sizeof(raw_packet)); continue; } /* receive data from the card (and forward it to the tun) if needed */ while(SW2(sw)) { sw = recv_apdu(hContext,hCard,&tunnel,sw,&card_status); if(SW1(sw) < 0x90 ) { printf("Error: %02x%02x\n",SW1(sw),SW2(sw)); break; } } if(card_status) { check_terminal_status(hContext,hCard); } memset(&packet,0,sizeof(raw_packet)); } } } close_tunnel(&tunnel); release_terminal(&hContext,&hCard); return 0; }
int sendAdminES(int type, char* param1) { ODR out = getODROutputStream(); char *dbname = odr_strdup (out, databaseNames[0]); /* Type: 1=reindex, 2=truncate, 3=delete, 4=create, 5=import, 6=refresh, 7=commit */ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest ); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; Z_External *r; Odr_oid *oid; Z_ESAdminOriginPartToKeep *toKeep; Z_ESAdminOriginPartNotToKeep *notToKeep; printf ("Admin request\n"); fflush(stdout); oid = odr_oiddup(out, yaz_oid_extserv_admin); req->packageType = oid; req->packageName = "1.Extendedserveq"; /* Allocate the external */ r = req->taskSpecificParameters = (Z_External *) odr_malloc (out, sizeof(*r)); r->direct_reference = odr_oiddup(out,oid); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_ESAdmin; r->u.adminService = (Z_Admin *) odr_malloc(out, sizeof(*r->u.adminService)); r->u.adminService->which = Z_Admin_esRequest; r->u.adminService->u.esRequest = (Z_AdminEsRequest *) odr_malloc(out, sizeof(*r->u.adminService->u.esRequest)); toKeep = r->u.adminService->u.esRequest->toKeep = (Z_ESAdminOriginPartToKeep *) odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->toKeep)); toKeep->which=type; toKeep->databaseName = dbname; switch ( type ) { case Z_ESAdminOriginPartToKeep_reIndex: toKeep->u.reIndex=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_truncate: toKeep->u.truncate=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_drop: toKeep->u.drop=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_create: toKeep->u.create=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_import: toKeep->u.import = (Z_ImportParameters*) odr_malloc(out, sizeof(*toKeep->u.import)); toKeep->u.import->recordType=param1; /* Need to add additional setup of records here */ break; case Z_ESAdminOriginPartToKeep_refresh: toKeep->u.refresh=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_commit: toKeep->u.commit=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_shutdown: toKeep->u.commit=odr_nullval(); break; case Z_ESAdminOriginPartToKeep_start: toKeep->u.commit=odr_nullval(); break; default: /* Unknown admin service */ break; } notToKeep = r->u.adminService->u.esRequest->notToKeep = (Z_ESAdminOriginPartNotToKeep *) odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->notToKeep)); notToKeep->which=Z_ESAdminOriginPartNotToKeep_recordsWillFollow; notToKeep->u.recordsWillFollow=odr_nullval(); send_apdu(apdu); return 0; }
int cmd_adm_import(const char *arg) { char type_str[20], dir_str[1024], pattern_str[1024]; char *cp; char *sep = "/"; DIR *dir; struct dirent *ent; int chunk = 10; Z_APDU *apdu = 0; Z_Segment *segment = 0; ODR out = getODROutputStream(); if (arg && sscanf (arg, "%19s %1023s %1023s", type_str, dir_str, pattern_str) != 3) return 0; if (num_databaseNames != 1) return 0; dir = opendir(dir_str); if (!dir) return 0; sendAdminES(Z_ESAdminOriginPartToKeep_import, type_str); printf ("sent es request\n"); if ((cp=strrchr(dir_str, '/')) && cp[1] == 0) sep=""; while ((ent = readdir(dir))) { if (fnmatch (pattern_str, ent->d_name, 0) == 0) { char fname[1024]; struct stat status; FILE *inf; sprintf (fname, "%s%s%s", dir_str, sep, ent->d_name); stat (fname, &status); if (S_ISREG(status.st_mode) && (inf = fopen(fname, "r"))) { Z_NamePlusRecord *rec; Odr_oct *oct = (Odr_oct *) odr_malloc (out, sizeof(*oct)); if (!apdu) { apdu = zget_APDU(out, Z_APDU_segmentRequest); segment = apdu->u.segmentRequest; segment->segmentRecords = (Z_NamePlusRecord **) odr_malloc (out, chunk * sizeof(*segment->segmentRecords)); } rec = (Z_NamePlusRecord *) odr_malloc (out, sizeof(*rec)); rec->databaseName = 0; rec->which = Z_NamePlusRecord_intermediateFragment; rec->u.intermediateFragment = (Z_FragmentSyntax *) odr_malloc (out, sizeof(*rec->u.intermediateFragment)); rec->u.intermediateFragment->which = Z_FragmentSyntax_notExternallyTagged; rec->u.intermediateFragment->u.notExternallyTagged = oct; oct->len = oct->size = status.st_size; oct->buf = (unsigned char *) odr_malloc (out, oct->size); if (fread(oct->buf, 1, oct->size, inf) != oct->size) { printf("Incomplete read of file %s\n", fname); } if (fclose(inf)) { printf("Close failed for file %s\n", fname); } segment->segmentRecords[segment->num_segmentRecords++] = rec; if (segment->num_segmentRecords == chunk) { send_apdu (apdu); apdu = 0; } } } } if (apdu) send_apdu(apdu); apdu = zget_APDU(out, Z_APDU_segmentRequest); send_apdu (apdu); closedir(dir); return 2; }