static int verify_signature(const bytestring_t *source, const bytestring_t *signature) { static const char *pubkey_value = CARDPEEK_PUBLIC_KEY; BIO *bp; RSA* pubkey; int retval; unsigned char digest[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; if ((bp = BIO_new_mem_buf((void*)pubkey_value,strlen(pubkey_value)))==NULL) { log_printf(LOG_ERROR,"Failed to build BIO for memory object"); return 0; } if ((pubkey = PEM_read_bio_RSA_PUBKEY(bp, NULL, NULL, NULL))==NULL) { log_printf(LOG_ERROR,"Failed to load public in memory"); BIO_free(bp); return 0; } BIO_free(bp); SHA256_Init(&sha256); SHA256_Update(&sha256,bytestring_get_data(source),bytestring_get_size(source)); SHA256_Final(digest,&sha256); retval= RSA_verify(NID_sha256, digest, SHA256_DIGEST_LENGTH, (unsigned char *)bytestring_get_data(signature), bytestring_get_size(signature), pubkey); if (retval==0) { log_printf(LOG_ERROR, "Signature verification failed for update information (%s)\n", ERR_error_string(ERR_get_error(),NULL)); } RSA_free(pubkey); return retval; }
static int update_filter_files(update_t *update) { unsigned char digest[SHA256_DIGEST_LENGTH]; char* filename; update_item_t **prev = &(update->items); update_item_t *item = update->items; int excluded = 0; while (item) { filename = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,NULL); if (sha256sum(filename,digest)!=0) { if (memcmp(digest,bytestring_get_data(&item->digest),SHA256_DIGEST_LENGTH)!=0) { log_printf(LOG_INFO,"File %s needs to be updated.",filename); prev = &(item->next); item = item->next; } else { /* log_printf(LOG_DEBUG,"No update needed for %s",filename); */ *prev = item->next; update_item_free(item); excluded++; item = *prev; update->item_count--; } } else { log_printf(LOG_INFO,"File %s is proposed for creation in current script updates.",filename); prev = &(item->next); item = item->next; } g_free(filename); } return excluded; }
int cardpeek_update_perform(void) { const char* cardpeek_update_file = path_config_get_string(PATH_CONFIG_FILE_CARDPEEK_UPDATE); a_string_t *contents; update_t *update; int remove; update_item_t *item; time_t now = time(NULL); int updated = 0; char *url = NULL; char *local_file; char *local_dnld; unsigned char digest[SHA256_DIGEST_LENGTH]; a_string_t *url_request; unsigned first_update; first_update = (unsigned)luax_variable_get_integer("cardpeek.updates.first_update"); /* STEP 1: get cardpeek.update file */ url=luax_variable_get_strdup("cardpeek.updates.url"); if (url==NULL) url = g_strdup(DEFAULT_UPDATE_URL); log_printf(LOG_INFO,"Fetching '%s'",url); url_request = a_strnew(NULL); a_sprintf(url_request,"%s?u=%x&v=%s",url,first_update,VERSION); if (http_download(a_strval(url_request),cardpeek_update_file)==0) { g_free(url); return 0; } g_free(url); a_strfree(url_request); /* STEP 2: parse file */ if ((contents=file_get_contents(cardpeek_update_file))==NULL) { log_printf(LOG_ERROR,"failed to read update file information."); unlink(cardpeek_update_file); return 0; } update = update_new(); if ((update_load(update,a_strval(contents),a_strlen(contents)))==0) { unlink(cardpeek_update_file); a_strfree(contents); update_free(update); return 0; } a_strfree(contents); /* log_printf(LOG_DEBUG,"Updates correctly loaded from '%s'",cardpeek_update_file); */ if ((remove = update_filter_version(update,VERSION))>0) log_printf(LOG_WARNING,"%d updates will not be installed because they require a newer version of Cardpeek."); remove = update_filter_files(update); if (update->item_count) log_printf(LOG_INFO,"A total of %d files will be updated, %d files are kept unchanged.",update->item_count,remove); else log_printf(LOG_INFO,"No files will be updated, %d files are kept unchanged.",remove); item = update->items; while (item) { local_dnld = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,".download"); local_file = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,NULL); if (http_download(item->url,local_dnld)!=0) { if (sha256sum(local_dnld,digest)) { if (memcmp(digest,bytestring_get_data(&item->digest),SHA256_DIGEST_LENGTH)==0) { unlink(local_file); if (rename(local_dnld,local_file)==0) { log_printf(LOG_INFO,"Successfuly updated %s", local_file); updated++; } else { log_printf(LOG_ERROR,"Failed to copy %s to %s: %s", local_dnld, local_file, strerror(errno)); } } else { log_printf(LOG_WARNING,"File %s was not updated: authentication failed.",local_file); } } unlink(local_dnld); } g_free(local_dnld); g_free(local_file); item = item->next; } if (updated == update->item_count) { luax_variable_set_integer("cardpeek.updates.next_update",(int)(now+7*(24*3600))); luax_config_table_save(); } unlink(cardpeek_update_file); update_free(update); /* STEP 3: finish */ return 1; }
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; }