Error sending APDU commands with Arduino. Change the module context - c

I try to send APDU commands using Arduino Uno and PN532. PN532 finds the EMV card, but when I try to send the command I get:
Status code indicates error
The response dump shows this result (the first 8 bytes):
0x00 0x00 0xFF 0x03 0xFD 0xD5 0x41 0x27
The command I send(SELECT PPSE):
00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
According to the documentation, the code 0x27 (8 byte) means:
This command is not acceptable due to the current context of the PN532 (Initiator vs. Target, unknown target number, Target not in the good state, ...)
How do I change the context to the one I need for sending commands?
My code:
void loop(void) {
uint8_t success;
uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t uidLength;
// EMV card
bool apdusuccess;
uint8_t apdu[255];
uint8_t berBuffer[255];
uint8_t berLength = 255;
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, & uidLength);
if (success && uid && (uidLength == 4)) {
uint8_t apdu[] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
apdusuccess = nfc.inDataExchange(apdu, sizeof(apdu), berBuffer, &berLength);
Serial.print("APDU Success: ");
Serial.println(apdusuccess);
}
}

I found a solution and it worked with inListPassiveTarget:
void loop(void) {
uint8_t success;
uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};
uint8_t uidLength;
// EMV card
bool apdusuccess;
uint8_t apdu[255];
uint8_t berBuffer[255];
uint8_t berLength = 255;
success = nfc.inListPassiveTarget();
if (success) {
uint8_t apdu[] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
apdusuccess = nfc.inDataExchange(apdu, sizeof(apdu), berBuffer, &berLength);
Serial.print("APDU Success: ");
Serial.println(apdusuccess);
}
}

Related

How to enable 16 bit color in ili9486?

