diff options
| author | J08nY | 2019-11-26 20:37:19 +0100 |
|---|---|---|
| committer | J08nY | 2019-11-26 20:37:19 +0100 |
| commit | bb00fee9702155586e674b9d6a3b838bd54baac2 (patch) | |
| tree | cc35efecb92ae20dbab88694737a6b7d53a62782 /pyecsca/codegen | |
| parent | 6784477dfc8f34f8d1a262517fe83ae70a59b325 (diff) | |
| download | pyecsca-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/Makefile | 2 | ||||
| -rw-r--r-- | pyecsca/codegen/asn1.c | 97 | ||||
| -rw-r--r-- | pyecsca/codegen/asn1.h | 13 | ||||
| -rw-r--r-- | pyecsca/codegen/bn.c | 18 | ||||
| -rw-r--r-- | pyecsca/codegen/bn.h | 6 | ||||
| -rw-r--r-- | pyecsca/codegen/hal/host/uart.c | 2 | ||||
| -rw-r--r-- | pyecsca/codegen/hal/host/uart.h | 2 | ||||
| -rw-r--r-- | pyecsca/codegen/main.c | 63 | ||||
| -rw-r--r-- | pyecsca/codegen/simpleserial/simpleserial.c | 18 | ||||
| -rw-r--r-- | pyecsca/codegen/simpleserial/simpleserial.h | 5 |
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 |
