Wrong usage of AES library? - c

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);

Related

Error sending APDU commands with Arduino. Change the module context

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);
}
}

Unable to compute a CMAC using Cygwin and OpenSSL

I want to compute a CMAC using OpenSSL. I found this question which helped me.
But I am encountering a problem with the following code:
#include <openssl/cmac.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
int i=0;
for (i=0; i<size-1; i++) {
printf("%02X ", buffer[i]);
}
printf("%02x\n", buffer[i]);
}
int main() {
size_t out_len;
unsigned char res[16];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
CMAC_CTX *cmac = CMAC_CTX_new();
CMAC_Init(cmac, mac_key, 16, EVP_aes_128_cbc(), NULL);
CMAC_Update(cmac, msg, sizeof(msg));
CMAC_Final(cmac, res, &out_len);
dispHex(res, sizeof(res));
return 0;
}
I compile it with gcc -o test_cmac test_cmac_openssl.c -L C:/OpenSSL-Win32 -llibeay32 -I C:/OpenSSL-Win32/include and it produces test_cmac.exe without problem.
but when I run it (./test_cmac.exe), nothing happens. It just prints an empty line and stops:
xxx#DESKTOP /cygdrive/e/
$ ./test_cmac.exe
xx#DESKTOP /cygdrive/e/
Even if I add printf("..."); before the CMAC computation it goes the same way.
What is strange is that the following program:
#include <openssl/hmac.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
int i=0;
for (i=0; i<size-1; i++) {
printf("%02X ", buffer[i]);
}
printf("%02X\n", buffer[i]);
}
int main() {
size_t out_len;
unsigned char res[32];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
HMAC_CTX hmac;
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, mac_key, 16, EVP_sha256(), NULL);
HMAC_Update(&hmac, msg, sizeof(msg));
HMAC_Final(&hmac, res, &out_len);
dispHex(res, sizeof(res));
return 0;
}
runs normally: after gcc -o test_hmac test_hmac_openssl.c -L C:/OpenSSL-Win32 -llibeay32 -I C:/OpenSSL-Win32/include and ./test_hmac.exe I get:
xxx#DESKTOP /cygdrive/e/
$ ./test_hmac.exe
...9A 21 F8 2D 60 84 6C 09 08 98 A5 1F 23 8C C8 8F C4 A9 0C C4 49 45 DA 10 B9 39 C0 93 C3 10 60 BE
xxx#DESKTOP /cygdrive/e/
So I'm a little confused... Why does it works with the HMAC primitive but not with the CMAC one? Does anybody already encountered this kind of problem?
I am using OpenSSL 32bit version: openssl version returns OpenSSL 1.0.2e 3 Dec 2015.
I also checked that C:\OpenSSL-Win32\ is declared in the PATH environment variable.
Looking at CMAC_Init, it appears initialization of the CMAC object is not performed because IMPL is NULL:
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t const EVP_CIPHER *cipher, ENGINE *IMPL)
if (!key && !cipher && !IMPL && keylen == 0) {
/* Not initialised */
if (ctx->nlast_block == -1)
return 0;
if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0;
memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(ctx->cctx));
ctx->nlast_block = 0;
return 1;
}
Why does it works with the HMAC primitive but not with the CMAC one? Does anybody already encountered this kind of problem?
I'm guessing most of the problems are due to mixing and matching compilers. Shining Light's Win32 OpenSSL use Microsoft's compiler, while you are using GCC. There's probably some mixing and matching of runtimes, too.
I'm kind of surprised the HMAC code worked as expected in the configuration. I guess you got lucky.
The following works for me, but there are some differences:
#include <openssl/evp.h>
#include <openssl/cmac.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
void dispHex(const unsigned char *buffer, unsigned int size) {
unsigned int i=0;
for (i=0; i<size; i++) {
printf("%02X ", buffer[i]);
}
printf("\n");
}
int main() {
int rc = 0;
size_t out_len = 0;
unsigned char res[EVP_MAX_MD_SIZE];
unsigned char mac_key[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
unsigned char msg[16] = { 0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01 ,0x02 ,0x03, 0x04, 0x05, 0x06, 0x07};
CMAC_CTX *cmac = CMAC_CTX_new();
assert(cmac != NULL);
rc = CMAC_Init(cmac, mac_key, sizeof(mac_key), EVP_aes_128_cbc(), NULL);
assert(rc == 1);
rc = CMAC_Update(cmac, msg, sizeof(msg));
assert(rc == 1);
rc = CMAC_Final(cmac, res, &out_len);
assert(rc == 1);
dispHex(res, out_len);
CMAC_CTX_free(cmac);
return 0;
}
The differences between your configuration and the one I used:
The same compiler is used for both OpenSSL and the test program
res is EVP_MAX_MD_SIZE in size
CMAC_Init uses sizeof(mac_key)
out_len is initialized
displayHex uses out_len, and not sizeof(res)
Using sizeof(res) will print the 16 bytes of the MAC, and then print 16 garbage characters because res is declared as unsigned char res[32]. I don't think you got that far, so keep it in mind.
The program produces the following result. I don't know if this is the corrected/expected result, but it produces a result and prints it:
$ ./test.exe
43 91 63 0E 47 4E 75 A6 2D 95 7A 04 1A E8 CC CC
OpenSSL does not support Cygwin-x64, so you will need to use i686 version of things. Also see Issue #4326: Failed to configure for Cygwin-x64 on the OpenSSL Bug Tracker.
Here's how to build OpenSSL under Cygwin-x64. OpenSSL's build script has a few bends, so you can't use config. You have to use Configure and call out the triplet. The bug tracker issue is still valid because config is supposed to get things right.
$ curl https://www.openssl.org/source/openssl-1.0.2f.tar.gz -o openssl-1.0.2f.tar.gz
...
$ tar -xzf openssl-1.0.2f.tar.gz
...
$ cd openssl-1.0.2f
Then:
$ export KERNEL_BITS=64
$ ./Configure Cygwin-x86_64 shared no-ssl2 no-ssl3 --openssldir="$HOME/ssl"
...
$ make depend
...
$ make
...
$ make install_sw
install_sw installs the headers in $OPENSSLDIR/include, and the libraries in $OPENSSLDIR/lib. It does not install the man pages.
You then compile and link with:
$ gcc -I "$HOME/ssl/include" test.c -o test.exe "$HOME/ssl/lib/libcrypto.a"
Linking against libcrypto.a means you avoid library path problems. Things will "just work" for you.

How to correctly convert TAG value to the right format so that to Verify HMAC?

I'm working on HMAC generation and verifying to check data integrity. I can correctly generate the MAC value but when sending it through socket to another program for verification, I faced with formatting mismatch. I appreciate your support. Thanks.
unsigned char* MAC(unsigned char* key,unsigned char* message)
{
unsigned char* result;
unsigned int result_len = 32;
int i;
result = (unsigned char*) malloc(sizeof(char) * result_len);
result = HMAC(EVP_sha256 (), key , strlen (key), message , strlen(message) , NULL, NULL);
return result;
}
int verifyMAC(unsigned char* key,unsigned char* message, unsigned char* receivedTag)
{
printf("\n\n ==================== MAC Verification ==================\n\n");
unsigned char* newHash; // newly generated hash value
unsigned int newHash_len = 32;
int i,flag=0;
newHash = (unsigned char*) malloc(sizeof(char) * newHash_len);
newHash = HMAC(EVP_sha256 (), key , strlen (key), message , strlen(message) , NULL, NULL);
for (i=0; i!=newHash_len; i++)
{
if (receivedTag[i]!=newHash[i])
{
printf("DATA MISMATCH: Found %02X instead of %02X at index %d!\n", newHash[i], receivedTag[i], i);
break;
}
}
if (i==newHash_len)
{
printf("MAC verified!\n");
flag = 1;
}
return flag;
}
int main(int argc, char *argv[])
{
unsigned char* key = "1234567890";
unsigned char* message = (unsigned char*) "hello world";
....
}
Console result:
Hashed data: E4 5F 60 72 61 7C CE 5E 06 A9 5B E4 81 C4 33 51 02 3D 99 23 35 99 EA C9 FD AF FC 95 81 42 62 9A
==================== MAC Verification ==================
DATA MISMATCH: Found E4 instead of 65 at index 0!
ERROR: data is modified
I thought this problem was somewhat interesting so I went through the trouble to recreate the scenario. Maybe this is not even right. But a simple case of what I thought the problem is:
void main(int argc, char *argv[])
{
//the original hash
unsigned char newHash[] = {0xE4, 0x5F, 0x60, 0x72, 0x61, 0x7C, 0xCE, 0x5E, 0x06, 0xA9, 0x5B, 0xE4, 0x81, 0xC4, 0x33, 0x51,
0x02, 0x3D, 0x99, 0x23, 0x35, 0x99, 0xEA, 0xC9, 0xFD, 0xAF, 0xFC, 0x95, 0x81, 0x42, 0x62, 0x9A};
//what I think is recieved from the socket
unsigned char* receivedTag = "e45f6072617cce5e06a95be481c43351023d99233599eac9fdaffc958142629a";
for (int i=0; i!=32; i++)
{
if (receivedTag[i]!=newHash[i])
{
printf("DATA MISMATCH: Found %02X instead of %02X at index %d!\n", newHash[i], receivedTag[i], i);
break;
}
}
return;
}
and the output was
DATA MISMATCH: Found E4 instead of 65 at index 0!
So, I thought the solution would be to just convert the Hex array to string just like it was received from the socket.
Maybe this is not the most elegant of ways to do things. But a solution None the less.
char* hexStringToCharString(unsigned char hash[], int length);
void main(int argc, char *argv[])
{
//the original hash
unsigned char newHash[] = {0xE4, 0x5F, 0x60, 0x72, 0x61, 0x7C, 0xCE, 0x5E, 0x06, 0xA9, 0x5B, 0xE4, 0x81, 0xC4, 0x33, 0x51,
0x02, 0x3D, 0x99, 0x23, 0x35, 0x99, 0xEA, 0xC9, 0xFD, 0xAF, 0xFC, 0x95, 0x81, 0x42, 0x62, 0x9A};
//what I think is recieved from the socket
unsigned char* receivedTag = "e45f6072617cce5e06a95be481c43351023d99233599eac9fdaffc958142629a";
char *newString = hexStringToCharString(newHash, 32);
for (int i=0; i!=strlen(newString); i++)
{
if (receivedTag[i]!=newString[i])
{
printf("DATA MISMATCH: Found %02X instead of %02X at index %d!\n", newHash[i], receivedTag[i], i);
break;
}
}
free(newString);
printf("Yay\n");
return;
}
char* hexStringToCharString(unsigned char hash[], int length){
char temp[3];
//need length*2 characters which is 64 plus one for null!
char *theString = (char *)malloc(sizeof(char)*((length*2)+1));
strcpy(theString, "");
for(int i=0;i<length;i++){
sprintf(temp, "%02x", hash[i]);
strcat(theString, temp);
}
return theString;
}
The output in this case
Yay
So, Maybe this is entirely wrong. But if you find this solution needs editing then comment below.

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.

Resources