Wanna use 16 bit color, changed register 3A to 0x55 and when I’m trying to fill out my screen with red color 0xf800, nothing happens. When I use 18 bit color 0x3A = 0x66 red color is correct
UPD: Here is my piece of code that I used for 18 bit and how I rewrite it to use with 16 bit
typedef struct {
uint8_t cmd;
uint8_t data[16];
uint8_t databytes;
} lcd_init_cmd_t;
// 18 bit color
DRAM_ATTR static const lcd_init_cmd_t ili_init_cmds_18b[]={
/* SW reset */
{0x01, {0}, 0},
/* Sleep out, also SW reset */
{0x11, {0}, 0},
{0xc0, {0x0D, 0x0D}, 2},
/* 18 bit - 0x66, 16 bit 0x55 */
{0x3A, {0x66}, 1},
/* Power Control 3 (For Normal Mode) */
{0xC2, {0x44}, 1},
/* VCOM Control */
{0xC5, {0,0,0,0}, 4},
/* Positive gamma correction */
{0xE0, {0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0X98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00}, 15},
/* Negative gamma correction */
{0xE1, {0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00}, 15},
/* Display Inversion OFF */
{0x20, {0}, 0},
/* Memory access contorl, MX=MY=0, MV=1, ML=0, BGR=1, MH=0 */
{0x36, {0x28}, 1},
/* Display on */
{0x29, {0}, 0},
};
// 16 bit color
DRAM_ATTR static const lcd_init_cmd_t ili_init_cmds_16b[] = {
{0x01, {0}, 0},
{0x28, {0}, 0},
{0x11, {0}, 0},
{0xC0, {0x0D, 0x0D}, 2},
{0xc1, {0x43, 0x00}, 2},
{0xc2, {0x00}, 1},
{0xC5, {0x00, 0x48}, 2},
{0xB6, {0x00, 0x01, 0x3B}, 3},
{0xE0, {0x0F, 0x24, 0x1C, 0x0A, 0x0F, 0x08, 0x43, 0x88, 0x32, 0x0F, 0x10, 0x06, 0x0F, 0x07, 0x00}, 15},
{0xE1, {0x0F, 0x38, 0x30, 0x09, 0x0F, 0x0F, 0x4E, 0x77, 0x3C, 0x07, 0x10, 0x05, 0x23, 0x1B, 0x00}, 15},
{0x20, {0x00}, 1},
{0x36, {0xE8}, 1},
{0x3A, {0x55}, 1},
{0x2A, {0x00, 0x00, 0x01, 0xDF}, 4},
{0x2B, {0x00, 0x00, 0x01, 0x3F}, 4},
{0x29, {0x00}, 0}
}; // 16-bit color
void lcd_init(){
ili_init_cmds = ili_init_cmds_18b; // <- pseudocode
//Send all the commands
uint8_t len = sizeof(ili_init_cmds)/sizeof(ili_init_cmds[0]);
for (uint8_t i=0; i<len; i++){
lcd_cmd(spi, ili_init_cmds[i].cmd);
lcd_data(spi, ili_init_cmds[i].data, ili_init_cmds[i].databytes & 0x1F);
if (ili_init_cmds[i].cmd == 0x01 || ili_init_cmds[i].cmd == 0x11 || ili_init_cmds[i].cmd == 0x28 || ili_init_cmds[i].cmd == 0x29){
vTaskDelay(100 / portTICK_RATE_MS);
}
}
}
void fill_screen(){
uint16_t color = 0xf800;
uint8_t GRAM_BUFF[1440] = {0}; // width 480 pixels * 3 bytes of color
uint16_t i;
// for 18 bit
for(i=0; i<1440; i+=3){
GRAM_BUFF[i] = RGB_R(color);
GRAM_BUFF[i+1] = RGB_G(color);
GRAM_BUFF[i+2] = RGB_B(color);
}
// for 16 bit
for (i=0; i< 1440; i+=2){
GRAM_BUFF[i] = (uint8_t)(color >> 8);
GRAM_BUFF[i+1] = (uint8_t)(color);
}
for (i=0; i<HEIGHT; i+=3){ // HEIGHT = 320pixels
send_lines(spi, i, GRAM_BUFF);
}

Manual HMACSHA1 calculation differs from openssl results

I am trying to implement HMACSHA1 by Hand, to check if our serviceprovider or we calculate a wrong HMAC for a Support-Ticket (a SOAP call, hence the xml content).
The problem is, I stick to NIST Specification for HMACs and get a different result by Hand and when using openssl HMAC functions.
The following code prints:
B92674DCBA96F2DA93F7043071B931F5F2583FBD
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D
while the result by openssl is the same we get in our application - so I assume, on the basis that openssl is so commonly used, that my result is wrong - but where is my error?
This is the spec I refer to:
http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <string.h>
#define byte unsigned char
#define IPAD 0x36
#define OPAD 0x5c
#define DIGESTSIZE 20
int main () {
byte *derivedKey = (byte[DIGESTSIZE]) {0x42,0xA9,0x78,0x90,0xFC,0xE5,0x16,0x8E,0x58,0x12,0x2F,0xF1,0xBA,0x32,0x5F,0x09,0x88,0x94,0x02,0x91};
byte *content = "<ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\"><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"soap\"></ec:InclusiveNamespaces></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"></ds:SignatureMethod><ds:Reference URI=\"#TS-B183A13FEB0189143115136776276601\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"wsse soap\"></ec:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></ds:DigestMethod><ds:DigestValue>rXJdGuDqoRrUJxuGiA1eyAozifk=</ds:DigestValue></ds:Reference></ds:SignedInfo>";
byte *oPadKey = malloc(DIGESTSIZE);
byte *iPadKey = malloc(DIGESTSIZE);
int i;
for(i=0;i<DIGESTSIZE;i++){
iPadKey[i]=derivedKey[i]^IPAD;
oPadKey[i]=derivedKey[i]^OPAD;
}
byte *rOpInput= malloc(strlen(content)+DIGESTSIZE);
//concat iPad and content
memcpy(rOpInput, iPadKey, DIGESTSIZE);
memcpy(rOpInput+DIGESTSIZE,content,strlen(content));
//SHA1 (iPad||content) gives the rightmost 20 bytes of the final SHA1 Input
byte *rOp=malloc(DIGESTSIZE); // H(iPad||content)
SHA1(rOpInput,strlen(content)+DIGESTSIZE,rOp);
free(rOpInput);
byte *finalInput = malloc(2*DIGESTSIZE); //oPad||H(iPad||content)
//concat oPad and H(ipad||content)
memcpy(finalInput, oPadKey,DIGESTSIZE);
memcpy(finalInput+DIGESTSIZE,rOp,DIGESTSIZE);
free(rOp);
free(oPadKey);
free(iPadKey);
//SHA1(oPad||H(iPad||content))
byte *hmac = malloc(DIGESTSIZE);
SHA1(finalInput,40,hmac);
free(finalInput);
//print calculated HMAC as HEX
for(i=0;i<DIGESTSIZE;i++){
printf("%02X", (hmac[i] & 0xFF ));
}
printf("\n");
//verify with openssl HMAC
byte *result = HMAC(EVP_sha1(), derivedKey, DIGESTSIZE, content, strlen(content), NULL, NULL);
for(i=0;i<DIGESTSIZE;i++){
printf("%02X", (result[i] & 0xFF ));
}
printf("\n");
return 0;
}
The bug is simple. The ipad and opad need to be (input) block size in length, not the length of the digest output. I.e. they must be 512 bits (64 bytes) for SHA-1, not 20.
I.e.
#define INPUT_BLOCK_SIZE 64
byte derivedKey[64] = {0x42,0xA9,0x78,0x90,0xFC,0xE5,0x16,0x8E,0x58,0x12,
0x2F,0xF1,0xBA,0x32,0x5F,0x09,0x88,0x94,0x02,0x91};
// null-padded on the right
and then change the DIGESTSIZE to INPUT_BLOCK_SIZE for wherever the length of ipad, opad is needed.
Result:
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D
From Wikipedia
K' is another secret key, derived from the original key K (by padding K to the right with extra zeroes to the input block size of the hash function, or by hashing K if it is longer than that block size)
(emphasis mine).
P.S. It would be better to use the SHA1_Init/Update/Final, as then lots of copying would be skipped. You can also avoid allocating memory for the ipad and opad separately by first calculating ipad and after it has been used, then xorring in place by 0x6a to get the opad.
Please refer this. You can easily calculate the hash
https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA1.pdf
#define IPAD 0x36
#define OPAD 0x5c
#define DIGESTSIZE 20
#define INPUT_BLOCK_SIZE 64
#define byte unsigned char
static byte mykey[64];
int main () {
int i;
byte mykey[INPUT_BLOCK_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
byte content[] = {0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x6D, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x6B, 0x65, 0x79, 0x6C, 0x65, 0x6E, 0x3D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x6C, 0x65, 0x6E };
byte k0_ipad_text[sizeof(content) + INPUT_BLOCK_SIZE];
byte hmac[DIGESTSIZE];
byte k0_opad_hash[INPUT_BLOCK_SIZE + DIGESTSIZE];
/*
* K0 is mykey as size is 0x40 = 64 bytes
*/
byte *oPadKey = malloc(INPUT_BLOCK_SIZE);
byte *iPadKey = malloc(INPUT_BLOCK_SIZE);
memset(oPadKey, 0, INPUT_BLOCK_SIZE);
memset(iPadKey, 0, INPUT_BLOCK_SIZE);
for(i=0;i<INPUT_BLOCK_SIZE;i++){
iPadKey[i]=mykey[i]^IPAD;
oPadKey[i]=mykey[i]^OPAD;
}
printf("\n iPad key = ");
for(i=0;i<INPUT_BLOCK_SIZE;i++){
printf("%02x ", iPadKey[i]);
}
printf("\n oPad key = ");
for(i=0;i<INPUT_BLOCK_SIZE;i++){
printf("%02x ", oPadKey[i]);
}
//Key^ipad)||text)
memcpy(k0_ipad_text, iPadKey, INPUT_BLOCK_SIZE);
memcpy(k0_ipad_text + INPUT_BLOCK_SIZE, content, sizeof(content));
SHA1(k0_ipad_text, INPUT_BLOCK_SIZE + sizeof(content), hmac);
#if 0
printf("\n hmac = ");
for(i=0;i<DIGESTSIZE;i++){
printf("%02x ", hmac[i]);
}
#endif
memcpy(k0_opad_hash, oPadKey, INPUT_BLOCK_SIZE);
memcpy(k0_opad_hash + INPUT_BLOCK_SIZE, hmac, DIGESTSIZE);
SHA1(k0_opad_hash, INPUT_BLOCK_SIZE + DIGESTSIZE, hmac);
printf("\n hmac \n");
for(i=0;i<DIGESTSIZE;i++){
printf("%02x", hmac[i]);
}
printf("\n");
//verify with openssl HMAC
byte *result = HMAC(EVP_sha1(), mykey, INPUT_BLOCK_SIZE, content, sizeof(content), NULL, NULL);
for(i=0;i<DIGESTSIZE;i++){
printf("%02X", (result[i] & 0xFF ));
}
printf("\n");
return 0;
}

How to translate pem public key into openssl RSA* structure

Suppose i have to public pem key like this
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk
O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2
eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1
QWPdspTBKcxeFbccDwIDAQAB
-----END PUBLIC KEY-----
And i want to use openssl
int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,RSA *rsa, int padding). How can i translate the pem key to RSA *rsa structure?
FYI: I can't use BIO because i just want to transplant openssl into a bootloader which doesn't have a UNIX filesystem. The only way i can do is translate public key into a C array.
I can't use BIO because i just want to transplant openssl into a bootloader which doesn't have a UNIX filesystem
I think you can still use a BIO, it just has to be a memory BIO, and not a file BIO.
If you can't use a memory BIO either, then I'm not sure you can use OpenSSL here.
How to translate pem public key into openssl RSA* structure
Use PEM_read_PUBKEY or PEM_read_bio_PUBKEY (or one of the *_PUBKEY routines). They return an EVP_PKEY. Then, use EVP_PKEY_get1_RSA to convert it to a RSA.
Something like:
static const char key[] = "-----BEGIN PUBLIC KEY-----\n"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk\n"
"O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2\n"
"eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1\n"
"QWPdspTBKcxeFbccDwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key));
ASSERT(bio != NULL);
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
ASSERT(pkey != NULL);
int type = EVP_PKEY_get_type(pkey);
ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2);
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
ASSERT(rsa != NULL);
...
EVP_PKEY_free(pkey);
RSA_free(rsa);
BIO_free(bio);
And here's the helper you need. EVP_PKEY_get_type is not part of the library:
int EVP_PKEY_get_type(EVP_PKEY *pkey)
{
ASSERT(pkey);
if (!pkey)
return EVP_PKEY_NONE;
return EVP_PKEY_type(pkey->type);
}
Related, you can also use the non-PEM version, which is the ASN.1/DER encoding of the key. This will allow you to save some size in the image. Then, you would use d2i_PUBKEY_bio to read the key.
Converting from PEM to ASN.1/DER will save about 110 bytes:
$ ls -al pubkey.*
-rw-r--r-- 1 user staff 162 Jun 5 00:36 pubkey.der
-rw-r--r-- 1 user staff 272 Jun 5 00:52 pubkey.pem
To convert the PEM encoded public key to ASN.1/DER, follow these steps. First, copy the key to the clipboard. Second, pipe it into openssl pkey with a tool like pbpaste on OS X or xclip on Linux:
$ pbpaste | openssl pkey -pubin -inform PEM -out pubkey.der -outform DER
Then, inspect the public key:
$ dumpasn1 pubkey.der
0 159: SEQUENCE {
3 13: SEQUENCE {
5 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
16 0: NULL
: }
18 141: BIT STRING, encapsulates {
22 137: SEQUENCE {
25 129: INTEGER
: 00 BB BD BA 9A 8C 3C 38 A3 A8 09 CB C5 2D 98 86
: E4 72 99 E4 3B 72 B0 73 8A AC 12 74 99 A7 F4 D1
: F9 F4 22 EB 61 7B F5 11 D6 9B 02 8E B4 59 B0 B5
: E5 11 80 B6 E3 EC 3F D6 1A E3 4B 18 E7 DA FF 6B
: EC 7B 71 B6 78 79 C7 97 90 81 F2 BB 91 5F D7 C1
: 97 F2 A0 C0 25 6B D8 96 84 B9 49 BA E9 B0 50 78
: FE 57 78 1A 2D 75 1E 1C BD 7D FC B8 F6 22 BC 20
: DD 3E 32 75 41 63 DD B2 94 C1 29 CC 5E 15 B7 1C
: 0F
157 3: INTEGER 65537
: }
: }
: }
Finally, do something like:
int main(int argc, char* argv[])
{
UNUSED(argc), UNUSED(argv);
static const unsigned char key[] = {
0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xbd, 0xba,
0x9a, 0x8c, 0x3c, 0x38, 0xa3, 0xa8, 0x09, 0xcb, 0xc5, 0x2d, 0x98, 0x86, 0xe4, 0x72, 0x99, 0xe4,
0x3b, 0x72, 0xb0, 0x73, 0x8a, 0xac, 0x12, 0x74, 0x99, 0xa7, 0xf4, 0xd1, 0xf9, 0xf4, 0x22, 0xeb,
0x61, 0x7b, 0xf5, 0x11, 0xd6, 0x9b, 0x02, 0x8e, 0xb4, 0x59, 0xb0, 0xb5, 0xe5, 0x11, 0x80, 0xb6,
0xe3, 0xec, 0x3f, 0xd6, 0x1a, 0xe3, 0x4b, 0x18, 0xe7, 0xda, 0xff, 0x6b, 0xec, 0x7b, 0x71, 0xb6,
0x78, 0x79, 0xc7, 0x97, 0x90, 0x81, 0xf2, 0xbb, 0x91, 0x5f, 0xd7, 0xc1, 0x97, 0xf2, 0xa0, 0xc0,
0x25, 0x6b, 0xd8, 0x96, 0x84, 0xb9, 0x49, 0xba, 0xe9, 0xb0, 0x50, 0x78, 0xfe, 0x57, 0x78, 0x1a,
0x2d, 0x75, 0x1e, 0x1c, 0xbd, 0x7d, 0xfc, 0xb8, 0xf6, 0x22, 0xbc, 0x20, 0xdd, 0x3e, 0x32, 0x75,
0x41, 0x63, 0xdd, 0xb2, 0x94, 0xc1, 0x29, 0xcc, 0x5e, 0x15, 0xb7, 0x1c, 0x0f, 0x02, 0x03, 0x01,
0x00, 0x01
};
BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key));
ASSERT(bio != NULL);
EVP_PKEY* pkey = d2i_PUBKEY_bio(bio, NULL);
ASSERT(pkey != NULL);
int type = EVP_PKEY_get_type(pkey);
ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2);
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
ASSERT(rsa != NULL);
// ...
EVP_PKEY_free(pkey);
RSA_free(rsa);
BIO_free(bio);
return 0;
}
To load the RSA pub key from the pem file
int loadKey(string &fileName, RSA ** pubkey)
{
FILE *fp = fopen(fileName.data(), "r");
if (fp < 0){
printf("%s\n","Invalide certificate file name");
return -1;
}
*pubkey = PEM_read_RSA_PUBKEY(fp,pubkey, NULL, NULL);
if(*pubkey == NULL){
printf("%s\n","error reading Public key");
return -1;
}
To verify the signature
int verify_signature(vector<uint8_t> &msg, vector<uint8_t> &sig, RSA* pkey)
{
/* Returned to caller */
int result = -1;
vector <uint8_t> pDecrypted(PACKAGE_SIGNATURE_SIZE);
result = RSA_public_decrypt(PACKAGE_SIGNATURE_SIZE, sig.data(), pDecrypted.data(), pkey, RSA_NO_PADDING);
if (result == -1)
{
printf("RSA_public_decrypt failed with error %s\n", ERR_error_string(ERR_get_error(), NULL));
// goto prog_end;
}
/* verify the data */
result = RSA_verify_PKCS1_PSS(pkey,msg.data() , EVP_sha256(), pDecrypted.data(), -2 /* salt length recovered from signature*/);
if (result == 1)
{
printf("Signature verification successfull!\n");
}
else
{
printf("RSA_verify_PKCS1_PSS failed with error %s\n", ERR_error_string(ERR_get_error(), NULL));
}
return !!result;
}

Encryption Difference between processor and coprocessor

i am trying to handle a problem using encryption and decryption algorithms, i used below program to test my requirements and i realised an odd problem.
i am using polarssl for my encryption and decryption needs.
This program works well when i compile it with icc compiler on intel processor using this command :(aes.c from polarssl)
icc Deneme.c aes.c -o deneme
Output:
Encryption result, encrypted value:
11 22 7 86 a2 d3 ed 95 b9 14 c0 57 f7 af 5f dc 93 66 77 68 44 12 9f 1b 72 6a ea 51 b8 f7 1d a4
Decryption result, plain array:
a2 d8 69 9c 77 73 c7 5e 1d 3b 83 26 6e 2f 35 30 9d f0 f2 e5 0 0 0 0 0 0 0 0 0 0 0 0
When i tried to compile with icc compiler but this time run on microprocessor; encryption result are not true.
command:
icc -mmic Deneme.c aes.c -o deneme
Output:
Encryption result, encrypted value:
4a 4b 4c 32 e0 ef fb 22 4a 67 7e 2c 3a fe 36 65 4b 5b 18 9 63 28 a1 c4 8e b7 e4 c6 33 a7 36 7c
Decryption result, plain array:
a2 d8 69 9c 77 73 c7 5e 1d 3b 83 26 6e 2f 35 30 9d f0 f2 e5 0 0 0 0 0 0 0 0 0 0 0 0
What makes my encrypted values different??
here is full program
#include <stdio.h>
#include <polarssl/aes.h>
const int ENCRIPTION = 1;
const int DECRIPTION = 0;
void printByteArray(unsigned char * array, int length) {
int i = 0;
for (i = 0; i < length; i++) {
printf("%x ", array[i]);
}
printf("\n");
}
void encrypt() {
unsigned char o[32];
unsigned char key[16] = { 0x03, 0xC9, 0xD8, 0xE6, 0x01, 0xA5, 0x05,
0x9F, 0x11, 0xBF, 0x44, 0x9D, 0xF9, 0x55, 0x18, 0xED
};
unsigned char iv[16] = { 0x03, 0xB5, 0x62, 0x57, 0xC8, 0x69, 0x22, 0x89,
0xF4, 0x96, 0x2B, 0x05, 0x44, 0x2B, 0xD0, 0xA7
};
unsigned char plain[32]=
{
0xA2, 0xD8, 0x69, 0x9C, 0x77, 0x73, 0xC7, 0x5E, 0x1D, 0x3B, 0x83, 0x26, 0x6E, 0x2F, 0x35, 0x30,
0x9D, 0xF0, 0xF2, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
aes_context aesCtx;
aes_setkey_enc(&aesCtx, key, 128);
aes_crypt_cbc(&aesCtx, ENCRIPTION, 32, iv, plain, o);
printf("Encryption result, encrypted value:\n");
printByteArray(o, 32);
}
decrypt() {
unsigned char o[32];
unsigned char key[16] = { 0x03, 0xC9, 0xD8, 0xE6, 0x01, 0xA5, 0x05,
0x9F, 0x11, 0xBF, 0x44, 0x9D, 0xF9, 0x55, 0x18, 0xED
};
unsigned char iv[16] = { 0x03, 0xB5, 0x62, 0x57, 0xC8, 0x69, 0x22, 0x89,
0xF4, 0x96, 0x2B, 0x05, 0x44, 0x2B, 0xD0, 0xA7
};
unsigned char encryptedValue[32] = { 0x11, 0x22, 0x07, 0x86,
0xA2, 0xD3, 0xED, 0x95, 0xB9, 0x14, 0xC0, 0x57, 0xF7, 0xAF, 0x5F,
0xDC, 0x93, 0x66, 0x77, 0x68, 0x44, 0x12, 0x9F, 0x1B, 0x72, 0x6A,
0xEA, 0x51, 0xB8, 0xF7, 0x1D, 0xA4 };
aes_context aesCtx;
aes_setkey_dec(&aesCtx, key, 128);
aes_crypt_cbc(&aesCtx, DECRIPTION, 32, iv, encryptedValue,
o);
printf("Decryption result, plain array:\n");
printByteArray(o, 32);
}
int main() {
encrypt();
decrypt();
}
icc by default uses optimization for performance on your code and this limits correctness. However, you can use -O0 option to compile without any optimization on both and compare the results.
-mmic generates instruction set for MIC ie Xeon phi architecture.

Wrong usage of AES library?

I want to use a memory-saving AES-128 implementation. I found the implementation of Karl Malbrain.
I am using it with the code below:
void encryptUboot(void){
//uint8_t key[AES_KEY_LENGTH] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
uint8_t key[AES_KEY_LENGTH] = {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x21, 0x21};
uint8_t keyschedule[AES_KEY_LENGTH * AES_ROUNDS] = {0x00};
uint8_t message[5] = "test";
uint8_t cipher[16] = {0x00};
uint8_t i;
if(debug) printf("\n[D] Running AES-128 encryption\n");
aes_expand_key(key, keyschedule);
aes_encrypt(message, keyschedule, cipher);
printf("message: %s | cipher: ", message);
for(i = 0; i<AES_KEY_LENGTH; i++){
printf("%02x ", cipher[i]);
}
}
This outputs:
[D] Running AES-128 encryption
message: test | cipher: 2d 58 45 71 24 43 f5 cd 69 6d 07 b3 a3 29 de 8f
However, using the code from here (zip file) with the code below ...
// AES usage example
// compile as: gcc main.c aes.h aes.c
#include <stdlib.h>
#include "aes.h"
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
unsigned char key[KEY_128] = {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x21, 0x21};
unsigned char ptext[16] = "test";
unsigned char ctext[16];
unsigned char decptext[16];
unsigned int i = 0;
aes_ctx_t *ctx;
init_aes();
ctx = aes_alloc_ctx(key, sizeof(key));
if(!ctx) {
perror("aes_alloc_ctx");
return EXIT_FAILURE;
}
aes_encrypt(ctx, ptext, ctext);
for(i=0;i<KEY_128;i++) printf("%02x ", ctext[i]);
puts("");
aes_decrypt(ctx, ctext, decptext);
puts(decptext);
aes_free_ctx(ctx);
return EXIT_SUCCESS;
}
.. it outputs a different cipher:
1f 53 3f 60 15 d5 ab 16 69 b6 c6 3b 9e 77 2f 0c
test
Do you see my mistake? Obviously, I am instrumenting these libraries in a wrong way.
Thanks,
-P
Although I couldn't find the exact function you use in Malbrains code, I believe your problem lies in the difference in array length for message. The algorithm encrypts blocks of 128 bit (16 bytes), but you only allocated 5 bytes.
uint8_t message[5] = "test";
vs
unsigned char ptext[16] = "test";
Try initialising it with exactly the same data.
uint8_t message[16];
memset(message, 0, sizeof(message));
memcpy(message, "test", 5);

Resources