We trying to interface with a PIV smart card on iphone. We have the necessary libraries loaded and can send commands. Using a combination of get data and get response commands we are able to retrieve all the relevant certificates from the smart card. We are now trying to send general authenticate command to sign some data but receiving 6A80 . We are chaining this command. The first part of chain executes successfully with return code 90 00 but second command gives 6a80.
Our card description says
We are hashing our data with SHA1 256 and padding it with pkcs v 1.5 padding . We have also encoded the hash with DER encoding. But either ways (with or without der encoding) we receive 6a80 error. Here is our code,
// gets data signed from the smart card
-(void) signData:(unsigned char *)origdata:(int) origdatalen:(int) key_reference :(int) key_size:(int) hash_reference
{
bool debug=false;
unsigned char * encodedandpadded;
unsigned char * digest;
NSMutableString* cplc = [[NSMutableString alloc]init];
int derHeaderLen=0;
int keyModulo=0;
int digestLen=0;
if (key_size==2048){
keyModulo=256;
} else if (key_size==1024){
keyModulo=128;
}
unsigned char * derHeader=nil;
switch (hash_reference){
case SHA1:
derHeaderLen=15;
derHeader=(unsigned char *) calloc(derHeaderLen,sizeof(unsigned char));
derHeader[0]=0x30;
derHeader[1]=0x21;
derHeader[2]=0x30;
derHeader[3]=0x09;
derHeader[4]=0x06;
derHeader[5]=0x05;
derHeader[6]=0x2b;
derHeader[7]=0x0e;
derHeader[8]=0x03;
derHeader[9]=0x02;
derHeader[10]=0x1a;
derHeader[11]=0x05;
derHeader[12]=0x00;
derHeader[13]=0x04;
derHeader[14]=0x14;
digestLen=CC_SHA1_DIGEST_LENGTH;
digest = (unsigned char*) calloc(digestLen,sizeof(unsigned char));
CC_SHA1(origdata, origdatalen,digest);
break;
case SHA256:
derHeaderLen=19;
derHeader=(unsigned char *) calloc(derHeaderLen,sizeof(unsigned char));
derHeader[0]=0x30;
derHeader[1]=0x31;
derHeader[2]=0x30;
derHeader[3]=0x09;
derHeader[4]=0x06;
derHeader[5]=0x09;
derHeader[6]=0x60;
derHeader[7]=0x86;
derHeader[8]=0x48;
derHeader[9]=0x01;
derHeader[10]=0x65;
derHeader[11]=0x03;
derHeader[12]=0x04;
derHeader[13]=0x02;
derHeader[14]=0x01;
derHeader[15]=0x05;
derHeader[16]=0x00;
derHeader[17]=0x04;
derHeader[18]=0x20;
digestLen=CC_SHA256_DIGEST_LENGTH;
digest = (unsigned char*) calloc(digestLen,sizeof(unsigned char));
CC_SHA256(origdata, origdatalen,digest);
break;
case SHA512:
derHeaderLen=19;
derHeader=(unsigned char *) calloc(derHeaderLen,sizeof(unsigned char));
derHeader[0]=0x30;
derHeader[1]=0x51;
derHeader[2]=0x30;
derHeader[3]=0x09;
derHeader[4]=0x06;
derHeader[5]=0x09;
derHeader[6]=0x60;
derHeader[7]=0x86;
derHeader[8]=0x48;
derHeader[9]=0x01;
derHeader[10]=0x65;
derHeader[11]=0x03;
derHeader[12]=0x04;
derHeader[13]=0x02;
derHeader[14]=0x03;
derHeader[15]=0x05;
derHeader[16]=0x00;
derHeader[17]=0x04;
derHeader[18]=0x40;
break;
default:
break;
}
// {0x00, 0x01, PS, 0x00, T},
bool derEncoding=true;
int psLen;
int finalLen;
if (derEncoding){
psLen=keyModulo-3-(derHeaderLen+digestLen);
finalLen=3+psLen+derHeaderLen+digestLen;
} else {
psLen=keyModulo-3-(digestLen);
finalLen=3+psLen+digestLen;
}
encodedandpadded =(unsigned char *) calloc(finalLen,sizeof(unsigned char));
int count=0;
encodedandpadded[count++]=0x00;
encodedandpadded[count++]=0x01;
for (int i=0;i<psLen;i++){
encodedandpadded[count++]=0xFF;
}
encodedandpadded[count++]=0x00;
if (derEncoding) {
for (int i=0;i<derHeaderLen;i++){
encodedandpadded[count++]=derHeader[i];
}
}
for (int i=0;i<digestLen;i++){
encodedandpadded[count++]=digest[i];
}
if (debug){
[cplc appendString:[NSString stringWithFormat:@" psLen=%d derHeaderLen=%d digestlent=%d finalLen=%d count=%d",psLen,derHeaderLen,digestLen,finalLen,count]];
for (int i=0;i<finalLen;i++){
[cplc appendString:[NSString stringWithFormat:@" %02x ",encodedandpadded[i]]];
}
[self printData:cplc];
}
[self generalAuthenticate:encodedandpadded :256];
}
- (void) generalAuthenticate:(unsigned char *) paddeddata:(int) paddeddatalen{
bool debug=true;
PBSmartcardStatus result;
// the first command in the chain , we will send first 128 bytes in this command
unsigned char dat[] = {0x10, 0x87, 0x07, 0x9C};
NSMutableData * prepCommand1 = [[NSMutableData alloc] initWithBytes:dat length:4];
unsigned char dat2[] = {0x86,0x7C,0x84};
[prepCommand1 appendBytes:dat2 length:3];
unsigned char dat3[] = {0x82,0x00,0x81,0x80};
[prepCommand1 appendBytes:dat3 length:4];
unsigned char * part1 =(unsigned char *) calloc((paddeddatalen/2),sizeof(unsigned char));
unsigned char * part2=(unsigned char *) calloc((paddeddatalen/2),sizeof(unsigned char));
int count=0;
for(int i=0;i<(paddeddatalen/2);i++){
part1[i]=paddeddata[count++];
}
[prepCommand1 appendBytes:part1 length:(paddeddatalen/2)];
for(int i=0;i<(paddeddatalen/2);i++){
part2[i]=paddeddata[count++];
}
//the second command in the chain, we will send rest of 128 bytes in this command
unsigned char dat4[]={0x00, 0x87, 0x07, 0x9C, 0x80};
NSMutableData * prepCommand2 = [[NSMutableData alloc] initWithBytes:dat4 length:5];
[prepCommand2 appendBytes:part2 length:(paddeddatalen/2)];
unsigned char dat5[]={0x00};
[prepCommand2 appendBytes:dat5 length:1];
//unsigned char get_cplc_command[] = {0x10, 0x87, 0x07, 0x9C,(macOut.length+4),0x82,0x00,0x81,macOut.length};
NSMutableString* cplc = [[NSMutableString alloc]init];
unsigned char received_data[255] = {0};
unsigned short received_data_length;
// on input received_data_length holds the size of the receive buffer.
received_data_length = sizeof(received_data);
unsigned char * prepCmd1=(unsigned char *)[prepCommand1 bytes];
int prepCmd1Len=[prepCommand1 length];
// send the command APDU and get the response from the card.
if (debug){
[cplc appendString:[NSString stringWithFormat:@"Length %d %d",prepCmd1Len,(paddeddatalen/2), count]];
[self printData:cplc];
for (int i=0;i<prepCmd1Len;i++){
[cplc appendString:[NSString stringWithFormat:@"%02x",prepCmd1[i]]];
}
[self printData:cplc];
}
result = [smartcard transmit:prepCmd1
withCommandLength:prepCmd1Len
andResponseBuffer:received_data
andResponseLength:&received_data_length];
LOG(@"transmit = %d", result);
// check if the command was succefully sent to the card
// if(result != PBSmartcardStatusSuccess)
// {
// goto done;
// }
if (debug){
[cplc appendString:[NSString stringWithFormat:@"Response bytes from card for general authenticate command %02X %02X length %d\n",received_data[received_data_length-2],received_data[received_data_length-1],received_data_length]];
[self printData:cplc];
}
unsigned char received_data_2[300] = {0};
unsigned short received_data_length_2;
// on input received_data_length holds the size of the receive buffer.
received_data_length_2 = sizeof(received_data_2);
unsigned char * prepCmd2=(unsigned char *)[prepCommand2 bytes];
int prepCmd2Len=[prepCommand2 length];
// send the command APDU and get the response from the card.
if (debug){
[cplc appendString:[NSString stringWithFormat:@"Length %d",prepCmd2Len]];
[self printData:cplc];
for (int i=0;i<prepCmd2Len;i++){
[cplc appendString:[NSString stringWithFormat:@"%02x",prepCmd2[i]]];
}
[self printData:cplc];
}
result = [smartcard transmit:prepCmd2
withCommandLength:prepCmd2Len
andResponseBuffer:received_data_2
andResponseLength:&received_data_length_2];
if (debug){
[cplc appendString:[NSString stringWithFormat:@"Response bytes from card for general authenticate command %02X %02X length %d\n",received_data_2[received_data_length_2-2],received_data_2[received_data_length_2-1],received_data_length_2]];
[self printData:cplc];
}
}
Send only the hash value in the command data field instead of the PKCS#1 padded hash value. The card will likely do the padding as part of the signature operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With