Java Card setExponent() method fails when exponent has more than 10 bytes - cryptography

I'm trying to implement the modPow function on Java Card using the build in RSA CryptoSystem. The code seems trivial but I have issued on implementation.
My code untill now :
Cipher m_encryptCipherRSA = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); // create the cipher
RSAPublicKey m_rsaPublicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,KeyBuilder.LENGTH_RSA_1024,false); // create the public key
m_random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
m_random.generateData(temp1, (short)0, MODULUS_LENGTH);
m_rsaPublicKey.setModulus(temp1,(short)0, MODULUS_LENGTH); //generate modulus
m_random.generateData(temp1,(short)0, (short) EXPONENT_LENGTH);
m_rsaPublicKey.setExponent(temp1,(short)0, (short)EXPONENT_LENGTH);
The cod seems to work ok if EXPONENT_LENGTH has no more than 10 bytes.The Java Card I have has limited the dimension of public exponent. However my project is based on numbers up to 128bytes long.Is there a way to create a generic modpow function based on this hardware limitation? Is there another way I could implement the power exponentiation which is still feasible.

I managed to solve the problem by using the private exponent ( which seems not be constraint by RSA cryptosystem).Below is the working code.
public byte[] modPow(byte[] x,short xOffset,short xLength,byte[] y,short yOffset,short yLength)
{
Util.arrayCopy(y, yOffset, tempBuffer, (short)(Configuration.TEMP_OFFSET_EXPONENT+4), yLength);
Util.arrayFillNonAtomic(tempBuffer, Configuration.TEMP_OFFSET_EXPONENT, (byte)4,(byte)0x00);
mRsaPrivateKeyModPow.setExponent(tempBuffer,Configuration.TEMP_OFFSET_EXPONENT, (short)(yLength+4));
mRsaCipherModPow.init(mRsaPrivateKeyModPow, Cipher.MODE_DECRYPT);
Util.arrayCopy(x,xOffset,tempBuffer, Configuration.TEMP_OFFSET_RSA, Configuration.LENGTH_RSAOBJECT_MODULUS);
mRsaCipherModPow.doFinal(tempBuffer,Configuration.TEMP_OFFSET_RSA, (short) (Configuration.LENGTH_RSAOBJECT_MODULUS), tempBuffer,Configuration.TEMP_OFFSET_RSA);
mRsaPrivateKeyModPow.clearKey();
return tempBuffer;
}

Well, I tried both RSAPublicKey and RSAPrivateKey for two different cards, and both worked fine:
package soqPack;
import javacard.framework.*;
import javacard.security.KeyBuilder;
import javacard.security.RSAPrivateKey;
import javacard.security.RSAPublicKey;
import javacard.security.RandomData;
import javacardx.biometry.BioBuilder;
import javacardx.crypto.Cipher;
public class modPowtest extends Applet {
//Definition Of INS in APDU command
public static final byte INS_MOD_POW = (byte) 0x00;
//Switch cases to choose RSA Public key or RSA Private key for ModPow()
//P1 in APDU command.
public static final byte USE_PUB_KEY = (byte) 0x00;
public static final byte USE_PRI_KEY = (byte) 0x01;
//Required objects
byte[] tempMem;
Cipher myCipher;
RSAPrivateKey rsaPriKey;
RSAPublicKey rsaPubKey;
RandomData random;
public static void install(byte[] bArray, short bOffset, byte bLength) {
new modPowtest();
}
protected modPowtest() {
myCipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
rsaPriKey = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_1024, false);
rsaPubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_1024, false);
tempMem = JCSystem.makeTransientByteArray((short) 0x80, JCSystem.CLEAR_ON_DESELECT);
random = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
register();
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_INS]) {
case INS_MOD_POW:
modPow(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
public void modPow(APDU apdu) {
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_P1]) {
case USE_PUB_KEY:
random.generateData(tempMem, (short) 0x00, (short) 0x80);
rsaPubKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
random.generateData(tempMem, (short) 0x00, (short) 0x03);
rsaPubKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
break;
case USE_PRI_KEY:
random.generateData(tempMem, (short) 0x00, (short) 0x80);
rsaPriKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
random.generateData(tempMem, (short) 0x00, (short) 0x03);
rsaPriKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
break;
default:
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
}
}
}
Works as below:
Download Cap begin...
Download Cap successful.
Install Applet begin...
Install Applet successful.
Select Applet begin...
Select Applet successful.
Send: 00 00 00 00 00
Recv: 90 00
Send: 00 00 01 00 00
Recv: 90 00
Update: (Related your new question in the comments and here):
I also, changed value of tempMem[0] just before the setModulus and setExponent methods to 0x69, and it still works fine.

