aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/codegen
diff options
context:
space:
mode:
authorJ08nY2019-11-26 20:37:19 +0100
committerJ08nY2019-11-26 20:37:19 +0100
commitbb00fee9702155586e674b9d6a3b838bd54baac2 (patch)
treecc35efecb92ae20dbab88694737a6b7d53a62782 /pyecsca/codegen
parent6784477dfc8f34f8d1a262517fe83ae70a59b325 (diff)
downloadpyecsca-codegen-bb00fee9702155586e674b9d6a3b838bd54baac2.tar.gz
pyecsca-codegen-bb00fee9702155586e674b9d6a3b838bd54baac2.tar.zst
pyecsca-codegen-bb00fee9702155586e674b9d6a3b838bd54baac2.zip
Add ASN.1 parsing and more utility functions, + commands sketch.
Diffstat (limited to 'pyecsca/codegen')
-rw-r--r--pyecsca/codegen/Makefile2
-rw-r--r--pyecsca/codegen/asn1.c97
-rw-r--r--pyecsca/codegen/asn1.h13
-rw-r--r--pyecsca/codegen/bn.c18
-rw-r--r--pyecsca/codegen/bn.h6
-rw-r--r--pyecsca/codegen/hal/host/uart.c2
-rw-r--r--pyecsca/codegen/hal/host/uart.h2
-rw-r--r--pyecsca/codegen/main.c63
-rw-r--r--pyecsca/codegen/simpleserial/simpleserial.c18
-rw-r--r--pyecsca/codegen/simpleserial/simpleserial.h5
10 files changed, 208 insertions, 18 deletions
diff --git a/pyecsca/codegen/Makefile b/pyecsca/codegen/Makefile
index 73a6eca..13122d0 100644
--- a/pyecsca/codegen/Makefile
+++ b/pyecsca/codegen/Makefile
@@ -1,6 +1,6 @@
TARGET = pyecsca-codegen
-SRC += main.c bn.c ecdh.c ecdsa.c hash/hash.c mult/mult.c prng/prng.c
+SRC += main.c bn.c ecdh.c ecdsa.c asn1.c hash/hash.c mult/mult.c prng/prng.c
CDEFS += -DHASH=HASH_SHA224
diff --git a/pyecsca/codegen/asn1.c b/pyecsca/codegen/asn1.c
new file mode 100644
index 0000000..3fd1f5f
--- /dev/null
+++ b/pyecsca/codegen/asn1.c
@@ -0,0 +1,97 @@
+#include "asn1.h"
+
+#include <stdlib.h>
+
+uint8_t *asn1_der_encode(const bn_t *r, const bn_t *s, size_t *result_len) {
+ uint8_t r_len = (uint8_t) bn_to_bin_size(r);
+ uint8_t s_len = (uint8_t) bn_to_bin_size(s);
+
+ // Pad with one zero byte in case most-significant bit of top byte is one.
+ uint8_t r_length = r_len + (bn_get_bit(r, r_len * 8) ? 1 : 0);
+ uint8_t s_length = s_len + (bn_get_bit(s, s_len * 8) ? 1 : 0);
+
+ // R and S are < 128 bytes, so 1 byte tag + 1 byte len + len bytes value
+ size_t seq_value_len = 2 + r_length + 2 + s_length;
+ size_t whole_len = seq_value_len;
+
+ // The SEQUENCE length might be >= 128, so more bytes of length
+ size_t seq_len_len = 0;
+ if (seq_value_len >= 128) {
+ size_t s = seq_value_len;
+ do {
+ seq_len_len++;
+ } while ((s = s >> 8));
+ }
+ // seq_len_len bytes for length and one for length of length
+ whole_len += seq_len_len + 1;
+
+ // 1 byte tag for SEQUENCE
+ whole_len += 1;
+
+ uint8_t *data = malloc(whole_len);
+ size_t i = 0;
+ data[i++] = 0x30; // SEQUENCE
+ if (seq_value_len < 128) {
+ data[i++] = (uint8_t) seq_value_len;
+ } else {
+ data[i++] = (uint8_t) (seq_len_len | (1 << 7));
+ for (size_t j = 0; j < seq_len_len; ++j) {
+ data[i++] = (uint8_t) (seq_value_len & (0xff << (8 * (seq_len_len - j - 1))));
+ }
+ }
+ data[i++] = 0x02; //INTEGER
+ data[i++] = r_length;
+ if (bn_get_bit(r, r_len * 8)) {
+ data[i++] = 0;
+ }
+ bn_to_bin(r, data + i);
+ i += r_len;
+ data[i++] = 0x02; //INTEGER
+ data[i++] = s_length;
+ if (bn_get_bit(s, s_len * 8)) {
+ data[i++] = 0;
+ }
+ bn_to_bin(s, data + i);
+ i += s_len;
+
+ return data;
+}
+
+bool asn1_der_decode(const uint8_t *sig, size_t sig_len, bn_t *r, bn_t *s) {
+ size_t i = 0;
+ if (sig[i++] != 0x30) {//SEQUENCE
+ return false;
+ }
+ size_t seq_value_len = 0;
+ if (!(sig[i] & 0x80)) {
+ seq_value_len = sig[i++];
+ } else {
+ size_t seq_len_len = sig[i++] & 0x7f;
+ while (seq_len_len > 0) {
+ seq_value_len |= (sig[i++] << (seq_len_len - 1));
+ seq_len_len--;
+ }
+ }
+
+ if (sig[i++] != 0x02) {//INTEGER
+ return false;
+ }
+ size_t r_length = sig[i++];
+ size_t r_offset = i;
+ i += r_length;
+
+ if (sig[i++] != 0x02) {//INTEGER
+ return false;
+ }
+ size_t s_length = sig[i++];
+ size_t s_offset = i;
+ i += s_length;
+
+ if (i != sig_len) {
+ return false;
+ }
+
+ bn_from_bin(sig + r_offset, r_length, r);
+ bn_from_bin(sig + s_offset, s_length, s);
+ return true;
+} \ No newline at end of file
diff --git a/pyecsca/codegen/asn1.h b/pyecsca/codegen/asn1.h
new file mode 100644
index 0000000..691755c
--- /dev/null
+++ b/pyecsca/codegen/asn1.h
@@ -0,0 +1,13 @@
+#ifndef ASN1_H_
+#define ASN1_H_
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include "bn.h"
+
+uint8_t *asn1_der_encode(const bn_t *r, const bn_t *s, size_t *result_len);
+
+bool asn1_der_decode(const uint8_t *sig, size_t sig_len, bn_t *r, bn_t *s);
+
+#endif //ASN1_H_ \ No newline at end of file
diff --git a/pyecsca/codegen/bn.c b/pyecsca/codegen/bn.c
index 26149ba..aa33124 100644
--- a/pyecsca/codegen/bn.c
+++ b/pyecsca/codegen/bn.c
@@ -12,6 +12,10 @@ void bn_clear(bn_t *bn) {
mp_clear(bn);
}
+int bn_from_bin(const uint8_t *data, size_t size, bn_t *out) {
+ return mp_from_ubin(out, data, size);
+}
+
int bn_from_hex(const char *data, bn_t *out) {
return mp_read_radix(out, data, 16);
}
@@ -21,6 +25,20 @@ int bn_from_int(uint64_t value, bn_t *out) {
return MP_OKAY;
}
+void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size) {
+ size_t ubin_size = mp_ubin_size(one);
+ size_t offset = size - ubin_size;
+ mp_to_ubin(one, data + offset, ubin_size, NULL);
+}
+
+void bn_to_bin(const bn_t *one, uint8_t *data) {
+ mp_to_ubin(one, data, mp_ubin_size(one), NULL);
+}
+
+size_t bn_to_bin_size(const bn_t *one) {
+ return mp_ubin_size(one);
+}
+
void bn_mod_add(bn_t *one, bn_t *other, bn_t *mod, bn_t *out) {
mp_addmod(one, other, mod, out);
}
diff --git a/pyecsca/codegen/bn.h b/pyecsca/codegen/bn.h
index 2cad2a0..0690310 100644
--- a/pyecsca/codegen/bn.h
+++ b/pyecsca/codegen/bn.h
@@ -15,8 +15,14 @@ bn_err bn_init(bn_t *bn);
void bn_copy(bn_t *from, bn_t *to);
void bn_clear(bn_t *bn);
+int bn_from_bin(const uint8_t *data, size_t size, bn_t *out);
int bn_from_hex(const char *data, bn_t *out);
int bn_from_int(uint64_t value, bn_t *out);
+
+void bn_to_binpad(const bn_t *one, uint8_t *data, size_t size);
+void bn_to_bin(const bn_t *one, uint8_t *data);
+size_t bn_to_bin_size(const bn_t *one);
+
void bn_mod_add(bn_t *one, bn_t *other, bn_t *mod, bn_t *out);
void bn_mod_sub(bn_t *one, bn_t *other, bn_t *mod, bn_t *out);
void bn_mod_mul(bn_t *one, bn_t *other, bn_t *mod, bn_t *out);
diff --git a/pyecsca/codegen/hal/host/uart.c b/pyecsca/codegen/hal/host/uart.c
index 3931d6d..0410462 100644
--- a/pyecsca/codegen/hal/host/uart.c
+++ b/pyecsca/codegen/hal/host/uart.c
@@ -2,6 +2,6 @@
void init_uart0(void) {}
-char input_ch_0(void) { return getchar(); }
+int input_ch_0(void) { return getchar(); }
void output_ch_0(char data) { putchar(data); } \ No newline at end of file
diff --git a/pyecsca/codegen/hal/host/uart.h b/pyecsca/codegen/hal/host/uart.h
index d6063bc..ffbc964 100644
--- a/pyecsca/codegen/hal/host/uart.h
+++ b/pyecsca/codegen/hal/host/uart.h
@@ -6,7 +6,7 @@
void init_uart0(void);
-char input_ch_0(void);
+int input_ch_0(void);
void output_ch_0(char data);
diff --git a/pyecsca/codegen/main.c b/pyecsca/codegen/main.c
index fba5dc2..a1d43da 100644
--- a/pyecsca/codegen/main.c
+++ b/pyecsca/codegen/main.c
@@ -6,21 +6,74 @@
#include "hash/hash.h"
#include "bn.h"
#include "prng.h"
-#include <string.h>
+#include "defs.h"
+#include <stdlib.h>
+
+static point_t *pubkey;
+static bn_t privkey;
+
+static curve_t *curve;
-uint8_t cmd_init_prng(uint8_t *data, uint16_t len) {
+static uint8_t cmd_init_prng(uint8_t *data, uint16_t len) {
prng_seed(data, len);
return 0;
}
+static uint8_t cmd_set_curve(uint8_t *data, uint16_t len) {
+ // need p, [params], gx, gy, n
+ return 0;
+}
+
+static uint8_t cmd_generate(uint8_t *data, uint16_t len) {
+ // generate a keypair, export privkey and affine pubkey
+ return 0;
+}
+
+static uint8_t cmd_set_privkey(uint8_t *data, uint16_t len) {
+ // set the current privkey
+ return 0;
+}
+
+static uint8_t cmd_set_pubkey(uint8_t *data, uint16_t len) {
+ // set the current pubkey
+ return 0;
+}
+
+static uint8_t cmd_scalar_mult(uint8_t *data, uint16_t len) {
+ // perform base point scalar mult with supplied scalar, return affine point.
+ return 0;
+}
+
+static uint8_t cmd_ecdh(uint8_t *data, uint16_t len) {
+ //perform ECDH with provided point (and current privkey), output shared secret
+ return 0;
+}
+
+static uint8_t cmd_ecdsa_sign(uint8_t *data, uint16_t len) {
+ //perform ECDSA signature on supplied data, output signature
+ return 0;
+}
+
+static uint8_t cmd_ecdsa_verify(uint8_t *data, uint16_t len) {
+ //perform ECDSA verification on supplied data (and current pubkey), output status
+ return 0;
+}
+
int main(void) {
platform_init();
prng_init();
init_uart();
trigger_setup();
simpleserial_init();
- simpleserial_addcmd('i', 4, cmd_init_prng);
- while(1)
- simpleserial_get();
+ simpleserial_addcmd('i', 32, cmd_init_prng);
+ simpleserial_addcmd('c', MAX_SS_LEN, cmd_set_curve);
+ simpleserial_addcmd('g', 0, cmd_generate);
+ simpleserial_addcmd('s', MAX_SS_LEN, cmd_set_privkey);
+ simpleserial_addcmd('w', MAX_SS_LEN, cmd_set_pubkey);
+ simpleserial_addcmd('m', MAX_SS_LEN, cmd_scalar_mult);
+ simpleserial_addcmd('e', MAX_SS_LEN, cmd_ecdh);
+ simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign);
+ simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify);
+ while(simpleserial_get());
return 0;
} \ No newline at end of file
diff --git a/pyecsca/codegen/simpleserial/simpleserial.c b/pyecsca/codegen/simpleserial/simpleserial.c
index ca7c54d..d15b309 100644
--- a/pyecsca/codegen/simpleserial/simpleserial.c
+++ b/pyecsca/codegen/simpleserial/simpleserial.c
@@ -3,7 +3,6 @@
#include "simpleserial.h"
#include <stdint.h>
#include "hal.h"
-#include <stdio.h>
typedef struct ss_cmd
{
@@ -12,12 +11,9 @@ typedef struct ss_cmd
uint8_t (*fp)(uint8_t*, uint16_t);
} ss_cmd;
-#define MAX_SS_CMDS 26
static ss_cmd commands[MAX_SS_CMDS];
static int num_commands = 0;
-#define MAX_SS_LEN 256
-
#define SS_VER_1_0 0
#define SS_VER_1_1 1
@@ -89,14 +85,17 @@ int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint16
return 0;
}
-void simpleserial_get(void)
+int simpleserial_get(void)
{
char ascii_buf[2*MAX_SS_LEN];
uint8_t data_buf[MAX_SS_LEN];
- char c;
+ int ci;
// Find which command we're receiving
- c = getch();
+ ci = getch();
+ if (ci == -1)
+ return 0;
+ char c = (char) ci;
int cmd;
for(cmd = 0; cmd < num_commands; cmd++)
@@ -107,7 +106,7 @@ void simpleserial_get(void)
// If we didn't find a match, give up right away
if(cmd == num_commands)
- return;
+ return 1;
// Receive characters until we fill the ASCII buffer
int i = 0;
@@ -125,7 +124,7 @@ void simpleserial_get(void)
// ASCII buffer is full: convert to bytes
// Check for illegal characters here
if(hex_decode(i, ascii_buf, data_buf))
- return;
+ return 1;
// Callback
uint8_t ret[1];
@@ -135,6 +134,7 @@ void simpleserial_get(void)
#if SS_VER == SS_VER_1_1
simpleserial_put('z', 1, ret);
#endif
+ return 1;
}
void simpleserial_put(char c, int size, uint8_t* output)
diff --git a/pyecsca/codegen/simpleserial/simpleserial.h b/pyecsca/codegen/simpleserial/simpleserial.h
index fa64865..a5dff81 100644
--- a/pyecsca/codegen/simpleserial/simpleserial.h
+++ b/pyecsca/codegen/simpleserial/simpleserial.h
@@ -6,6 +6,9 @@
#include <stdint.h>
+#define MAX_SS_CMDS 26
+#define MAX_SS_LEN 512
+
// Set up the SimpleSerial module
// This prepares any internal commands
void simpleserial_init(void);
@@ -32,7 +35,7 @@ int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint16
// - First character didn't match any known commands
// - One of the characters wasn't in [0-9|A-F|a-f]
// - Data was too short or too long
-void simpleserial_get(void);
+int simpleserial_get(void);
// Write some data to the serial port
// Prepends the character c to the start of the line