SGX calculating HMAC inside enclave - hmac

I'm trying to calculate an HMAC with SHA512 inside an Intel SGX enclave.
I got the code to work but receive the wrong results. I have an example that uses static pre-defined key and nonce from which the HMAC is calculated, but when verifying the received result it does not match the correct one.
Apparantely there are two different variants to calculate the HMAC (according to this enter link description here, I've tried both.
Here is the function from the enclave:
int calculateHMAC(uint8_t *key, uint8_t *nonce, uint8_t *res_hmac) {
IppsHMACState *ctx;
IppStatus status;
int psize = 0;
//VARIANT 1
status = ippsHMAC_GetSize(&psize);
if (status == ippStsNullPtrErr)
return 1;
ctx = (IppsHMACState*) malloc(psize);
status = ippsHMAC_Init(key, 16, ctx, ippHashAlg_SHA512);
if (status != ippStsNoErr)
return 1;
status = ippsHMAC_Update(nonce, 16, ctx);
if (status != ippStsNoErr)
return 1;
uint8_t hmac[64];
memset(hmac, '\0', 64);
status = ippsHMAC_Final(hmac, 64, ctx);
if (status != ippStsNoErr)
return 1;
memcpy(res_hmac, hmac, 64);
//VARIANT 2
// uint8_t test_hmac[HMAC_LENGTH];
// status = ippsHMAC_Message(nonce, 16, key, 16, test_hmac, 64, ippHashAlg_SHA512);
// if (status != ippStsNoErr)
// return 1;
// memcpy(res_hmac, test_hmac, 64);
return 0;
}
Here is the UPDATED call:
uint8_t ba_nonce[16] = {
0x7d, 0x93, 0x09, 0x9f, 0x7f, 0xed, 0x16, 0x21,
0x58, 0x36, 0xf7, 0xba, 0xd4, 0xdb, 0x0e, 0x48
};
uint8_t ba_key[16] = {
0xa5, 0xb1, 0x15, 0x53, 0x6d, 0x5b, 0xf3, 0x50,
0xc5, 0xb0, 0xfa, 0x6f, 0x69, 0x24, 0x2f, 0x18
};
uint8_t t_hmac[64];
memset(t_hmac, '\0', 64);
int error = calculateHMAC(ba_key, ba_nonce, t_hmac);
I don't see what I'm doing wrong!?
This will result in
7d2f2e3d57c84a58945b9016fb37e2df03afdde313c9d79c31ec1e6612d6d6b20456a8fcf799ef74d16f60c7f283e621400004422885f33fb3d2bb7ae7a1daa3
which is wrong according to this calculator here

Your issue is strtol(). It expects a string. In C a string is an arbitrary sequence of characters terminated with a NULL-byte. However, it is provided a pointer to an array of size two where the last entry is not NULL. Therefore, strtol() also analysis the bytes behind your tmp array.
Since, tmp is stored on the stack we can not assume that the subsequent bytes are always the same for different invocations. Thus, you get random results.
Solution: Either, you increase the size of tmp and add a NULL byte in the last place or - and this is probably the better solution - you directly initialize nonce and key with what you need (see also this post):
uint8_t ba_nonce[16] = {
0x7d, 0x93, 0x09, 0x9f, 0x7f, 0xed, 0x16, 0x21,
0x58, 0x36, 0xf7, 0xba, 0xd4, 0xdb, 0x0e, 0x48
};
uint8_t ba_key[16] = {
0xa5, 0xb1, 0x15, 0x53, 0x6d, 0x5b, 0xf3, 0x50,
0xc5, 0xb0, 0xfa, 0x6f, 0x69, 0x24, 0x2f, 0x18
};

Related

USB Audio class 2.0 enumeration issue

I am trying to develop a USB audio device compliant to USB Audio Class version 2.0 specification. I have written the descriptors by referring to the specification as such. But, I find that the device is not enumerating correctly. The status in device manager just shows "This device cannot start (Code 10)."
Please find the configuration descriptors that I am using below:
/* Configuration descriptor */
0x09, /* Descriptor size */
0x02, /* Configuration descriptor type */
0x8A,0x00, /* Length of this descriptor and all sub descriptors */
0x02, /* Number of interfaces */
0x01, /* Configuration number */
0x00, /* Configuration string index */
0x80, /* Config characteristics - Bus powered */
0x32, /* Max power consumption of device (in 8mA unit) : 400mA */
//IAD
0x08, /* bLength */
0x0B, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x01, /* bFunctionClass */
0x00, /* bFunctionSubClass */
0x20, /* bFunctionProtocol */
0x00, /* iFunction */
/* Standard AC Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndoints */
0x01, /* bInterfaceClass */
0x01, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Class-Specific AC Interface Header Descriptor */
0x09, /* bLength */
0x24, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x00, 0x02, /* bcdADC */
0x03, /* bCatagory MICROPHONE*/
0x2E, 0x00, /* wTotalLength (46 Bytes) */
0x00, /* bmControls */
/* Class-Specific AC Clock Source Descriptor (INTERNAL) */
0x08, /* bLength */
0x24, /* bDescriptorType */
0x0A, /* bDescriptorSubtype */
0x10, /* bClockID */
0x01, /* bmAttributes:
D[1:0]:
00: External Clock
01: Internal Fixed Clock
10: Internal Variable Clock
11: Internal Progamable Clock
D[2]:
Clock Synced to SOF
D[7:3]:
Reserved (0) */
0x00, /* bmControls:
D[1:0]:
Clock Freq Control
D[3:2]:
Clock Validity Control
D[7:4]:
Reserved (0) */
0x00, /* bAssocTerminal */
0x00, /* iClockSource */
/* Class-Specific AC Input Terminal Descriptor */
0x11, /* bLength */
0x24, /* bDescriptorType */
0x02, /* bDescriptorSubtype */
0x01, /* bTerminalID */
0x01, 0x02, /* wTerminalType */
0x00, /* bAssocTerminal */
0x10, /* bCSourceID */
0x02, /* bNrChannels,indicate has number of channel in cluster*/
0x03, 0x00, 0x00, 0x00, /* bmChannelConfig,spatial positions*/
0x00, /* iChannelNames,index remaining channel spatial positions descripte*/
0x00, 0x00, /* bmControls */
0x00, /* iTerminal */
/* Class-Specific AC Output Terminal Descriptor*/
0x0C, /* bLength */
0x24, /* bDescriptorType */
0x03, /* bDescriptorSubtype */
0x02, /* bTerminalID */
0x01, 0x01, /* wTerminalType */
0x00, /* bAssocTerminal */
0x01, /* bSourceID */
0x10, /* bCSourceID */
0x00, 0x00, /* bmControls */
0x00, /* iTerminal */
/* Audio In Standard AS Interface Descriptor (Alt 0 - Zero Bandwidth) */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x01, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio In Standard AS Interface Descriptor (Alt 1) */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x01, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x20, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio In Class-Specific AS Interface descriptor */
0x10, /* bLength */
0x24, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x02, /* bTerminalLink,Terminal ID of Output Terminal */
0x00, /* bmControls */
0x01, /* bFormatType */
0x01, 0x00, 0x00, 0x00, /* bmFormats PCM*/
0x02, /* bNrChannels 2 channel*/
0x03, 0x00, 0x00, 0x00, /* bmChannelConfig */
0x00, /* iChannelNames */
/* Audio In Class-Specific AS Type I Format Descriptor */
0x0B, /* Descriptor size */
0x24, /* Class-specific Interface Descriptor Type */
0x02, /* Format Type Descriptor subtype */
0x01, /* PCM FORMAT_TYPE_I */
0x02, /* Number of channels - 2 */
0x02, /* Subframe size - 2 bytes per audio subframe */
0x10, /* Bit resolution - 16 bits */
0x01, /* Number of samping frequencies - 1 */
0x80, 0xBB, 0x00, /* Sampling frequency - 48000 Hz */
/* Audio In Standard AS Isochronous Data EP Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x05, /* bmAttributes */
0xC8, 0x00, /* wMaxPacketSize 200byte*/
0x01, /* bInterval */
/* Superspeed Endpoint Companion Descriptor */
0x06, /* bLength */
0x30, /* bDescriptorType */
0x00, /* bMaxBurst */
0x00, /* bmAttributes */
0x60, 0x00, /* wBytesPerInterval */
/* Audio In Class-Specific AS Isochronous Data EP Descriptor */
0x08, /* bLength */
0x25, /* bDescriptorType */
0x01, /* bDescriptorSubtype */
0x00, /* bmAttributes */
0x00, /* bmControls */
0x02, /* bLockDelayUnits */
0x08, 0x00, /* wLockDelay */

ESP OTA updating over https web server

I have an old code which works great and has no problem but I have been asked to change the OTA configuration so that this code can update itself from a SSL server. I have the certificate and the fingerprint needed for this (downloaded it from google chrome). I have googled and tried most of the advised method for OTA over HTTPS. but none of them worked for me. the results which I get from 'ESPhttpUpdate.update' is always "-1" which means "connection failed".
can anybody propose a method which works all right? as I don't have any correct code I don't post any. I just want a suggestion or a sample code.
thank you all in advance
The problem was solved.
I had split the server address into 2 parts (as the sample code suggested), URL and URI; but I don't know why, when I concatenated them together, the problem was solved.
here is the code for those who may need it:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <FS.h>
#include "ESP8266httpUpdate.h"
/********************************************************
********************************************************
********************************************************/
const char* ssid = "********"; // modify this
const char* password = "********"; // modify this
const char* host = "https://server/steamer_v1_2.bin"; // modify this
/********************************************************
********************************************************
********************************************************/
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
for (uint8_t t = 4; t > 0; t--)
{
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
if (WiFi.SSID() != ssid) {
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// configure time
configTime(3 * 3600, 0, "pool.ntp.org");
BearSSL::WiFiClientSecure client;
const uint8_t fingerprint[20] = {0xdd, 0xa5, 0x2d, 0x31, 0x25, 0x31, 0xae, 0x7a, 0x10, 0x0b, 0x68, 0xba, 0x22, 0x84, 0x1a, 0x94, 0xec, 0x79, 0xb4, 0xbb}; // modify this
client.setFingerprint(fingerprint);
auto ret = ESPhttpUpdate.update(client, host);
// if successful, ESP will restart
Serial.println("update failed");
Serial.println((int) ret);
}
/********************************************************
********************************************************
********************************************************/
void loop() {
}

Composite USB CDC/HID device on STMF32F303

I'm following the advice:
It is possible to achieve your own composite USB Device, by combining the desired classes' drivers into one class, under your own folder within: Middlewares\ST\STM32_USB Device Library\Class
from https://community.st.com/s/question/0D50X00009XkgYtSAJ/stm32f4-hal-composite-usb-device-example
I now have a unified configuration descriptor.
/* USB CDC device Configuration Descriptor */
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x03, /* bNumInterfaces: 2 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/*---------------------------------------------------------------------------*/
//////////////////////////////////////////////////////////////////////////////////////
//Add 1 IAD class here // this one is for COM port
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x00, // bFirstInterface //starting of interface
0x02, // bInterfaceCount //interfaces under this IAD class
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
//////////////////////////////////////////////////////////////////////////////////////
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
CDC_FS_BINTERVAL, /* bInterval: */
/*---------------------------------------------------------------------------*/
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
///////////////////////////////////////////////////////////////////////////////////////////////
// IAD Mouse
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
0x02, // bFirstInterface //starts from zero .. hence 0-1- and now 2
0x01, // bInterfaceCount //no of interfaces used in function. for above cdc it was 2
0x03, //*bInterfaceClass: HID*/
0x01, //*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, //*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0x02, //*iInterface: Index of string descriptor*/
////////////////////////////////////////////////////////////////////////////////////////////////
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x02, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0x02, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval */
/* 34 */
} ;
and a unified init:
static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
uint8_t ret = 0U;
USBD_CDC_HandleTypeDef *hcdc;
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Open EP IN */
USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
CDC_DATA_HS_IN_PACKET_SIZE);
pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
/* Open EP OUT */
USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
CDC_DATA_HS_OUT_PACKET_SIZE);
pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
}
else
{
/* Open EP IN */
USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
CDC_DATA_FS_IN_PACKET_SIZE);
pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
/* Open EP OUT */
USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
CDC_DATA_FS_OUT_PACKET_SIZE);
pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
}
/* Open Command IN EP */
USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
if (pdev->pClassData == NULL)
{
ret = 1U;
}
else
{
hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
/* Init physical Interface components */
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
/* Init Xfer states */
hcdc->TxState = 0U;
hcdc->RxState = 0U;
if (pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);
}
else
{
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
CDC_DATA_FS_OUT_PACKET_SIZE);
}
}
// HID
/* Open EP IN */
USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof(USBD_HID_HandleTypeDef));
if (pdev->pClassData == NULL)
{
return USBD_FAIL;
}
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return ret;
}
I am concerned that the value of CDC_IN_EP (0x81) clashes with HID_EPIN_ADDR (also 0x81).
Is this a valid concern?
Is there an example of making a composite CDC/HID using CubeMX?
I needed to use 0x83 as the HID endpoint. I confirmed that this worked in the simple HID example, too.
There are still many other obstacles in the way of getting a working CDC/HID composite device on STM32.