Related

Illegal Value CryptoException when setting ECC Private Key S value in JavaCard

I am getting an CRYPTOEXCEPTION.ILLEGAL_VALUE when attempting to set an ECPrivateKey with its S,A,B,G,R,Field values manually for a SECP-256-R1 private key.
protected static byte[] EC_P256R1_FIELD_A = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFC
};
protected static byte[] EC_P256R1_FIELD_B = {
(byte)0x5A,(byte)0xC6,(byte)0x35,(byte)0xD8,(byte)0xAA,(byte)0x3A,(byte)0x93,(byte)0xE7,
(byte)0xB3,(byte)0xEB,(byte)0xBD,(byte)0x55,(byte)0x76,(byte)0x98,(byte)0x86,(byte)0xBC,
(byte)0x65,(byte)0x1D,(byte)0x06,(byte)0xB0,(byte)0xCC,(byte)0x53,(byte)0xB0,(byte)0xF6,
(byte)0x3B,(byte)0xCE,(byte)0x3C,(byte)0x3E,(byte)0x27,(byte)0xD2,(byte)0x60,(byte)0x4B
};
protected static byte[] EC_P256R1_FIELD_G = {
(byte)0x04,
(byte)0x6B,(byte)0x17,(byte)0xD1,(byte)0xF2,(byte)0xE1,(byte)0x2C,(byte)0x42,(byte)0x47,
(byte)0xF8,(byte)0xBC,(byte)0xE6,(byte)0xE5,(byte)0x63,(byte)0xA4,(byte)0x40,(byte)0xF2,
(byte)0x77,(byte)0x03,(byte)0x7D,(byte)0x81,(byte)0x2D,(byte)0xEB,(byte)0x33,(byte)0xA0,
(byte)0xF4,(byte)0xA1,(byte)0x39,(byte)0x45,(byte)0xD8,(byte)0x98,(byte)0xC2,(byte)0x96,
(byte)0x4F,(byte)0xE3,(byte)0x42,(byte)0xE2,(byte)0xFE,(byte)0x1A,(byte)0x7F,(byte)0x9B,
(byte)0x8E,(byte)0xE7,(byte)0xEB,(byte)0x4A,(byte)0x7C,(byte)0x0F,(byte)0x9E,(byte)0x16,
(byte)0x2B,(byte)0xCE,(byte)0x33,(byte)0x57,(byte)0x6B,(byte)0x31,(byte)0x5E,(byte)0xCE,
(byte)0xCB,(byte)0xB6,(byte)0x40,(byte)0x68,(byte)0x37,(byte)0xBF,(byte)0x51,(byte)0xF5
};
protected static byte[] EC_P256R1_FIELD_R = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xBC,(byte)0xE6,(byte)0xFA,(byte)0xAD,(byte)0xA7,(byte)0x17,(byte)0x9E,(byte)0x84,
(byte)0xF3,(byte)0xB9,(byte)0xCA,(byte)0xC2,(byte)0xFC,(byte)0x63,(byte)0x25,(byte)0x51
};
protected static byte[] EC_P256R1_FP = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF
public void initSigner(byte[] input, short offset, short len) {
ECPrivateKey tempKey = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false);
tempKey.setS(input, offset, len);
tempKey.setA(EC_P256R1_FIELD_A, (short) 0, (short) EC_P256R1_FIELD_A.length);
tempKey.setB(EC_P256R1_FIELD_B, (short) 0, (short) EC_P256R1_FIELD_B.length);
tempKey.setG(EC_P256R1_FIELD_G, (short) 0, (short) EC_P256R1_FIELD_G.length);
tempKey.setR(EC_P256R1_FIELD_R, (short) 0, (short) EC_P256R1_FIELD_R.length);
tempKey.setFieldFP(EC_P256R1_FP, (short) 0, (short) EC_P256R1_FP.length);
Signature signer = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, true);
signer.init(tempKey, Signature.MODE_SIGN);
}
Is there anything I am missing out when setting the ECC P256R1 values manually and how do I get the above code to work ?
I figured out that the particular card does not support KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET thus the reason why it kept throwing CRYPTOEXCEPTION.ILLEGAL_VALUE.

