void DAPLUGCALL Daplug_computeDiversifiedKeys(Keyset keys, Keyset *div_keys, char *div){ char enc_key[GP_KEY_SIZE*2+1]="", mac_key[GP_KEY_SIZE*2+1]="", dek_key[GP_KEY_SIZE*2+1]=""; char div_enc_key[GP_KEY_SIZE*2+1]="", div_mac_key[GP_KEY_SIZE*2+1]="", div_dek_key[GP_KEY_SIZE*2+1]=""; if(strlen(div)==0 || strlen(div)!=16*2 || !isHexInput(div)){ fprintf(stderr,"\nDaplug_ComputeDiversifiedKeys(): Wrong value for diversifier !\n"); return; } bytesToStr(keys.key[0],GP_KEY_SIZE,enc_key); bytesToStr(keys.key[1],GP_KEY_SIZE,mac_key); bytesToStr(keys.key[2],GP_KEY_SIZE,dek_key); computeDiversifiedKey(enc_key,div,div_enc_key); computeDiversifiedKey(mac_key,div,div_mac_key); computeDiversifiedKey(dek_key,div,div_dek_key); strToBytes(div_enc_key,div_keys->key[0]); strToBytes(div_mac_key,div_keys->key[1]); strToBytes(div_dek_key,div_keys->key[2]); }
int DAPLUGCALL keyboard_addHotpCode(Keyboard *k, int flag, int digitsNb, int keysetVersion, int counterFileId, char *div){ char flag_s[1*2+1]="", digitsNb_s[1*2+1]="", ksv_s[1*2+1]="", cfi_s[2*2+1]="", tmp[21*2+1]=""; sprintf(flag_s,"%02X",flag); sprintf(digitsNb_s,"%02X",digitsNb); sprintf(ksv_s,"%02X",keysetVersion); sprintf(cfi_s,"%04X",counterFileId); strcat(tmp,flag_s); strcat(tmp,digitsNb_s); strcat(tmp,ksv_s); if(strcmp(div,"")){ if(isHexInput(div) && strlen(div)/2 == 16){ strcat(tmp,div); }else{ fprintf(stderr,"\nkeyboard_addHotpCode(): Invalid diversifier !\n"); return 0; } } strcat(tmp,cfi_s); int len_tmp = strlen(tmp)/2; char len_tmp_s[1*2+1]=""; sprintf(len_tmp_s,"%02X",len_tmp); int added_len = strlen("50")+strlen(len_tmp_s)+strlen(tmp); added_len = added_len/2; if(k->currentContentSize+added_len <= MAX_KB_CONTENT_SIZE){ strcat(k->content,"50"); strcat(k->content,len_tmp_s); strcat(k->content,tmp); k->currentContentSize = k->currentContentSize+added_len; }else{ fprintf(stderr,"\nkeyboard_addReturn(): Keyboard maximum content size exceeded !\n"); return 0; } return 1; }
void DAPLUGCALL Daplug_selectPath(DaplugDongle *dpd, char *path){ if(!isHexInput(path) || strlen(path)%4 != 0){ fprintf(stderr,"\nselectFile(): Wrong path : %s !\n",path); return; } int i = 0, j = 0, id; while(j<strlen(path)/4){ char *tmp = NULL; sscanf(tmp = str_sub(path,i,i+3),"%04X",&id); free(tmp); tmp = NULL; Daplug_selectFile(dpd,id); i = i+4; j++; } }
void DAPLUGCALL Daplug_writeData(DaplugDongle *dpd, int offset, char* data_to_write){ Apdu update_binary_apdu; char update_binary_apdu_str[APDU_CMD_MAXLEN*2+1]=""; char pos[2*2+1]=""; char last_part_len_str[2*2+1]=""; int p = offset, length = strlen(data_to_write)/2, last_part_len = length % MAX_REAL_DATA_SIZE; sprintf(last_part_len_str,"%02X",last_part_len); if(length%2 !=0 || length <=0 || length + p > MAX_FS_FILE_SIZE || !isHexInput(data_to_write)){ fprintf(stderr,"\nwriteData(): Wrong data !\n"); return; } sprintf(pos,"%04X",p); //We write parts of MAX_FS_DATA_RW_SIZE bytes : EF = FF - 8 - 8 (data max len - possible mac - possible pad when enc) int write_nb = 0; if(length % MAX_REAL_DATA_SIZE== 0) write_nb = length/MAX_REAL_DATA_SIZE; else write_nb = (int)length/MAX_REAL_DATA_SIZE+1; char part[MAX_REAL_DATA_SIZE*2+1]=""; int i = 0; while(write_nb > 0){ strcpy(update_binary_apdu_str,""); strcat(update_binary_apdu_str,"80d6"); strcat(update_binary_apdu_str,pos); if(write_nb > 1 || length % MAX_REAL_DATA_SIZE == 0){ strcat(update_binary_apdu_str,"EF"); char *tmp = NULL; strcpy(part,tmp = str_sub(data_to_write,i,i+MAX_REAL_DATA_SIZE*2-1)); free(tmp); tmp = NULL; }else{ char *tmp = NULL; strcat(update_binary_apdu_str,last_part_len_str); strcpy(part,tmp = str_sub(data_to_write,i,i+(length%MAX_REAL_DATA_SIZE)*2-1)); free(tmp); tmp = NULL; } strcat(update_binary_apdu_str,part); //Set to apdu cde setApduCmd(update_binary_apdu_str,&update_binary_apdu); //exchange it exchangeApdu(dpd,&update_binary_apdu); if(strcmp(update_binary_apdu.sw_str,"9000")){ fprintf(stderr,"\nwriteData(): Write failure !\n"); return; } sscanf(pos,"%04X",&p); p = p + MAX_REAL_DATA_SIZE; sprintf(pos,"%04X",p); i = i+MAX_REAL_DATA_SIZE*2; write_nb--; } }
void DAPLUGCALL Daplug_authenticate(DaplugDongle *dpd, Keyset keys, int mode, char *div, char *chlg){ Byte hostChallenge[8]; char counter[2*2+1] = "", cardChallenge[6*2+1] = "", returnedCardCryptogram[8*2+1]="", computedCardCryptogram[8*2+1]="", hostCryptogram[8*2+1] = "", s_hostChallenge[8*2+1]="", temp[APDU_CMD_MAXLEN*2+1]=""; Apdu initialize_update, external_authenticate; //close any sc previously opened Daplug_deAuthenticate(dpd); if(!strcmp(chlg,"")){ //generate host challenge generateChallenge(hostChallenge,8); bytesToStr(hostChallenge,8,s_hostChallenge); }else{ if(strlen(chlg)!=8*2 || !isHexInput(chlg)){ fprintf(stderr,"\nDaplug_authenticate(): Wrong value for challenge !\n"); return; } strncpy(s_hostChallenge,chlg,16); s_hostChallenge[16]='\0'; } //Keyset version char version[1*2+1]=""; sprintf(version,"%02X",keys.version); //Any diversifier? if(strlen(div) != 0){ if(strlen(div)!=16*2 || !isHexInput(div)){ fprintf(stderr,"\nDaplug_authenticate(): Wrong value for diversifier !\n"); return; } } if(strlen(div) == 0){ //initialize update without diversifier strcat(temp,"8050"); strcat(temp,version); strcat(temp,"0008"); strcat(temp,s_hostChallenge); setApduCmd(temp,&initialize_update); }else{ //diversified initialize update strcat(temp,"D050"); strcat(temp,version); strcat(temp,"1018"); strcat(temp,s_hostChallenge); strcat(temp,div); setApduCmd(temp,&initialize_update); } //exchange exchangeApdu(dpd,&initialize_update); if(strcmp(initialize_update.sw_str,"9000")){ fprintf(stderr,"\nauthenticate(): initialize update error ! sw = %s\n", initialize_update.sw_str); return; } //extract data returned by the card char *tmp = NULL; strcpy(counter,tmp = str_sub(initialize_update.r_str, 24, 27)); free(tmp); tmp = NULL; strcpy(cardChallenge,tmp = str_sub(initialize_update.r_str, 28, 39)); free(tmp); tmp = NULL; strcpy(returnedCardCryptogram,tmp = str_sub(initialize_update.r_str, 40, 55)); free(tmp); tmp = NULL; //compute session keys & update dpd char enc_key[GP_KEY_SIZE*2+1]="", mac_key[GP_KEY_SIZE*2+1]="", dek_key[GP_KEY_SIZE*2+1]=""; bytesToStr(keys.key[0],GP_KEY_SIZE,enc_key); bytesToStr(keys.key[1],GP_KEY_SIZE,mac_key); bytesToStr(keys.key[2],GP_KEY_SIZE,dek_key); //session s-enc key computeSessionKey(counter,"0182",enc_key,dpd->s_enc_key); //session s-enc key computeSessionKey(counter,"0183",enc_key,dpd->r_enc_key); //session c-mac key computeSessionKey(counter, "0101", mac_key, dpd->c_mac_key); //session r-mac key computeSessionKey(counter, "0102", mac_key, dpd->r_mac_key); //session dek key. In case of need it will be used. (to form "put key" command for example) computeSessionKey(counter,"0181", dek_key, dpd->s_dek_key); //compute card cryptogram computeCardCryptogram(s_hostChallenge,cardChallenge,counter,dpd->s_enc_key,computedCardCryptogram); //check card cryptogram if(!checkCardCryptogram(returnedCardCryptogram,computedCardCryptogram)){ fprintf(stderr,"\nauthenticate(): Card Cryptogram verification failed !\n"); return; } else{ //compute data that an external Daplug_authenticate apdu needs computeHostCryptogram(s_hostChallenge, cardChallenge, counter, dpd->s_enc_key, hostCryptogram); //mode char sec_l[1*2+1]=""; sprintf(sec_l,"%02X",mode); //external Daplug_authenticate strcpy(temp,""), strcat(temp,"8082"); strcat(temp,sec_l); strcat(temp,"0008"); strcat(temp,hostCryptogram); setApduCmd(temp,&external_authenticate); //exchange exchangeApdu(dpd,&external_authenticate); if(strcmp(external_authenticate.sw_str,"9000")){ fprintf(stderr,"\nauthenticate(): external Daplug_authenticate error ! sw = %s\n", external_authenticate.sw_str); return; } } fprintf(stderr,"\nauthenticate() : Successful authentication !\n"); //update dpd strcpy(dpd->r_mac,dpd->c_mac); dpd->securityLevel = mode; dpd->session_opened = 1; }
static void encdec(DaplugDongle *dpd, int enc, int keyVersion, int keyID, int mode, char *iv, char *div1, char *div2, char *inData, char *outData){ Apdu enc_dec_apdu; char enc_dec_apdu_str[APDU_CMD_MAXLEN*2+1]=""; char enc_s[1*2+1]="", mode_s[1*2+1]="", kv_s[1*2+1]="", kid_s[1*2+1]=""; sprintf(enc_s,"%02X",enc); sprintf(mode_s,"%02X",mode); sprintf(kv_s,"%02X",keyVersion); sprintf(kid_s,"%02X",keyID); if(enc != 0x01 && enc != 0x02){ fprintf(stderr,"\nencdec(): Wrong value for enc !\n"); return; } char iv_[8*2+1]=""; if(strlen(iv)==0){ strcpy(iv_,"0000000000000000"); }else{ strcpy(iv_,iv); } if(!isHexInput(iv_) || strlen(iv_)!=8*2){ fprintf(stderr,"\nencdec(): Wrong IV !\n"); return; } if(mode & ENC_ECB && mode & ENC_CBC){ fprintf(stderr,"\nencdec(): Wrong mode value !\n"); return; } char div1_[16*2+1]=""; int lc = 10; //kv, kid, iv if(mode & ENC_1_DIV || mode & ENC_2_DIV){ if(strlen(div1)==0 || strlen(div1)!=16*2 || !isHexInput(div1)){ fprintf(stderr,"\nencdec(): Wrong value for the first diversifier !\n"); return; }else{ strcpy(div1_,div1); lc = lc + 16; } } char div2_[16*2+1]=""; if(mode & ENC_2_DIV){ if(strlen(div2)==0 || strlen(div2)!=16*2 || !isHexInput(div2)){ fprintf(stderr,"\nencdec(): Wrong value for the second diversifier !\n"); return; }else{ strcpy(div2_,div2); lc = lc + 16; } } char data_[(MAX_REAL_DATA_SIZE-10)*2+1]=""; if(!isHexInput(inData)){ fprintf(stderr,"\nencdec(): Wrong value for input data !\n"); return; } if(strlen(inData) == 0 || strlen(inData)%(8*2) != 0 || lc+strlen(inData)/2 > MAX_REAL_DATA_SIZE){ fprintf(stderr,"\nencdec(): Wrong length for input data !\n"); return; } strcpy(data_,inData); lc = lc + strlen(data_)/2; char lc_s[1*2+1]=""; sprintf(lc_s,"%02X",lc); //Form the apdu strcat(enc_dec_apdu_str,"D020"); strcat(enc_dec_apdu_str,enc_s); strcat(enc_dec_apdu_str,mode_s); strcat(enc_dec_apdu_str,lc_s); strcat(enc_dec_apdu_str,kv_s); strcat(enc_dec_apdu_str,kid_s); strcat(enc_dec_apdu_str,iv_); strcat(enc_dec_apdu_str,div1_); strcat(enc_dec_apdu_str,div2_); strcat(enc_dec_apdu_str,data_); //Set to apdu cde setApduCmd(enc_dec_apdu_str,&enc_dec_apdu); //exchange it exchangeApdu(dpd,&enc_dec_apdu); if(strcmp(enc_dec_apdu.sw_str,"9000")){ if(enc == 1){ fprintf(stderr,"\nencdec(): Cannot encrypt data !\n"); } if(enc == 2){ fprintf(stderr,"\nencdec(): Cannot decrypt data !\n"); } return; } strcpy(outData,enc_dec_apdu.r_str); }
static void hmac_sha1(DaplugDongle *dpd, int keyVersion, int options, char *div1, char *div2, char* inData, char* outData){ Apdu hmac_apdu; char hmac_apdu_str[APDU_CMD_MAXLEN*2+1]=""; char kv_s[1*2+1]=""; sprintf(kv_s,"%02X",keyVersion); char opt_s[1*2+1]=""; sprintf(opt_s,"%02X",options); int lc = 0; char div1_[16*2+1]=""; if(options & OTP_1_DIV || options & OTP_2_DIV){ if(strlen(div1)==0 || strlen(div1)!=16*2 || !isHexInput(div1)){ fprintf(stderr,"\nhmac_sha1(): Wrong value for the first diversifier !\n"); return; }else{ strcpy(div1_,div1); lc = lc + 16; } } char div2_[16*2+1]=""; if(options & OTP_2_DIV){ if(strlen(div2)==0 || strlen(div2)!=16*2 || !isHexInput(div2)){ fprintf(stderr,"\nhmac_sha1(): Wrong value for the second diversifier !\n"); return; }else{ strcpy(div2_,div2); lc = lc + 16; } } char data_[MAX_REAL_DATA_SIZE*2+1]=""; if(!isHexInput(inData)){ fprintf(stderr,"\nhmac_sha1(): Wrong value for input data !\n"); return; } if(lc+strlen(inData)/2 > MAX_REAL_DATA_SIZE){ //for Daplug_totp, data can be null => we exclude condition strlen(inData) = 0 fprintf(stderr,"\nhmac_sha1(): Wrong length for input data !\n"); return; } strcpy(data_,inData); lc = lc + strlen(data_)/2; char lc_s[1*2+1]=""; sprintf(lc_s,"%02X",lc); //Form the apdu strcat(hmac_apdu_str,"D022"); strcat(hmac_apdu_str,kv_s); strcat(hmac_apdu_str,opt_s); strcat(hmac_apdu_str,lc_s); strcat(hmac_apdu_str,div1_); strcat(hmac_apdu_str,div2_); strcat(hmac_apdu_str,data_); //Set to apdu cde setApduCmd(hmac_apdu_str,&hmac_apdu); //exchange it exchangeApdu(dpd,&hmac_apdu); if(strcmp(hmac_apdu.sw_str,"9000")){ fprintf(stderr,"\nhmac_sha1(): Cannot sign data !\n"); return; } strcpy(outData,hmac_apdu.r_str); }