/* Example GF(2^m) Elliptic Curve Diffie-Hellman program for very constrained environments. Uses point compression. Stack-only memory allocation. 16-bit version. The Koblitz curve variant is ideal for wireless sensor networks. Use with this mirdef.h header (for a PC using MS C) #define MR_LITTLE_ENDIAN #define MIRACL 16 #define mr_utype short #define MR_IBITS 32 #define MR_LBITS 32 #define mr_unsign32 unsigned int #define mr_dltype int #define MR_DLTYPE_IS_INT #define MR_STATIC 11 #define MR_ALWAYS_BINARY #define MR_NOASM #define MR_STRIPPED_DOWN #define MR_GENERIC_MT #define MAXBASE ((mr_small)1<<(MIRACL-1)) #define MR_BITSINCHAR 8 #define MR_NO_SS #define MR_SIMPLE_BASE #define MR_SIMPLE_IO and also possibly #define MR_NO_FILE_IO #define MR_NO_STANDARD_IO Build the library from these modules (Example using MS C compiler) -------------------------------- 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 mrec2m.c cl /c /O2 /W3 mrgf2m.c rem rem Create library 'miracl.lib' del miracl.lib lib /OUT:miracl.lib mrbits.obj mrio1.obj lib /OUT:miracl.lib miracl.lib mrarth0.obj mrarth1.obj mrcore.obj lib /OUT:miracl.lib miracl.lib mrec2m.obj mrgf2m.obj del mr*.obj rem Create the program cl /O2 ecdh2m16.c miracl.lib ------------------------------- On an msp430, try using this mirdef.h #define MIRACL 16 #define MR_LITTLE_ENDIAN #define mr_utype int #define mr_unsign32 unsigned long #define mr_dltype long #define mr_unsign64 unsigned long long #define MR_IBITS 16 #define MR_LBITS 32 #define MR_NOASM #define MR_NO_FILE_IO #define MR_STATIC 11 #define MR_ALWAYS_BINARY #define MAXBASE ((mr_small)1<<(MIRACL-1)) #define MR_BITSINCHAR 8 #define MR_GENERIC_MT #define MR_STRIPPED_DOWN #define MR_SIMPLE_IO #define MR_SIMPLE_BASE #define MR_NO_SS #define MR_SMALL_EWINDOW #define MR_NO_STANDARD_IO */ #include #include #include "miracl.h" #define HEXDIGS (MIRACL/4) /* !!!!!! THIS CODE AND THESE ROMS ARE NOW CREATED AUTOMATICALLY USING THE ROMAKER2.C APPLICATION !!!!!!!! */ /* !!!!!! READ COMMENTS IN ROMAKER2.C !!!!!! */ #define CURVE_M 163 #define CURVE_A 7 #define CURVE_B 6 #define CURVE_C 3 /* NIST b163 elliptic curve Y^2+XY=X^3+A.X^2+B (from nist163.ecs). Irreducible polynomial is x^163+x^7+x^6+x^3+1. Here is stored B, the group order q, and the generator G(x,y) */ /* static const mr_small rom[]= {0x05FD,0x4A32,0x7874,0x512F,0xEB10,0x1481,0x53CA,0xB8C9,0x1907,0x0A60,2, 0x4C33,0xA423,0x0C12,0x77E7,0x92FE,0x0002,0,0,0,0,4, 0x3E36,0xE834,0x4637,0xD499,0x1168,0xA099,0xD57E,0x86A2,0xA162,0xF0EB,3, 0x24F1,0x7973,0x5C0C,0xB11C,0xD545,0xA2CD,0x094F,0x71A0,0xBC6C,0xD51F,0}; */ /* NIST k163 Koblitz curve */ static const mr_small rom[]= { 0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0xA5EF,0x99F8,0xCC0D,0xA2E0,0x0108,0x2,0x0,0x0,0x0,0x0,0x4, 0xA80F,0x109C,0xE90E,0x272D,0x911D,0x37CA,0x7A2B,0x5EF8,0x0B47,0x96C3,0x3, 0x6391,0xD6E7,0xA253,0x2923,0x142D,0xBABB,0x1DC3,0x8BB4,0x0E4C,0x947D,0x3}; #define WINDOW 4 /* 2^4 =16 precomputed points based on fixed generator G(x,y) */ /* (created using romaker2.c program with window size of 4) */ /* standard curve 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, 0x3e36,0xe834,0x4637,0xd499,0x1168,0xa099,0xd57e,0x86a2,0xa162,0xf0eb,0x3, 0x24f1,0x7973,0x5c0c,0xb11c,0xd545,0xa2cd,0x94f,0x71a0,0xbc6c,0xd51f,0x0, 0x9372,0x5fd,0xfdf2,0xaa17,0xe974,0x6648,0x5c03,0x31dd,0xf527,0x75f1,0x2, 0x90e0,0xdcf9,0x7c6a,0x7911,0xf662,0x5d2f,0xbdb2,0x9865,0x4960,0xb091,0x0, 0x87a6,0x78a8,0xfe58,0xe478,0x2364,0x3d3d,0xb263,0x3b85,0x885e,0x34c6,0x5, 0x3598,0xef27,0xe436,0xa6d7,0x1bd9,0x5300,0x731c,0x75cc,0x4f74,0xbf41,0x3, 0x5f08,0x4f68,0xaf88,0x6f8d,0x1b1f,0xd1c7,0x13ff,0x6f49,0x682a,0xbaa8,0x2, 0x1336,0xd530,0xdd1e,0xb4f6,0x423b,0x6454,0xaf45,0x4eb,0xe401,0x65c6,0x2, 0xc73d,0xa700,0x2a26,0x6f84,0xf5fd,0xe8f5,0x6da9,0x4db,0xdc95,0x48fc,0x6, 0x57cb,0x1db7,0x42ba,0xb5bf,0x25b4,0xabfd,0x5be3,0x466e,0x7012,0x2cf2,0x7, 0xd12e,0xeb7a,0x8e87,0x47e3,0x4ef1,0x5f9c,0x5483,0x2fcd,0x822e,0x3893,0x0, 0xbf09,0x7c98,0x9589,0xa41f,0xa2a3,0x680c,0x3842,0xdfa8,0x1659,0xedd4,0x1, 0x3d19,0xa346,0x4bb0,0xaf8c,0x658a,0x2288,0xc40d,0x84b3,0x449b,0x90cd,0x2, 0xbf11,0x6bb4,0x6afa,0x5e99,0xe97a,0x9b2a,0x1307,0xff21,0x8239,0xfbf5,0x5, 0xc649,0x4ab8,0x2ee,0x2fcf,0xfb85,0x3c7e,0x9ad9,0x76f0,0x45da,0xdbca,0x7, 0x93af,0xeeba,0xf276,0x59ad,0x3760,0xd25e,0xb2c1,0x3292,0x1b84,0x271d,0x4, 0x391c,0x37f9,0xfd60,0xf423,0x9624,0xbf07,0x36e0,0x4c90,0x5e19,0x6307,0x4, 0xdfb5,0xb726,0x49b3,0x38c3,0x88b7,0x6e09,0x4141,0x87b5,0xd73b,0xcb8,0x2, 0xdb88,0xd1ac,0x1fcc,0x64ca,0xfa73,0x690d,0x8b6f,0xc670,0x3919,0xb44b,0x2, 0x67d9,0x2b3f,0xcb1e,0xc01c,0xdcc8,0x5311,0xdd9a,0xdb9f,0x31e,0x9118,0x0, 0xd6e,0x9a5c,0x152f,0x4e99,0x3232,0xaf85,0xdccc,0x8db0,0x58d7,0xef0f,0x5, 0x3148,0x6db6,0x7e0a,0xefdd,0x9e67,0xcc81,0x79bc,0x56a9,0x69b4,0x8d11,0x3, 0xb917,0x8670,0xa2ac,0x3d61,0x588a,0x6ed8,0x4655,0x5cc9,0x413e,0x8096,0x2, 0x5f72,0xd871,0x6e6,0xc2ce,0x5c77,0xd50c,0xa69b,0x1553,0xfadc,0x8a20,0x2, 0x77b2,0x9dd0,0x8893,0xb297,0x17bb,0x7aa6,0xc172,0xadba,0xa9a2,0xf57d,0x1, 0xbbe2,0x6800,0xd74e,0x837a,0xcd95,0xdac7,0xc382,0x1082,0x4b2,0xb5ec,0x0, 0x5328,0x4383,0xd58b,0xa986,0x7c4e,0x8d7f,0x2a8d,0xfd64,0x62d4,0x6d44,0x3, 0x1e9,0xf199,0x3930,0x6099,0x8e9b,0x67c9,0xc90d,0x1ab9,0x4593,0x5d7f,0x6, 0x752,0x39e1,0x6730,0xde36,0xdb73,0xa867,0x53b5,0x5bcb,0x56c0,0x6b5e,0x3, 0xdcaa,0xaf59,0xf9ff,0x8bdb,0xc861,0x2221,0x5c1a,0x52b4,0x9b1f,0x221a,0x6}; */ /* Koblitz curve */ 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, 0xa80f,0x109c,0xe90e,0x272d,0x911d,0x37ca,0x7a2b,0x5ef8,0xb47,0x96c3,0x3, 0x6391,0xd6e7,0xa253,0x2923,0x142d,0xbabb,0x1dc3,0x8bb4,0xe4c,0x947d,0x3, 0x995f,0xc028,0xc193,0x2522,0xd939,0x5e65,0xa7b2,0xb529,0xbfa7,0xcf3b,0x3, 0x8b9b,0x15a9,0x596,0x8dc,0xf769,0xb43,0x9dbe,0xf449,0xd1b5,0x469e,0x3, 0x6d58,0x8430,0x716f,0x9e47,0xa1e1,0xb642,0xc627,0x42a3,0xc42d,0x3bc0,0x4, 0x22c5,0x4777,0x1328,0x7d37,0xccee,0xf2aa,0x48da,0xb649,0x1975,0x3258,0x4, 0xf8ec,0x9f6f,0x657a,0x5407,0x6dd,0x64b6,0xd3c4,0x2ed2,0xb3ce,0xb359,0x2, 0xc1bc,0xe161,0x2aaf,0xa168,0xe151,0xb399,0xe43e,0x50e2,0x3d25,0x36f5,0x2, 0x1b3d,0xe2e5,0x6c41,0xfcb6,0x9a93,0xb168,0xb6a5,0xdb00,0x8b24,0x8b07,0x6, 0x986d,0x487e,0xb259,0x6e67,0xd461,0xa44b,0xdbb8,0xc3a4,0x1cb9,0x2c36,0x5, 0x16a6,0x69cf,0x1b27,0x95d6,0xae2f,0xa0e9,0x6e40,0x8aa0,0x1992,0x7663,0x0, 0x5bb6,0xd3db,0xe73e,0x9ba7,0x2a49,0xedfb,0x54c8,0xbd03,0xaa14,0x5776,0x4, 0x6cea,0x7952,0x9495,0x17d0,0x9857,0xc8ab,0x28e9,0x9918,0xbd1b,0x7088,0x4, 0x84c8,0xca42,0xbcd9,0x86b,0x5933,0x2169,0x3751,0x69cf,0x8eb1,0x6614,0x0, 0x443c,0xbaf9,0xd850,0x5c37,0x8c1d,0x102,0xc5ae,0x48dc,0x8924,0xbdf7,0x7, 0xae90,0x64f0,0x1c0a,0x2b1d,0x39ae,0xe292,0x6898,0x385,0x5c3c,0x7ea9,0x5, 0xe7d5,0x13c1,0xd193,0xaf75,0x7253,0xa5b4,0xff4,0x8ba0,0x6942,0x8ba5,0x5, 0x2a8,0xd2e8,0x2bd2,0xc23e,0xb5a9,0xbdbf,0x9b7b,0xf181,0x68b7,0xb5fc,0x1, 0xf539,0xef19,0xca18,0xcaf,0x47bd,0x53a,0xc744,0x6158,0x86eb,0x8a62,0x1, 0x1827,0x8c84,0x237f,0x8533,0xf9ad,0xcb90,0xff83,0x3e5b,0x5350,0x34b0,0x2, 0x7391,0x8ea3,0xb6d3,0xa2c2,0x99b4,0xf3db,0x1a6b,0x8f68,0xb788,0xca6d,0x7, 0x107a,0x10e9,0xdde2,0xfc4c,0x338,0xf2d9,0xd6d8,0xf4cf,0xffe0,0x28b5,0x7, 0xee97,0x44d7,0x81c2,0xb22,0xdcfa,0xcfc9,0xcf8,0x9ad9,0x21d3,0xc84b,0x7, 0x1333,0x4bd5,0xe63d,0xb9a2,0x6fe,0x695a,0xc8d8,0x78ed,0xcba4,0x9b42,0x7, 0xfb03,0xb995,0xba77,0x8c0a,0xc44c,0x6503,0x3b5a,0xaac6,0x816d,0x5822,0x6, 0x3659,0xef07,0x6e3f,0xd368,0x597f,0xde09,0xb5dc,0x1c4c,0x322d,0x8080,0x7, 0x8101,0x22b0,0x40d8,0x8ffd,0xff52,0x96fa,0x9d69,0x8858,0x9fc2,0x187b,0x4, 0x5955,0xf979,0xad7b,0x805b,0x8673,0x8e4,0x4f73,0x891e,0xdac6,0x7c21,0x3, 0xd66d,0xd03c,0xc732,0x2b2,0xad5c,0x60b8,0x6b89,0x1ac2,0x99bc,0x18d3,0x3, 0x8b4,0xa252,0xe5d,0x543a,0xe178,0x81,0x439,0x5ead,0xf33b,0x1d22,0x4}; #define WORDS 11 /* Number of words per big variable 11*16 > 163 */ /* 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 *PB; big A,B,a,b,q,pa,pb,key,x,y; ebrick2 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(1)]; /* ..and two elliptic curve points */ memset(mem_big, 0, MR_BIG_RESERVE(10)); /* clear the memory */ memset(mem_ecp, 0, MR_ECP_RESERVE(1)); 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); q=mirvar_mem(mip,mem_big,7); a=mirvar_mem(mip, mem_big, 8); b=mirvar_mem(mip, mem_big, 9); PB=epoint_init_mem(mip, mem_ecp, 0); /* initialise Elliptic Curve point */ irand(mip, 3L); /* change parameter for different random numbers */ promptr=0; init_big_from_rom(B,WORDS,rom,WORDS*4,&promptr); /* Read in curve parameter B from ROM */ /* don't need q or G(x,y) (we have precomputed table from it) */ init_big_from_rom(q,WORDS,rom,WORDS*4,&promptr); init_big_from_rom(x,WORDS,rom,WORDS*4,&promptr); init_big_from_rom(y,WORDS,rom,WORDS*4,&promptr); convert(mip,1,A); /* set A=1 */ /* Create precomputation instance from precomputed table in ROM */ ebrick2_init(&binst,prom,A,B,CURVE_M,CURVE_A,CURVE_B,CURVE_C,WINDOW,CURVE_M); /* offline calculations */ bigbits(mip,CURVE_M,a); /* A's random number */ mul2_brick(mip,&binst,a,pa,pa); /* a*G =(pa,ya) */ bigbits(mip,CURVE_M,b); /* B's random number */ mul2_brick(mip,&binst,b,pb,pb); /* b*G =(pb,yb) */ /* online calculations */ ecurve2_init(mip,CURVE_M,CURVE_A,CURVE_B,CURVE_C,A,B,FALSE,MR_PROJECTIVE); epoint2_set(mip,pb,pb,0,PB); /* decompress PB */ ecurve2_mult(mip,a,PB,PB); epoint2_get(mip,PB,key,key); /* since internal base is HEX, can use otnum instead of cotnum - avoiding a base change */ printf("Alice's Key= "); otnum(mip,key,stdout); epoint2_set(mip,pa,pa,0,PB); /* decompress PA */ ecurve2_mult(mip,b,PB,PB); epoint2_get(mip,PB,key,key); printf("Bob's Key= "); otnum(mip,key,stdout); /* clear the memory */ memset(mem_big, 0, MR_BIG_RESERVE(10)); memset(mem_ecp, 0, MR_ECP_RESERVE(1)); return 0; }