When connect to an OBD device, setCharacteristicNotification and writeCharacteristic, onCharacteristicChanges received 3E 00 00 3F notification

When connected to an OBD device, setCharacteristicNotification and writeCharacteristic. Notification was received onCharacteristicChanged.
But the notification showed 3E 00 00 3F, same conditions for many write requests. It is expected to return the information about the device.
The codes are as following:
public void writeCharacteristic(String commnd, BluetoothGattCharacteristic characteristic, boolean enabled) {
int commandLength = commnd.length(); // length of the string used for the loop
byte[] bytes = new byte[commnd.length()];
for(int i = 0; i < commandLength ; i++){ // while counting characters if less than the length add one
char character = commnd.charAt(i); // start on the first character
int ascii = (int) character; //convert the first character
bytes[i] = (byte) Integer.parseInt(String.valueOf(ascii));
Log.w(TAG, "byte index:"+i+", ascii:"+ascii+", bytes i:"+bytes[i]);
}
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
characteristic.setValue(bytes);//ch);//messageBytes);
boolean success = mBluetoothGatt.writeCharacteristic(characteristic);
Log.w("Gatt", "write result:"+success);
Log.w(TAG, "set characteric notification, enabled?"+enabled);
setCharacteristicNotificationWithDescriptor(characteristic, true);
}
protected static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public boolean setCharacteristicNotificationWithDescriptor(BluetoothGattCharacteristic characteristic, boolean enable) {
Log.w(TAG, "setCharacteristicNotification(UUID=" + characteristic.getUuid().toString() + ", enable=" + enable + " )");
mBluetoothGatt.setCharacteristicNotification(characteristic, enable);
Log.w(TAG, "descriptor:"+CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[] { 0x00, 0x00 });
Log.w(TAG, "notification value:"+BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE+", false:"+new byte[] { 0x00, 0x00 }.toString());
boolean status = mBluetoothGatt.writeDescriptor(descriptor); //descriptor write operation successfully started?
Log.w(TAG, "write descriptor:"+status);
return status;
}
Not sure how to get the correct response? I sent the AT command with 0D. Thank you.

UART sending wrong characters on pic18