AES 128 GCM objective C osx

I am trying to encrypt/decrypt a string in an AES-128 GCM format in objective c. I have looked everywhere but can't seem to find a working solution.
Not so long ago I had a similar problem and the best answer I could find was this one. To sum up, iOS has some functions to do what you want but they are private.
So, until Apple decides to release these functions, I opted for developing my own library, currently stored in GitHub and available in CocoaPods.
The case you describe could be implemented this way:
#import <CommonCrypto/CommonCrypto.h>
#import "IAGAesGcm.h"
// For the case you describe, the key length is 128 bits (16 bytes)
u_char keyBytes[kCCKeySizeAES128] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
NSData *key = [NSData dataWithBytes:keyBytes length:sizeof(keyBytes)];
// GCM recommends a IV size of 96 bits (12 bytes), but you are free
// to use other sizes
u_char ivBytes[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
NSData *iv = [NSData dataWithBytes:ivBytes length:sizeof(ivBytes)];
NSData *aad = [#"AdditionalAuthenticatedData" dataUsingEncoding:NSUTF8StringEncoding];
// Authenticated Encryption Function
NSData *expectedPlainData = [#"PlainData" dataUsingEncoding:NSUTF8StringEncoding];
// The returned ciphered data is a simple class with 2 properties: the actual encrypted data and the authentication tag.
// The authentication tag can have multiple sizes and it is up to you to set one, in this case the size is 128 bits
// (16 bytes)
IAGCipheredData *cipheredData = [IAGAesGcm cipheredDataByAuthenticatedEncryptingPlainData:expectedPlainData
withAdditionalAuthenticatedData:aad
authenticationTagLength:IAGAuthenticationTagLength128
initializationVector:iv
key:key
error:nil];
// Authenticated Decryption Function
NSData *plainData = [IAGAesGcm plainDataByAuthenticatedDecryptingCipheredData:cipheredData
withAdditionalAuthenticatedData:aad
initializationVector:iv
key:key
error:nil];
XCTAssertEqualObjects(expectedPlainData, plainData);
Hope this code is of any help.
To end (and thanks zaph for mentioning this), I have not performed any benchmarking of this code, so assume that it is slow. I intend to use it to decipher tokens in a JWE string and only from time to time, I do not recommend anything more requiring than that.
Regards.
/*
typical GCM use case: sending an authenticated packet
+--------------+-------+--------------+
| header | seq. | Data |
+--------------+-------+--------------+
| | |
| | |
Addtl auth data IV plain text
| | |
| | V
| | +--------------------+
| +---->| |
| | | GCM encryption |
+---------------->| |
| | +--------------------+
| | | |
| | cipher text Auth tag
| | | |
V V V V
+--------------+-------+----------------+---------+
| header | seq. | encrypted data | ICV |
+--------------+-------+----------------+---------+
*/
#define CCCryptorGCMprologue() CCCryptor *cryptor = getRealCryptor(cryptorRef, 0); \
CC_DEBUG_LOG("Entering\n"); \
if(!cryptor) return kCCParamError;
static inline CCCryptorStatus translate_err_code(int err)
{
if (err==0) {
return kCCSuccess;
} /*else if(err == CCMODE_INVALID_CALL_SEQUENCE){ //unti we can read error codes from corecrypto
return kCCCallSequenceError;
} */ else {
return kCCUnspecifiedError;
}
}
CCCryptorStatus
CCCryptorGCMAddIV(CCCryptorRef cryptorRef,
const void *iv,
size_t ivLen)
{
CCCryptorGCMprologue();
if(ivLen!=0 && iv==NULL) return kCCParamError;
//it is okay to call with ivLen 0 and/OR iv==NULL
//infact this needs to be done even with NULL values, otherwise ccgcm_ is going to return call sequence error.
//currently corecrypto accepts NULL
//rdar://problem/23523093
int rc = ccgcm_set_iv_legacy(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, ivLen, iv);
return translate_err_code(rc);
}
//Add additional authentication data
CCCryptorStatus
CCCryptorGCMAddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
CCCryptorGCMprologue();
if(aDataLen!=0 && aData==NULL) return kCCParamError;
//it is okay to call with aData zero
int rc = ccgcm_gmac(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, aDataLen, aData);
return translate_err_code(rc);
}
// This is for old iOS5 clients
CCCryptorStatus
CCCryptorGCMAddADD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
// This was a temp mistake in MacOSX8
CCCryptorStatus
CCCryptorGCMaddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
//we are not providing this function to users.
//The reason is that we don't want to create more liability for ourself
//and a new interface function just increases the number of APIs
//without actually helping users
//User's use the old CCCryptorGCMEncrypt() and CCCryptorGCMDecrypt()
static CCCryptorStatus gcm_update(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
CCCryptorGCMprologue();
if(dataInLength!=0 && dataIn==NULL) return kCCParamError;
//no data is okay
if(dataOut == NULL) return kCCParamError;
int rc = ccgcm_update(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef,
void *tagOut,
size_t *tagLength)
{
CCCryptorGCMprologue();
if(tagOut == NULL || tagLength == NULL) return kCCParamError;
int rc = ccgcm_finalize(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, *tagLength, (void *) tagOut);
if(rc == -1)
return kCCUnspecifiedError;
else
return kCCSuccess; //this includes 0 and any error message other than -1
// ccgcm_finalize() returns CCMODE_INTEGRITY_FAILURE (-3) if the expected tag is not coppied to the buffer. but that doesn't mean there is an error
}
CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef)
{
CCCryptorGCMprologue();
int rc = ccgcm_reset(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCM(CCOperation op, /* kCCEncrypt, kCCDecrypt */
CCAlgorithm alg,
const void *key, size_t keyLength, /* raw key material */
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
void *tagOut, size_t *tagLength)
{
CCCryptorRef cryptorRef;
CCCryptorStatus retval;
CC_DEBUG_LOG("Entering Op: %d Cipher: %d\n", op, alg);
retval = CCCryptorCreateWithMode(op, kCCModeGCM, alg, 0, NULL, key, keyLength,
NULL, 0, 0, 0, &cryptorRef);
if(retval) return retval;
//call even with NULL pointer and zero length IV
retval = CCCryptorGCMAddIV(cryptorRef, iv, ivLen);
if(retval) return retval;
retval = CCCryptorGCMaddAAD(cryptorRef, aData, aDataLen);
if(retval) return retval;
retval = gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
if(retval) return retval;
retval = CCCryptorGCMFinal(cryptorRef, tagOut, tagLength);
CCCryptorRelease(cryptorRef);
return retval;
}

Mifare DESfire EV1 4k AES Authentication

Has anyone been able to authenticate with this card using this encryption method? I have no clue what to do after selecting the app and starting the authentication. Below is my code. Only copied the relevant parts and used example KEY and SELECT_APP
//AUTHENTICATION COMMANDS
private static final byte[] NATIVE_AUTHENTICATION_KEY = new byte[] {
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x04, (byte) 0x05,
(byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09, (byte) 0x0A,
(byte) 0x0B, (byte) 0x0C, (byte) 0x0D, (byte) 0x0E, (byte) 0x0F,
(byte) 0x00 };
private static final byte[] START_AUTHENTICATION_COMMAND = new byte[] {
(byte) 0xAA, (byte) 0x01 };
private static byte[] SELECT_APPLICATION = { (byte) 0x5A, (byte) 0x01,
(byte) 0x02, (byte) 0x03 };
//AUTHENTICATION FUNCTION
private void StartAuthentication(Tag tag) {
try {
IsoDep.get(tag).connect();
byte[] response = IsoDep.get(tag)
.transceive(SELECT_APPLICATION);
Log.e("SELECT_APP", ByteArrayToHexString(response));
byte[] response2 = IsoDep.get(tag).transceive(START_AUTHENTICATION_COMMAND);
Log.e("START_AUTH", ByteArrayToHexString(response2));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
SELECT_APP returns 0x00 (OK) and START_AUTH returns 0xAF+(16bit). What to do after getting that?
If your answer returns 0xAF means extra info is pending.
Send 0xAF till you get 0x00 in retun, 0xAF means more data in return is pending.