http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/fp12.swift
----------------------------------------------------------------------
diff --git a/version22/swift/fp12.swift b/version22/swift/fp12.swift
new file mode 100644
index 0000000..8743677
--- /dev/null
+++ b/version22/swift/fp12.swift
@@ -0,0 +1,584 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  fp12.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+final class FP12
+{
+    private final var a:FP4
+    private final var b:FP4
+    private final var c:FP4
+    
+    /* reduce all components of this mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+        c.reduce()
+    }
+    /* normalise all components of this */
+    func norm()
+    {
+        a.norm();
+        b.norm();
+        c.norm();
+    }
+    /* Constructors */
+    init(_ d:FP4)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:Int)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:FP4,_ e:FP4,_ f:FP4)
+    {
+        a=FP4(d)
+        b=FP4(e)
+        c=FP4(f)
+    }
+    
+    init(_ x:FP12)
+    {
+        a=FP4(x.a)
+        b=FP4(x.b)
+        c=FP4(x.c)
+    }
+    /* test x==0 ? */
+    func iszilch() -> Bool
+    {
+        reduce();
+        return a.iszilch() && b.iszilch() && c.iszilch()
+    }
+    /* test x==1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP4(1)
+        return a.equals(one) && b.iszilch() && c.iszilch()
+    }
+    /* return 1 if x==y, else 0 */
+    func equals(_ x:FP12) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)
+    }
+    /* extract a from self */
+    func geta() -> FP4
+    {
+        return a
+    }
+    /* extract b */
+    func getb()  -> FP4
+    {
+        return b
+    }
+    /* extract c */
+    func getc() -> FP4
+    {
+        return c
+    }
+    /* copy self=x */
+    func copy(_ x:FP12)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+        c.copy(x.c)
+    }
+    /* set self=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+        c.zero()
+    }
+    /* self=conj(self) */
+    func conj()
+    {
+        a.conj()
+        b.nconj()
+        c.conj()
+    }
+    /* Granger-Scott Unitary Squaring */
+    func usqr()
+    {
+        let A=FP4(a)
+        let B=FP4(c)
+        let C=FP4(b)
+        let D=FP4(0)
+    
+        a.sqr()
+        D.copy(a); D.add(a)
+        a.add(D)
+    
+        a.norm()
+        A.nconj()
+    
+        A.add(A)
+        a.add(A)
+        B.sqr()
+        B.times_i()
+    
+        D.copy(B); D.add(B)
+        B.add(D)
+        B.norm()
+    
+        C.sqr()
+        D.copy(C); D.add(C)
+        C.add(D)
+        C.norm()
+    
+        b.conj()
+        b.add(b)
+        c.nconj()
+    
+        c.add(c)
+        b.add(B)
+        c.add(C)
+        reduce()
+    
+    }
+    /* Chung-Hasan SQR2 method from 
http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+    func sqr()
+    {
+        let A=FP4(a)
+        let B=FP4(b)
+        let C=FP4(c)
+        let D=FP4(a)
+    
+        A.sqr()
+        B.mul(c)
+        B.add(B)
+        C.sqr()
+        D.mul(b)
+        D.add(D)
+
+        c.add(a)
+        c.add(b)
+        c.sqr()
+    
+        a.copy(A)
+    
+        A.add(B)
+        A.norm()
+        A.add(C)
+        A.add(D)
+        A.norm()
+    
+        A.neg()
+        B.times_i()
+        C.times_i()
+    
+        a.add(B)
+
+        b.copy(C); b.add(D)
+        c.add(A)
+    
+        norm()
+    }
+    
+    /* FP12 full multiplication this=this*y */
+    func mul(_ y:FP12)
+    {
+        let z0=FP4(a)
+        let z1=FP4(0)
+        let z2=FP4(b)
+        let z3=FP4(0)
+        let t0=FP4(a)
+        let t1=FP4(y.a)
+    
+        z0.mul(y.a)
+        z2.mul(y.b)
+    
+        t0.add(b)
+        t1.add(y.b)
+    
+        z1.copy(t0); z1.mul(t1)
+        t0.copy(b); t0.add(c)
+    
+        t1.copy(y.b); t1.add(y.c)
+        z3.copy(t0); z3.mul(t1)
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        z1.add(t0)
+        z1.norm()
+        b.copy(z1); b.add(t1)
+    
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t1.copy(y.a); t1.add(y.c)
+        t0.mul(t1)
+        z2.add(t0)
+    
+        t0.copy(c); t0.mul(y.c)
+        t1.copy(t0); t1.neg()
+    
+        z2.norm()
+        z3.norm()
+        b.norm()
+    
+        c.copy(z2); c.add(t1)
+        z3.add(t1)
+        t0.times_i()
+        b.add(t0)
+    
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+    
+    /* Special case of multiplication arises from special form of ATE pairing 
line function */
+    func smul(_ y:FP12)
+    {
+        let z0=FP4(a)
+        let z2=FP4(b)
+        let z3=FP4(b)
+        let t0=FP4(0)
+        let t1=FP4(y.a)
+    
+        z0.mul(y.a)
+        z2.pmul(y.b.real())
+        b.add(a)
+        t1.real().add(y.b.real())
+    
+        b.mul(t1)
+        z3.add(c)
+        z3.pmul(y.b.real())
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        b.add(t0)
+        b.norm()
+    
+        b.add(t1)
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t0.mul(y.a)
+        c.copy(z2); c.add(t0)
+    
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+    /* self=1/self */
+    func inverse()
+    {
+        let f0=FP4(a)
+        let f1=FP4(b)
+        let f2=FP4(a)
+        let f3=FP4(0)
+    
+        norm()
+        f0.sqr()
+        f1.mul(c)
+        f1.times_i()
+        f0.sub(f1)
+    
+        f1.copy(c); f1.sqr()
+        f1.times_i()
+        f2.mul(b)
+        f1.sub(f2)
+    
+        f2.copy(b); f2.sqr()
+        f3.copy(a); f3.mul(c)
+        f2.sub(f3)
+    
+        f3.copy(b); f3.mul(f2)
+        f3.times_i()
+        a.mul(f0)
+        f3.add(a)
+        c.mul(f1)
+        c.times_i()
+    
+        f3.add(c)
+        f3.inverse()
+        a.copy(f0); a.mul(f3)
+        b.copy(f1); b.mul(f3)
+        c.copy(f2); c.mul(f3)
+    }
+    
+    /* self=self^p using Frobenius */
+    func frob(_ f:FP2)
+    {
+        let f2=FP2(f)
+        let f3=FP2(f)
+    
+        f2.sqr()
+        f3.mul(f2)
+    
+        a.frob(f3)
+        b.frob(f3)
+        c.frob(f3)
+    
+        b.pmul(f)
+        c.pmul(f2)
+    }
+    
+    /* trace function */
+    func trace() -> FP4
+    {
+        let t=FP4(0)
+        t.copy(a)
+        t.imul(3)
+        t.reduce()
+        return t
+    }
+    /* convert from byte array to FP12 */
+    static func fromBytes(_ w:[UInt8]) -> FP12
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+    
+        for i in 0 ..< RM {t[i]=w[i]}
+        var a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+RM]}
+        var b=BIG.fromBytes(t)
+        var c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+2*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+3*RM]}
+        b=BIG.fromBytes(t)
+        var d=FP2(a,b)
+    
+        let e=FP4(c,d)
+    
+        for i in 0 ..< RM {t[i]=w[i+4*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+5*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+6*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+7*RM]}
+        b=BIG.fromBytes(t)
+        d=FP2(a,b)
+    
+        let f=FP4(c,d)
+    
+    
+        for i in 0 ..< RM {t[i]=w[i+8*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+9*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+10*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+11*RM]}
+        b=BIG.fromBytes(t);
+        d=FP2(a,b)
+    
+        let g=FP4(c,d)
+    
+        return FP12(e,f,g)
+    }
+    
+    /* convert this to byte array */
+    func toBytes(_ w:inout [UInt8])
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        a.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i]=t[i]}
+        a.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+RM]=t[i]}
+        a.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+2*RM]=t[i]}
+        a.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+3*RM]=t[i]}
+    
+        b.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+4*RM]=t[i]}
+        b.geta().getB().toBytes(&t);
+        for i in 0 ..< RM {w[i+5*RM]=t[i]}
+        b.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+6*RM]=t[i]}
+        b.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+7*RM]=t[i]}
+    
+        c.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+8*RM]=t[i]}
+        c.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+9*RM]=t[i]}
+        c.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+10*RM]=t[i]}
+        c.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+11*RM]=t[i]}
+    }
+    /* convert to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")
+    }
+    
+    /* self=self^e */
+    /* Note this is simple square and multiply, so not side-channel safe */
+    func pow(_ e:BIG) -> FP12
+    {
+        norm()
+        e.norm()
+        let w=FP12(self)
+        let z=BIG(e)
+        let r=FP12(1)
+    
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.usqr()
+        }
+        r.reduce()
+        return r
+    }
+    /* constant time powering by small integer of max length bts */
+    func pinpow(_ e:Int32,_ bts:Int32)
+    {
+        var R=[FP12]()
+        R.append(FP12(1));
+        R.append(FP12(self));
+
+        //for var i=bts-1;i>=0;i--
+        for i in (0...bts-1).reversed()
+        {
+            let b=Int((e>>i)&1)
+            R[1-b].mul(R[b])
+            R[b].usqr()
+        }
+        copy(R[0]);
+    }
+    
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+    /* Timing attack secure, but not cache attack secure */
+    
+    static func pow4(_ q:[FP12],_ u:[BIG]) -> FP12
+    {
+        var a=[Int32](repeating: 0,count: 4)
+        var g=[FP12]();
+        
+        for _ in 0 ..< 8 {g.append(FP12(0))}
+        var s=[FP12]();
+        for _ in 0 ..< 2 {s.append(FP12(0))}
+        
+        let c=FP12(1)
+        let p=FP12(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 4
+            {t.append(BIG(u[i]))}
+        
+        let mt=BIG(0);
+        var w=[Int8](repeating: 0,count: ROM.NLEN*Int(ROM.BASEBITS)+1)
+    
+        g[0].copy(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0])
+        g[1].copy(g[0])
+        g[2].copy(g[0])
+        g[3].copy(g[0])
+        g[4].copy(q[0]); g[4].mul(q[1])
+        g[5].copy(g[4])
+        g[6].copy(g[4])
+        g[7].copy(g[4])
+    
+        s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0])
+        s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0])
+        g[2].mul(s[1])
+        g[5].mul(s[0])
+        g[6].mul(s[1])
+        s[1].copy(q[2]); s[1].mul(q[3])
+        s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0])
+        g[3].mul(s[1])
+        g[4].mul(s[0])
+        g[7].mul(s[1])
+
+    /* if power is even add 1 to power, and add q to correction */
+    
+        for i in 0 ..< 4
+        {
+            if t[i].parity()==0
+            {
+                               t[i].inc(1); t[i].norm()
+                               c.mul(q[i])
+            }
+            mt.add(t[i]); mt.norm()
+        }
+        c.conj();
+        let nb=1+mt.nbits();
+    
+    /* convert exponent to signed 1-bit window */
+        for j in 0 ..< nb
+        {
+            for i in 0 ..< 4
+            {
+                               a[i]=Int32(t[i].lastbits(2)-2)
+                               t[i].dec(Int(a[i]));
+                t[i].norm()
+                               t[i].fshr(1)
+            }
+            w[j]=Int8(8*a[0]+4*a[1]+2*a[2]+a[3])
+        }
+        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))
+        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))
+        p.copy(g[Int(w[nb]-1)/2])
+    
+        //for var i=nb-1;i>=0;i--
+        for i in (0...nb-1).reversed()
+        {
+            let m=w[i]>>7
+            let j=(w[i]^m)-m  /* j=abs(w[i]) */
+            let k=Int((j-1)/2)
+            s[0].copy(g[k]); s[1].copy(g[k]); s[1].conj()
+            p.usqr()
+            p.mul(s[Int(m&1)])
+        }
+        p.mul(c)  /* apply correction */
+        p.reduce()
+        return p
+    }
+    
+    
+    
+    
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/fp2.swift
----------------------------------------------------------------------
diff --git a/version22/swift/fp2.swift b/version22/swift/fp2.swift
new file mode 100644
index 0000000..cdc1711
--- /dev/null
+++ b/version22/swift/fp2.swift
@@ -0,0 +1,329 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  fp2.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+
+final class FP2
+{
+    private var a:FP
+    private var b:FP
+
+    /* Constructors */
+    init(_ c: Int)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ x:FP2)
+    {
+        a=FP(x.a)
+        b=FP(x.b)
+    }
+
+    init(_ c:FP,_ d:FP)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+    
+    init(_ c:BIG,_ d:BIG)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+
+    init(_ c:FP)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ c:BIG)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+
+    /* test this=0 ? */
+    func iszilch() -> Bool
+    {
+        reduce()
+        return (a.iszilch() && b.iszilch())
+    }
+    
+    func cmove(_ g:FP2,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+    /* test this=1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP(1)
+        return (a.equals(one) && b.iszilch())
+    }
+    
+    /* test this=x */
+    func equals(_ x:FP2) -> Bool
+    {
+        return (a.equals(x.a) && b.equals(x.b));
+    }
+    
+    
+    /* reduce components mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    
+    /* normalise components of w */
+    func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    
+    /* extract a */
+    func getA() -> BIG
+    {
+        return a.redc()
+    }
+    
+    /* extract b */
+    func getB() -> BIG
+    {
+        return b.redc()
+    }
+
+    /* copy self=x */
+    func copy(_ x:FP2)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    
+    /* set self=0 */
+    func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    
+    /* set self=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+    }
+    
+    /* negate self mod Modulus */
+    func neg()
+    {
+        norm();
+        let m=FP(a)
+        let t=FP(0)
+    
+        m.add(b)
+        m.neg()
+        m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+    }
+    
+    /* set to a-ib */
+    func conj()
+    {
+        b.neg()
+    }
+
+    /* self+=a */
+    func add(_ x:FP2)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    
+    /* self-=a */
+    func sub(_ x:FP2)
+    {
+        let m=FP2(x)
+        m.neg()
+        add(m)
+    }
+
+    /* self*=s, where s is an FP */
+    func pmul(_ s:FP)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+    
+    /* self*=i, where i is an int */
+    func imul(_ c:Int)
+    {
+        a.imul(c);
+        b.imul(c);
+    }
+    
+    /* self*=self */
+    func sqr()
+    {
+        norm();
+    
+        let w1=FP(a)
+        let w3=FP(a)
+        let mb=FP(b)
+        w3.mul(b)
+        w1.add(b)
+        mb.neg()
+        a.add(mb)
+        a.mul(w1)
+        b.copy(w3); b.add(w3)
+        norm()
+    }
+    /* self*=y */
+    func mul(_ y:FP2)
+    {
+        norm();  /* This is needed here as {a,b} is not normed before 
additions */
+    
+        let w1=FP(a)
+        let w2=FP(b)
+        let w5=FP(a)
+        let mw=FP(0)
+    
+        w1.mul(y.a)  // w1=a*y.a  - this norms w1 and y.a, NOT a
+        w2.mul(y.b)  // w2=b*y.b  - this norms w2 and y.b, NOT b
+        w5.add(b)    // w5=a+b
+        b.copy(y.a); b.add(y.b) // b=y.a+y.b
+    
+        b.mul(w5)
+        mw.copy(w1); mw.add(w2); mw.neg()
+    
+        b.add(mw); mw.add(w1)
+        a.copy(w1);    a.add(mw)
+    
+        norm()
+    
+    }
+ 
+    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) 
*/
+    /* returns true if this is QR */
+    func sqrt() -> Bool
+    {
+        if iszilch() {return true}
+        var w1=FP(b)
+        var w2=FP(a)
+        w1.sqr(); w2.sqr(); w1.add(w2)
+        if w1.jacobi() != 1 { zero(); return false; }
+        w1=w1.sqrt()
+        w2.copy(a); w2.add(w1); w2.div2()
+        if w2.jacobi() != 1
+        {
+            w2.copy(a); w2.sub(w1); w2.div2()
+            if w2.jacobi() != 1 { zero(); return false }
+        }
+        w2=w2.sqrt()
+        a.copy(w2)
+        w2.add(w2)
+        w2.inverse()
+        b.mul(w2)
+        return true
+    }
+    /* output to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+
+    /* self=1/self */
+    func inverse()
+    {
+        norm();
+        let w1=FP(a)
+        let w2=FP(b)
+    
+        w1.sqr()
+        w2.sqr()
+        w1.add(w2)
+        w1.inverse()
+        a.mul(w1)
+        w1.neg()
+        b.mul(w1)
+    }
+
+    /* self/=2 */
+    func div2()
+    {
+        a.div2();
+        b.div2();
+    }
+    
+    /* self*=sqrt(-1) */
+    func times_i()
+    {
+        let z=FP(a)
+        a.copy(b); a.neg()
+        b.copy(z)
+    }
+
+    /* w*=(1+sqrt(-1)) */
+    /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+    func mul_ip()
+    {
+        norm();
+        let t=FP2(self)
+        let z=FP(a)
+        a.copy(b)
+        a.neg()
+        b.copy(z)
+        add(t)
+        norm()
+    }
+    /* w/=(1+sqrt(-1)) */
+    func div_ip()
+    {
+        let t=FP2(0)
+        norm()
+        t.a.copy(a); t.a.add(b)
+        t.b.copy(b); t.b.sub(a)
+        copy(t)
+        div2()
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/fp4.swift
----------------------------------------------------------------------
diff --git a/version22/swift/fp4.swift b/version22/swift/fp4.swift
new file mode 100644
index 0000000..3cba394
--- /dev/null
+++ b/version22/swift/fp4.swift
@@ -0,0 +1,517 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  fp4.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+final class FP4 {
+    private final var a:FP2
+    private final var b:FP2
+
+    /* constructors */
+    init(_ c:Int)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    
+    init(_ x:FP4)
+    {
+        a=FP2(x.a)
+        b=FP2(x.b)
+    }
+    
+    init(_ c:FP2,_ d:FP2)
+    {
+        a=FP2(c)
+        b=FP2(d)
+    }
+    
+    init(_ c:FP2)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    /* reduce all components of this mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    /* normalise all components of this mod Modulus */
+    func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    /* test this==0 ? */
+    func iszilch() -> Bool
+    {
+        reduce()
+        return a.iszilch() && b.iszilch()
+    }
+    /* test this==1 ? */
+    func isunity() -> Bool
+    {
+    let one=FP2(1);
+    return a.equals(one) && b.iszilch()
+    }
+    
+    /* test is w real? That is in a+ib test b is zero */
+    func isreal() -> Bool
+    {
+        return b.iszilch();
+    }
+    /* extract real part a */
+    func real() -> FP2
+    {
+        return a;
+    }
+    
+    func geta() -> FP2
+    {
+        return a;
+    }
+    /* extract imaginary part b */
+    func getb() -> FP2
+    {
+    return b;
+    }
+    /* test self=x? */
+    func equals(_ x:FP4) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b)
+    }
+    /* copy self=x */
+    func copy(_ x:FP4)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    /* set this=0 */
+    func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    /* set this=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+    }
+    /* set self=-self */
+    func neg()
+    {
+        let m=FP2(a)
+        let t=FP2(0)
+        m.add(b)
+        m.neg()
+        m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+    }
+    /* self=conjugate(self) */
+    func conj()
+    {
+        b.neg(); b.norm()
+    }
+    /* this=-conjugate(this) */
+    func nconj()
+    {
+        a.neg(); a.norm()
+    }
+    /* self+=x */
+    func add(_ x:FP4)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    /* self-=x */
+    func sub(_ x:FP4)
+    {
+        let m=FP4(x)
+        m.neg()
+        add(m)
+    }
+    
+    /* self*=s where s is FP2 */
+    func pmul(_ s:FP2)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+    /* self*=c where c is int */
+    func imul(_ c:Int)
+    {
+        a.imul(c)
+        b.imul(c)
+    }
+    /* self*=self */
+    func sqr()
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+        let t3=FP2(a)
+    
+        t3.mul(b)
+        t1.add(b)
+        t2.mul_ip()
+    
+        t2.add(a)
+        a.copy(t1)
+    
+        a.mul(t2)
+    
+        t2.copy(t3)
+        t2.mul_ip()
+        t2.add(t3)
+        t2.neg()
+        a.add(t2)
+    
+        b.copy(t3)
+        b.add(t3)
+    
+        norm()
+    }
+    /* self*=y */
+    func mul(_ y:FP4)
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+        let t3=FP2(0)
+        let t4=FP2(b)
+    
+        t1.mul(y.a)
+        t2.mul(y.b)
+        t3.copy(y.b)
+        t3.add(y.a)
+        t4.add(a)
+    
+        t4.mul(t3)
+        t4.sub(t1)
+        t4.norm()
+    
+        b.copy(t4)
+        b.sub(t2)
+        t2.mul_ip()
+        a.copy(t2)
+        a.add(t1)
+    
+        norm()
+    }
+    /* convert this to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+    /* self=1/self */
+    func inverse()
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+    
+        t1.sqr()
+        t2.sqr()
+        t2.mul_ip()
+        t1.sub(t2)
+        t1.inverse()
+        a.mul(t1)
+        t1.neg()
+        b.mul(t1)
+    }
+    
+    /* self*=i where i = sqrt(-1+sqrt(-1)) */
+    func times_i()
+    {
+        norm();
+        let s=FP2(b)
+        let t=FP2(b)
+        s.times_i()
+        t.add(s)
+        t.norm()
+        b.copy(a)
+        a.copy(t)
+    }
+    
+    /* self=self^p using Frobenius */
+    func frob(_ f:FP2)
+    {
+        a.conj()
+        b.conj()
+        b.mul(f)
+    }
+    /* self=self^e */
+    func pow(_ e:BIG) -> FP4
+    {
+        norm()
+        e.norm()
+        let w=FP4(self)
+        let z=BIG(e)
+        let r=FP4(1)
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.sqr()
+        }
+        r.reduce()
+        return r
+    }
+    /* XTR xtr_a function */
+    func xtr_A(_ w:FP4,_ y:FP4,_ z:FP4)
+    {
+        let r=FP4(w)
+        let t=FP4(w)
+        r.sub(y)
+        r.pmul(a)
+        t.add(y)
+        t.pmul(b)
+        t.times_i()
+    
+        copy(r)
+        add(t)
+        add(z)
+    
+        norm()
+    }
+    /* XTR xtr_d function */
+    func xtr_D()
+    {
+        let w=FP4(self)
+        sqr(); w.conj()
+        w.add(w)
+        sub(w)
+        reduce()
+    }
+    /* r=x^n using XTR method on traces of FP12s */
+    func xtr_pow(_ n:BIG) -> FP4
+    {
+        let a=FP4(3)
+        let b=FP4(self)
+        let c=FP4(b)
+        c.xtr_D()
+        let t=FP4(0)
+        let r=FP4(0)
+    
+        n.norm();
+        let par=n.parity()
+        let v=BIG(n); v.fshr(1)
+        if par==0 {v.dec(1); v.norm()}
+    
+        let nb=v.nbits()
+        //for i in (0...nb-1).reverse()
+        var i=nb-1
+        //for var i=nb-1;i>=0;i--
+        while i>=0
+        {
+            if (v.bit(UInt(i)) != 1)
+            {
+                               t.copy(b)
+                               conj()
+                               c.conj()
+                               b.xtr_A(a,self,c)
+                               conj()
+                               c.copy(t)
+                               c.xtr_D()
+                               a.xtr_D()
+            }
+            else
+            {
+                               t.copy(a); t.conj()
+                               a.copy(b)
+                               a.xtr_D()
+                               b.xtr_A(c,self,t)
+                               c.xtr_D()
+            }
+            i-=1
+        }
+        if par==0 {r.copy(c)}
+        else {r.copy(b)}
+        r.reduce()
+        return r
+    }
+    
+    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. 
See Stam thesis. */
+    func xtr_pow2(_ ck:FP4,_ ckml:FP4,_ ckm2l:FP4,_ a:BIG,_ b:BIG) -> FP4
+    {
+        a.norm(); b.norm()
+        let e=BIG(a)
+        let d=BIG(b)
+        let w=BIG(0)
+    
+        let cu=FP4(ck)  // can probably be passed in w/o copying
+        let cv=FP4(self)
+        let cumv=FP4(ckml)
+        let cum2v=FP4(ckm2l)
+        var r=FP4(0)
+        let t=FP4(0)
+    
+        var f2:Int=0
+        while d.parity()==0 && e.parity()==0
+        {
+            d.fshr(1);
+            e.fshr(1);
+            f2 += 1;
+        }
+    
+        while (BIG.comp(d,e) != 0)
+        {
+            if BIG.comp(d,e)>0
+            {
+                               w.copy(e); w.imul(4); w.norm()
+                               if BIG.comp(d,w)<=0
+                               {
+                    w.copy(d); d.copy(e)
+                    e.rsub(w); e.norm()
+    
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cum2v.conj()
+                    cumv.copy(cv)
+                    cv.copy(cu)
+                    cu.copy(t)
+    
+                               }
+                               else if d.parity()==0
+                               {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                               }
+                               else if e.parity()==1
+                               {
+                    d.sub(e); d.norm()
+                    d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cu.xtr_D()
+                    cum2v.copy(cv)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cv.copy(t)
+                               }
+                               else
+                               {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                               }
+            }
+            if BIG.comp(d,e)<0
+            {
+                               w.copy(d); w.imul(4); w.norm()
+                               if BIG.comp(e,w)<=0
+                               {
+                    e.sub(d); e.norm()
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cumv.copy(cu)
+                    cu.copy(t)
+                               }
+                               else if e.parity()==0
+                               {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                               }
+                               else if d.parity()==1
+                               {
+                    w.copy(e)
+                    e.copy(d)
+                    w.sub(d); w.norm()
+                    d.copy(w); d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cumv.conj()
+                    cum2v.copy(cu)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cu.copy(cv)
+                    cu.xtr_D()
+                    cv.copy(t)
+                               }
+                               else
+                               {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                               }
+            }
+        }
+        r.copy(cv)
+        r.xtr_A(cu,cumv,cum2v)
+        for _ in 0 ..< f2
+            {r.xtr_D()}
+        r=r.xtr_pow(d)
+        return r
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/gcm.swift
----------------------------------------------------------------------
diff --git a/version22/swift/gcm.swift b/version22/swift/gcm.swift
new file mode 100644
index 0000000..15a6657
--- /dev/null
+++ b/version22/swift/gcm.swift
@@ -0,0 +1,326 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  gcm.swift
+//
+//  Created by Michael Scott on 23/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+/*
+* Implementation of the AES-GCM Encryption/Authentication
+*
+* Some restrictions..
+* 1. Only for use with AES
+* 2. Returned tag is always 128-bits. Truncate at your own risk.
+* 3. The order of function calls must follow some rules
+*
+* Typical sequence of calls..
+* 1. call GCM_init
+* 2. call GCM_add_header any number of times, as long as length of header is 
multiple of 16 bytes (block size)
+* 3. call GCM_add_header one last time with any length of header
+* 4. call GCM_add_cipher any number of times, as long as length of 
cipher/plaintext is multiple of 16 bytes
+* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+* 6. call GCM_finish to extract the tag.
+*
+* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+*/
+
+final class GCM {
+    static let NB:Int=4
+    static let GCM_ACCEPTING_HEADER:Int=0
+    static let GCM_ACCEPTING_CIPHER:Int=1
+    static let GCM_NOT_ACCEPTING_MORE:Int=2
+    static let GCM_FINISHED:Int=3
+    static let GCM_ENCRYPTING:Int=0
+    static let GCM_DECRYPTING:Int=1
+    
+    private var table=[[UInt32]](repeating: [UInt32](repeating: 0,count: 
4),count: 128) /* 2k bytes */
+    private var stateX=[UInt8](repeating: 0,count: 16)
+    private var Y_0=[UInt8](repeating: 0,count: 16)
+    
+    private var counter:Int=0
+    private var lenA=[UInt32](repeating: 0,count: 2)
+    private var lenC=[UInt32](repeating: 0,count: 2)
+    private var status:Int=0
+    private var a=AES()
+    
+    private static func pack(_ b: [UInt8]) -> UInt32
+    { /* pack bytes into a 32-bit Word */
+        var r=((UInt32(b[0])&0xff)<<24)|((UInt32(b[1])&0xff)<<16)
+        r = r|((UInt32(b[2])&0xff)<<8)|(UInt32(b[3])&0xff)
+        return r
+    }
+    
+    private static func unpack(_ a: UInt32) -> [UInt8]
+    { /* unpack bytes from a word */
+        let 
b:[UInt8]=[UInt8((a>>24)&0xff),UInt8((a>>16)&0xff),UInt8((a>>8)&0xff),UInt8(a&0xff)];
+        return b
+    }
+    
+    private func precompute(_ H: [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+            table[0][i]=GCM.pack(b);
+            j+=4
+        }
+        for i in 1 ..< 128
+        {
+            var c:UInt32=0
+            for j in 0 ..< GCM.NB {table[i][j]=c|(table[i-1][j])>>1; 
c=table[i-1][j]<<31;}
+            if c != 0  {table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }
+    }
+ 
+    private func gf2mul()
+    { /* gf2m mul - Z=H*X mod 2^128 */
+        var P=[UInt32](repeating: 0,count: 4)
+    
+        for i in 0 ..< 4 {P[i]=0}
+        var j=8; var m=0;
+        for i in 0 ..< 128
+        {
+            j-=1
+            var c=UInt32((stateX[m]>>UInt8(j))&1); c = ( ~c ) + 1
+            for k in 0 ..< GCM.NB {P[k]^=(table[i][k] & c)}
+            if (j==0)
+            {
+               j=8; m += 1;
+                if (m==16) {break}
+            }
+        }
+        j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(P[i])
+            stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; 
stateX[j+3]=b[3];
+            j+=4
+        }
+    }
+    private func wrap()
+    { /* Finish off GHASH */
+        var F=[UInt32](repeating: 0,count: 4)
+        var L=[UInt8](repeating: 0,count: 16)
+    
+    /* convert lengths from bytes to bits */
+        F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>29
+        F[1]=lenA[1]<<3;
+        F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>29
+        F[3]=lenC[1]<<3;
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(F[i]);
+            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]
+            j+=4
+        }
+        for i in 0 ..< 16 {stateX[i]^=L[i]}
+        gf2mul()
+    }
+    
+    private func ghash(_ plain: [UInt8],_ len: Int) -> Bool
+    {
+    //    var B=[UInt8](count:16,repeatedValue:0)
+    
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if (status != GCM.GCM_ACCEPTING_CIPHER) {return false}
+        
+        var j=0;
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+                               stateX[i]^=plain[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break;}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+    
+    /* Initialize GCM mode */
+    func init_it(_ key: [UInt8],_ niv: Int,_ iv: [UInt8])
+    { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 
16,24 or 32 bytes */
+        var H=[UInt8](repeating: 0,count: 16)
+        
+        for i in 0 ..< 16 {H[i]=0; stateX[i]=0}
+        
+        a.init_it(AES.ECB,key,iv)
+        a.ecb_encrypt(&H);    /* E(K,0) */
+        precompute(H)
+        
+        lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        if (niv==12)
+        {
+            for i in 0 ..< 12 {a.f[i]=iv[i]}
+            var b=GCM.unpack(UInt32(1))
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* 
initialise IV */
+            for i in 0 ..< 16 {Y_0[i]=a.f[i]}
+        }
+        else
+        {
+            status=GCM.GCM_ACCEPTING_CIPHER;
+            ghash(iv,niv) /* GHASH(H,0,IV) */
+            wrap()
+            for i in 0 ..< 16 {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0}
+            lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        }
+        status=GCM.GCM_ACCEPTING_HEADER;
+    }
+    
+    /* Add Header data - included but not encrypted */
+    func add_header(_ header: [UInt8],_ len: Int) -> Bool
+    { /* Add some header. Won't be encrypted, but will be authenticated. len 
is length of header */
+        if status != GCM.GCM_ACCEPTING_HEADER {return false}
+    
+        var j=0
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+                               stateX[i]^=header[j];
+                j+=1;
+                lenA[1]+=1; if lenA[1]==0 {lenA[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_ACCEPTING_CIPHER}
+        return true;
+    }
+    /* Add Plaintext - included and encrypted */
+    func add_plain(_ plain: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var cipher=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        if status == GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+        
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* 
increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+    
+            for i in 0 ..< 16
+            {
+               cipher[j]=(plain[j]^B[i]);
+               stateX[i]^=cipher[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return cipher;
+    }
+    /* Add Ciphertext - decrypts to plaintext */
+    func add_cipher(_ cipher: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var plain=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+    
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* 
increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+            for i in 0 ..< 16
+            {
+                let oc=cipher[j]
+                plain[j]=(cipher[j]^B[i]);
+                stateX[i]^=oc;
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul()
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return plain;
+    }
+    
+    /* Finish and extract Tag */
+    func finish(_ extract: Bool) -> [UInt8]
+    { /* Finish off GHASH and extract tag (MAC) */
+        var tag=[UInt8](repeating: 0,count: 16)
+    
+        wrap();
+        /* extract tag */
+        if (extract)
+        {
+            a.ecb_encrypt(&Y_0);        /* E(K,Y0) */
+            for i in 0 ..< 16 {Y_0[i]^=stateX[i]}
+            for i in 0 ..< 16 {tag[i]=Y_0[i];Y_0[i]=0;stateX[i]=0;}
+        }
+        status=GCM.GCM_FINISHED;
+        a.end();
+        return tag;
+    }
+    
+    static func hex2bytes(_ s: String) -> [UInt8]
+    {
+        var array=Array(arrayLiteral: s)
+        let len=array.count;
+        var data=[UInt8](repeating: 0,count: len/2)
+
+        var i=0
+        while (i<len)
+        {
+            data[i / 2] = 
UInt8(strtoul(String(array[i]),nil,16)<<4)+UInt8(strtoul(String(array[i+1]),nil,16))
+            i+=2
+        }
+        return data;
+    }
+    
+    
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/hash256.swift
----------------------------------------------------------------------
diff --git a/version22/swift/hash256.swift b/version22/swift/hash256.swift
new file mode 100644
index 0000000..6140da5
--- /dev/null
+++ b/version22/swift/hash256.swift
@@ -0,0 +1,188 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  hash256.swift - Implementation of SHA-256
+//
+//  Created by Michael Scott on 17/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  SHA256 Implementation
+//
+
+final class HASH256{
+    
+    private var length=[UInt32](repeating: 0,count: 2)
+    private var h=[UInt32](repeating: 0,count: 8)
+    private var w=[UInt32](repeating: 0,count: 64)
+    static let H0:UInt32=0x6A09E667
+    static let H1:UInt32=0xBB67AE85
+    static let H2:UInt32=0x3C6EF372
+    static let H3:UInt32=0xA54FF53A
+    static let H4:UInt32=0x510E527F
+    static let H5:UInt32=0x9B05688C
+    static let H6:UInt32=0x1F83D9AB
+    static let H7:UInt32=0x5BE0CD19
+    
+    static let len:Int=32
+    
+    static let K:[UInt32]=[
+    
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+    
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+    
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+    
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+    
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+    
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+    
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+    
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2]
+    
+    
+    private static func S(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return ((x>>n)|(x<<(32-n)))
+    }
+
+    private static func R(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return (x>>n)
+    }
+    
+    private static func Ch(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt32) -> UInt32
+    {
+        return (S(2,x)^S(13,x)^S(22,x))
+    }
+    
+    private static func Sig1(_ x: UInt32) -> UInt32
+    {
+        return (S(6,x)^S(11,x)^S(25,x))
+    }
+    
+    private static func theta0(_ x: UInt32) -> UInt32
+    {
+        return (S(7,x)^S(18,x)^R(3,x))
+    }
+    
+    private static func theta1(_ x: UInt32) -> UInt32
+    {
+        return (S(17,x)^S(19,x)^R(10,x))
+    }
+ 
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt32
+        for j in 16 ..< 64
+        {
+            
w[j]=HASH256.theta1(w[j-2])&+w[j-7]&+HASH256.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+    
+        for j in 0 ..< 64
+        { /* 64 times - mush it up */
+            t1=hh&+HASH256.Sig1(e)&+HASH256.Ch(e,f,g)&+HASH256.K[j]&+w[j]
+            t2=HASH256.Sig0(a)&+HASH256.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 64 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH256.H0;
+        h[1]=HASH256.H1;
+        h[2]=HASH256.H2;
+        h[3]=HASH256.H3;
+        h[4]=HASH256.H4;
+        h[5]=HASH256.H5;
+        h[6]=HASH256.H6;
+        h[7]=HASH256.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/32)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt32(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%512)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+
+    /* Generate 32-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 32)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%512) != 448) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH256.len
+        { /* convert to bytes */
+            let r=(8*(3-UInt32(i)%4));
+            digest[i]=UInt8((h[i/4]>>r) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/hash384.swift
----------------------------------------------------------------------
diff --git a/version22/swift/hash384.swift b/version22/swift/hash384.swift
new file mode 100644
index 0000000..de89d4c
--- /dev/null
+++ b/version22/swift/hash384.swift
@@ -0,0 +1,198 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  hash384.swift - Implementation of SHA-384
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+final class HASH384{
+    
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0xcbbb9d5dc1059ed8
+    static let H1:UInt64=0x629a292a367cd507
+    static let H2:UInt64=0x9159015a3070dd17
+    static let H3:UInt64=0x152fecd8f70e5939
+    static let H4:UInt64=0x67332667ffc00b31
+    static let H5:UInt64=0x8eb44a8768581511
+    static let H6:UInt64=0xdb0c2e0d64f98fa7
+    static let H7:UInt64=0x47b5481dbefa4fa4
+    
+    static let len:Int=48
+    
+    static let K:[UInt64]=[
+        
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            
w[j]=HASH384.theta1(w[j-2])&+w[j-7]&+HASH384.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH384.Sig1(e)&+HASH384.Ch(e,f,g)&+HASH384.K[j]&+w[j]
+            t2=HASH384.Sig0(a)&+HASH384.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH384.H0;
+        h[1]=HASH384.H1;
+        h[2]=HASH384.H2;
+        h[3]=HASH384.H3;
+        h[4]=HASH384.H4;
+        h[5]=HASH384.H5;
+        h[6]=HASH384.H6;
+        h[7]=HASH384.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 48-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 48)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH384.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/hash512.swift
----------------------------------------------------------------------
diff --git a/version22/swift/hash512.swift b/version22/swift/hash512.swift
new file mode 100644
index 0000000..634f944
--- /dev/null
+++ b/version22/swift/hash512.swift
@@ -0,0 +1,198 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  hash512.swift - Implementation of SHA-512
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+final class HASH512{
+    
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0x6a09e667f3bcc908
+    static let H1:UInt64=0xbb67ae8584caa73b
+    static let H2:UInt64=0x3c6ef372fe94f82b
+    static let H3:UInt64=0xa54ff53a5f1d36f1
+    static let H4:UInt64=0x510e527fade682d1
+    static let H5:UInt64=0x9b05688c2b3e6c1f
+    static let H6:UInt64=0x1f83d9abfb41bd6b
+    static let H7:UInt64=0x5be0cd19137e2179
+    
+    static let len:Int=64
+    
+    static let K:[UInt64]=[
+        
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+    
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            
w[j]=HASH512.theta1(w[j-2])&+w[j-7]&+HASH512.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH512.Sig1(e)&+HASH512.Ch(e,f,g)&+HASH512.K[j]&+w[j]
+            t2=HASH512.Sig0(a)&+HASH512.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH512.H0;
+        h[1]=HASH512.H1;
+        h[2]=HASH512.H2;
+        h[3]=HASH512.H3;
+        h[4]=HASH512.H4;
+        h[5]=HASH512.H5;
+        h[6]=HASH512.H6;
+        h[7]=HASH512.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 48-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 64)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH512.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/main.swift
----------------------------------------------------------------------
diff --git a/version22/swift/main.swift b/version22/swift/main.swift
new file mode 100644
index 0000000..e464a0e
--- /dev/null
+++ b/version22/swift/main.swift
@@ -0,0 +1,13 @@
+//
+//  main.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+BenchtestPAIR()
+BenchtestEC()
+TestRSA()
+TestECDH()
+TestMPIN()
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/mpin.swift
----------------------------------------------------------------------
diff --git a/version22/swift/mpin.swift b/version22/swift/mpin.swift
new file mode 100644
index 0000000..c4bc28e
--- /dev/null
+++ b/version22/swift/mpin.swift
@@ -0,0 +1,833 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+       
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+//
+//  mpin.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+
+import Foundation
+
+final public class MPIN
+{
+    static public let EFS=Int(ROM.MODBYTES)
+    static public let EGS=Int(ROM.MODBYTES)
+    static public let PAS:Int=16
+    static let INVALID_POINT:Int = -14
+    static let BAD_PARAMS:Int = -11
+    static let WRONG_ORDER:Int = -18
+    static public let BAD_PIN:Int = -19
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    /* Configure your PIN here */
+    
+    static let MAXPIN:Int32 = 10000  // PIN less than this
+    static let PBLEN:Int32 = 14      // Number of bits in PIN
+    static let TS:Int = 10         // 10 for 4 digit PIN, 14 for 6-digit PIN - 
2^TS/TS approx = sqrt(MAXPIN)
+    static let TRAP:Int = 200      // 200 for 4 digit PIN, 2000 for 6-digit 
PIN  - approx 2*sqrt(MAXPIN)
+
+    static public let HASH_TYPE=SHA256
+    
+    private static func mpin_hash(_ sha:Int,_ c: FP4,_ U: ECP) -> [UInt8]
+    {
+        var w=[UInt8](repeating: 0,count: EFS)
+        var t=[UInt8](repeating: 0,count: 6*EFS)
+        var h=[UInt8]()
+        
+        c.geta().getA().toBytes(&w); for i in 0 ..< EFS {t[i]=w[i]}
+        c.geta().getB().toBytes(&w); for i in EFS ..< 2*EFS {t[i]=w[i-EFS]}
+        c.getb().getA().toBytes(&w); for i in 2*EFS ..< 3*EFS {t[i]=w[i-2*EFS]}
+        c.getb().getB().toBytes(&w); for i in 3*EFS ..< 4*EFS {t[i]=w[i-3*EFS]}
+        
+        U.getX().toBytes(&w); for i in 4*EFS ..< 5*EFS {t[i]=w[i-4*EFS]}
+        U.getY().toBytes(&w); for i in 5*EFS ..< 6*EFS {t[i]=w[i-5*EFS]}
+        
+        if sha==SHA256
+        {
+            let H=HASH256()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA384
+        {
+            let H=HASH384()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA512
+        {
+            let H=HASH512()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if h.isEmpty {return h}
+        var R=[UInt8](repeating: 0,count: PAS)
+        for i in 0 ..< PAS {R[i]=h[i]}
+        return R
+    }
+    
+    // Hash number (optional) and string to point on curve
+    
+    private static func hashit(_ sha:Int,_ n:Int32,_ ID:[UInt8]) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            let H=HASH256()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            let H=HASH384()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            let H=HASH512()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if R.isEmpty {return R}
+        let RM=Int(ROM.MODBYTES)
+        var W=[UInt8](repeating: 0,count: RM)
+        if sha >= RM
+        {
+            for i in 0 ..< RM {W[i]=R[i]}
+        }
+        else
+        {
+            for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    static func mapit(_ h:[UInt8]) -> ECP
+    {
+        let q=BIG(ROM.Modulus)
+        let x=BIG.fromBytes(h)
+        x.mod(q)
+        var P=ECP(x,0)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1); x.norm();
+            P=ECP(x,0);
+        }
+        if ROM.CURVE_PAIRING_TYPE != ROM.BN_CURVE {
+            let c=BIG(ROM.CURVE_Cof)
+            P=P.mul(c)
+        }
+
+        return P
+    }
+
+    // needed for SOK
+    static func mapit2(_ h:[UInt8]) -> ECP2
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        let one=BIG(1)
+        var Q=ECP2()
+        x.mod(q);
+        while (true)
+        {
+            let X=FP2(one,x);
+            Q=ECP2(X);
+            if !Q.is_infinity() {break}
+            x.inc(1); x.norm();
+        }
+    // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+        let Fra=BIG(ROM.CURVE_Fra);
+        let Frb=BIG(ROM.CURVE_Frb);
+        let X=FP2(Fra,Frb);
+        x=BIG(ROM.CURVE_Bnx);
+    
+        let T=ECP2(); T.copy(Q)
+        T.mul(x); T.neg()
+        let K=ECP2(); K.copy(T)
+        K.dbl(); K.add(T); K.affine()
+    
+        K.frob(X)
+        Q.frob(X); Q.frob(X); Q.frob(X)
+        Q.add(T); Q.add(K)
+        T.frob(X); T.frob(X)
+        Q.add(T)
+        Q.affine()
+        return Q
+    }
+    
+    // return time in slots since epoch
+    static public func today() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970/(60*1440)))
+    }
+
+    // these next two functions help to implement elligator squared - 
http://eprint.iacr.org/2014/043
+    // maps a random u to a point on the curve
+    static func map(_ u:BIG,_ cb:Int) -> ECP
+    {
+        let x=BIG(u)
+        let p=BIG(ROM.Modulus)
+        x.mod(p)
+        var P=ECP(x,cb)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1);  x.norm()
+            P=ECP(x,cb)
+        }
+        return P
+    }
+
+    // returns u derived from P. Random value in range 1 to return value 
should then be added to u
+    static func unmap(_ u:inout BIG,_ P:ECP) -> Int
+    {
+        let s=P.getS()
+        var r:Int32=0
+        let x=P.getX()
+        u.copy(x)
+        var R=ECP()
+        while (true)
+        {
+            u.dec(1); u.norm()
+            r += 1
+            R=ECP(u,s)
+            if !R.is_infinity() {break}
+        }
+        return Int(r)
+    }
+    
+    static public func HASH_ID(_ sha:Int,_ ID:[UInt8]) -> [UInt8]
+    {
+        return hashit(sha,0,ID)
+    }
+    
+    // these next two functions implement elligator squared - 
http://eprint.iacr.org/2014/043
+    // Elliptic curve point E in format (0x04,x,y} is converted to form 
{0x0-,u,v}
+    // Note that u and v are indistinguisible from random strings
+    static public func ENCODING(_ rng:RAND,_ E:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        for i in 0 ..< EFS {T[i]=E[i+1]}
+        var u=BIG.fromBytes(T);
+        for i in 0 ..< EFS {T[i]=E[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let P=ECP(u,v);
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let p=BIG(ROM.Modulus)
+        u=BIG.randomnum(p,rng)
+    
+        var su=rng.getByte();
+        su%=2
+    
+        let W=MPIN.map(u,Int(su))
+        P.sub(W);
+        let sv=P.getS();
+        let rn=MPIN.unmap(&v,P)
+        let m=rng.getByte();
+        let incr=1+Int(m)%rn
+        v.inc(incr)
+        E[0]=(su+UInt8(2*sv))
+        u.toBytes(&T)
+        for i in 0 ..< EFS {E[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {E[i+EFS+1]=T[i]}
+    
+        return 0;
+    }
+
+    static public func DECODING(_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        if (D[0]&0x04) != 0 {return INVALID_POINT}
+    
+        for i in 0 ..< EFS {T[i]=D[i+1]}
+        var u=BIG.fromBytes(T)
+        for i in 0 ..< EFS {T[i]=D[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let su=D[0]&1
+        let sv=(D[0]>>1)&1
+        let W=map(u,Int(su))
+        let P=map(v,Int(sv))
+        P.add(W)
+        u=P.getX()
+        v=P.getY()
+        D[0]=0x04
+        u.toBytes(&T);
+        for i in 0 ..< EFS {D[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {D[i+EFS+1]=T[i]}
+    
+        return 0
+    }
+    // R=R1+R2 in group G1
+    static public func RECOMBINE_G1(_ R1:[UInt8],_ R2:[UInt8],_ R:inout 
[UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(R1)
+        let Q=ECP.fromBytes(R2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+    
+        P.toBytes(&R)
+        return 0;
+    }
+    // W=W1+W2 in group G2
+    static public func RECOMBINE_G2(_ W1:[UInt8],_ W2:[UInt8],_  W:inout 
[UInt8]) -> Int
+    {
+        let P=ECP2.fromBytes(W1)
+        let Q=ECP2.fromBytes(W2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+        
+        P.toBytes(&W)
+        return 0
+    }
+    // create random secret S
+    static public func RANDOM_GENERATE(_ rng:RAND,_ S:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        let s=BIG.randomnum(r,rng)
+       if ROM.AES_S>0
+       {
+               s.mod2m(2*ROM.AES_S)
+       }    
+        s.toBytes(&S);
+        return 0;
+    }
+    // Extract PIN from TOKEN for identity CID
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ 
TOKEN:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN.hashit(sha,0,CID)
+        var R=MPIN.mapit(h)
+
+        R=R.pinmul(pin%MAXPIN,MPIN.PBLEN)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN)
+    
+        return 0
+    }
+    // Implement step 2 on client side of MPin protocol
+    static public func CLIENT_2(_ X:[UInt8],_ Y:[UInt8],_ SEC:inout [UInt8]) 
-> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        var P=ECP.fromBytes(SEC)
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let px=BIG.fromBytes(X)
+        let py=BIG.fromBytes(Y)
+        px.add(py)
+        px.mod(r)
+     //   px.rsub(r)
+
+        P=PAIR.G1mul(P,px)
+        P.neg()
+        P.toBytes(&SEC);
+      //  PAIR.G1mul(P,px).toBytes(&SEC)
+        return 0
+    }
+    
+    // Implement step 1 on client side of MPin protocol
+    static public func CLIENT_1(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ 
rng:RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_ SEC:inout [UInt8],_ 
xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+   //     let q=BIG(ROM.Modulus)
+        var x:BIG
+        if rng != nil
+        {
+            x=BIG.randomnum(r,rng!)
+            if ROM.AES_S>0
+            {
+                x.mod2m(2*ROM.AES_S)
+            }
+            x.toBytes(&X);
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+    //    var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        var h=MPIN.hashit(sha,0,CLIENT_ID)
+        var P=mapit(h);
+    
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        var W=P.pinmul(pin%MPIN.MAXPIN,MPIN.PBLEN)
+        T.add(W)
+        if date != 0
+        {
+            W=ECP.fromBytes(PERMIT)
+            if W.is_infinity() {return INVALID_POINT}
+            T.add(W);
+            h=MPIN.hashit(sha,date,h)
+            W=MPIN.mapit(h);
+            if xID != nil
+            {
+                               P=PAIR.G1mul(P,x)
+                               P.toBytes(&xID!)
+                               W=PAIR.G1mul(W,x)
+                               P.add(W)
+            }
+            else
+            {
+                               P.add(W);
+                               P=PAIR.G1mul(P,x);
+            }
+            if xCID != nil {P.toBytes(&xCID!)}
+        }
+        else
+        {
+            if xID != nil
+            {
+                               P=PAIR.G1mul(P,x)
+                               P.toBytes(&xID!)
+            }
+        }
+    
+    
+        T.toBytes(&SEC);
+        return 0;
+    }
+    // Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is 
master secret
+    static public func GET_SERVER_SECRET(_ S:[UInt8],_ SST:inout [UInt8]) -> 
Int
+    {
+        var 
Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    
+        let s=BIG.fromBytes(S)
+        Q=PAIR.G2mul(Q,s)
+        Q.toBytes(&SST)
+        return 0
+    }
+ 
+    
+    //W=x*H(G);
+    //if RNG == NULL then X is passed in
+    //if RNG != NULL the X is passed out
+    //if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) 
is mapping of octet G to point on the curve
+    
+    static public func GET_G1_MULTIPLE(_ rng:RAND?,_ type:Int,_ X:inout 
[UInt8],_ G:[UInt8],_ W:inout [UInt8]) -> Int
+    {
+        var x:BIG
+        let r=BIG(ROM.CURVE_Order)
+        if rng != nil
+        {
+            x=BIG.randomnum(r,rng!)
+            if ROM.AES_S>0
+            {
+                x.mod2m(2*ROM.AES_S)
+            }
+            x.toBytes(&X)
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+        var P:ECP
+        if type==0
+        {
+            P=ECP.fromBytes(G)
+            if P.is_infinity() {return INVALID_POINT}
+        }
+        else
+            {P=MPIN.mapit(G)}
+    
+        PAIR.G1mul(P,x).toBytes(&W)
+        return 0;
+    }
+    // Client secret CST=S*H(CID) where CID is client ID and S is master secret
+    // CID is hashed externally
+    static public func GET_CLIENT_SECRET(_ S:inout [UInt8],_ CID:[UInt8],_ 
CST:inout [UInt8]) -> Int
+    {
+        return GET_G1_MULTIPLE(nil,1,&S,CID,&CST)
+    }
+    // Time Permit CTT=S*(date|H(CID)) where S is master secret
+    static public func GET_CLIENT_PERMIT(_ sha:Int,_ date:Int32,_ S:[UInt8],_ 
CID:[UInt8],_ CTT:inout [UInt8]) -> Int
+    {
+        let h=MPIN.hashit(sha,date,CID)
+        let P=MPIN.mapit(h)
+    
+        let s=BIG.fromBytes(S)
+        PAIR.G1mul(P,s).toBytes(&CTT)
+        return 0;
+    }
+  
+    // Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set 
HID=HTID
+    static public func SERVER_1(_ sha:Int,_ date:Int32,_ CID:[UInt8],_ 
HID:inout [UInt8],_ HTID:inout [UInt8])
+    {
+        var h=MPIN.hashit(sha,0,CID)
+        let P=MPIN.mapit(h)
+
+       P.toBytes(&HID)
+        if date != 0
+        {
+       //     if HID != nil {P.toBytes(&HID!)}
+            h=hashit(sha,date,h)
+            let R=MPIN.mapit(h)
+            P.add(R)
+            P.toBytes(&HTID)
+        }
+        //else {P.toBytes(&HID!)}
+    }
+    // Implement step 2 of MPin protocol on server side
+    static public func SERVER_2(_ date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8]?,_ 
Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ mSEC:[UInt8],_ E:inout 
[UInt8]?,_ F:inout [UInt8]?) -> Int
+    {
+      //  _=BIG(ROM.Modulus);
+        let 
Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+    
+        var R:ECP
+        if date != 0
+            {R=ECP.fromBytes(xCID!)}
+        else
+        {
+            if xID==nil {return MPIN.BAD_PARAMS}
+            R=ECP.fromBytes(xID!)
+        }
+        if R.is_infinity() {return INVALID_POINT}
+    
+        let y=BIG.fromBytes(Y)
+        var P:ECP
+        if date != 0 {P=ECP.fromBytes(HTID!)}
+        else
+        {
+            if HID==nil {return MPIN.BAD_PARAMS}
+            P=ECP.fromBytes(HID!)
+        }
+    
+        if P.is_infinity() {return INVALID_POINT}
+    
+        P=PAIR.G1mul(P,y)
+        P.add(R)
+        R=ECP.fromBytes(mSEC)
+        if R.is_infinity() {return MPIN.INVALID_POINT}
+
+    
+        var g=PAIR.ate2(Q,R,sQ,P)
+        g=PAIR.fexp(g)
+    
+        if !g.isunity()
+        {
+            if HID != nil && xID != nil && E != nil && F != nil
+            {
+                               g.toBytes(&E!)
+                               if date != 0
+                               {
+                    P=ECP.fromBytes(HID!)
+                    if P.is_infinity() {return MPIN.INVALID_POINT}
+                    R=ECP.fromBytes(xID!)
+                    if R.is_infinity() {return MPIN.INVALID_POINT}
+    
+                    P=PAIR.G1mul(P,y);
+                    P.add(R);
+                               }
+                               g=PAIR.ate(Q,P);
+                               g=PAIR.fexp(g);
+                               g.toBytes(&F!);
+            }
+            return MPIN.BAD_PIN;
+        }
+    
+        return 0
+    }
+    // Pollards kangaroos used to return PIN error
+    static public func KANGAROO(_ E:[UInt8],_ F:[UInt8]) -> Int
+    {
+        let ge=FP12.fromBytes(E)
+        let gf=FP12.fromBytes(F)
+        var distance=[Int]();
+        let t=FP12(gf);
+        var table=[FP12]()
+        
+        var s:Int=1
+        for _ in 0 ..< Int(TS)
+        {
+            distance.append(s)
+            table.append(FP12(t))
+            s*=2
+            t.usqr()
+ 
+        }
+        t.one()
+        var dn:Int=0
+        for _ in 0 ..< TRAP
+        {
+            let i=Int(t.geta().geta().getA().lastbits(8))%TS
+            t.mul(table[i])
+            dn+=distance[i]
+        }
+        gf.copy(t); gf.conj()
+        var steps=0; var dm:Int=0
+        var res=0;
+        while (dm-dn<Int(MAXPIN))
+        {
+            steps += 1;
+            if steps>4*TRAP {break}
+            let i=Int(ge.geta().geta().getA().lastbits(8))%TS
+            ge.mul(table[i])
+            dm+=distance[i]
+            if (ge.equals(t))
+            {
+                               res=dm-dn;
+                               break;
+            }
+            if (ge.equals(gf))
+            {
+                               res=dn-dm
+                               break
+            }
+    
+        }
+        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - 
probable invalid token
+        return res
+    }
+    // Functions to support M-Pin Full
+    
+    static public func PRECOMPUTE(_ TOKEN:[UInt8],_ CID:[UInt8],_ G1:inout 
[UInt8],_ G2:inout [UInt8]) -> Int
+    {
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        let P=MPIN.mapit(CID)
+    
+        let 
Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    
+        var g=PAIR.ate(Q,T)
+        g=PAIR.fexp(g)
+        g.toBytes(&G1)
+    
+        g=PAIR.ate(Q,P)
+        g=PAIR.fexp(g)
+        g.toBytes(&G2)
+    
+        return 0
+    }
+    
+    static public func HASH_ALL(_ sha:Int,_ HID:[UInt8],_ xID:[UInt8]?,_ 
xCID:[UInt8]?,_ SEC:[UInt8],_ Y:[UInt8],_ R:[UInt8],_ W:[UInt8]  ) -> [UInt8]
+    {
+        var T=[UInt8](repeating: 0,count: 10*EFS+4)
+        var tlen=0
+
+        for i in 0 ..< HID.count  {T[i]=HID[i]}
+        tlen+=HID.count
+        if xCID != nil {
+            for i in 0 ..< xCID!.count  {T[i+tlen]=xCID![i]}
+            tlen+=xCID!.count
+        } else {
+            for i in 0 ..< xID!.count {T[i+tlen]=xID![i]}
+            tlen+=xID!.count
+        }
+        for i in 0 ..< SEC.count {T[i+tlen]=SEC[i]}
+        tlen+=SEC.count;
+        for i in 0 ..< Y.count {T[i+tlen]=Y[i]}
+        tlen+=Y.count;
+        for i in 0 ..< R.count {T[i+tlen]=R[i]}
+        tlen+=R.count;
+        for i in 0 ..< W.count {T[i+tlen]=W[i]}
+        tlen+=W.count;
+
+        return hashit(sha,0,T);
+    }
+
+    // calculate common key on client side
+    // wCID = w.(A+AT)
+    static public func CLIENT_KEY(_ sha:Int,_ G1:[UInt8],_ G2:[UInt8],_ 
pin:Int32,_ R:[UInt8],_ X:[UInt8],_ H:[UInt8],_ wCID:[UInt8],_ CK:inout 
[UInt8]) -> Int
+    {
+        let g1=FP12.fromBytes(G1)
+        let g2=FP12.fromBytes(G2)
+        let z=BIG.fromBytes(R)
+        let x=BIG.fromBytes(X)
+        let h=BIG.fromBytes(H)
+    
+        var W=ECP.fromBytes(wCID)
+        if W.is_infinity() {return INVALID_POINT}
+    
+        W=PAIR.G1mul(W,x)
+    
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+        let r=BIG(ROM.CURVE_Order)
+        let q=BIG(ROM.Modulus)
+    
+        z.add(h)   // new
+        z.mod(r)
+
+        let m=BIG(q)
+        m.mod(r)
+    
+        let a=BIG(z)
+        a.mod(m)
+    
+        let b=BIG(z)
+        b.div(m);
+    
+        g2.pinpow(pin,PBLEN);
+        g1.mul(g2);
+    
+        var c=g1.trace()
+        g2.copy(g1)
+        g2.frob(f)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+      
+        let t=mpin_hash(sha,c,W)
+
+        for i in 0 ..< PAS {CK[i]=t[i]}
+    
+        return 0
+    }
+    // calculate common key on server side
+    // Z=r.A - no time permits involved
+    
+    static public func SERVER_KEY(_ sha:Int,_ Z:[UInt8],_ SST:[UInt8],_ 
W:[UInt8],_ H:[UInt8],_ HID:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,_ SK:inout 
[UInt8]) -> Int
+    {
+   //     var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        let R=ECP.fromBytes(Z)
+        if R.is_infinity() {return INVALID_POINT}
+        var A=ECP.fromBytes(HID)
+        if A.is_infinity() {return INVALID_POINT}
+    
+        var U:ECP
+        if xCID != nil
+            {U=ECP.fromBytes(xCID!)}
+        else
+            {U=ECP.fromBytes(xID)}
+        
+        if U.is_infinity() {return INVALID_POINT}
+    
+        let w=BIG.fromBytes(W)
+        let h=BIG.fromBytes(H)
+        A=PAIR.G1mul(A,h)
+        R.add(A)
+
+        U=PAIR.G1mul(U,w)
+        var g=PAIR.ate(sQ,R)
+        g=PAIR.fexp(g)
+    
+        let c=g.trace()
+        
+        let t=mpin_hash(sha,c,U)
+ 
+        for i in 0 ..< PAS {SK[i]=t[i]}
+    
+        return 0
+    }
+    
+    // return time since epoch
+    static public func GET_TIME() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970))
+    }
+
+    // Generate Y = H(epoch, xCID/xID)
+    static public func GET_Y(_ sha:Int,_ TimeValue:Int32,_ xCID:[UInt8],_ 
Y:inout [UInt8])
+    {
+        let h = MPIN.hashit(sha,TimeValue,xCID)
+        let y = BIG.fromBytes(h)
+        let q=BIG(ROM.CURVE_Order)
+        y.mod(q)
+       if ROM.AES_S>0
+       {
+               y.mod2m(2*ROM.AES_S)
+       }
+        y.toBytes(&Y)
+    }
+    // One pass MPIN Client
+    static public func CLIENT(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ 
RNG:RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_  SEC:inout [UInt8],_ 
xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8],_ TimeValue:Int32,_ 
Y:inout [UInt8]) -> Int
+    {
+        var rtn=0
+  
+        rtn = 
MPIN.CLIENT_1(sha,date,CLIENT_ID,RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT)
+
+        if rtn != 0 {return rtn}
+    
+        if date==0 {MPIN.GET_Y(sha,TimeValue,xID!,&Y)}
+        else {MPIN.GET_Y(sha,TimeValue,xCID!,&Y)}
+    
+        rtn = MPIN.CLIENT_2(X,Y,&SEC)
+        if (rtn != 0) {return rtn}
+    
+        return 0
+    }
+    // One pass MPIN Server
+    static public func SERVER(_ sha:Int,_ date:Int32,_ HID:inout [UInt8],_ 
HTID:inout [UInt8]?,_ Y:inout [UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ 
xCID:[UInt8],_ SEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?,_ 
CID:[UInt8],_ TimeValue:Int32) -> Int
+    {
+        var rtn=0
+    
+        var pID:[UInt8]
+        if date == 0
+            {pID = xID!}
+        else
+            {pID = xCID}
+    
+        SERVER_1(sha,date,CID,&HID,&HTID!);
+    
+        GET_Y(sha,TimeValue,pID,&Y);
+    
+        rtn = SERVER_2(date,HID,HTID!,Y,SST,xID,xCID,SEC,&E,&F);
+        if rtn != 0 {return rtn}
+    
+        return 0
+    }
+   
+    static public func printBinary(_ array: [UInt8])
+    {
+        for i in 0 ..< array.count
+        {
+            let h=String(format:"%02x",array[i])
+            print("\(h)", terminator: "")
+        }
+        print(" ");
+    }
+}
+ 
+


Reply via email to