I'm trying to simply send characters trough my UART Interface by calling the funktion: UART_Write_Text("hello");
this is the code executed in the the uart.c file:
void UART_Init(void)
{
//115200bps deafult value for RN4678
BRGH = 0; //Setting High Baud Rat
BRG16 = 0; //8-Bit mode
SPBRG = 8; //Writing SPBRG Register
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
RCSTAbits.CREN = 1; //Enables Reception
TXSTAbits.TXEN = 1; //Enables Transmission
}
/******************************************************************************/
//-----UART write byte
/******************************************************************************/
void UART_Write(char data)
{
while(!TRMT);
TXREG = data;
}
/******************************************************************************/
//-----UART check tx queue
/******************************************************************************/
char UART_TX_Empty(void)
{
return TRMT;
}
/******************************************************************************/
//-----UART write string
/******************************************************************************/
void UART_Write_Text(char *text)
{
for(int i=0; text[i]!='\0' || text[i] !=0x00; i++){
UART_Write(text[i]);
}
UART_Write('\n');
}
/******************************************************************************/
//-----UART data ready to read
/******************************************************************************/
char UART_Data_Ready(void)
{
return RCIF;
}
/******************************************************************************/
//-----UART read byte
/******************************************************************************/
char UART_Read(void)
{
while(!RCIF);
return RCREG;
}
/******************************************************************************/
//-----UART read string
/******************************************************************************/
void UART_Read_Text(char *Output, unsigned int length)
{
unsigned int i;
for(int i=0;i<length;i++)
Output[i] = UART_Read();
}
Now when I'm debugging it, I see that it writes the wright charakters into the TXREG. At the end it sended the following characters: 'h', 'e', 'l', 'l', 'o', '\n'.
I send them to the bluetooth module RN4678 with a baud rate of 115200bps which is also the default baud rate of the BT module. However when I read the sended character on my phone with a Bluetooth terminal i get only some characters wright and the other ones are questionmarks, so it doesn't recognise them (not always the same character unrecognised).
I already experimented with the baud rate, but it looks like its the right value I writed into the SPBRG.
I'm also polling the TRMT so there shouldn't be any collisions...
Someone knows what I'm doing wrong?
#include "Configuration_bits.h"
#include <xc.h>
#include <stdio.h>
#include <p18f67k22.h>
#include <string.h>
#include <stdlib.h>
#define _XTAL_FREQ 16000000
void UART_Init_1(){
TRISCbits.TRISC6=1; // TX1 Pin-31
TRISCbits.TRISC7=1; // RX1 Pin-32
RC1IE=1;
SPBRG1=34; // Baud Rate 115200
BAUDCON1bits.BRG16=1;
TXSTA1bits.BRGH=1;
//TXSTA 1 Register
TXSTA1bits.TX9=0; // 8-bit transmission
TXSTA1bits.TXEN=0;
TXSTA1bits.TXEN=1; // Transmit is enabled
TXSTA1bits.SYNC=0; // Asynchronous mode
TXSTA1bits.TRMT=1; // Transmit Shift Register Status bit
//RXSTA 1 Register
RCSTA1bits.SPEN=1; // Serial Port Enable bit
RCSTA1bits.RX9=0; // 8-bit reception
RCSTA1bits.CREN=1; // Continuous Receive Enable bit
}
void UART_Tx_1(unsigned char z[])
{
unsigned int uart_tx1=0;
while(z[uart_tx1]!='\0')
{
while(!TX1IF);
TXREG1=z[uart_tx1];
uart_tx1++;
}
}
void UART_Rx_1()
{
string_rx1[uart_rx1]=RCREG1;
uart_rx1++;
}
void interrupt ISR(void)
{
if(RC1IF && RC1IE) // UART_1
{
}
}
void main(void)
{
System_Initialization();
UART_Init_1();
while(1)
{
UART_Tx_1("HELLO\r\n"); // Transmit Hello
}
}

ESP8266 Sniffing and sending Mac address

