implemented bernstein-based aes timing experiment
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "bootrom_func.h"
|
#include "bootrom_func.h"
|
||||||
|
#include "bootrom_type.h"
|
||||||
#include "cacheutil.h"
|
#include "cacheutil.h"
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
@@ -112,12 +113,9 @@ void expand_key(unsigned char key[16], unsigned char key_sched[176], int n,
|
|||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
void aes128_encrypt_ecb(unsigned char *msg, unsigned int msg_len, unsigned char key[16],
|
void aes128_encrypt_ecb(unsigned char *msg, unsigned int msg_len, unsigned char key[16],
|
||||||
unsigned char sbox[16][16], unsigned char rc_lookup[11],
|
unsigned char sbox[16][16], unsigned char key_sched[176],
|
||||||
unsigned char mul2[256], unsigned char mul3[256])
|
unsigned char mul2[256], unsigned char mul3[256])
|
||||||
{
|
{
|
||||||
unsigned char key_sched[176];
|
|
||||||
expand_key(key, key_sched, 11, sbox, rc_lookup);
|
|
||||||
|
|
||||||
unsigned int num_blocks = msg_len / 16;
|
unsigned int num_blocks = msg_len / 16;
|
||||||
unsigned char *block;
|
unsigned char *block;
|
||||||
|
|
||||||
@@ -147,14 +145,6 @@ uint64_t entry_sync(unsigned char *msg, unsigned int msg_len, unsigned char key[
|
|||||||
unsigned char mul2[256], unsigned char mul3[256])
|
unsigned char mul2[256], unsigned char mul3[256])
|
||||||
{
|
{
|
||||||
unsigned long long start = 0;
|
unsigned long long start = 0;
|
||||||
// int i, j;
|
|
||||||
// for(i = 0; i < 256; i++)
|
|
||||||
// {
|
|
||||||
// for(j = 0; j < 4; j++)
|
|
||||||
// {
|
|
||||||
// clean_inv_l1_setway(i, j);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
start = get_ticks();
|
start = get_ticks();
|
||||||
aes128_encrypt_ecb(msg, msg_len, key, sbox, rc_lookup, mul2, mul3);
|
aes128_encrypt_ecb(msg, msg_len, key, sbox, rc_lookup, mul2, mul3);
|
||||||
@@ -164,8 +154,15 @@ uint64_t entry_sync(unsigned char *msg, unsigned int msg_len, unsigned char key[
|
|||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
void entry_async(uint64_t *base)
|
void entry_async(uint64_t *base)
|
||||||
{
|
{
|
||||||
unsigned long long start = 0, end = 0;
|
int i, j, iter_count = 0;
|
||||||
|
unsigned long long start = 0;
|
||||||
|
unsigned char *addr;
|
||||||
|
|
||||||
|
unsigned char msg_old[16];
|
||||||
|
unsigned char key_sched[176];
|
||||||
|
double timing;
|
||||||
|
|
||||||
|
// get initial params
|
||||||
unsigned char *msg = (unsigned char *) base[0];
|
unsigned char *msg = (unsigned char *) base[0];
|
||||||
unsigned int msg_len = (unsigned int) base[1];
|
unsigned int msg_len = (unsigned int) base[1];
|
||||||
unsigned char *key = (unsigned char *) base[2];
|
unsigned char *key = (unsigned char *) base[2];
|
||||||
@@ -174,20 +171,51 @@ void entry_async(uint64_t *base)
|
|||||||
unsigned char *mul2 = (unsigned char *) base[5];
|
unsigned char *mul2 = (unsigned char *) base[5];
|
||||||
unsigned char *mul3 = (unsigned char *) base[6];
|
unsigned char *mul3 = (unsigned char *) base[6];
|
||||||
|
|
||||||
base[0] = 0;
|
expand_key(key, key_sched, 11, sbox, rc_lookup);
|
||||||
|
|
||||||
|
struct aes_sw_bernstein_data *data = (struct aes_sw_bernstein_data *) base;
|
||||||
|
event_new(&data->ev_data, 1, 0);
|
||||||
|
event_new(&data->ev_done, 1, 0);
|
||||||
|
|
||||||
|
data->count = 0;
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
data->t[i][j] = 0;
|
||||||
|
data->tsq[i][j] = 0;
|
||||||
|
data->tnum[i][j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (start));
|
for(i = 0; i < 16; i++)
|
||||||
aes128_encrypt_ecb(msg, msg_len, key, sbox, rc_lookup, mul2, mul3);
|
msg_old[i] = msg[i];
|
||||||
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (end));
|
|
||||||
|
|
||||||
if(2 * end - start - 64 > 0)
|
for(addr = sbox; addr < sbox + 256; addr += 64)
|
||||||
|
inv_va(addr);
|
||||||
|
|
||||||
|
|
||||||
|
start = get_ticks();
|
||||||
|
aes128_encrypt_ecb(msg, msg_len, key, sbox, key_sched, mul2, mul3);
|
||||||
|
timing = (double) (get_ticks() - start);
|
||||||
|
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
timer_register_int(2 * end - start - 64);
|
data->t[i][msg_old[i]] += timing;
|
||||||
wfi();
|
data->tsq[i][msg_old[i]] += (timing * timing);
|
||||||
|
data->tnum[i][msg_old[i]] += 1;
|
||||||
|
|
||||||
|
data->count++;
|
||||||
|
data->ttotal += timing;
|
||||||
}
|
}
|
||||||
|
|
||||||
base[0]++;
|
iter_count++;
|
||||||
if(base[0] % 100000 == 0) task_resched();
|
if(iter_count % 100000 == 0)
|
||||||
|
{
|
||||||
|
if(event_try(&data->ev_data, 1))
|
||||||
|
event_wait(&data->ev_done);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
222
c8_remote/main.c
222
c8_remote/main.c
@@ -4,17 +4,20 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <zconf.h>
|
||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "payload.h"
|
#include "payload.h"
|
||||||
#include "usb_helpers.h"
|
#include "usb_helpers.h"
|
||||||
|
#include "bootrom_addr.h"
|
||||||
|
#include "bootrom_type.h"
|
||||||
|
|
||||||
#ifdef CHECKM8_LOGGING
|
#ifdef CHECKM8_LOGGING
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -160,6 +163,7 @@ struct aes_pointers
|
|||||||
|
|
||||||
struct aes_pointers *install_aes_data(struct pwned_device *dev)
|
struct aes_pointers *install_aes_data(struct pwned_device *dev)
|
||||||
{
|
{
|
||||||
|
int close;
|
||||||
struct aes_pointers *res = malloc(sizeof(struct aes_pointers));
|
struct aes_pointers *res = malloc(sizeof(struct aes_pointers));
|
||||||
|
|
||||||
unsigned char sbox[256] =
|
unsigned char sbox[256] =
|
||||||
@@ -224,11 +228,16 @@ struct aes_pointers *install_aes_data(struct pwned_device *dev)
|
|||||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||||
};
|
};
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
if(is_device_session_open(dev)) close = 0;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
printf("failed to open device session\n");
|
close = 1;
|
||||||
free(res);
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
return NULL;
|
{
|
||||||
|
printf("failed to open device session\n");
|
||||||
|
free(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res->addr_sbox = install_data(dev, SRAM, sbox, 256);
|
res->addr_sbox = install_data(dev, SRAM, sbox, 256);
|
||||||
@@ -263,11 +272,14 @@ struct aes_pointers *install_aes_data(struct pwned_device *dev)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
if(close)
|
||||||
{
|
{
|
||||||
printf("failed to close device session\n");
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
free(res);
|
{
|
||||||
return NULL;
|
printf("failed to close device session\n");
|
||||||
|
free(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -351,58 +363,52 @@ void aes_sw(struct pwned_device *dev)
|
|||||||
close_device_session(dev);
|
close_device_session(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void aes_sw_bernstein(struct pwned_device *dev)
|
DEV_PTR_T aes_sw_bernstein(struct pwned_device *dev)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
double timing;
|
|
||||||
|
|
||||||
double packets = 0;
|
|
||||||
double ttotal = 0;
|
|
||||||
double t[16][256] = {0};
|
|
||||||
double tsq[16][256] = {0};
|
|
||||||
long long tnum[16][256] = {0};
|
|
||||||
double u[16][256] = {0};
|
|
||||||
double udev[16][256] = {0};
|
|
||||||
|
|
||||||
DEV_PTR_T addr_data, addr_key, addr_async_buf;
|
DEV_PTR_T addr_data, addr_key, addr_async_buf;
|
||||||
|
|
||||||
unsigned char data[16];
|
unsigned char data[16];
|
||||||
unsigned char key[16];
|
unsigned char key[16];
|
||||||
|
memset(key, 0, 16);
|
||||||
|
|
||||||
for(j = 0; j < 16; j++)
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
key[j] = random();
|
{
|
||||||
|
printf("failed to open device session\n");
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct dev_cmd_resp *resp;
|
struct dev_cmd_resp *resp;
|
||||||
struct aes_pointers *ptrs = install_aes_data(dev);
|
struct aes_pointers *ptrs = install_aes_data(dev);
|
||||||
if(ptrs == NULL)
|
if(ptrs == NULL)
|
||||||
{
|
{
|
||||||
printf("failed to install aes constants\n");
|
printf("failed to install aes constants\n");
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_data = install_data(dev, SRAM, data, 16);
|
addr_data = install_data(dev, SRAM, data, 16);
|
||||||
if(addr_data == DEV_PTR_NULL)
|
if(addr_data == DEV_PTR_NULL)
|
||||||
{
|
{
|
||||||
printf("failed to install aes data\n");
|
printf("failed to install aes data\n");
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_key = install_data(dev, SRAM, key, 16);
|
addr_key = install_data(dev, SRAM, key, 16);
|
||||||
if(addr_key == DEV_PTR_NULL)
|
if(addr_key == DEV_PTR_NULL)
|
||||||
{
|
{
|
||||||
printf("failed to install aes key\n");
|
printf("failed to install aes key\n");
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_SYNC, SRAM)))
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_SYNC, SRAM)))
|
||||||
{
|
{
|
||||||
printf("failed to install sync payload\n");
|
printf("failed to install sync payload\n");
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_AES_SW, SRAM)))
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_AES_SW, SRAM)))
|
||||||
{
|
{
|
||||||
printf("failed to install aes payload\n");
|
printf("failed to install aes payload\n");
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
||||||
@@ -410,79 +416,24 @@ void aes_sw_bernstein(struct pwned_device *dev)
|
|||||||
{
|
{
|
||||||
printf("failed to execute sync payload\n");
|
printf("failed to execute sync payload\n");
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
return;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
addr_async_buf = setup_payload_async(dev, PAYLOAD_AES_SW, 32,
|
addr_async_buf = setup_payload_async(dev, PAYLOAD_AES_SW,
|
||||||
7, addr_data, 16, addr_key,
|
sizeof(struct aes_sw_bernstein_data),
|
||||||
ptrs->addr_sbox, ptrs->addr_rc, ptrs->addr_mul2, ptrs->addr_mul3);
|
7, addr_data, 16, addr_key,
|
||||||
|
ptrs->addr_sbox, ptrs->addr_rc, ptrs->addr_mul2, ptrs->addr_mul3);
|
||||||
run_payload_async(dev, PAYLOAD_AES_SW);
|
run_payload_async(dev, PAYLOAD_AES_SW);
|
||||||
close_device_session(dev);
|
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
for(i = 0; i < 1000000; i++)
|
|
||||||
{
|
{
|
||||||
for(j = 0; j < 16; j++)
|
printf("failed to close device session\n");
|
||||||
data[j] = random();
|
return DEV_PTR_NULL;
|
||||||
|
|
||||||
resp = write_gadget(dev, addr_data, data, 16);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
|
||||||
printf("failed to update data\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
|
|
||||||
resp = execute_payload(dev, PAYLOAD_AES_SW, 0, 7,
|
|
||||||
addr_data, 16, addr_key,
|
|
||||||
ptrs->addr_sbox, ptrs->addr_rc, ptrs->addr_mul2, ptrs->addr_mul3);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
|
||||||
printf("failed to execute sw AES payload\n");
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
timing = (double) resp->retval;
|
|
||||||
printf("%i) -> got timing %f\n", i, timing);
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
|
|
||||||
for(j = 0; j < 16; j++)
|
|
||||||
{
|
|
||||||
++packets;
|
|
||||||
ttotal += timing;
|
|
||||||
t[j][data[j]] += timing;
|
|
||||||
tsq[j][data[j]] += timing * timing;
|
|
||||||
tnum[j][data[j]] += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 256; j++)
|
|
||||||
{
|
|
||||||
u[i][j] = t[i][j] / tnum[i][j];
|
|
||||||
udev[i][j] = tsq[i][j] / tnum[i][j];
|
|
||||||
udev[i][j] -= u[i][j] * u[i][j];
|
|
||||||
udev[i][j] = sqrt(udev[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
for(j = 0; j < 256; j++)
|
|
||||||
{
|
|
||||||
printf("%2d %4d %3d %lld %.3f %.3f %.3f %.3f\n",
|
|
||||||
i, 16, j, tnum[i][j], u[i][j], udev[i][j],
|
|
||||||
u[i][j] - (ttotal / packets), udev[i][j] / sqrt(tnum[i][j])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uninstall_all_payloads(dev);
|
|
||||||
uninstall_all_data(dev);
|
|
||||||
free(ptrs);
|
free(ptrs);
|
||||||
|
return addr_async_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_task_exit(struct pwned_device *dev)
|
void usb_task_exit(struct pwned_device *dev)
|
||||||
@@ -539,7 +490,15 @@ void usb_task_exit(struct pwned_device *dev)
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
struct dev_cmd_resp *resp;
|
struct dev_cmd_resp *resp;
|
||||||
|
struct aes_sw_bernstein_data *data;
|
||||||
struct pwned_device *dev = exploit_device();
|
struct pwned_device *dev = exploit_device();
|
||||||
|
DEV_PTR_T addr_async_buf;
|
||||||
|
|
||||||
|
int j, b;
|
||||||
|
double u[16][256];
|
||||||
|
double udev[16][256];
|
||||||
|
double taverage;
|
||||||
|
|
||||||
if(dev == NULL || dev->status == DEV_NORMAL)
|
if(dev == NULL || dev->status == DEV_NORMAL)
|
||||||
{
|
{
|
||||||
printf("Failed to exploit device\n");
|
printf("Failed to exploit device\n");
|
||||||
@@ -549,7 +508,84 @@ int main()
|
|||||||
fix_heap(dev);
|
fix_heap(dev);
|
||||||
demote_device(dev);
|
demote_device(dev);
|
||||||
|
|
||||||
aes_sw_bernstein(dev);
|
addr_async_buf = aes_sw_bernstein(dev);
|
||||||
|
printf("got async buf ptr %llx\n", addr_async_buf);
|
||||||
|
if(addr_async_buf == DEV_PTR_NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
sleep(15);
|
||||||
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
|
{
|
||||||
|
printf("failed to open device session");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = execute_gadget(dev, ADDR_EVENT_NOTIFY, 0, 1,
|
||||||
|
addr_async_buf + offsetof(struct aes_sw_bernstein_data, ev_data));
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
printf("failed to signal for data\n");
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
resp = read_gadget(dev, addr_async_buf, sizeof(struct aes_sw_bernstein_data));
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
printf("failed to get data from device\n");
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (struct aes_sw_bernstein_data *) resp->data;
|
||||||
|
printf("have count %lli\n", data->count);
|
||||||
|
|
||||||
|
taverage = data->ttotal / (double) data->count;
|
||||||
|
for(j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
for(b = 0; b < 256; b++)
|
||||||
|
{
|
||||||
|
u[j][b] = data->t[j][b] / data->tnum[j][b];
|
||||||
|
udev[j][b] = data->tsq[j][b] / data->tnum[j][b];
|
||||||
|
udev[j][b] -= u[j][b] * u[j][b];
|
||||||
|
udev[j][b] = sqrt(udev[j][b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
for(b = 0; b < 256; b++)
|
||||||
|
{
|
||||||
|
printf("%2d %3d %lli %.3f %.3f %.3f %.3f\n",
|
||||||
|
j, b, (long long) data->tnum[j][b],
|
||||||
|
u[j][b], udev[j][b],
|
||||||
|
u[j][b] - taverage, udev[j][b] / sqrt(data->tnum[j][b])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
resp = execute_gadget(dev, ADDR_EVENT_NOTIFY, 0, 1,
|
||||||
|
addr_async_buf + offsetof(struct aes_sw_bernstein_data, ev_done));
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
printf("failed to signal data end\n");
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
|
{
|
||||||
|
printf("failed to close device session\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free_device(dev);
|
free_device(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CHECKM8_TOOL_CHECKM8_CONFIG_H
|
#ifndef CHECKM8_TOOL_CHECKM8_CONFIG_H
|
||||||
#define CHECKM8_TOOL_CHECKM8_CONFIG_H
|
#define CHECKM8_TOOL_CHECKM8_CONFIG_H
|
||||||
|
|
||||||
//#define CHECKM8_LOGGING
|
#define CHECKM8_LOGGING
|
||||||
|
|
||||||
//#define WITH_ARDUINO
|
//#define WITH_ARDUINO
|
||||||
#define ARDUINO_DEV "/dev/ttyACM0"
|
#define ARDUINO_DEV "/dev/ttyACM0"
|
||||||
|
|||||||
Reference in New Issue
Block a user