static const bytestring_t* pcsc_last_atr(cardreader_t* cr) { pcsc_data_t* pcsc = cr->extra_data; DWORD state; DWORD protocol; BYTE pbAtr[MAX_ATR_SIZE]; DWORD atrlen=MAX_ATR_SIZE; char readername[MAX_READERNAME]; DWORD readernamelen=MAX_READERNAME; /*char *tmp;*/ pcsc->status = SCardStatus(pcsc->hcard, readername,&readernamelen, &state, &protocol, pbAtr,&atrlen); if (pcsc->status==SCARD_S_SUCCESS) { bytestring_assign_data(cr->atr,atrlen,pbAtr); /*tmp = bytestring_to_format("%D",cr->atr); log_printf(LOG_INFO,"ATR is %i bytes: %s",atrlen,tmp); free(tmp);*/ } else { bytestring_clear(cr->atr); log_printf(LOG_ERROR,"Failed to query card status: %s (error 0x%08x).", pcsc_stringify_error(pcsc->status), pcsc->status ); } return cr->atr; }
crypto_error_t crypto_mac(bytestring_t *dst, const bytestring_t *ctx, const bytestring_t *src) { unsigned u,v; unsigned char tmp[8]; unsigned char clr[8]; unsigned char alg; crypto_error_t retval; bytestring_t *padded_src; DES_key_schedule key_schedule; DES_key_schedule key_schedule2; bytestring_get_element(&alg,ctx,0); if (alg==CRYPTO_ALG_ISO9797_M3) { padded_src = bytestring_new(8); retval = crypto_pad(padded_src,ctx,src); if (retval!=CRYPTO_OK) { bytestring_free(padded_src); return retval; } memset(tmp,0,8); memcpy(&key_schedule,ctx->data+KS_HEADER_SIZE,DES_KS_SIZE); memcpy(&key_schedule2,ctx->data+KS_HEADER_SIZE+DES_KS_SIZE,DES_KS_SIZE); for (u=0; u<bytestring_get_size(padded_src)/8; u++) { for (v=0; v<8; v++) clr[v]=padded_src->data[u*8+v]^tmp[v]; DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule, DES_ENCRYPT); } memcpy(clr,tmp,8); DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule2, DES_DECRYPT); memcpy(clr,tmp,8); DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule, DES_ENCRYPT); bytestring_assign_data(dst,8,tmp); bytestring_free(padded_src); } else return CRYPTO_ERROR_UNKNOWN_ALGORITHM; return CRYPTO_OK; }
int bytestring_substr(const bytestring_t *src, unsigned pos, unsigned len, bytestring_t* dst) { if (pos>src->len) { bytestring_clear(dst); return 1; } if (len==BYTESTRING_NPOS || pos+len>src->len) len = src->len-pos; return bytestring_assign_data(dst,len,src->data+pos); }
/* static void update_dump(update_t *update, FILE* out) { update_item_t *item = update->items; fprintf(out,"Update version %s\n",update->update_version); while (item) { update_item_dump(item,out); item = item->next; } } */ static int update_load(update_t *update, const char *data, unsigned data_len) { char *ptr = (char *)data; unsigned ptr_len = data_len; char *data_end; char *value; update_item_t *item = NULL; bytestring_t *signature; bytestring_t *source; int signature_verified; #define fail_update(m) { log_printf(LOG_ERROR,"Failed to parse update information: %s",m); \ goto update_new_fail; } if ((value = tokenizer_get_record(&ptr,&ptr_len))==NULL) fail_update("Missing header"); if (strcmp(value,"header")!=0) fail_update("Incorrect header"); g_free(value); if ((value = tokenizer_get_field("version",&ptr,&ptr_len))==NULL) fail_update("missing version"); update->update_version = value; /* don't free value */ data_end = ptr; while ((value = tokenizer_get_record(&ptr,&ptr_len))!=NULL) { if (strcmp(value,"update")!=0) break; g_free(value); item = update_item_new(); if ((value = tokenizer_get_field("file",&ptr,&ptr_len))==NULL) fail_update("missing file name"); item->file = value; if ((value = tokenizer_get_field("url",&ptr,&ptr_len))==NULL) fail_update("missing url"); item->url = value; if ((value = tokenizer_get_field("required_version",&ptr,&ptr_len))==NULL) fail_update("missing required version"); item->required_version = value; if ((value = tokenizer_get_field("digest",&ptr,&ptr_len))==NULL) fail_update("missing digest"); bytestring_assign_digit_string(&item->digest,value); g_free(value); if (bytestring_get_size(&item->digest)!=SHA256_DIGEST_LENGTH) fail_update("incorrect digest length"); if ((value = tokenizer_get_field("message",&ptr,&ptr_len))==NULL) fail_update("missing message"); item->message = value; update->item_count++; item->next = update->items; update->items = item; item = NULL; data_end = ptr; } if (value==NULL) fail_update("missing section"); if (strcmp(value,"authentication")!=0) fail_update("missing authentication"); g_free(value); if ((value = tokenizer_get_field("signature",&ptr,&ptr_len))==NULL) fail_update("missing signature"); signature = bytestring_new(8); bytestring_assign_digit_string(signature,value); g_free(value); log_printf(LOG_DEBUG,"Verifying %d bit signature on update information (%d bytes), representing %d files.", bytestring_get_size(signature)*8,data_end-data,update->item_count); source = bytestring_new(8); bytestring_assign_data(source,data_end-data,(const unsigned char *)data); if (verify_signature(source,signature)==0) { log_printf(LOG_ERROR,"Signature verification failed on update information."); signature_verified = 0; update_clear(update); } else { log_printf(LOG_INFO,"Signature verification succeeded on update information."); signature_verified = 1; } bytestring_free(signature); bytestring_free(source); return signature_verified; update_new_fail: if (value) g_free(value); if (update) update_clear(update); if (item) update_item_free(item); return 0; }
int bytestring_copy(bytestring_t *bs, const bytestring_t *src) { return bytestring_assign_data(bs,src->len,src->data); }
bytestring_t* bytestring_duplicate(const bytestring_t *bs) { bytestring_t* res=bytestring_new(); bytestring_assign_data(res,bs->len,bs->data); return res; }
static unsigned short pcsc_transmit(cardreader_t* cr, const bytestring_t* command, bytestring_t* result) { pcsc_data_t* pcsc = cr->extra_data; BYTE REC_DAT[MAX_PCSC_READ_LENGTH]; DWORD REC_LEN=MAX_PCSC_READ_LENGTH; unsigned short SW; if (cr->protocol==SCARD_PROTOCOL_T0) { pcsc->status = SCardTransmit(pcsc->hcard,SCARD_PCI_T0, bytestring_get_data(command), bytestring_get_size(command), SCARD_PCI_NULL, REC_DAT,&REC_LEN); } else if (cr->protocol==SCARD_PROTOCOL_T1) { pcsc->status = SCardTransmit(pcsc->hcard,SCARD_PCI_T1, bytestring_get_data(command), bytestring_get_size(command), SCARD_PCI_NULL, REC_DAT,&REC_LEN); } else { log_printf(LOG_ERROR,"Unknown smartcard protocol: %i",cr->protocol); return CARDPEEK_ERROR_SW; } if (pcsc->status!=SCARD_S_SUCCESS) { log_printf(LOG_ERROR,"Failed to transmit command to card: %s (error 0x%08x).", pcsc_stringify_error(pcsc->status), pcsc->status ); return CARDPEEK_ERROR_SW; } if (REC_LEN>=2) { bytestring_assign_data(result,REC_LEN-2,REC_DAT); SW = (REC_DAT[REC_LEN-2]<<8)|REC_DAT[REC_LEN-1]; } else if (REC_LEN==1) { bytestring_clear(result); SW = REC_DAT[0]; } else { log_printf(LOG_ERROR,"Transmited %i bytes to the card (%s), but recieved a response of length %i, without any status word included.", bytestring_get_size(command), pcsc_stringify_protocol(cr->protocol), REC_LEN); return CARDPEEK_ERROR_SW; } return SW; }