I'm trying to make my ESP8266 sniffing nearby devices, then posting them by with a HTTP request. With purpose is to record when my roommate and I are at home. Then in the future, trigger certain tasks like turning on/off the lights if we're home or not. I don't care at all about the packets content just the mac addresses.
So fare I've found this, script that prints out the mac adresses for nearby devices, created by kalanda: esp8266-sniffer.
Aswell as this HTTP posting script ESP8266 http get requests.
I've tried to combine those two and in the callback function make the ESP send the found data, but doesn't look like the ESP establish the wifi connection.
I tried using different WIFI modes: STATION_MODE, SOFTAP_MODE, STATIONAP_MODE. None of them worked for both sniffing and http request at the same time. I know that the STATIONAP_MODE do have some flaws. What I've found is that it has to switch both somehow, but unfortunately I'm not a ESP expert and don't know how this can be done.
Here is my code(srry for any rubbish coding on my side):
#include <ESP8266WiFi.h> // added this
#include <ESP8266HTTPClient.h> // added this
const char* ssid = "**********"; // Wifi SSID
const char* password = "**********"; // Wifi Password
String main_url = "http://*********.php?"; // Website url to post the information
String temp_url = ""; // Url with information
extern "C" {
#include <user_interface.h>
}
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04
struct RxControl {
signed rssi:8; // signal intensity of packet
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length:12; // if not 11n packet, shows length of packet.
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length:16;// if is 11n packet, shows length of packet.
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4; //which channel this packet in.
unsigned:12;
};
struct SnifferPacket{
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
// Only look for probe request packets
if (frameType != TYPE_MANAGEMENT ||
frameSubType != SUBTYPE_PROBE_REQUEST)
return;
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
uint8_t SSID_length = snifferPacket->data[25];
Serial.print(" SSID: ");
printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{
HTTPClient http; //Declare an object of class HTTPClient
temp_url = main_url;
temp_url = temp_url + "mac=30:a8:db:96:a4:75";
temp_url = temp_url + "&rssi=-90";
temp_url = temp_url + "&ssid=none";
http.begin(temp_url); //Specify request destination
int httpCode = http.GET(); //Send the request
temp_url = "";
if (httpCode > 0)
{ //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
}
else
{
Serial.println("Wifi connection failed"); //Prints out this
}
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for(uint16_t i = start; i < DATA_LENGTH && i < start+size; i++) {
Serial.write(data[i]);
}
}
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
#define CHANNEL_HOP_INTERVAL_MS 1000
static os_timer_t channelHop_timer;
/**
* Callback for channel hoping
*/
void channelHop()
{
// hoping channels 1-14
uint8 new_channel = wifi_get_channel() + 1;
if (new_channel > 14)
new_channel = 1;
wifi_set_channel(new_channel);
}
#define DISABLE 0
#define ENABLE 1
void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
delay(10);
wifi_set_opmode(STATION_MODE);
wifi_set_channel(1);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Connecting..");
}
Serial.println("");
Serial.println("Connected..");
// setup the channel hoping callback timer
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}
void loop() {
delay(10);
}
Here's the code which aggregates probe requests (MAC addresses and RSSIs) for 3 seconds and then sends them to specified server's endpoint using json (WIFI_AP_STA mode):
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <vector>
const char* apSsid = "ap-ssid";
const char* apPassword = "ap-password";
const char* clientSsid = "client-ssid";
const char* clientPassword = "client-password";
HTTPClient http;
WiFiEventHandler probeRequestPrintHandler;
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
std::vector<WiFiEventSoftAPModeProbeRequestReceived> myList;
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
myList.push_back(evt);
}
void setup() {
Serial.begin(115200);
Serial.println("Hello!");
// Don't save WiFi configuration in flash - optional
WiFi.persistent(false);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apSsid, apPassword);
WiFi.begin(clientSsid, clientPassword);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("");
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
}
void loop() {
delay(3000);
String json = "";
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonArray& probes = root.createNestedArray("probes");
for(WiFiEventSoftAPModeProbeRequestReceived w : myList){
JsonObject& probe = probes.createNestedObject();
probe["address"] = macToString(w.mac);
probe["rssi"] = w.rssi;
}
myList.clear();
root.printTo(json);
Serial.println("json:" + json);
http.begin("http://example.com/api/v1/probe");
http.addHeader("Content-Type", "application/json");
http.POST(json);
http.end();
}
Remember to use the latest version (actually a pre-release - 2.4.0-rc1 or newer) of arduino-esp8266 library since those WiFiEvents were just recently added.
You can download ArduinoJson library using Library Manager (Sketch -> Include Library -> Manage Libraries...) if you don't have that already.

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