Commit bb7b09be authored by hark's avatar hark
parents 5b1c82dd f33444f2
......@@ -22,3 +22,14 @@ some things on ECC:
http://www.infosecwriters.com/Papers/Anoopms_ECC.pdf
http://www.johannes-bauer.com/compsci/ecc/
TODO:
- find something to hash the secret before using it for the symetric encryption (this is recommended in the uECC lib not sure why)
- generate random IV
- find something to hash pubkeys and make an address out of them
- calculate the pubkeys out of the privkeys instead of hardcoded pubkey to save some memory
- fix returning shared secret in the calcSharedSecret() function
- figure out why the RadioHead lib has problems with bigger message length
- fix the serial input of the arduino-tx so you can send messages to it
- make a program to generate keypairs and upload them to the pager
- displaying the received messages in a proper way
......@@ -18,15 +18,19 @@ aes_context ctx; // context for the cbc crypto stuff
#define ADDRESS 2
#define MESSAGE_SIZE 32
#define PAGER_MESSAGE_SIZE 57
RH_ASK driver(3000);
//#define MESSAGE_SIZE 64
//#define PAGER_MESSAGE_SIZE 99
RH_ASK driver(2000);
RHDatagram manager(driver, ADDRESS);
const struct uECC_Curve_t * curve = CURVE;
uint8_t sharedSecret[NUM_ECC_DIGITS];
// uECC keys 192bit
uint8_t pubkey[NUM_ECC_DIGITS*2] = {0x99, 0x61, 0xB5, 0x38, 0xB3, 0x83, 0x7E, 0xFB, 0xD9, 0x3F, 0x71, 0xA3, 0x81, 0x77, 0xB0, 0x48, 0x32, 0x29, 0x24, 0x6B, 0x76, 0x48, 0x9C, 0x7A, 0x70, 0xFD, 0x3F, 0xC4, 0xB8, 0xAB, 0x8E, 0xCD, 0x31, 0x88, 0x50, 0x2D, 0xE6, 0x53, 0x49, 0xE8, 0xC0, 0xB4, 0xB5, 0xC6, 0x4F, 0x97, 0x7F, 0x6B};
uint8_t privkey[NUM_ECC_DIGITS+1] = {0xAD, 0x98, 0x8E, 0xC4, 0x79, 0x1D, 0xE0, 0x2C, 0xEE, 0xF8, 0xB0, 0xAA, 0xC9, 0x3E, 0x6F, 0x9D, 0x1E, 0x5E, 0xF7, 0x96, 0xD7, 0x3F, 0x7F, 0x2E, 0xF4};
static int RNG(uint8_t *dest, unsigned size) {
......@@ -87,12 +91,12 @@ void generateKeys()
void hashSecret(uint8_t *p_secret)
{
// Serial.println("Secret:");
Serial.println("Secret:");
for( int i=0; i < NUM_ECC_DIGITS; i++){
// Serial.print(p_secret[i]);
// Serial.print(" ");
Serial.print(p_secret[i]);
Serial.print(" ");
}
// Serial.println("");
Serial.println("");
}
char * encryptAES(char* p_data, uint8_t *p_key)
......@@ -109,9 +113,8 @@ char * encryptAES(char* p_data, uint8_t *p_key)
char* decryptAES(char* p_data, uint8_t *p_key)
{
delay(100);
// Serial.println("Decrypting with key:");
hashSecret(sharedSecret);
// hashSecret(sharedSecret);
uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
aes_context ctx;
ctx = aes192_cbc_dec_start(p_key, iv);
......@@ -120,19 +123,20 @@ char* decryptAES(char* p_data, uint8_t *p_key)
Serial.print("decrypted-cbc:");
Serial.println(p_data);
return p_data;
delay(100);
}
void calcSharedSecret(uint8_t *p_pubkey, uint8_t *p_privkey)
{
delay(100);
if(uECC_valid_public_key(p_pubkey, curve) == 1){
// Serial.println("Valid pubkey");
uECC_shared_secret(p_pubkey, p_privkey, sharedSecret, curve);
hashSecret(sharedSecret);
// delay(100);
if(uECC_valid_public_key(p_pubkey, curve) == 1){
// Serial.println("Valid pubkey");
uECC_shared_secret(p_pubkey, p_privkey, sharedSecret, curve);
// hashSecret(sharedSecret);
}
delay(100);
// Serial.println("Calculating shared secret finished");
// else
// Serial.println("INVALID pubkey");
// delay(100);
//return sharedSecret;
}
......@@ -150,49 +154,74 @@ void setup()
uECC_set_rng(&RNG);
}
void display(char *msg)
{
/* char line1[16];
char line2[16];
for(int i=0; i < MESSAGE_SIZE ; i++){
if(i < 16)
line1[i] = msg[i];
else
line2[i-16] = msg[i];
};
*/
lcd.clear();
lcd.println(msg);
}
void loop()
{
// generateKeys(); //function to generate keys, have to make a program for this to run on a computer
// pager vars
char *decryptedMessage;
// crypto vars //
uint8_t remotePubkey[NUM_ECC_DIGITS*2];
uint8_t compressedPubkey[NUM_ECC_DIGITS+1];
// uint8_t sharedSecret[NUM_ECC_DIGITS];
//const struct uECC_Curve_t * curve = CURVE;
// Radio vars //
char receivedData[32];
uint8_t receivedData[MESSAGE_SIZE];
uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t buflen = sizeof(buf);
uint8_t from;
uint8_t to;
uint8_t id;
//if(sharedSecret[0] != 0 && receivedData[0] != 0){decryptAES((char*)receivedData, sharedSecret);}
manager.waitAvailable();
if (manager.recvfrom(buf, &buflen, &from, &to ,&id))
{
// Serial.print("got message from : ");
// Serial.print(from, DEC);
// Serial.print(" : ");
// Serial.print(id);
// Serial.println(" : ");
Serial.print("got message from : ");
Serial.print(from, DEC);
Serial.print(" : ");
Serial.print(id);
Serial.println(" : ");
if (id == 50){ // receiving a public key...
for (int i = 0 ; i < NUM_ECC_DIGITS+1 ; i++){
compressedPubkey[i] = buf[i];
}
//if(sharedSecret[0] == 0){calcSharedSecret(remotePubkey, privkey);}
uECC_decompress(compressedPubkey, remotePubkey, curve);
calcSharedSecret(remotePubkey, privkey);
}
if (id == 51){ // receiving an encrypted message...
// Serial.println("Storing received message");
for(int i = 0 ; i < 32; i++){
for(int i = 0 ; i < MESSAGE_SIZE; i++){
receivedData[i] = buf[i];
}
//if(sharedSecret[0] !=0){decryptAES((char*)receivedData, sharedSecret);}
decryptAES((char*)receivedData, sharedSecret);
}
}
if (id == 52){ // receiving a complete message (pubkey and message)...
for (int i = 0 ; i < NUM_ECC_DIGITS+1 ; i++){ // first 25 byts is the compressed uECC pubkey
compressedPubkey[i] = buf[i];
}
uECC_decompress(compressedPubkey, remotePubkey, curve);
calcSharedSecret(remotePubkey, privkey); // then 32 bytes of encrypted message
for(int i=NUM_ECC_DIGITS+1; i < NUM_ECC_DIGITS+33; i++){
receivedData[i-(NUM_ECC_DIGITS+1)] = buf[i];
}
decryptedMessage = decryptAES((char*)receivedData, sharedSecret);
display(decryptedMessage);
}
}
}
......@@ -6,21 +6,22 @@
#include <SPI.h> // Not actually used but needed to compile
#include <MemoryFree.h>
#define BLOCK_SIZE 16
#define NUM_BLOCKS 1
#define ADDRESS 5
#define NUM_ECC_DIGITS 24 //size of privkey, curvesize in bytes
#define CURVE uECC_secp192r1()
#define MESSAGE_SIZE 32
#define PAGER_MESSAGE_SIZE 57
//#define MESSAGE_SIZE 64
//#define PAGER_MESSAGE_SIZE 99
RH_ASK driver(3000);
RH_ASK driver(2000);
RHDatagram manager(driver, ADDRESS);
const struct uECC_Curve_t * curve = CURVE;
uint8_t sharedSecret[NUM_ECC_DIGITS];
#define BLOCK_SIZE 16
#define NUM_BLOCKS 1
uint8_t iv[16];
// uECC keys 192bit
uint8_t pubkey[NUM_ECC_DIGITS*2] = {0x67, 0xCF, 0x6C, 0x6F, 0x64, 0x19, 0xCC, 0xBF, 0x44, 0x60, 0x36, 0x2C, 0x99, 0x1D, 0x8C, 0x38, 0xFB, 0x6D, 0x18, 0xF2, 0x24, 0xEC, 0x8F, 0x8, 0xAB, 0x23, 0x76, 0xC, 0x4F, 0xA4, 0x63, 0x55, 0x26, 0xF8, 0x30, 0x9A, 0xA7, 0x6C, 0x55, 0x54, 0x10, 0x31, 0x0, 0xCA, 0x55, 0xF9, 0xC1, 0xFA};
......@@ -28,6 +29,49 @@ uint8_t privkey[NUM_ECC_DIGITS+1] = {0xF6, 0x8B, 0x9B, 0x7F, 0xD9, 0xF8, 0xF7, 0
uint8_t remotePubkey[NUM_ECC_DIGITS*2] = {0x99, 0x61, 0xB5, 0x38, 0xB3, 0x83, 0x7E, 0xFB, 0xD9, 0x3F, 0x71, 0xA3, 0x81, 0x77, 0xB0, 0x48, 0x32, 0x29, 0x24, 0x6B, 0x76, 0x48, 0x9C, 0x7A, 0x70, 0xFD, 0x3F, 0xC4, 0xB8, 0xAB, 0x8E, 0xCD, 0x31, 0x88, 0x50, 0x2D, 0xE6, 0x53, 0x49, 0xE8, 0xC0, 0xB4, 0xB5, 0xC6, 0x4F, 0x97, 0x7F, 0x6B};
static int RNG(uint8_t *dest, unsigned size) {
// Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of
// random noise). This can take a long time to generate random data if the result of analogRead(0)
// doesn't change very frequently.
while (size) {
uint8_t val = 0;
for (unsigned i = 0; i < 8; ++i) {
int init = analogRead(0);
int count = 0;
while (analogRead(0) == init) {
++count;
}
if (count == 0) {
val = (val << 1) | (init & 0x01);
} else {
val = (val << 1) | (count & 0x01);
}
}
*dest = val;
++dest;
--size;
}
// NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar.
return 1;
}
uint8_t * generateIV()
{
Serial.print("IV:");
uint8_t iv[NUM_ECC_DIGITS];
static uint8_t *ptr_iv = iv;
for( int i=0 ; i < NUM_ECC_DIGITS; i++){
RNG(ptr_iv, 1);
Serial.print(iv[i] ,DEC);
Serial.print(" ");
ptr_iv++;
}
Serial.println("");
return ptr_iv;
}
void hashSecret(uint8_t *p_secret)
{
Serial.println("Secret:");
......@@ -38,50 +82,47 @@ void hashSecret(uint8_t *p_secret)
Serial.println("");
}
char * encryptAES(char* p_data, uint8_t *p_key)
char * encryptAES(char* p_data, uint8_t *p_key, uint8_t *p_iv)
{
Serial.println("encrypting with key:");
hashSecret(p_key);
uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
aes_context ctx;
ctx = aes192_cbc_enc_start(p_key, iv);
aes192_cbc_enc_continue(ctx, p_data, 32);
aes192_cbc_enc_finish(ctx);
// Serial.print("encrypted-cbc:");
// Serial.println(p_data);
// Serial.println("encrypting with key:");
// hashSecret(p_key);
// uint8_t iv[] = {0,1,2,3,4,5,6,7,122,9,10,11,12,13,14,15};
aes192_cbc_enc(p_key, p_iv, p_data, 32);
Serial.print("encrypted-cbc:");
Serial.println(p_data);
return p_data;
}
char* decryptAES(char* p_data, uint8_t *p_key)
{
uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
uint8_t iv[] = {5,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
aes_context ctx;
ctx = aes192_cbc_dec_start(p_key, iv);
aes192_cbc_dec_continue(ctx, p_data, 32);
aes192_cbc_dec_finish(ctx);
Serial.print("decrypted-cbc:");
Serial.println(p_data);
// Serial.print("decrypted-cbc:");
// Serial.println(p_data);
return p_data;
}
uint8_t *calcSharedSecret(uint8_t *p_pubkey, uint8_t *p_privkey)
{
delay(100);
delay(100);
if(uECC_valid_public_key(p_pubkey, curve) == 1){
Serial.println("Valid pubkey");
// Serial.println("Valid pubkey");
uECC_shared_secret(p_pubkey, p_privkey, sharedSecret, curve);
hashSecret(sharedSecret);
// hashSecret(sharedSecret);
}
delay(100);
//return sharedSecret;
delay(100);
}
void sendPubkey()
{
uint8_t compressedPubkey[25];
uint8_t compressedPubkey[NUM_ECC_DIGITS+1];
uECC_compress(pubkey, compressedPubkey, curve);
manager.setHeaderId(50);
manager.sendto((uint8_t *)compressedPubkey, 25, 2);
manager.sendto((uint8_t *)compressedPubkey, NUM_ECC_DIGITS+1, 2);
manager.waitPacketSent();
Serial.println("sending public key...");
}
......@@ -89,35 +130,60 @@ void sendPubkey()
void sendMessage(char* msg)
{
Serial.println("Sending message...");
//char* msg = "hallo";
manager.setHeaderId(51);
manager.sendto((uint8_t *)msg, 32, 2);
manager.sendto((uint8_t *)msg, MESSAGE_SIZE, 2);
manager.waitPacketSent();
}
void sendAll(char* msg)
{
uint8_t pagerMsg[56];
uint8_t compressedPubkey[25];
// Serial.println("sending");
uint8_t pagerMsg[PAGER_MESSAGE_SIZE];
uint8_t compressedPubkey[NUM_ECC_DIGITS+1];
char *encData;
//uint8_t *iv;
uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
// uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);
uECC_compress(pubkey, compressedPubkey, curve);
encData = encryptAES(msg, sharedSecret);
Serial.println("Sending pubkey and message...");
for(int i=0; i < 24; i++){
// iv = generateIV();;
encData = encryptAES(msg, sharedSecret, iv);
for(int i=0; i < NUM_ECC_DIGITS+1; i++){ // put the compressed pubkey in the first 25 bytes
pagerMsg[i] = compressedPubkey[i];
}
for(int i=23; i < 56; i++){
pagerMsg[i] = encData[i];
for(int i=NUM_ECC_DIGITS+1; i < NUM_ECC_DIGITS+33; i++){ // put the encrypted message in the next 32 bytes
pagerMsg[i] = msg[i-(NUM_ECC_DIGITS+1)];
}
// manager.setHeaderId(52);
// manager.sendto((uint8_t *)pagerMsg, 56, 2);
// manager.waitPacketSent();
Serial.println("done sending..");
manager.setHeaderId(52);
manager.sendto((uint8_t *)pagerMsg, PAGER_MESSAGE_SIZE, 2);
manager.waitPacketSent();
}
void messageInput()
{
byte byteRead;
char data[32];
int i = 0;
while( i < 32){
if (Serial.available() > 0) {
byteRead = Serial.read();
if(byteRead==13){ // return presses, send message and break
Serial.println();
calcSharedSecret(remotePubkey, privkey);
sendAll(data);
break;
}
else
data[i] = byteRead;
Serial.write(byteRead);
i++;
}
}
}
void setup()
{
Serial.begin(9600); // Debugging only
Serial.println("crypto test");
Serial.println("TX init");
if (!manager.init())
Serial.println("init failed");
Serial.print("freeMemory()=");
......@@ -126,25 +192,13 @@ void setup()
void loop()
{
Serial.println("start..");
uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
// messageInput();
Serial.println("start");
generateIV();
// uint8_t iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
char data[] = "Hallo dit is een test";
char *encData;
char *decData;
Serial.print("freeMemory()=");
Serial.println(freeMemory());
calcSharedSecret(remotePubkey, privkey);
sendAll(data);
// delay(2000);
// sendAll(data);
sendPubkey();
delay(5000);
encData = encryptAES(data, sharedSecret);
delay(100);
sendMessage(encData);
decData = decryptAES(encData, sharedSecret);
delay(3000);
}
This diff is collapsed.
#ifndef _MICRO_ECC_H_
#define _MICRO_ECC_H_
#include <stdint.h>
/* Define as 1 to enable ECDSA functions, 0 to disable.
*/
#define ECC_ECDSA 1
/* Optimization settings. Define as 1 to enable an optimization, 0 to disable it.
ECC_SQUARE_FUNC - If enabled, this will cause a specific function to be used for (scalar) squaring instead of the generic
multiplication function. Improves speed by about 8% .
*/
#define ECC_SQUARE_FUNC 1
/* Inline assembly options.
Currently we do not provide any inline assembly options. In the future we plan to offer
inline assembly for AVR and 8051.
Note: You must choose the appropriate option for your target architecture, or compilation will fail
with strange assembler messages.
*/
#define ecc_asm_none 0
#ifndef ECC_ASM
#define ECC_ASM ecc_asm_none
#endif
/* Curve selection options. */
#define secp128r1 16
#define secp192r1 24
#define secp256r1 32
#define secp384r1 48
#ifndef ECC_CURVE
#define ECC_CURVE secp192r1
#endif
#if (ECC_CURVE != secp128r1 && ECC_CURVE != secp192r1 && ECC_CURVE != secp256r1 && ECC_CURVE != secp384r1)
#error "Must define ECC_CURVE to one of the available curves"
#endif
#define NUM_ECC_DIGITS ECC_CURVE
typedef struct EccPoint
{
uint8_t x[NUM_ECC_DIGITS];
uint8_t y[NUM_ECC_DIGITS];
} EccPoint;
/* ecc_make_key() function.
Create a public/private key pair.
You must use a new nonpredictable random number to generate each new key pair.
Outputs:
p_publicKey - Will be filled in with the point representing the public key.
p_privateKey - Will be filled in with the private key.
Inputs:
p_random - The random number to use to generate the key pair.
Returns 1 if the key pair was generated successfully, 0 if an error occurred. If 0 is returned,
try again with a different random number.
*/
int ecc_make_key(EccPoint *p_publicKey, uint8_t p_privateKey[NUM_ECC_DIGITS], uint8_t p_random[NUM_ECC_DIGITS]);
/* ecc_valid_public_key() function.
Determine whether or not a given point is on the chosen elliptic curve (ie, is a valid public key).
Inputs:
p_publicKey - The point to check.
Returns 1 if the given point is valid, 0 if it is invalid.
*/
int ecc_valid_public_key(EccPoint *p_publicKey);
/* ecdh_shared_secret() function.
Compute a shared secret given your secret key and someone else's public key.
Optionally, you can provide a random multiplier for resistance to DPA attacks. The random multiplier
should probably be different for each invocation of ecdh_shared_secret().
Outputs:
p_secret - Will be filled in with the shared secret value.
Inputs:
p_publicKey - The public key of the remote party.
p_privateKey - Your private key.
p_random - An optional random number to resist DPA attacks. Pass in NULL if DPA attacks are not a concern.
Returns 1 if the shared secret was computed successfully, 0 otherwise.
Note: It is recommended that you hash the result of ecdh_shared_secret before using it for symmetric encryption or HMAC.
If you do not hash the shared secret, you must call ecc_valid_public_key() to verify that the remote side's public key is valid.
If this is not done, an attacker could create a public key that would cause your use of the shared secret to leak information
about your private key. */
int ecdh_shared_secret(uint8_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint8_t p_privateKey[NUM_ECC_DIGITS], uint8_t p_random[NUM_ECC_DIGITS]);
#if ECC_ECDSA
/* ecdsa_sign() function.
Generate an ECDSA signature for a given hash value.
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
this function along with your private key and a random number.
You must use a new nonpredictable random number to generate each new signature.
Outputs:
r, s - Will be filled in with the signature values.
Inputs:
p_privateKey - Your private key.
p_random - The random number to use to generate the signature.
p_hash - The message hash to sign.
Returns 1 if the signature generated successfully, 0 if an error occurred. If 0 is returned,
try again with a different random number.
*/
int ecdsa_sign(uint8_t r[NUM_ECC_DIGITS], uint8_t s[NUM_ECC_DIGITS], uint8_t p_privateKey[NUM_ECC_DIGITS],
uint8_t p_random[NUM_ECC_DIGITS], uint8_t p_hash[NUM_ECC_DIGITS]);
/* ecdsa_verify() function.
Verify an ECDSA signature.
Usage: Compute the hash of the signed data using the same hash as the signer and
pass it to this function along with the signer's public key and the signature values (r and s).
Inputs:
p_publicKey - The signer's public key
p_hash - The hash of the signed data.
r, s - The signature values.
Returns 1 if the signature is valid, 0 if it is invalid.
*/
int ecdsa_verify(EccPoint *p_publicKey, uint8_t p_hash[NUM_ECC_DIGITS], uint8_t r[NUM_ECC_DIGITS], uint8_t s[NUM_ECC_DIGITS]);
#endif /* ECC_ECDSA */
/* ecc_bytes2native() function.
Convert an integer in standard octet representation to the native format.
Outputs:
p_native - Will be filled in with the native integer value.
Inputs:
p_bytes - The standard octet representation of the integer to convert.
*/
void ecc_bytes2native(uint8_t p_native[NUM_ECC_DIGITS], uint8_t p_bytes[NUM_ECC_DIGITS*4]);
/* ecc_native2bytes() function.
Convert an integer in native format to the standard octet representation.
Outputs:
p_bytes - Will be filled in with the standard octet representation of the integer.
Inputs:
p_native - The native integer value to convert.
*/
void ecc_native2bytes(uint8_t p_bytes[NUM_ECC_DIGITS*4], uint8_t p_native[NUM_ECC_DIGITS]);
#endif /* _MICRO_ECC_H_ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment