262 lines
9.9 KiB
C
262 lines
9.9 KiB
C
/*
|
|
|
|
Example Elliptic Curve Diffie-Hellman program for 8-bit constrained environments. Uses point compression.
|
|
Stack-only memory allocation
|
|
|
|
Use with this mirdef.h header (for a PC using MS C)
|
|
|
|
#define MR_LITTLE_ENDIAN
|
|
#define MIRACL 8
|
|
#define mr_utype char
|
|
#define MR_IBITS 32
|
|
#define MR_LBITS 32
|
|
#define mr_unsign32 unsigned int
|
|
#define mr_dltype short
|
|
#define MR_STATIC 20
|
|
#define MR_ALWAYS_BINARY
|
|
#define MR_NOASM
|
|
#define MR_STRIPPED_DOWN
|
|
#define MR_GENERIC_MT
|
|
#define MAXBASE ((mr_small)1<<(MIRACL-1))
|
|
#define MR_COMBA 20
|
|
#define MR_SPECIAL
|
|
#define MR_PSEUDO_MERSENNE
|
|
#define MR_BITSINCHAR 8
|
|
#define MR_SMALL_EWINDOW
|
|
#define MR_NO_ECC_MULTIADD
|
|
#define MR_NO_LAZY_REDUCTION
|
|
#define MR_SIMPLE_BASE
|
|
#define MR_SIMPLE_IO
|
|
|
|
Build the library from these modules (Example using MS C compiler)
|
|
|
|
mex 20 c mrcomba
|
|
rem In a real 8-bit setting, a suitable assembly language .mcs file would be used. Here we use C.
|
|
cl /c /O2 /W3 mrcore.c
|
|
cl /c /O2 /W3 mrarth0.c
|
|
cl /c /O2 /W3 mrarth1.c
|
|
cl /c /O2 /W3 mrio1.c
|
|
cl /c /O2 /W3 mrbits.c
|
|
cl /c /O2 /W3 mrcurve.c
|
|
cl /c /O2 /W3 mrsroot.c
|
|
cl /c /O2 /W3 mrjack.c
|
|
cl /c /O2 /W3 mrlucas.c
|
|
cl /c /O2 /W3 mrarth2.c
|
|
cl /c /O2 /W3 mrmonty.c
|
|
cl /c /O2 /W3 mrcomba.c
|
|
cl /c /O2 /W3 mrxgcd.c
|
|
cl /c /O2 /W3 mrebrick.c
|
|
|
|
rem
|
|
rem Create library 'miracl.lib'
|
|
del miracl.lib
|
|
|
|
lib /OUT:miracl.lib mrio1.obj mrmonty.obj mrcomba.obj mrxgcd.obj
|
|
lib /OUT:miracl.lib miracl.lib mrbits.obj mrarth2.obj mrlucas.obj mrjack.obj
|
|
lib /OUT:miracl.lib miracl.lib mrarth0.obj mrarth1.obj mrcore.obj mrebrick.obj
|
|
lib /OUT:miracl.lib miracl.lib mrcurve.obj mrsroot.obj
|
|
del mr*.obj
|
|
|
|
rem Create the program
|
|
|
|
cl /O2 ecdhp8.c miracl.lib
|
|
|
|
For Atmel AVR (atmega128) use
|
|
|
|
#define MR_LITTLE_ENDIAN
|
|
#define MIRACL 8
|
|
#define mr_utype char
|
|
#define MR_IBITS 16
|
|
#define MR_LBITS 32
|
|
#define mr_unsign32 unsigned long
|
|
#define mr_dltype int
|
|
#define mr_qltype long
|
|
#define MR_STATIC 20
|
|
#define MR_ALWAYS_BINARY
|
|
#define MR_STRIPPED_DOWN
|
|
#define MR_GENERIC_MT
|
|
#define MAXBASE ((mr_small)1<<(MIRACL-1))
|
|
#define MR_COMBA 20
|
|
#define MR_SPECIAL
|
|
#define MR_PSEUDO_MERSENNE
|
|
#define MR_NOASM
|
|
#define MR_BITSINCHAR 8
|
|
#define MR_NO_STANDARD_IO
|
|
#define MR_NO_FILE_IO
|
|
#define MR_NO_LAZY_REDUCTION
|
|
#define MR_NO_ECC_MULTIADD
|
|
#define MR_SIMPLE_BASE
|
|
#define MR_SIMPLE_IO
|
|
#define MR_SMALL_EWINDOW
|
|
#define MR_AVR
|
|
|
|
Note this last line is added manually - it will not be added by config
|
|
|
|
and execute
|
|
|
|
mex 20 avr4 mrcomba
|
|
|
|
Note that reading data from program memory (NVM) is a little complex on the AVR!
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "miracl.h"
|
|
|
|
/* !!!!!! THIS CODE AND THESE ROMS ARE NOW CREATED AUTOMATICALLY USING THE ROMAKER.C APPLICATION !!!!!!!! */
|
|
/* !!!!!! READ COMMENTS IN ROMAKER.C !!!!!! */
|
|
|
|
#define HEXDIGS (MIRACL/4)
|
|
#define CURVE_BITS 160
|
|
|
|
/* Pseudo Mersenne 160 bit elliptic curve Y^2=X^3-3X+383 modulo 2^160-57
|
|
Here is stored P, B, the group order q, and the generator G(x,y) */
|
|
|
|
|
|
#ifdef MR_AVR
|
|
__attribute__((__progmem__))
|
|
#endif
|
|
|
|
static const mr_small rom[]=
|
|
{
|
|
0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
|
0x7F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x25,0x32,0x7F,0x71,0x4B,0x4F,0xA0,0x01,0x3F,0x0E,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
|
|
0xf1,0x66,0x56,0xb7,0xee,0xbf,0x27,0xd0,0x4a,0xd0,0xb7,0x9,0x20,0x4e,0x59,0xed,0x5e,0xdc,0x8a,0xa,
|
|
0xda,0xc9,0x45,0x55,0xcc,0x6c,0x1c,0x11,0x9f,0x38,0x4d,0xac,0xd3,0x43,0x76,0xaf,0x5c,0x2d,0xfb,0x20};
|
|
|
|
#define WINDOW 4
|
|
|
|
/* 16 precomputed points based on fixed generator G(x,y) */
|
|
/* (created using romaker.c program with window size of 4) */
|
|
|
|
/* These values are only correct if MR_SPECIAL is defined! */
|
|
|
|
#ifdef MR_AVR
|
|
__attribute__((__progmem__))
|
|
#endif
|
|
static const mr_small prom[]=
|
|
{
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0xf1,0x66,0x56,0xb7,0xee,0xbf,0x27,0xd0,0x4a,0xd0,0xb7,0x9,0x20,0x4e,0x59,0xed,0x5e,0xdc,0x8a,0xa,
|
|
0xda,0xc9,0x45,0x55,0xcc,0x6c,0x1c,0x11,0x9f,0x38,0x4d,0xac,0xd3,0x43,0x76,0xaf,0x5c,0x2d,0xfb,0x20,
|
|
0xa,0xf8,0xdc,0xe5,0x96,0x7b,0xa2,0xad,0x89,0xa7,0xf2,0x19,0xfe,0xd6,0xcb,0xa0,0x91,0x44,0xaf,0xc6,
|
|
0x35,0xee,0xc1,0xa4,0x76,0xbe,0xda,0x91,0x5c,0xa3,0x6f,0xd9,0x24,0xe8,0x41,0x4f,0xe7,0x0,0xa,0x67,
|
|
0x16,0x9d,0xb1,0x30,0x2d,0xfa,0x9a,0x47,0x30,0x39,0x82,0xbb,0x39,0x7e,0x78,0x9e,0x1d,0xc9,0xa5,0x31,
|
|
0x64,0xe3,0x3,0x9b,0x4f,0xde,0x51,0x3f,0xb5,0x2,0x9f,0x68,0xe,0x65,0x3a,0x2f,0xae,0x4a,0xe9,0x79,
|
|
0xbf,0x66,0x86,0x3f,0xa0,0x5d,0x7f,0xc7,0x55,0x27,0x85,0x75,0xaa,0x9f,0x58,0x97,0x1f,0xec,0xe6,0xab,
|
|
0x92,0x36,0x32,0xf7,0x73,0x20,0x9d,0xdf,0x78,0x84,0x29,0x6d,0x3f,0x45,0x92,0xe7,0xd0,0x2d,0x64,0x2e,
|
|
0x62,0xd4,0x5d,0x1,0xe0,0x73,0x26,0xca,0xaa,0xcb,0xe7,0x87,0xf5,0xdd,0xa4,0xfe,0xd1,0xc7,0xbf,0xc7,
|
|
0x75,0x18,0x47,0xea,0x19,0xcb,0x4,0xd9,0x99,0x4f,0xc5,0x8b,0x57,0xf6,0xc0,0xe,0x11,0xaf,0x99,0x84,
|
|
0xdc,0x3b,0x49,0x31,0xb,0x77,0x55,0xdc,0x97,0xaa,0x56,0x7c,0x35,0x70,0x27,0x2c,0xd7,0xb5,0xee,0xc8,
|
|
0x4d,0x17,0x43,0xfe,0x80,0x8f,0x47,0x30,0xc2,0x83,0x91,0x94,0x17,0x65,0xa,0xfd,0x28,0xa5,0x4a,0x32,
|
|
0xb2,0x76,0xef,0xb8,0x49,0xdb,0xa,0xb0,0xb6,0x1a,0x5f,0xef,0x47,0x62,0x9f,0x37,0x7f,0xc,0xc,0x98,
|
|
0xe1,0x34,0x68,0x6b,0x46,0xe1,0x7,0x6c,0x4f,0x82,0xba,0x5d,0xf9,0xea,0xeb,0x69,0xa9,0xc2,0xa,0xa,
|
|
0x9e,0x9c,0xda,0xb0,0xfa,0xec,0x83,0xd1,0x38,0xc7,0x51,0x78,0x9d,0xe6,0xd4,0x5,0x83,0xde,0x56,0x1e,
|
|
0xf9,0x58,0xce,0x14,0x79,0xc7,0x63,0xa5,0x9b,0x10,0xf5,0x31,0x26,0x9c,0x1c,0x8b,0xba,0x7b,0x2b,0xcc,
|
|
0xdc,0x70,0xf7,0xc7,0xb5,0x3a,0xf0,0xc8,0x7d,0x5f,0x27,0xc1,0x4f,0x7b,0x26,0x84,0x8d,0xc4,0x88,0x9d,
|
|
0x7d,0x91,0xee,0x3e,0x20,0xc8,0xaf,0x22,0x5,0x47,0x58,0x4c,0x83,0xc6,0xae,0x76,0x6e,0x43,0x4b,0xd4,
|
|
0x54,0xf8,0xdf,0xa2,0xb9,0x4f,0xf5,0x83,0xfd,0x8e,0xbd,0xd7,0xf8,0xf0,0x4a,0xac,0xfa,0x13,0xa7,0xd0,
|
|
0xf3,0x25,0x61,0x4f,0x6b,0xec,0x13,0xdf,0xe1,0x4d,0x35,0x7e,0xba,0xf4,0xd9,0xa3,0xc,0x6e,0x82,0xb2,
|
|
0xf9,0xf4,0xf1,0x6d,0xce,0x72,0x63,0x7c,0x81,0x4b,0xaf,0x42,0xd8,0x85,0xa9,0xab,0xea,0xc9,0x1d,0x53,
|
|
0xb2,0xce,0xf9,0xd5,0x41,0x72,0xc8,0x5a,0x8f,0xc,0x75,0xbc,0xa9,0xf7,0x93,0xe5,0x6e,0xbe,0x76,0xd2,
|
|
0x6f,0x54,0xc9,0x15,0x86,0x48,0xe6,0x99,0xdc,0xcc,0x75,0x1a,0xfd,0xd6,0xd0,0x8c,0xcd,0x8,0xa7,0x39,
|
|
0xd0,0x64,0x2d,0xc,0xf3,0xa2,0xda,0x5d,0x96,0x76,0xf4,0x31,0x86,0xa,0x74,0xe7,0x6,0x60,0x29,0xb2,
|
|
0xbb,0xde,0x8,0x56,0x9f,0x8b,0x3f,0xff,0x30,0x4b,0xdc,0x32,0x4c,0x8f,0xb,0x63,0xd5,0x47,0x3f,0xb,
|
|
0xda,0x1c,0x77,0x84,0x5b,0x9d,0xaa,0x2f,0x77,0x6f,0xe8,0x1d,0x4e,0x69,0x6,0x8f,0x3d,0x7c,0xaf,0x7,
|
|
0xa1,0x42,0xae,0x2,0x24,0xa3,0x53,0x31,0x1f,0xe6,0x43,0x56,0x21,0x70,0x6e,0x1f,0x32,0xb3,0x17,0xe4,
|
|
0x51,0x4a,0xc0,0xd1,0xd1,0xb7,0xee,0xd6,0xc6,0xa8,0x3b,0x9a,0xe2,0xb8,0x11,0x8c,0x0,0xae,0x9b,0xdf,
|
|
0x3,0xbc,0x2c,0x78,0x5f,0xcf,0x24,0xba,0x7f,0x60,0x9,0x4c,0x8c,0x86,0xdd,0x11,0xfe,0x3f,0xe1,0xf5,
|
|
0xa0,0xb0,0x30,0xb6,0xb7,0x80,0xd8,0xb4,0x6a,0xbc,0x2e,0x43,0xaa,0x3b,0x4,0x28,0x13,0xef,0xa1,0x47};
|
|
|
|
#define WORDS 20 /* Number of words per big variable 20*8 = 160 */
|
|
|
|
/* Note that in a real application a source of real random numbers would be required, to
|
|
replace those generated by MIRACL's internal pseudo-random generator "bigbits"
|
|
Alternatively from a truly random and unguessable seed, use MIRACL's strong random
|
|
number generator */
|
|
|
|
/* Elliptic Curve Diffie-Hellman, using point compression to minimize bandwidth,
|
|
and precomputation to speed up off-line calculation */
|
|
|
|
|
|
int main()
|
|
{
|
|
int promptr;
|
|
epoint *PA,*PB;
|
|
big A,B,p,a,b,pa,pb,key,x,y;
|
|
ebrick binst;
|
|
miracl instance; /* create miracl workspace on the stack */
|
|
|
|
/* Specify base 16 here so that HEX can be read in directly without a base-change */
|
|
|
|
miracl *mip=mirsys(&instance,WORDS*HEXDIGS,16); /* size of bigs is fixed */
|
|
char mem_big[MR_BIG_RESERVE(10)]; /* we need 10 bigs... */
|
|
char mem_ecp[MR_ECP_RESERVE(2)]; /* ..and two elliptic curve points */
|
|
memset(mem_big, 0, MR_BIG_RESERVE(10)); /* clear the memory */
|
|
memset(mem_ecp, 0, MR_ECP_RESERVE(2));
|
|
|
|
A=mirvar_mem(mip, mem_big, 0); /* Initialise big numbers */
|
|
B=mirvar_mem(mip, mem_big, 1);
|
|
pa=mirvar_mem(mip, mem_big, 2);
|
|
pb=mirvar_mem(mip, mem_big, 3);
|
|
key=mirvar_mem(mip, mem_big, 4);
|
|
x=mirvar_mem(mip, mem_big, 5);
|
|
y=mirvar_mem(mip, mem_big, 6);
|
|
a=mirvar_mem(mip, mem_big, 7);
|
|
b=mirvar_mem(mip, mem_big, 8);
|
|
p=mirvar_mem(mip, mem_big, 9);
|
|
|
|
PA=epoint_init_mem(mip, mem_ecp, 0); /* initialise Elliptic Curve points */
|
|
PB=epoint_init_mem(mip, mem_ecp, 1);
|
|
|
|
irand(mip, 3L); /* change parameter for different random numbers */
|
|
|
|
promptr=0;
|
|
init_big_from_rom(p,WORDS,rom,WORDS*5,&promptr); /* Read in prime modulus p from ROM */
|
|
init_big_from_rom(B,WORDS,rom,WORDS*5,&promptr); /* Read in curve parameter B from ROM */
|
|
/* don't need q or G(x,y) (we have precomputed table from it) */
|
|
|
|
convert(mip,-3,A); /* set A=-3 */
|
|
|
|
/* Create precomputation instance from precomputed table in ROM */
|
|
|
|
ebrick_init(&binst,prom,A,B,p,WINDOW,CURVE_BITS);
|
|
|
|
/* offline calculations */
|
|
|
|
bigbits(mip,CURVE_BITS,a); /* A's random number */
|
|
mul_brick(mip,&binst,a,pa,pa); /* a*G =(pa,ya) */
|
|
bigbits(mip,CURVE_BITS,b); /* B's random number */
|
|
mul_brick(mip,&binst,b,pb,pb); /* b*G =(pb,yb) */
|
|
|
|
/* swap X values of point */
|
|
|
|
/* online calculations */
|
|
ecurve_init(mip,A,B,p,MR_PROJECTIVE);
|
|
epoint_set(mip,pb,pb,0,PB); /* decompress PB */
|
|
ecurve_mult(mip,a,PB,PB);
|
|
epoint_get(mip,PB,key,key);
|
|
|
|
/* since internal base is HEX, can use otnum instead of cotnum - avoiding a base change */
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf("Alice's Key= ");
|
|
otnum(mip,key,stdout);
|
|
#endif
|
|
epoint_set(mip,pa,pa,0,PB); /* decompress PA */
|
|
ecurve_mult(mip,b,PB,PB);
|
|
epoint_get(mip,PB,key,key);
|
|
#ifndef MR_NO_STANDARD_IO
|
|
printf("Bob's Key= ");
|
|
otnum(mip,key,stdout);
|
|
#endif
|
|
/* clear the memory */
|
|
|
|
memset(mem_big, 0, MR_BIG_RESERVE(10));
|
|
memset(mem_ecp, 0, MR_ECP_RESERVE(2));
|
|
|
|
return 0;
|
|
}
|