diff --git a/mac.txt b/mac.txt
index 965e4ae..4123ce2 100644
--- a/mac.txt
+++ b/mac.txt
@@ -11,3 +11,7 @@ On a MAC using GCC, use the flag
when compiling MIRACL assembly language modules..
(Thanks Augusto)
+
+There is also a known problem with the mac port of g++ involving friend
+declarations in big.h and zzn.h. This can be solved by substituting the files
+in ./source/mac for the ones found in ./include and ./source
diff --git a/source/mac/big.cpp b/source/mac/big.cpp
new file mode 100644
index 0000000..f8196a4
--- /dev/null
+++ b/source/mac/big.cpp
@@ -0,0 +1,449 @@
+
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox MIRACL Crypto SDK. *
+ *
+The CertiVox MIRACL Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox MIRACL Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox MIRACL Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox MIRACL Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox MIRACL Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+/*
+ * MIRACL C++ functions big.cpp
+ *
+ * AUTHOR : N.Coghlan
+ * Modified by M.Scott
+ *
+ * PURPOSE : Implementation of class Big functions
+ */
+
+#include "big.h"
+
+void Big::negate() const
+ { negify(fn,fn); }
+big Big::getbig() const
+ { return fn;}
+BOOL Big::iszero() const
+ { if (size(fn)==0) return TRUE; return FALSE;}
+BOOL Big::isone() const
+ { if (size(fn)==1) return TRUE; return FALSE;}
+int Big::len() const
+ { return numdig(fn); }
+
+Big operator-(const Big& b)
+{Big nb; negify(b.fn,nb.fn); return nb;}
+Big operator+(const Big& b,int i)
+{Big abi; incr(b.fn, i, abi.fn); return abi;}
+Big operator+(int i,const Big& b)
+{Big aib; incr(b.fn, i, aib.fn); return aib;}
+Big operator+(const Big& b1, const Big& b2)
+{Big abb;add(b1.fn,b2.fn,abb.fn);return abb;}
+
+Big operator-(const Big& b, int i)
+{Big mbi; decr(b.fn, i, mbi.fn); return mbi;}
+Big operator-(int i, const Big& b)
+{Big mib;decr(b.fn, i, mib.fn);negify(mib.fn,mib.fn);return mib;}
+Big operator-(const Big& b1, const Big& b2)
+{Big mbb; subtract(b1.fn,b2.fn,mbb.fn); return mbb;}
+
+Big operator*(const Big& b, int i)
+{Big xbi; premult(b.fn, i, xbi.fn); return xbi;}
+Big operator*(int i, const Big& b)
+{Big xib; premult(b.fn, i, xib.fn); return xib;}
+Big operator*(const Big& b1, const Big& b2)
+{Big xbb; multiply(b1.fn,b2.fn,xbb.fn); return xbb;}
+
+#ifndef MR_STATIC
+BOOL fmt(int n,const Big& b1,const Big& b2,Big& f)
+{
+#ifdef MR_KCM
+ return kcm_top(n,b1.fn,b2.fn,f.fn); /* see mrkcm.tpl */
+#else
+ return fastmultop(n,b1.fn,b2.fn,f.fn); /* see mrfast.c */
+#endif
+}
+#endif
+
+Big operator/(const Big& b, int i)
+{Big dbi; subdiv(b.fn, i, dbi.fn); return dbi;}
+Big operator/(const Big& b1, const Big& b2)
+{Big dbb; copy(b1.fn,dbb.fn); divide(dbb.fn,b2.fn,dbb.fn); return dbb;}
+
+int operator%(const Big& b, int i)
+{Big mdbi; return(subdiv(b.fn,i, mdbi.fn));}
+Big operator%(const Big& b1, const Big& b2)
+{Big mdbb;copy(b1.fn,mdbb.fn);divide(mdbb.fn,b2.fn,b2.fn);return mdbb;}
+
+Big operator<<(const Big& b, int i)
+{Big ms; sftbit(b.fn,i,ms.fn); return ms;}
+
+Big operator>>(const Big& b, int i)
+{Big ms; sftbit(b.fn,-i,ms.fn); return ms;}
+
+#ifndef MR_FP
+Big land(const Big& x,const Big& y)
+{Big z; mr_and(x.fn,y.fn,z.fn); return z;}
+Big lxor(const Big& x,const Big& y)
+{Big z; mr_xor(x.fn,y.fn,z.fn); return z;}
+
+#endif
+
+Big from_binary(int len,char *ptr)
+{Big z; bytes_to_big(len,ptr,z.fn); return z;}
+//int to_binary(const Big& b,int max,char *ptr,BOOL justify)
+//{ return big_to_bytes(max,b.fn,ptr,justify);}
+
+Big modmult(const Big& b1,const Big& b2,const Big& m)
+{Big z; mad(b1.fn,b2.fn,b2.fn,m.fn,m.fn,z.fn); return z;}
+Big mad(const Big& b1,const Big& b2,const Big& b3,const Big& m,Big &r)
+{Big q; mad(b1.fn,b2.fn,b3.fn,m.fn,q.fn,r.fn); return q;}
+
+Big norm(const Big& b) {Big z; normalise(b.fn,z.fn); return z;}
+Big sqrt(const Big& b) {Big z; nroot(b.fn, 2, z.fn); return z;}
+Big abs(const Big& b) {Big z; absol(b.fn,z.fn); return z;}
+Big root(const Big &b,int n) {Big z; nroot(b.fn, n, z.fn); return z;}
+Big gcd(const Big& b1, const Big& b2){Big z;egcd(b1.fn,b2.fn,z.fn);return z;}
+Big pow(const Big& b,int n)
+{Big z;int x;
+if (mr_abs(x=size(b.fn))fn,z.fn);
+// else lucas(b1.fn,b2.fn,b3.fn,z.fn,z.fn);
+//return z;}
+
+
+Big inverse(const Big& b1, const Big& b2)
+{Big z; xgcd(b1.fn,b2.fn,z.fn,z.fn,z.fn);return z;}
+
+Big moddiv(const Big& b1,const Big& b2,const Big& m)
+{Big z; xgcd(b2.fn,m.fn,z.fn,z.fn,z.fn); mad(b1.fn,z.fn,z.fn,m.fn,m.fn,z.fn); return z;}
+
+#ifndef MR_NO_RAND
+
+Big rand(const Big& b) {Big z; bigrand(b.fn,z.fn); return z;}
+Big rand(int n,int b) {Big z; bigdig(n,b,z.fn); return z;}
+Big randbits(int n) {Big z; bigbits(n,z.fn); return z;}
+
+Big strong_rand(csprng *rng,const Big& b) {Big z; strong_bigrand(rng,b.fn,z.fn); return z;}
+Big strong_rand(csprng *rng,int n,int b) {Big z; strong_bigdig(rng,n,b,z.fn); return z;}
+
+#endif
+
+Big nextprime(const Big& b) {Big z; nxprime(b.fn,z.fn); return z;}
+Big nextsafeprime(int type,int subset,const Big& b) {Big z;
+nxsafeprime(type,subset,b.fn,z.fn); return z; }
+Big trial_divide(const Big& b) {Big r; trial_division(b.fn,r.fn); return r;}
+BOOL small_factors(const Big& b)
+{if (trial_division(b.fn,b.fn)==0) return TRUE; return FALSE;}
+BOOL perfect_power(const Big& b)
+{int i;
+ miracl *mip=get_mip();
+ if (size(b.fn)<4) return FALSE;
+ for (i=2;;i++)
+ {
+ if (nroot(b.fn,i,mip->w8)) return TRUE;
+ if (size(mip->w8)<=1) break;
+ }
+ return FALSE;
+}
+
+
+Big sqrt(const Big& x,const Big& p) {Big z; sqroot(x.fn,p.fn,z.fn); return z;}
+
+void modulo(const Big& n) {prepare_monty(n.fn);}
+Big get_modulus()
+{Big m;
+miracl *mip=get_mip();
+copy(mip->modulus,m.fn);
+return m;}
+
+
+Big nres(const Big& b) {Big z; nres(b.fn,z.fn); return z;}
+Big redc(const Big& b) {Big z; redc(b.fn,z.fn);return z;}
+
+/*
+
+Big nres_negate(const Big& b)
+{ Big z; nres_negate(b.fn,z.fn); return z;}
+Big nres_modmult(const Big& b1,const Big& b2)
+{ Big z; nres_modmult(b1.fn,b2.fn,z.fn); return z;}
+Big nres_premult(const Big& b1,int i)
+{ Big z; nres_premult(b1.fn,i,z.fn); return z;}
+
+Big nres_modadd(const Big& b1,const Big& b2)
+{ Big z; nres_modadd(b1.fn,b2.fn,z.fn); return z;}
+Big nres_modsub(const Big& b1,const Big& b2)
+{ Big z; nres_modsub(b1.fn,b2.fn,z.fn); return z;}
+Big nres_moddiv(const Big& b1,const Big& b2)
+{ Big z; nres_moddiv(b1.fn,b2.fn,z.fn); return z;}
+Big nres_pow(const Big& b1,const Big& b2)
+{ Big z; nres_powmod(b1.fn,b2.fn,z.fn); return z;}
+
+
+
+
+Big nres_pow2(const Big& b1,const Big& b2,const Big& b3,const Big& b4)
+{ Big z; nres_powmod2(b1.fn,b2.fn,b3.fn,b4.fn,z.fn); return z;}
+
+
+Big nres_pown(int n,Big *a,Big *b)
+{
+ Big z;
+ int i;
+ big *x=(big *)mr_alloc(n,sizeof(big));
+ big *y=(big *)mr_alloc(n,sizeof(big));
+ for (i=0;ifn,z.fn);
+ else nres_lucas(b1.fn,b2.fn,z.fn,z.fn);
+ return z;}
+
+Big nres_sqrt(const Big& b)
+{ Big z; nres_sqroot(b.fn,z.fn); return z;}
+*/
+
+Big shift(const Big&b,int n)
+{
+ Big r;
+ mr_shift(b.fn,n,r.fn);
+ return r;
+}
+
+int length(const Big& b)
+{
+ return mr_lent(b.fn);
+}
+
+/* Note that when inputting text as a number the CR is NOT *
+ * included in the text, unlike C I/O which does include CR. */
+
+#ifndef MR_NO_STANDARD_IO
+#ifndef MR_SIMPLE_IO
+
+istream& operator>>(istream& s, Big& x)
+{
+ miracl *mip=get_mip();
+#ifndef MR_SIMPLE_BASE
+
+ if (mip->IOBASE>60)
+ {
+ s.sync();
+ s.getline(mip->IOBUFF,mip->IOBSIZ);
+ }
+ else
+#endif
+ s >> mip->IOBUFF;
+ if (s.eof() || s.bad())
+ {
+ zero(x.fn);
+ return s;
+ }
+#ifdef MR_SIMPLE_BASE
+ instr(x.fn,mip->IOBUFF);
+#else
+ cinstr(x.fn,mip->IOBUFF);
+#endif
+ return s;
+}
+
+#endif
+#endif
+
+// Note new parameter of window_size. Default to 5, but reduce to 4 (or even 3) to save RAM
+
+//int window(const Big& x,int i,int *nbs,int *nzs,int window_size)
+//{ /* returns sliding window value, max. of 5 bits, *
+// * starting at i-th bit of big x. nbs is number of bits *
+// * processed, nzs is the number of additional trailing *
+// * zeros detected. Returns valid bit pattern 1x..x1 with *
+ // * no two adjacent 0's. So 10101 will return 21 with *
+// * nbs=5, nzs=0. 11001 will return 3, with nbs=2, nzs=2, *
+ // * having stopped after the first 11.. */
+
+ // return mr_window(x.fn,i,nbs,nzs,window_size);
+//}
+
+//int naf_window(const Big& x,const Big& x3,int i,int *nbs,int *nzs,int store)
+//{ /* returns sliding window value, max of 5 bits *
+// * starting at i-th bit of x. nbs is number of bits *
+// * processed. nzs is number of additional trailing *
+// * zeros detected. x and x3 (which is 3*x) are *
+// * combined to produce the NAF (non-adjacent form) *
+// * So if x=11011(27) and x3 is 1010001, the LSB is *
+// * ignored and the value 100T0T (32-4-1=27) processed, *
+// * where T is -1. Note x.P = (3x-x)/2.P. This value will *
+// * return +7, with nbs=4 and nzs=1, having stopped after *
+// * the first 4 bits. Note in an NAF non-zero elements *
+// * are never side by side, so 10T10T won't happen */
+
+
+// return mr_naf_window(x.fn,x3.fn,i,nbs,nzs,store);
+//}
+
+#ifndef MR_NO_ECC_MULTIADD
+void jsf(const Big& k0,const Big& k1,Big& u0p,Big& u0m,Big& u1p,Big& u1m)
+{
+ mr_jsf(k0.fn,k1.fn,u0p.fn,u0m.fn,u1p.fn,u1m.fn);
+}
+#endif
+
+#ifndef MR_NO_STANDARD_IO
+
+ostream& operator<<(ostream& s, const Big& x)
+{
+ miracl *mip=get_mip();
+#if defined(MR_SIMPLE_BASE) || defined(MR_SIMPLE_IO)
+ otstr(x.fn,mip->IOBUFF);
+#else
+ cotstr(x.fn,mip->IOBUFF);
+#endif
+ s << mip->IOBUFF;
+ return s;
+}
+
+#ifdef MR_FLASH
+
+ostream& otfloat(ostream& s,const Big& m,int e)
+{
+ miracl *mip=get_mip();
+ copy(m.fn,mip->w5);
+
+ convert(1,mip->w6);
+ copy(mip->w6,mip->w9);
+ mr_shift(mip->w6,mr_lent(m.fn),mip->w6);
+ mround(mip->w5,mip->w6,mip->w8);
+ if (e>=-2 && e<=2)
+ {
+ if (e>0)
+ {
+ mr_shift(mip->w9,e,mip->w9);
+ fmul(mip->w8,mip->w9,mip->w8);
+ }
+ else
+ {
+ mr_shift(mip->w9,-e,mip->w9);
+ fdiv(mip->w8,mip->w9,mip->w8);
+ }
+#if defined(MR_SIMPLE_BASE) || defined(MR_SIMPLE_IO)
+ otstr(mip->w8,mip->IOBUFF);
+#else
+ cotstr(mip->w8,mip->IOBUFF);
+#endif
+ s << mip->IOBUFF;
+ }
+ else
+ {
+#if defined(MR_SIMPLE_BASE) || defined(MR_SIMPLE_IO)
+ otstr(mip->w8,mip->IOBUFF);
+#else
+ cotstr(mip->w8,mip->IOBUFF);
+#endif
+ s << mip->IOBUFF;
+ s << ".2^" << e*MIRACL;
+ }
+
+ return s;
+}
+
+#endif
+
+#endif
+
+char* operator<<(char *s,const Big& x)
+{
+ miracl *mip=get_mip();
+ int i,n;
+#if defined(MR_SIMPLE_BASE) || defined(MR_SIMPLE_IO)
+ n=otstr(x.fn,mip->IOBUFF);
+#else
+ n=cotstr(x.fn,mip->IOBUFF);
+#endif
+ if (s!=mip->IOBUFF) for (i=0;i<=n;i++) s[i]=mip->IOBUFF[i];
+ return s;
+}
+
+void ecurve(const Big& a,const Big& b,const Big& p,int t)
+{
+ ecurve_init(a.fn,b.fn,p.fn,t);
+}
+
+BOOL ecurve2(int m,int a,int b,int c,const Big& a2,const Big& a6,BOOL check,int t)
+{ return ecurve2_init(m,a,b,c,a2.fn,a6.fn,check,t);}
+
diff --git a/source/mac/big.h b/source/mac/big.h
new file mode 100644
index 0000000..0888e0e
--- /dev/null
+++ b/source/mac/big.h
@@ -0,0 +1,440 @@
+
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox MIRACL Crypto SDK. *
+ *
+The CertiVox MIRACL Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox MIRACL Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox MIRACL Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox MIRACL Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox MIRACL Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+/*
+ *
+ * MIRACL C++ Header file big.h
+ *
+ * AUTHOR : N.Coghlan
+ * Modified by M.Scott
+ *
+ * PURPOSE : Definition of class Big
+ *
+ * Bigs are normally created on the heap, but by defining BIGS=m
+ * on the compiler command line, Bigs are instead mostly created from the
+ * stack. Note that m must be same or less than the n in the main program
+ * with for example
+ *
+ * Miracl precison(n,0);
+ *
+ * where n is the (fixed) size in words of each Big.
+ *
+ * This may be faster, as C++ tends to create and destroy lots of
+ * temporaries. Especially recommended if m is small. Do not use
+ * for program development
+ *
+ * However Bigs created from a string are always allocated from the heap.
+ * This is useful for creating large read-only constants which are larger
+ * than m.
+ *
+ * NOTE:- I/O conversion
+ *
+ * To convert a hex character string to a Big
+ *
+ * Big x;
+ * char c[100];
+ *
+ * mip->IOBASE=16;
+ * x=c;
+ *
+ * To convert a Big to a hex character string
+ *
+ * mip->IOBASE=16;
+ * c << x;
+ *
+ * To convert to/from pure binary, see the from_binary()
+ * and to_binary() friend functions.
+ *
+ * int len;
+ * char c[100];
+ * ...
+ * Big x=from_binary(len,c); // creates Big x from len bytes of binary in c
+ *
+ * len=to_binary(x,100,c,FALSE); // converts Big x to len bytes binary in c[100]
+ * len=to_binary(x,100,c,TRUE); // converts Big x to len bytes binary in c[100]
+ * // (right justified with leading zeros)
+ */
+
+#ifndef BIG_H
+#define BIG_H
+
+#include
+//#include
+#include
+
+#include "mirdef.h"
+
+#ifdef MR_CPP
+#include "miracl.h"
+#else
+extern "C"
+{
+ #include "miracl.h"
+}
+#endif
+
+#ifndef MR_NO_STANDARD_IO
+#include
+using std::istream;
+using std::ostream;
+#endif
+
+#ifndef MIRACL_CLASS
+#define MIRACL_CLASS
+
+#ifdef __cplusplus
+#ifdef MR_GENERIC_MT
+#error "The generic method isn't supported for C++, its C only"
+#endif
+#endif
+
+class Miracl
+{ /* dummy class to initialise MIRACL - MUST be called before any Bigs *
+ * are created. This could be a problem for static/global data declared *
+ * in modules other than the main module */
+ miracl *mr;
+public:
+ Miracl(int nd,mr_small nb=0)
+ {mr=mirsys(nd,nb);
+#ifdef MR_FLASH
+mr->RPOINT=TRUE;
+#endif
+}
+ miracl *operator&() {return mr;}
+ ~Miracl() {mirexit();}
+};
+
+#endif
+
+/*
+#ifdef BIGS
+#define MR_INIT_BIG memset(mem,0,mr_big_reserve(1,BIGS)); fn=(big)mirvar_mem_variable(mem,0,BIGS);
+#else
+#define MR_INIT_BIG mem=(char *)memalloc(1); fn=(big)mirvar_mem(mem,0);
+#endif
+*/
+
+#ifdef BIGS
+#define MR_INIT_BIG fn=&b; b.w=a; b.len=0; for (int i=0;ilen=1; fn->w[0]=s; return *this;}
+ Big& operator=(const Big& b) {copy(b.fn,fn); return *this;}
+ Big& operator=(big& b) {copy(b,fn); return *this;}
+ Big& operator=(big* b) {fn=*b; return *this;}
+#ifndef MR_SIMPLE_IO
+#ifdef MR_SIMPLE_BASE
+ Big& operator=(char* s){instr(fn,s);return *this;}
+#else
+ Big& operator=(char* s){cinstr(fn,s);return *this;}
+#endif
+#endif
+ Big& operator++() {incr(fn,1,fn); return *this;}
+ Big& operator--() {decr(fn,1,fn); return *this;}
+ Big& operator+=(int i) {incr(fn,i,fn); return *this;}
+ Big& operator+=(const Big& b){add(fn,b.fn,fn); return *this;}
+
+ Big& operator-=(int i) {decr(fn,i,fn); return *this;}
+ Big& operator-=(const Big& b) {subtract(fn,b.fn,fn); return *this;}
+
+ Big& operator*=(int i) {premult(fn,i,fn); return *this;}
+ Big& operator*=(const Big& b) {multiply(fn,b.fn,fn); return *this;}
+
+ Big& operator/=(int i) {subdiv(fn,i,fn); return *this;}
+ Big& operator/=(const Big& b) {divide(fn,b.fn,fn); return *this;}
+
+ Big& operator%=(int i) {convert(subdiv(fn,i,fn),fn); return *this;}
+ Big& operator%=(const Big& b) {divide(fn,b.fn,b.fn); return *this;}
+
+ Big& operator<<=(int i) {sftbit(fn,i,fn); return *this;}
+ Big& operator>>=(int i) {sftbit(fn,-i,fn); return *this;}
+
+ Big& shift(int n) {mr_shift(fn,n,fn); return *this;}
+
+ mr_small& operator[](int i) {return fn->w[i];}
+
+ void negate() const;
+ BOOL iszero() const;
+ BOOL isone() const;
+ int get(int index) { int m; m=getdig(fn,index); return m; }
+ void set(int index,int n) { putdig(n,fn,index);}
+ int len() const;
+
+ big getbig() const;
+
+ friend class Flash;
+
+ friend Big operator-(const Big&);
+
+ friend Big operator+(const Big&,int);
+ friend Big operator+(int,const Big&);
+ friend Big operator+(const Big&,const Big&);
+
+ friend Big operator-(const Big&, int);
+ friend Big operator-(int,const Big&);
+ friend Big operator-(const Big&,const Big&);
+
+ friend Big operator*(const Big&, int);
+ friend Big operator*(int,const Big&);
+ friend Big operator*(const Big&,const Big&);
+
+ friend BOOL fmt(int n,const Big&,const Big&,Big&); // fast mult - top half
+
+ friend Big operator/(const Big&,int);
+ friend Big operator/(const Big&,const Big&);
+
+ friend int operator%(const Big&, int);
+ friend Big operator%(const Big&, const Big&);
+
+ friend Big operator<<(const Big&, int);
+ friend Big operator>>(const Big&, int);
+
+ friend BOOL operator<=(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)<=0) return TRUE; else return FALSE;}
+ friend BOOL operator>=(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)>=0) return TRUE; else return FALSE;}
+ friend BOOL operator==(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)==0) return TRUE; else return FALSE;}
+ friend BOOL operator!=(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)!=0) return TRUE; else return FALSE;}
+ friend BOOL operator<(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)<0) return TRUE; else return FALSE;}
+ friend BOOL operator>(const Big& b1,const Big& b2)
+ {if (mr_compare(b1.fn,b2.fn)>0) return TRUE; else return FALSE;}
+
+ friend Big from_binary(int,char *);
+ friend int to_binary(const Big& b,int max,char *ptr,BOOL justify=FALSE)
+{ return big_to_bytes(max,b.fn,ptr,justify);}
+ friend Big modmult(const Big&,const Big&,const Big&);
+ friend Big mad(const Big&,const Big&,const Big&,const Big&,Big&);
+ friend Big norm(const Big&);
+ friend Big sqrt(const Big&);
+ friend Big root(const Big&,int);
+ friend Big gcd(const Big&,const Big&);
+ friend void set_zzn3(int cnr,Big& sru) {get_mip()->cnr=cnr; nres(sru.fn,get_mip()->sru);}
+ friend int recode(const Big& e,int t,int w,int i) {return recode(e.fn,t,w,i);}
+
+#ifndef MR_FP
+ friend Big land(const Big&,const Big&); // logical AND
+ friend Big lxor(const Big&,const Big&); // logical XOR
+#endif
+ friend Big pow(const Big&,int); // x^m
+ friend Big pow(const Big&, int, const Big&); // x^m mod n
+ friend Big pow(int, const Big&, const Big&); // x^m mod n
+ friend Big pow(const Big&, const Big&, const Big&); // x^m mod n
+ friend Big pow(const Big&, const Big&, const Big&, const Big&, const Big&);
+ // x^m.y^k mod n
+ friend Big pow(int,Big *,Big *,Big); // x[0]^m[0].x[1].m[1]... mod n
+
+ friend Big luc(const Big& b1,const Big& b2, const Big& b3, Big *b4=NULL)
+{Big z; if (b4!=NULL) lucas(b1.fn,b2.fn,b3.fn,b4->fn,z.fn);
+ else lucas(b1.fn,b2.fn,b3.fn,z.fn,z.fn);
+return z;}
+ friend Big moddiv(const Big&,const Big&,const Big&);
+ friend Big inverse(const Big&, const Big&);
+ friend void multi_inverse(int,Big*,const Big&,Big *);
+#ifndef MR_NO_RAND
+ friend Big rand(const Big&); // 0 < rand < parameter
+ friend Big rand(int,int); // (digits,base) e.g. (32,16)
+ friend Big randbits(int); // n random bits
+ friend Big strong_rand(csprng *,const Big&);
+ friend Big strong_rand(csprng *,int,int);
+#endif
+ friend Big abs(const Big&);
+// This next only works if MIRACL is using a binary base...
+ friend int bit(const Big& b,int i) {return mr_testbit(b.fn,i);}
+ friend int bits(const Big& b) {return logb2(b.fn);}
+ friend int ham(const Big& b) {return hamming(b.fn);}
+ friend int jacobi(const Big& b1,const Big& b2) {return jack(b1.fn,b2.fn);}
+ friend int toint(const Big& b) {return size(b.fn);}
+ friend BOOL prime(const Big& b) {return isprime(b.fn);}
+ friend Big nextprime(const Big&);
+ friend Big nextsafeprime(int type,int subset,const Big&);
+ friend Big trial_divide(const Big& b);
+ friend BOOL small_factors(const Big& b);
+ friend BOOL perfect_power(const Big& b);
+ friend Big sqrt(const Big&,const Big&);
+
+ friend void ecurve(const Big&,const Big&,const Big&,int);
+ friend BOOL ecurve2(int,int,int,int,const Big&,const Big&,BOOL,int);
+ friend BOOL is_on_curve(const Big&);
+ friend void modulo(const Big&);
+ friend BOOL modulo(int,int,int,int,BOOL);
+ friend Big get_modulus(void);
+ friend int window(const Big& x,int i,int* nbs,int *nzs,int window_size=5)
+{
+return mr_window(x.fn,i,nbs,nzs,window_size);
+
+}
+ friend int naf_window(const Big& x,const Big& x3,int i,int *nbs,int *nzs,int store=11)
+{
+return mr_naf_window(x.fn,x3.fn,i,nbs,nzs,store);
+}
+
+ friend void jsf(const Big&,const Big&,Big&,Big&,Big&,Big&);
+
+/* Montgomery stuff */
+
+ friend Big nres(const Big&);
+ friend Big redc(const Big&);
+/*
+ friend Big nres_negate(const Big&);
+ friend Big nres_modmult(const Big&,const Big&);
+ friend Big nres_premult(const Big&,int);
+ friend Big nres_pow(const Big&,const Big&);
+ friend Big nres_pow2(const Big&,const Big&,const Big&,const Big&);
+ friend Big nres_pown(int,Big *,Big *);
+ friend Big nres_luc(const Big&,const Big&,Big *b3=NULL);
+ friend Big nres_sqrt(const Big&);
+ friend Big nres_modadd(const Big&,const Big&);
+ friend Big nres_modsub(const Big&,const Big&);
+ friend Big nres_moddiv(const Big&,const Big&);
+*/
+/* these are faster.... */
+/*
+ friend void nres_modmult(Big& a,const Big& b,Big& c)
+ {nres_modmult(a.fn,b.fn,c.fn);}
+ friend void nres_modadd(Big& a,const Big& b,Big& c)
+ {nres_modadd(a.fn,b.fn,c.fn);}
+ friend void nres_modsub(Big& a,const Big& b,Big& c)
+ {nres_modsub(a.fn,b.fn,c.fn);}
+ friend void nres_negate(Big& a,Big& b)
+ {nres_negate(a.fn,b.fn);}
+ friend void nres_premult(Big& a,int b,Big& c)
+ {nres_premult(a.fn,b,c.fn);}
+ friend void nres_moddiv(Big & a,const Big& b,Big& c)
+ {nres_moddiv(a.fn,b.fn,c.fn);}
+*/
+ friend Big shift(const Big&b,int n);
+ friend int length(const Big&b);
+
+
+/* Note that when inputting text as a number the CR is NOT *
+ * included in the text, unlike C I/O which does include CR. */
+
+#ifndef MR_NO_STANDARD_IO
+
+ friend istream& operator>>(istream&, Big&);
+ friend ostream& operator<<(ostream&, const Big&);
+ friend ostream& otfloat(ostream&,const Big&,int);
+
+#endif
+
+// output Big to a String
+ friend char * operator<<(char * s,const Big&);
+
+ ~Big() {
+ // zero(fn);
+#ifndef BIGS
+ mr_free(fn);
+#endif
+ }
+};
+
+extern BOOL modulo(int,int,int,int,BOOL);
+extern Big get_modulus(void);
+extern Big rand(int,int);
+extern Big strong_rand(csprng *,int,int);
+extern Big from_binary(int,char *);
+//extern int to_binary(const Big&,int,char *,BOOL);
+
+using namespace std;
+
+#endif
+
diff --git a/source/mac/zzn.cpp b/source/mac/zzn.cpp
new file mode 100644
index 0000000..09a69c7
--- /dev/null
+++ b/source/mac/zzn.cpp
@@ -0,0 +1,192 @@
+
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox MIRACL Crypto SDK. *
+ *
+The CertiVox MIRACL Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox MIRACL Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox MIRACL Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox MIRACL Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox MIRACL Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+/*
+ *
+ * MIRACL C++ functions zzn.cpp
+ *
+ * AUTHOR : M. Scott
+ *
+ * PURPOSE : Implementation of class ZZn functions using Montgomery
+ * representation
+ * NOTE : Must be used in conjunction with big.h and big.cpp
+ *
+ */
+
+#include "zzn.h"
+
+big ZZn::getzzn(void) const
+ { return fn;}
+
+ZZn& ZZn::operator/=(int i)
+{
+ if (i==1) return *this;
+ if (i==2)
+ { // make a special effort... modulus is odd
+ nres_div2(fn,fn);
+ return *this;
+ }
+ ZZn x=i;
+ nres_moddiv(fn,x.fn,fn);
+ return *this;
+}
+
+BOOL ZZn::iszero() const
+{ if (size(fn)==0) return TRUE; return FALSE;}
+
+ZZn operator-(const ZZn& b)
+{ZZn x=b; nres_negate(x.fn,x.fn); return x;}
+
+ZZn operator+(const ZZn& b,int i)
+{ZZn abi=b; abi+=i; return abi;}
+ZZn operator+(int i, const ZZn& b)
+{ZZn aib=b; aib+=i; return aib;}
+ZZn operator+(const ZZn& b1, const ZZn& b2)
+{ZZn abb=b1; abb+=b2; return abb;}
+
+ZZn operator-(const ZZn& b, int i)
+{ZZn mbi=b; mbi-=i; return mbi;}
+ZZn operator-(int i, const ZZn& b)
+{ZZn mib=i; mib-=b; return mib;}
+ZZn operator-(const ZZn& b1, const ZZn& b2)
+{ZZn mbb=b1; mbb-=b2; return mbb;}
+
+ZZn operator*(const ZZn& b,int i)
+{ZZn xbb=b; xbb*=i; return xbb;}
+ZZn operator*(int i, const ZZn& b)
+{ZZn xbb=b; xbb*=i; return xbb;}
+ZZn operator*(const ZZn& b1, const ZZn& b2)
+{ZZn xbb=b1; xbb*=b2; return xbb;}
+
+ZZn operator/(const ZZn& b1, int i)
+{ZZn z=b1; z/=i; return z; }
+
+ZZn operator/(int i, const ZZn& b2)
+{ZZn z=i; nres_moddiv(z.fn,b2.fn,z.fn); return z;}
+ZZn operator/(const ZZn& b1, const ZZn& b2)
+{ZZn z=b1; z/=b2; return z;}
+
+ZZn pow( const ZZn& b1, const Big& b2)
+{ZZn z; nres_powmod(b1.fn,b2.getbig(),z.fn);return z;}
+
+ZZn pow( const ZZn& b,int i)
+{ZZn z; Big ib=i; nres_powmod(b.fn,ib.getbig(),z.fn); return z;}
+
+ZZn pow( const ZZn& b1, const Big& b2, const ZZn& b3,const Big& b4)
+{ZZn z; nres_powmod2(b1.fn,b2.getbig(),b3.fn,b4.getbig(),z.fn); return z;}
+
+int jacobi(const ZZn& x)
+{redc(x.fn,get_mip()->w1); return jack(get_mip()->w1,get_mip()->modulus); }
+
+#ifndef MR_NO_RAND
+ZZn randn(void)
+{ZZn z; bigrand(get_mip()->modulus,z.fn); return z;}
+#endif
+BOOL qr(const ZZn& x)
+{redc(x.fn,get_mip()->w1); if (jack(get_mip()->w1,get_mip()->modulus)==1) return TRUE; return FALSE; }
+
+BOOL qnr(const ZZn& x)
+{redc(x.fn,get_mip()->w1); if (jack(get_mip()->w1,get_mip()->modulus)==-1) return TRUE; return FALSE;}
+
+ZZn one(void)
+{
+ ZZn w;
+ w=get_mip()->one;
+ return w;
+}
+
+ZZn getA(void)
+{
+ ZZn w;
+ if (get_mip()->AsizeAsize;
+ else w=get_mip()->A;
+ return w;
+}
+
+ZZn getB(void)
+{
+ ZZn w;
+ if (get_mip()->BsizeBsize;
+ else w=get_mip()->B;
+ return w;
+}
+
+#ifndef MR_STATIC
+
+ZZn pow(int n,ZZn *a,Big *b)
+{
+ ZZn z;
+ int i;
+ big *x=(big *)mr_alloc(n,sizeof(big));
+ big *y=(big *)mr_alloc(n,sizeof(big));
+ for (i=0;ifn,z.fn);
+// else nres_lucas(b1.fn,b2.getbig(),z.fn,z.fn);
+// return z;}
+
+
+ZZn sqrt(const ZZn& b)
+{ZZn z; nres_sqroot(b.fn,z.fn); return z;}
+
+#ifndef MR_NO_STANDARD_IO
+
+ostream& operator<<(ostream& s,const ZZn& xx)
+{
+ ZZn b=xx;
+ Big x=(Big)b;
+ s << x;
+ return s;
+}
+
+#endif
diff --git a/source/mac/zzn.h b/source/mac/zzn.h
new file mode 100644
index 0000000..36ca294
--- /dev/null
+++ b/source/mac/zzn.h
@@ -0,0 +1,215 @@
+
+/***************************************************************************
+ *
+Copyright 2013 CertiVox UK Ltd. *
+ *
+This file is part of CertiVox MIRACL Crypto SDK. *
+ *
+The CertiVox MIRACL Crypto SDK provides developers with an *
+extensive and efficient set of cryptographic functions. *
+For further information about its features and functionalities please *
+refer to http://www.certivox.com *
+ *
+* The CertiVox MIRACL Crypto SDK is free software: you can *
+ redistribute it and/or modify it under the terms of the *
+ GNU Affero General Public License as published by the *
+ Free Software Foundation, either version 3 of the License, *
+ or (at your option) any later version. *
+ *
+* The CertiVox MIRACL Crypto SDK is distributed in the hope *
+ that it will be useful, but WITHOUT ANY WARRANTY; without even the *
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ See the GNU Affero General Public License for more details. *
+ *
+* You should have received a copy of the GNU Affero General Public *
+ License along with CertiVox MIRACL Crypto SDK. *
+ If not, see . *
+ *
+You can be released from the requirements of the license by purchasing *
+a commercial license. Buying such a license is mandatory as soon as you *
+develop commercial activities involving the CertiVox MIRACL Crypto SDK *
+without disclosing the source code of your own applications, or shipping *
+the CertiVox MIRACL Crypto SDK with a closed source product. *
+ *
+***************************************************************************/
+/*
+ *
+ * MIRACL C++ Header file zzn.h
+ *
+ * AUTHOR : M. Scott
+ *
+ * PURPOSE : Definition of class ZZn (Arithmetic mod n), using
+ * Montgomery's Method for modular multiplication
+ * NOTE : Must be used in conjunction with zzn.cpp
+ * The modulus n is always set dynamically (via the modulo()
+ * routine) - so beware the pitfalls implicit in declaring
+ * static or global ZZn's (which are initialised before n is
+ * set!). Uninitialised data is OK
+ */
+
+#ifndef ZZN_H
+#define ZZN_H
+
+#include "big.h"
+
+/*
+
+#ifdef ZZNS
+#define MR_INIT_ZZN memset(mem,0,mr_big_reserve(1,ZZNS)); fn=(big)mirvar_mem_variable(mem,0,ZZNS);
+#define MR_CLONE_ZZN(x) fn->len=x->len; for (int i=0;iw[i]=x->w[i];
+#define MR_ZERO_ZZN {fn->len=0; for (int i=0;iw[i]=0;}
+#else
+#define MR_INIT_ZZN mem=(char *)memalloc(1); fn=(big)mirvar_mem(mem,0);
+#define MR_CLONE_ZZN(x) copy(x,fn);
+#define MR_ZERO_ZZN zero(fn);
+#endif
+
+*/
+
+#ifdef ZZNS
+#ifdef MR_COMBA
+#define UZZNS ZZNS
+#else
+#define UZZNS ZZNS+1 // one extra required in case of carry overflow in addition
+#endif
+#endif
+
+#ifdef ZZNS
+#define MR_INIT_ZZN fn=&b; b.w=a; b.len=UZZNS;
+#define MR_CLONE_ZZN(x) b.len=x->len; for (int i=0;iw[i];
+#define MR_ZERO_ZZN {b.len=0; for (int i=0;i ZZn */
+ ZZn(big& c) {MR_INIT_ZZN MR_CLONE_ZZN(c);}
+ ZZn(const ZZn& c) {MR_INIT_ZZN MR_CLONE_ZZN(c.fn);}
+ ZZn(char* s) {MR_INIT_ZZN cinstr(fn,s); nres(fn,fn);}
+
+ ZZn& operator=(const ZZn& c) {MR_CLONE_ZZN(c.fn) return *this;}
+ ZZn& operator=(big c) {MR_CLONE_ZZN(c) return *this; }
+
+ ZZn& operator=(int i) {if (i==0) MR_ZERO_ZZN else {convert(i,fn); nres(fn,fn);} return *this;}
+ ZZn& operator=(char* s){cinstr(fn,s); nres(fn,fn); return *this;}
+
+
+/* Use fast in-line code */
+
+ ZZn& operator++()
+ {nres_modadd(fn,get_mip()->one,fn);return *this;}
+ ZZn& operator--()
+ {nres_modsub(fn,get_mip()->one,fn);return *this;}
+ ZZn& operator+=(int i)
+ {ZZn inc=i; nres_modadd(fn,inc.fn,fn);return *this;}
+ ZZn& operator-=(int i)
+ {ZZn dec=i; nres_modsub(fn,dec.fn,fn); return *this;}
+ ZZn& operator+=(const ZZn& b)
+ {nres_modadd(fn,b.fn,fn); return *this;}
+ ZZn& operator-=(const ZZn& b)
+ {nres_modsub(fn,b.fn,fn); return *this;}
+ ZZn& operator*=(const ZZn& b)
+ {nres_modmult(fn,b.fn,fn); return *this;}
+ ZZn& operator*=(int i)
+ {nres_premult(fn,i,fn); return *this;}
+
+ ZZn& negate()
+ {nres_negate(fn,fn); return *this;}
+
+ BOOL iszero() const;
+
+ operator Big() {Big c; redc(fn,c.getbig()); return c;} /* ZZn -> Big */
+ friend big getbig(ZZn& z) {return z.fn;}
+
+ ZZn& operator/=(const ZZn& b) {nres_moddiv(fn,b.fn,fn); return *this;}
+ ZZn& operator/=(int);
+
+ friend ZZn operator-(const ZZn&);
+ friend ZZn operator+(const ZZn&,int);
+ friend ZZn operator+(int, const ZZn&);
+ friend ZZn operator+(const ZZn&, const ZZn&);
+
+ friend ZZn operator-(const ZZn&, int);
+ friend ZZn operator-(int, const ZZn&);
+ friend ZZn operator-(const ZZn&, const ZZn&);
+
+ friend ZZn operator*(const ZZn&,int);
+ friend ZZn operator*(int, const ZZn&);
+ friend ZZn operator*(const ZZn&, const ZZn&);
+
+ friend ZZn operator/(const ZZn&, int);
+ friend ZZn operator/(int, const ZZn&);
+ friend ZZn operator/(const ZZn&, const ZZn&);
+
+ friend BOOL operator==(const ZZn& b1,const ZZn& b2)
+ { if (mr_compare(b1.fn,b2.fn)==0) return TRUE; else return FALSE;}
+ friend BOOL operator!=(const ZZn& b1,const ZZn& b2)
+ { if (mr_compare(b1.fn,b2.fn)!=0) return TRUE; else return FALSE;}
+
+ friend ZZn one(void);
+ friend ZZn pow( const ZZn&, const Big&);
+ friend ZZn pow( const ZZn&,int);
+ friend ZZn powl(const ZZn&, const Big&);
+ friend ZZn pow( const ZZn&, const Big&, const ZZn&, const Big&);
+ friend ZZn pow( int,ZZn *,Big *);
+ friend int jacobi(const ZZn&);
+#ifndef MR_NO_RAND
+ friend ZZn randn(void); // random number < modulus
+#endif
+ friend BOOL qr(const ZZn&); // test for quadratic residue
+ friend BOOL qnr(const ZZn&); // test for quadratic non-residue
+ friend ZZn getA(void); // get A parameter of elliptic curve
+ friend ZZn getB(void); // get B parameter of elliptic curve
+
+ friend ZZn sqrt(const ZZn&); // only works if modulus is prime
+ friend ZZn luc( const ZZn& b1, const Big& b2, ZZn* b3=NULL)
+{ZZn z; if (b3!=NULL) nres_lucas(b1.fn,b2.getbig(),b3->fn,z.fn);
+ else nres_lucas(b1.fn,b2.getbig(),z.fn,z.fn);
+ return z;}
+
+
+ big getzzn(void) const;
+
+#ifndef MR_NO_STANDARD_IO
+ friend ostream& operator<<(ostream&,const ZZn&);
+#endif
+
+
+ ~ZZn()
+ {
+ // MR_ZERO_ZZN // slower but safer
+#ifndef ZZNS
+ mr_free(fn);
+#endif
+ }
+};
+#ifndef MR_NO_RAND
+extern ZZn randn(void);
+#endif
+extern ZZn getA(void);
+extern ZZn getB(void);
+extern ZZn one(void);
+
+#endif
+