http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/swift/rsa.swift
----------------------------------------------------------------------
diff --git a/version22/swift/rsa.swift b/version22/swift/rsa.swift
new file mode 100644
index 0000000..fd3fa84
--- /dev/null
+++ b/version22/swift/rsa.swift
@@ -0,0 +1,400 @@
+/*
+       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.
+*/
+
+//
+//  rsa.swift
+//
+//  Created by Michael Scott on 25/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+/* RSA API high-level functions  */
+
+final public class rsa_private_key {
+    var p:FF
+    var q:FF
+    var dp:FF
+    var dq:FF
+    var c:FF
+    
+    public init(_ n: Int)
+    {
+    p=FF(n);
+    q=FF(n);
+    dp=FF(n);
+    dq=FF(n);
+    c=FF(n);
+    }
+}
+
+final public class rsa_public_key
+{
+    var e:Int
+    var n:FF
+    
+    public init(_ m:Int)
+    {
+        e=0;
+        n=FF(m);
+    }
+}
+
+final public class RSA {
+    
+    static public let RFS=Int(ROM.MODBYTES*ROM.FFLEN)
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    static public let HASH_TYPE=SHA384
+    
+    /* Hash number (optional) and string to array size of Bigs */
+ 
+    static private func hashit(_ sha:Int,_ A: [UInt8]?,_ n: Int32) -> [UInt8]
+    {
+        if sha==RSA.SHA256
+        {
+            let H=HASH256()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA384
+        {
+            let H=HASH384()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA512
+        {
+            let H=HASH512()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        return [UInt8]()
+    }
+
+    /* generate an RSA key pair */
+    
+    static public func KEY_PAIR(_ rng: RAND,_ e:Int,_ PRIV:rsa_private_key,_ 
PUB:rsa_public_key)
+    { /* IEEE1363 A16.11/A16.12 more or less */
+    
+        let n=PUB.n.getlen()/2;
+        let t = FF(n);
+        let p1=FF(n);
+        let q1=FF(n);
+    
+        while true
+        {
+    
+            PRIV.p.random(rng);
+            while PRIV.p.lastbits(2) != 3 {PRIV.p.inc(1)}
+            while !FF.prime(PRIV.p,rng) {PRIV.p.inc(4)}
+    
+            p1.copy(PRIV.p);
+            p1.dec(1);
+    
+            if p1.cfactor(e) {continue}
+            break;
+        }
+    
+        while true
+        {
+            PRIV.q.random(rng);
+            while PRIV.q.lastbits(2) != 3 {PRIV.q.inc(1)}
+            while !FF.prime(PRIV.q,rng) {PRIV.q.inc(4)}
+    
+            q1.copy(PRIV.q);
+            q1.dec(1);
+    
+            if q1.cfactor(e) {continue}
+    
+            break;
+        }
+    
+        PUB.n=FF.mul(PRIV.p,PRIV.q);
+        PUB.e=e;
+    
+        t.copy(p1);
+        t.shr();
+        PRIV.dp.set(e);
+        PRIV.dp.invmodp(t);
+        if (PRIV.dp.parity()==0) {PRIV.dp.add(t)}
+        PRIV.dp.norm();
+    
+        t.copy(q1);
+        t.shr();
+        PRIV.dq.set(e);
+        PRIV.dq.invmodp(t);
+        if (PRIV.dq.parity()==0) {PRIV.dq.add(t)}
+        PRIV.dq.norm();
+    
+        PRIV.c.copy(PRIV.p);
+        PRIV.c.invmodp(PRIV.q);
+    
+        return;
+    }
+    /* Mask Generation Function */
+    
+    static func MGF1(_ sha: Int,_ Z: [UInt8],_ olen:Int,_ K:inout [UInt8])
+    {
+        let hlen=sha
+    
+        var k=0;
+        for i in 0 ..< K.count {K[i]=0}
+    
+        var cthreshold=Int32(olen/hlen); if (olen%hlen != 0) {cthreshold += 1}
+        for counter:Int32 in 0 ..< cthreshold
+        {
+            var B=RSA.hashit(sha,Z,counter)
+            if (k+hlen>olen) {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+    }
+    
+    static public func printBinary(_ array: [UInt8])
+    {
+        for i in 0 ..< array.count
+        {
+            let h=String(array[i],radix:16)
+            print("\(h)", terminator: "")
+        }
+        print("");
+    }
+    
+    static let 
SHA256ID:[UInt8]=[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20]
+    static let 
SHA384ID:[UInt8]=[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30]
+    static let 
SHA512ID:[UInt8]=[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40]
+    
+    /* PKCS 1.5 padding of a message to be signed */
+    static public func PKCS15(_ sha:Int,_ m:[UInt8],_ w:inout [UInt8])->Bool
+    {
+        let hlen=sha
+        let olen=Int(ROM.FF_BITS/8)
+        let idlen=19;
+        
+        if olen<idlen+hlen+10 {return false}
+        let H=hashit(sha,m,-1)
+        for i in 0 ..< w.count {w[i]=0}
+        
+        w[0]=0
+        w[1]=1
+        var i=2
+        var j=0
+        
+        while j<olen-idlen-hlen-3
+        {
+            w[i]=0xff
+            i+=1; j+=1
+        }
+        w[i]=0; i+=1;
+        
+        if hlen==RSA.SHA256
+        {
+            for j in 0 ..< idlen {w[i]=SHA256ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA384
+        {
+            for j in 0 ..< idlen {w[i]=SHA384ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA512
+        {
+            for j in 0 ..< idlen {w[i]=SHA512ID[j]; i+=1}
+        }
+        
+        for j in 0 ..< hlen {w[i]=H[j];i+=1}
+        
+        return true
+    }
+    
+    
+    /* OAEP Message Encoding for Encryption */
+    static public func OAEP_ENCODE(_ sha:Int,_ m:[UInt8],_ rng:RAND,_ 
p:[UInt8]?) -> [UInt8]
+    {
+        let olen=RFS-1;
+        let mlen=m.count;
+        var f=[UInt8](repeating: 0,count: RSA.RFS)
+    
+        let hlen=sha;
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen;
+        if (mlen>olen-hlen-seedlen-1) {return [UInt8]()}
+    
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {f[i]=h[i]}
+    
+        let slen=olen-mlen-hlen-seedlen-1;
+    
+        for i in 0 ..< slen {f[hlen+i]=0}
+        f[hlen+slen]=1;
+        for i in 0 ..< mlen {f[hlen+slen+1+i]=m[i]}
+    
+        for i in 0 ..< seedlen {SEED[i]=rng.getByte()}
+        RSA.MGF1(sha,SEED,olen-seedlen,&DBMASK)
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+        RSA.MGF1(sha,DBMASK,seedlen,&f)
+    
+        for i in 0 ..< seedlen {f[i]^=SEED[i]}
+    
+        for i in 0 ..< olen-seedlen {f[i+seedlen]=DBMASK[i]}
+    
+    /* pad to length RFS */
+        let d:Int=1;
+        for i in (d...RFS-1).reversed()
+            {f[i]=f[i-d]}
+        for i in 0...d-1
+            {f[i]=0}
+    
+        return f;
+    }
+    
+    /* OAEP Message Decoding for Decryption */
+    static public func OAEP_DECODE(_ sha: Int,_ p: [UInt8]?,_ f:inout [UInt8]) 
-> [UInt8]
+    {
+        let olen=RFS-1
+        var k:Int
+        let hlen=sha
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen
+        var CHASH=[UInt8](repeating: 0,count: hlen)
+        
+        if olen<seedlen+hlen+1 {return [UInt8()]}
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        if (f.count<RFS)
+        {
+            let d=RFS-f.count;
+            for i in (d...RFS-1).reversed()
+                {f[i]=f[i-d]}
+            for i in 0...d-1
+                {f[i]=0}
+    
+        }
+    
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {CHASH[i]=h[i]}
+    
+        let x=f[0];
+    
+        for i in seedlen ..< olen
+            {DBMASK[i-seedlen]=f[i+1]}
+    
+        RSA.MGF1(sha,DBMASK,seedlen,&SEED);
+        for i in 0 ..< seedlen {SEED[i]^=f[i+1]}
+        RSA.MGF1(sha,SEED,olen-seedlen,&f);
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+    
+        var comp=true;
+        for i in 0 ..< hlen
+        {
+            if (CHASH[i] != DBMASK[i]) {comp=false}
+        }
+    
+        for i in 0 ..< olen-seedlen-hlen
+        {DBMASK[i]=DBMASK[i+hlen]}
+    
+        for i in 0 ..< hlen
+            {SEED[i]=0;CHASH[i]=0;}
+    
+        k=0
+        while (true)
+        {
+            if (k>=olen-seedlen-hlen) {return [UInt8]()}
+            if (DBMASK[k] != 0) {break}
+            k+=1
+        }
+    
+        let t=DBMASK[k];
+        if (!comp || x != 0 || t != 0x01)
+        {
+            for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+            return [UInt8]()
+        }
+    
+        var r=[UInt8](repeating: 0,count: olen-seedlen-hlen-k-1)
+    
+        for i in 0 ..< olen-seedlen-hlen-k-1
+            {r[i]=DBMASK[i+k+1]}
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        return r;
+    }
+    /* destroy the Private Key structure */
+    static public func PRIVATE_KEY_KILL(_ PRIV: rsa_private_key)
+    {
+        PRIV.p.zero();
+        PRIV.q.zero();
+        PRIV.dp.zero();
+        PRIV.dq.zero();
+        PRIV.c.zero();
+    }
+    /* RSA encryption with the public key */
+    static public func ENCRYPT(_ PUB: rsa_public_key,_ F:[UInt8],_ G:inout 
[UInt8])
+    {
+        let n=PUB.n.getlen()
+        let f=FF(n)
+    
+        FF.fromBytes(f,F)
+        f.power(PUB.e,PUB.n)
+        f.toBytes(&G)
+    }
+    /* RSA decryption with the private key */
+    static public func DECRYPT(_ PRIV: rsa_private_key,_ G:[UInt8],_ F:inout 
[UInt8])
+    {
+        let n=PRIV.p.getlen()
+        let g=FF(2*n)
+    
+        FF.fromBytes(g,G)
+        let jp=g.dmod(PRIV.p)
+        var jq=g.dmod(PRIV.q)
+    
+        jp.skpow(PRIV.dp,PRIV.p)
+        jq.skpow(PRIV.dq,PRIV.q)
+    
+        g.zero()
+        g.dscopy(jp)
+        jp.mod(PRIV.q)
+        if (FF.comp(jp,jq)>0) {jq.add(PRIV.q)}
+        jq.sub(jp)
+        jq.norm()
+    
+        var t=FF.mul(PRIV.c,jq)
+        jq=t.dmod(PRIV.q)
+    
+        t=FF.mul(jq,PRIV.p)
+        g.add(t);
+        g.norm();
+    
+        g.toBytes(&F);
+    }
+    
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/LICENSE-2.0.TXT
----------------------------------------------------------------------
diff --git a/version3/LICENSE-2.0.TXT b/version3/LICENSE-2.0.TXT
new file mode 100644
index 0000000..9b5e401
--- /dev/null
+++ b/version3/LICENSE-2.0.TXT
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/NOTICE.txt
----------------------------------------------------------------------
diff --git a/version3/NOTICE.txt b/version3/NOTICE.txt
new file mode 100644
index 0000000..2e6c028
--- /dev/null
+++ b/version3/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Milagro Crypto Libraries
+Copyright 2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/amcl3.pdf
----------------------------------------------------------------------
diff --git a/version3/amcl3.pdf b/version3/amcl3.pdf
new file mode 100644
index 0000000..3fb26e1
Binary files /dev/null and b/version3/amcl3.pdf differ

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/bestpair.cpp
----------------------------------------------------------------------
diff --git a/version3/bestpair.cpp b/version3/bestpair.cpp
new file mode 100644
index 0000000..f3e47bd
--- /dev/null
+++ b/version3/bestpair.cpp
@@ -0,0 +1,623 @@
+//
+// Program to generate "best" BN, BLS12, BLS24 and BLS48 curves (with modulus 
p=3 mod 8)
+//
+// g++ -O2 bestpair.cpp zzn8.cpp zzn4.cpp zzn2.cpp zzn.cpp ecn8.cpp ecn4.cpp 
ecn2.cpp ecn.cpp big.cpp miracl.a -o bestpair.exe
+//
+// Further tests may be needed to ensure full satisfaction (e.g. twist 
security, even x, etc.)
+//
+// Note that finding curves that are both GT and G2 Strong, can take a while
+//
+// Suggestions:-
+// For AES-128 security: bestpair BLS12 64 3
+// For AES-192 security: bestpair BLS24 48 4
+// FOr AES-256 security: bestpair BLS48 32 4
+
+// Some possible rational points on y^2=x^3+b (x^3+b is a perfect square)
+// b=1, x=0, -1 or 2
+// b=2, x=-1
+// b=3, x=1
+// b=4, x=0
+// b=5, x=-1
+// b=8, x=-2, 1, 2
+// b=9, x=0, 3, 6, 40
+// b=10, x=-1
+// b=12, x=-2, 13
+
+// b=-1, x=1
+// b=-2, x=3;
+// b=-4, x=2, 5
+// b=-7, x=2, 32
+// b=-8, x=2
+// b=-11, x=3, 15
+
+// of course these points need to be checked for correct order...
+
+#include <iostream>
+#include "big.h"
+#include "ecn.h"
+#include "ecn2.h"
+#include "ecn4.h"
+#include "ecn8.h"
+
+#define BN 0
+#define BLS12 1
+#define BLS24 2
+#define BLS48 3
+
+using namespace std;
+
+Miracl precision=500;
+
+// Number of ways of selecting k items from n
+Big combo(int n,int k)
+{ // calculate n C k
+       int i;
+       Big c,d;
+
+       d=1;
+       for (i=2;i<=k;i++)
+               d*=i;
+
+       c=1;
+       for (i=n;i>n-k;i--)
+               c*=i;
+
+       c/=d;
+       return c;
+}
+
+// Number of candidates to be searched.
+Big count(int b,int h)
+{
+       Big c=combo(b-h+1,h-1)+combo(b-h+1,h-2);
+       c*=pow((Big)2,h);
+       return c;
+}
+
+// Move to next NAF pattern
+int iterate(int *x,int n)
+{
+       int i,j,k,gotone=0;
+       for (i=0;i<n-1;i++)
+       {
+               if (x[i]==1 && x[i+2]==0)
+               {
+                       gotone=1;
+                       x[i+1]=1;
+                       x[i]=0;
+                       if (x[0]==1) break;
+                       for (k=1;;k++)
+                               if (x[k]!=0) break;
+                       for (j=0;j<i-k;j+=2)
+                       {
+                               x[j]=x[j+k];
+                               x[j+k]=0;
+                       }
+                       break;
+               }
+               
+       }
+       return gotone;
+}
+
+int main(int argc, char *argv[])
+{
+       int HW,BITS,S,type,xm8,xm3,xm24,percent,pc;
+       Big cnt,odds,total;
+    int i,j,k,m,jj,bt,hw,twist,pb,nb,b,cb[40],ip;
+       int xb[256];
+       BOOL G2,GT,gotH,gotB,gotT,progress;
+    Big msb,c,r,m1,n,p,q,t,x,y,w,X,Y,cof,cof2,coft,tau[9];
+    Big PP,TT,FF;
+       Big xp[10];
+       int pw[10];
+    miracl *mip=&precision;
+    ECn P;
+
+       argc--; argv++;
+
+    if (argc<2)
+    {
+       cout << "Missing arguments" << endl;
+          cout << "Program to find best pairing-friendly curves" << endl;
+       cout << "bestpair type bits Hamming-weight" << endl;
+          cout << "where type is the curve (BN, BLS12, BLS24, BLS48)" << endl;
+          cout << "where bits is number of bits in curve x parameter (>30 and 
<200)" << endl;
+       cout << "and hamming-weight is the number of non-zero bits (>1 and 
<10)" << endl;
+       cout << "e.g. bestpair BLS12 77 3" << endl;
+          cout << "Use flag /GT for GT-Strong curves" << endl;
+          cout << "Use flag /G2 for G2-Strong curves" << endl;
+          cout << "Use flag /P to show progress" << endl;
+
+       exit(0);
+    }
+
+       ip=0; HW=0; BITS=0; 
+       G2=GT=gotB=gotH=gotT=progress=FALSE;
+
+       while (ip<argc)
+       {
+               if (!gotT && strcmp(argv[ip],"BN")==0)
+               {
+                       ip++;
+                       gotT=TRUE;
+                       type=BN;
+               }
+               if (!gotT && strcmp(argv[ip],"BLS12")==0)
+               {
+                       ip++;
+                       gotT=TRUE;
+                       type=BLS12;
+               }
+               if (!gotT && strcmp(argv[ip],"BLS24")==0)
+               {
+                       ip++;
+                       gotT=TRUE;
+                       type=BLS24;
+               }
+               if (!gotT && strcmp(argv[ip],"BLS48")==0)
+               {
+                       ip++;
+                       gotT=TRUE;
+                       type=BLS48;
+               }
+               if (!G2 && strcmp(argv[ip],"/G2")==0)
+               {
+                       ip++;
+                       G2=TRUE;
+                       continue;
+               }
+               if (!GT && strcmp(argv[ip],"/GT")==0)
+               {
+                       ip++;
+                       GT=TRUE;
+                       continue;
+               }
+               if (!progress && strcmp(argv[ip],"/P")==0)
+               {
+                       ip++;
+                       progress=TRUE;
+                       continue;
+               }
+               if (!gotB)
+               {
+                       BITS=atoi(argv[ip++]);
+                       gotB=TRUE;
+                       continue;
+               }
+
+               if (!gotH)
+               {
+                       HW=atoi(argv[ip++]);
+                       gotH=TRUE;
+                       continue;
+               }
+
+        cout << "Error in command line" << endl;
+        return 0;
+
+       }
+    if (!gotH || !gotB || !gotT || HW>9 || HW<2 || BITS>=200 || BITS<30)
+    {
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+
+       hw=HW-1;
+       msb=pow((Big)2,BITS);
+
+       for (i=0;i<=BITS;i++)
+               xb[i]=0;
+
+       for (i=0;i<hw;i++)
+               xb[2*i]=1;
+
+       S=0;
+
+       total=count(BITS,HW);
+       cout << "search " << total << " candidates" << endl;
+
+// very approximate estimate of odds of success. Assumes primes are not 
correlated (but they are!)
+       if (type==BN)
+       {
+               odds = (7*(4*BITS+5)/10)*(7*(4*BITS+5)/10);
+               if (G2)
+                       odds*=(7*(4*BITS+5)/10);
+               if (GT)
+                       odds*=(7*(12*BITS+16)/10);
+       }
+       if (type==BLS12)
+       {
+               odds = ((7*4*BITS)/10)*((7*6*BITS)/10);
+               if (G2)
+                       odds*=(7*(8*BITS)/10);
+               if (GT)
+                       odds*=(7*(20*BITS)/10);
+       }
+       if (type==BLS24)
+       {
+               odds = ((7*8*BITS)/10)*((7*10*BITS)/10);
+               if (G2)
+                       odds*=(7*(32*BITS)/10);
+               if (GT)
+                       odds*=(7*(72*BITS)/10);
+       }
+       if (type==BLS48)
+       {
+               odds = ((7*16*BITS)/10)*((7*18*BITS)/10);
+               if (G2)
+                       odds*=(7*(128*BITS)/10);
+               if (GT)
+                       odds*=(7*(272*BITS)/10);
+       }
+
+       odds/=8;  // frig factor
+       cout << "one in " << odds << " expected to be OK" << endl;
+
+//     gprime(1000);
+       percent=-1;
+       cnt=0;
+       for (;;)
+       {
+               if (cnt>0 && !iterate(xb,BITS)) break;
+               for (i=j=0;i<BITS;i++)
+               { // assign values to set bits
+                       if (xb[i]==1)
+                       {
+                               xp[j]=pow((Big)2,i);
+                               pw[j]=i;
+                               j++;
+                       }
+               }
+               xp[j]=msb;
+               pw[j]=BITS;
+               j++;
+
+               // iterate through all combinations of + and - terms
+               for (i=0;i<(1<<j);i++)
+               {
+                       cnt+=1; 
+                       if (progress)
+                       {
+                               pc=toint((100*cnt)/total);
+
+                               if (percent<pc)
+                               {
+                                       percent=pc;
+                                       cout << pc << "\%" << endl;
+                               }
+                       }
+                       x=0;
+                       bt=1;
+                       //cout << "x= ";
+                       for (k=0;k<j;k++)
+                       {
+                               if ((bt&i)!=0) {x+=xp[k]; /*cout << "+2^" << 
pw[k];*/}
+                               else {x-=xp[k]; /*cout << "-2^" << pw[k];*/}
+                               bt<<=1;
+                       }
+
+                       if (type==BLS12)
+                       {
+                               xm24=x%24;
+                               if (x<0) xm24+=24;
+                               xm24%=24;
+                               xm3=xm24%3;
+                               if (xm3!=1) continue;   // quick exit for p%3=0
+                               xm8=xm24%8;
+                               if (xm8!=0 && xm8!=7) continue;  // quick exit 
for p=3 mod 8 condition
+
+                               q=pow(x,4)-x*x+1;
+                               p=q*(((x-1)*(x-1))/3)+x;
+
+                               t=x+1;
+                               n=p+1-t;
+
+                       }
+                       if (type==BLS24)
+                       {
+                               xm24=x%24;
+                               if (x<0) xm24+=24;
+                               xm24%=24;
+                               xm3=xm24%3;
+                               if (xm3!=1) continue;   // quick exit for p%3=0
+                               xm8=xm24%8;
+                               if (xm8!=0 && xm8!=7) continue;  // quick exit 
for p=3 mod 8 condition
+
+                               q=pow(x,8)-pow(x,4)+1;
+                               p=q*(((x-1)*(x-1))/3)+x;
+
+                               t=x+1;
+                               n=p+1-t;
+                               
+                       }
+
+                       if (type==BLS48)
+                       {
+                               xm24=x%24;
+                               if (x<0) xm24+=24;
+                               xm24%=24;
+                               xm3=xm24%3;
+                               if (xm3!=1) continue;   // quick exit for p%3=0
+                               xm8=xm24%8;
+                               if (xm8!=0 && xm8!=7) continue;  // quick exit 
for p=3 mod 8 condition
+
+                               q=pow(x,16)-pow(x,8)+1;
+                               p=q*(((x-1)*(x-1))/3)+x;
+               
+                               t=x+1;
+                               n=p+1-t;
+                               
+                       }
+
+                       if (type==BN)
+                       {
+                               xm8=x%8;
+                               if (x<0) xm8+=8;
+                               xm8%=8;
+                               if (xm8!=3 && xm8!=7) continue;  // quick exit 
for p=3 mod 8 condition
+
+                               p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1;
+                               t=6*x*x+1;
+                               n=p+1-t;
+                               q=n;
+                       }
+
+                       if (p%8!=3) continue;                           // 
restriction here could be eased
+
+                       if (small_factors(q)) continue;
+                       if (small_factors(p)) continue;
+
+                       cof=n/q;
+
+                       if (type==BLS24)
+                       {
+                               coft=(pow(p,8)-pow(p,4)+1)/q;
+                       }
+
+                       if (type==BLS48)
+                       {
+                               coft=(pow(p,16)-pow(p,8)+1)/q;
+                       }
+
+                       if (type==BLS12 || type==BN)
+                       {
+                               coft=(pow(p,4)-p*p+1)/q;
+                       }
+
+                       if (GT)
+                       {
+                               if (small_factors(coft)) continue;
+                       }
+
+                       if (type==BLS12)
+                       {
+                               TT=t*t-2*p;
+                               PP=p*p;
+                               FF=t*(2*x*x*x-2*x*x-x+1)/3;
+                               m1=PP+1-(-3*FF+TT)/2;
+                       }
+
+                       if (type==BLS24)
+                       {
+                               TT=t*t*t*t-4*p*t*t+2*p*p;
+                               PP=pow(p,4);
+                               FF=sqrt((4*PP-TT*TT)/3);
+                               m1=PP+1-(3*FF+TT)/2;
+                       }
+                       if (type==BLS48)
+                       {
+                               tau[0]=2;  // count points on twist over 
extension p^8
+                               tau[1]=t;
+                               for (jj=1;jj<8;jj++ ) 
tau[jj+1]=t*tau[jj]-p*tau[jj-1];
+
+                               TT=tau[8];
+
+                               PP=pow(p,8);
+                               FF=sqrt((4*PP-TT*TT)/3);
+                               m1=PP+1-(3*FF+TT)/2;  //?
+                       }
+                       if (type==BN)
+                       {
+                               TT=t*t-2*p;
+                               PP=p*p;
+                               FF=sqrt((4*PP-TT*TT)/3);
+                               m1=PP+1-(3*FF+TT)/2;
+                       }
+                       cof2=m1/q;
+
+                       if (G2)
+                       {
+                               if (small_factors(cof2)) continue;
+                       }
+
+                       if (!prime(q)) continue;
+                       if (!prime(p)) continue;
+                       modulo(p);
+
+                       ZZn2 xi;
+
+                       xi.set(1,1);                // for p=3 mod 8
+               
+// make sure its irreducible
+                       if (pow(xi,(p*p-1)/2)==1)
+                               continue;
+               
+                       if (pow(xi,(p*p-1)/3)==1) 
+                               continue;  // make sure that x^6-c is 
irreducible
+
+                       if (G2)
+                       {
+                               if (!prime(cof2)) continue;
+                       }
+
+                       if (GT)
+                       {
+                               if (!prime(coft)) continue;
+                       }
+
+                       
+// we have a solution
+// Find curve b parameter - uses first positive one found (but collect some 
other possibilities)
+                       pb=0;
+                       b=0;
+                       m=0;
+                       while (pb<=20 || b==0)
+                       {
+                               pb+=1;
+                               ecurve(0,pb,p,MR_AFFINE);
+                               while (!P.set(rand(p))) ;
+                               P*=cof;
+                               if ((q*P).iszero())
+                               {
+                                       if (b==0) b=pb;
+                                       else cb[m++]=pb;
+                               }
+
+                       }
+                       nb=0;
+                       while (nb>=-20)
+                       {
+                               nb-=1;
+                               ecurve(0,nb,p,MR_AFFINE);
+                               while (!P.set(rand(p))) ;
+                               P*=cof;
+                               if ((q*P).iszero())
+                                       cb[m++]=nb;
+                       }
+
+                       ecurve(0,b,p,MR_AFFINE);
+// find number of points on sextic twist..
+                       twist=MR_SEXTIC_D;
+                       mip->TWIST=MR_SEXTIC_D;
+
+                       if (type==BLS12 || type==BN)
+                       {
+                               ECn2 Q;
+                               ZZn2 rr;
+
+                               do
+                               {
+                                       rr=randn2();
+                               } while (!Q.set(rr));
+        
+                               Q*=cof2;
+                               if (!(n*Q).iszero()) 
+                               {
+                                       twist=MR_SEXTIC_M;
+                                       mip->TWIST=MR_SEXTIC_M;
+                                       do
+                                       {
+                                               rr=randn2();
+                                       } while (!Q.set(rr));
+        
+                                       Q*=cof2;
+                                       if (!(n*Q).iszero()) 
+                                       {
+                                               cout << "Never Happens" << endl;
+                                               continue;
+                                       }
+                               }
+                       }
+                       if (type==BLS24)
+                       {
+                               ECn4 Q;
+                               ZZn4 rr;
+                               do
+                               {
+                                       rr=randn4();
+                               } while (!Q.set(rr));
+
+                               Q*=cof2;
+                               if (!(n*Q).iszero()) 
+                               {
+                                       twist=MR_SEXTIC_M;
+                                       mip->TWIST=MR_SEXTIC_M;
+                                       do
+                                       {
+                                               rr=randn4();
+                                       } while (!Q.set(rr));
+        
+                                       Q*=cof2;
+                                       if (!(n*Q).iszero()) 
+                                       {
+                                               cout << "Never Happens" << endl;
+                                               continue;
+                                       }
+                               }
+                       }
+                       if (type==BLS48)
+                       {
+                               ECn8 Q;
+                               ZZn8 rr;
+                               do
+                               {
+                                       rr=randn8();
+                               } while (!Q.set(rr));
+
+                               Q*=cof2;
+                               if (!(n*Q).iszero()) 
+                               {
+                                       twist=MR_SEXTIC_M;
+                                       mip->TWIST=MR_SEXTIC_M;
+                                       do
+                                       {
+                                               rr=randn8();
+                                       } while (!Q.set(rr));
+        
+                                       Q*=cof2;
+                                       if (!(n*Q).iszero()) 
+                                       {
+                                               cout << "Never Happens" << endl;
+                                               continue;
+                                       }
+                               }
+                       }
+                       S++;
+                       cout << endl;
+                       cout << "Solution " << S << endl;
+                       x=0;
+                       bt=1;
+                       mip->IOBASE=16;
+
+                       cout << "x= ";
+                       for (k=0;k<j;k++)
+                       {
+                               if ((bt&i)!=0) {x+=xp[k]; cout << "+2^" << 
pw[k];}
+                               else {x-=xp[k]; cout << "-2^" << pw[k];}
+                               bt<<=1;
+                       }
+                       cout << " = " << x << endl;
+                       cout << "Curve is y^2=x^3+" << b;
+                       if (m>0)
+                       {
+                               cout << " (or) ";
+                               for (jj=0;jj<m;jj++)
+                                       cout << cb[jj] << " ";
+                       }
+                       else cout << endl;
+                       cout << "\np= " << p << " (" << bits(p) << " bits)";
+                       if (twist==MR_SEXTIC_D) cout << " D-Type" << endl;
+                       if (twist==MR_SEXTIC_M) cout << " M-Type" << endl;
+                       if (progress) cout << endl;
+                       mip->IOBASE=10;
+               //      cout << "twist= " << p+1+t << endl;
+               }
+       }
+
+       cout << endl;
+       cout << cnt << " candidates searched" << endl;
+
+       if (S==0)
+       {
+               cout << "No solutions found" << endl;
+               return 0;
+       }
+       if (S==1)
+       {
+               cout << "One solution found" << endl;
+               return 0;
+       }
+       cout << S << " solutions found" << endl;
+       return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/bigtobig.cpp
----------------------------------------------------------------------
diff --git a/version3/bigtobig.cpp b/version3/bigtobig.cpp
new file mode 100644
index 0000000..fbc89ea
--- /dev/null
+++ b/version3/bigtobig.cpp
@@ -0,0 +1,292 @@
+/*
+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.
+*/
+
+//
+// Program to convert from Big to AMCL BIG format
+// cl /O2 bigtobig.cpp big.cpp miracl.lib
+// g++ -O2 bigtobig.cpp big.cpp miracl.a -o bigtobig
+//
+//
+
+#include <iostream>
+#include "zzn.h"
+
+using namespace std;
+
+Miracl precision=100;
+
+// Code to parse formula in command line
+// This code isn't mine, but its public domain
+// Shamefully I forget the source
+//
+// NOTE: It may be necessary on some platforms to change the operators * and #
+//
+
+#if defined(unix)
+#define TIMES '.'
+#define RAISE '^'
+#else
+#define TIMES '*'
+#define RAISE '#'
+#endif
+
+Big tt;
+static char *ss;
+
+void eval_power (Big& oldn,Big& n,char op)
+{
+        if (op) n=pow(oldn,toint(n));    // power(oldn,size(n),n,n);
+}
+
+void eval_product (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case TIMES:
+                n*=oldn; 
+                break;
+        case '/':
+                n=oldn/n;
+                break;
+        case '%':
+                n=oldn%n;
+        }
+}
+
+void eval_sum (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case '+':
+                n+=oldn;
+                break;
+        case '-':
+                n=oldn-n;
+        }
+}
+
+void eval (void)
+{
+        Big oldn[3];
+        Big n;
+        int i;
+        char oldop[3];
+        char op;
+        char minus;
+        for (i=0;i<3;i++)
+        {
+            oldop[i]=0;
+        }
+LOOP:
+        while (*ss==' ')
+        ss++;
+        if (*ss=='-')    /* Unary minus */
+        {
+        ss++;
+        minus=1;
+        }
+        else
+        minus=0;
+        while (*ss==' ')
+        ss++;
+        if (*ss=='(' || *ss=='[' || *ss=='{')    /* Number is subexpression */
+        {
+        ss++;
+        eval ();
+        n=tt;
+        }
+        else            /* Number is decimal value */
+        {
+        for (i=0;ss[i]>='0' && ss[i]<='9';i++)
+                ;
+        if (!i)         /* No digits found */
+        {
+                cout <<  "Error - invalid number" << endl;
+                exit (20);
+        }
+        op=ss[i];
+        ss[i]=0;
+        n=atoi(ss);
+        ss+=i;
+        *ss=op;
+        }
+        if (minus) n=-n;
+        do
+        op=*ss++;
+        while (op==' ');
+        if (op==0 || op==')' || op==']' || op=='}')
+        {
+        eval_power (oldn[2],n,oldop[2]);
+        eval_product (oldn[1],n,oldop[1]);
+        eval_sum (oldn[0],n,oldop[0]);
+        tt=n;
+        return;
+        }
+        else
+        {
+        if (op==RAISE)
+        {
+                eval_power (oldn[2],n,oldop[2]);
+                oldn[2]=n;
+                oldop[2]=RAISE;
+        }
+        else
+        {
+                if (op==TIMES || op=='/' || op=='%')
+                {
+                eval_power (oldn[2],n,oldop[2]);
+                oldop[2]=0;
+                eval_product (oldn[1],n,oldop[1]);
+                oldn[1]=n;
+                oldop[1]=op;
+                }
+                else
+                {
+                if (op=='+' || op=='-')
+                {
+                        eval_power (oldn[2],n,oldop[2]);
+                        oldop[2]=0;
+                        eval_product (oldn[1],n,oldop[1]);
+                        oldop[1]=0;
+                        eval_sum (oldn[0],n,oldop[0]);
+                        oldn[0]=n;
+                        oldop[0]=op;
+                }
+                else    /* Error - invalid operator */
+                {
+                        cout <<  "Error - invalid operator" << endl;
+                        exit (20);
+                }
+                }
+        }
+        }
+        goto LOOP;
+}
+
+void output(int w,Big t,Big m)
+{
+       Big y=t;
+
+       for (int i=0;i<w;i++)
+       {
+               cout << "0x" << y%m ;
+               if (i<w-1) cout << ",";
+               y/=m;
+       }
+       cout << endl;
+}
+
+int main(int argc, char **argv)
+{
+    int i,ip,chunk,basebits;
+    Big n,m;
+    BOOL gotP,gotA,gotB;
+    int Base;
+    miracl *mip=&precision;
+    argv++; argc--;
+    if (argc<1)
+    {
+        cout << "Program converts from Big to BIG" << endl;
+        cout << "bigtobig <big number> <chunk>> <basebits>" << endl;
+        cout << "OR" << endl;
+        cout << "bigtobig <formula for big number> <chunk>> <basebits>" << 
endl;
+#if defined(unix)
+        cout << "e.g. bigtobig -f 2^255-19 32 29" << endl;
+#else
+        cout << "e.g. bigtobig -f 2#255-19 32 29" << endl;
+#endif
+        cout << "To input Big number in Hex, precede with -h" << endl;
+        return 0;
+    }
+
+    ip=0;
+    gprime(1000);
+    gotP=gotA=gotB=FALSE;
+    n=0;
+    Base=10;
+    while (ip<argc)
+    { 
+        if (!gotP && strcmp(argv[ip],"-f")==0)
+        {
+            ip++;
+            if (!gotP && ip<argc)
+            {
+
+                ss=argv[ip++];
+                tt=0;
+                eval();
+                n=tt;
+                gotP=TRUE;
+                continue;
+            }
+            else
+            {
+                cout << "Error in command line" << endl;
+                return 0;
+            }
+        }
+ 
+
+        if (strcmp(argv[ip],"-h")==0)
+        {
+            ip++;
+            Base=16;
+            continue;
+        }
+   
+        if (!gotP)
+        {
+            mip->IOBASE=Base;
+            n=argv[ip++];
+            mip->IOBASE=10;
+            gotP=TRUE;
+            continue;
+        }
+        if (!gotA) 
+        {
+            mip->IOBASE=Base;
+            chunk=atoi(argv[ip++]);
+            gotA=TRUE;
+            continue;
+        }
+        if (!gotB) 
+        {
+            mip->IOBASE=Base;
+            basebits=atoi(argv[ip++]);
+            gotB=TRUE;
+            continue;
+        }
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+    if (!gotP || !gotA || !gotB)
+    {
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+
+       mip->IOBASE=16;
+
+       m=pow((Big)2,basebits);
+
+       output(1+bits(n)/basebits,n,m);
+
+    return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/aes.c
----------------------------------------------------------------------
diff --git a/version3/c/aes.c b/version3/c/aes.c
new file mode 100644
index 0000000..656a031
--- /dev/null
+++ b/version3/c/aes.c
@@ -0,0 +1,704 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the NIST Advanced Ecryption Standard
+ *
+ * SU=m, SU is Stack Usage
+ */
+
+#include <stdlib.h>
+#include "arch.h"
+#include "amcl.h"
+
+/* this is fixed */
+#define NB 4
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+#define ROTL8(x) (((x)<<8)|((x)>>24))
+#define ROTL16(x) (((x)<<16)|((x)>>16))
+#define ROTL24(x) (((x)<<24)|((x)>>8))
+
+static const uchar InCo[4]= {0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
+
+static const uchar ptab[]=
+{
+    1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+    95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+    229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+    83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+    76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+    131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+    181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+    254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+    251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+    195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+    159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+    155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+    252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+    69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+    18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+    57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
+};
+
+static const uchar ltab[]=
+{
+    0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+    100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+    125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+    101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+    150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+    102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+    126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+    43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+    175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+    44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+    127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+    204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+    151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+    83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+    68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+    103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
+};
+
+static const uchar fbsub[]=
+{
+    99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+    202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+    183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+    4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+    9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+    83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+    208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+    81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+    205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+    96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+    224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+    231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+    186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+    112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+    225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+    140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
+};
+
+static const uchar rbsub[]=
+{
+    82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+    124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+    84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+    8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+    114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+    108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+    144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+    208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+    58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+    150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+    71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+    252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+    31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+    96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+    160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+    23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
+};
+
+static const unsign32 rco[]=
+{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
+
+static const unsign32 ftable[]=
+{
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
+};
+
+static const unsign32 rtable[]=
+{
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
+};
+
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return 
((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[0]=MR_TOBYTE(a);
+    b[1]=MR_TOBYTE(a>>8);
+    b[2]=MR_TOBYTE(a>>16);
+    b[3]=MR_TOBYTE(a>>24);
+}
+
+/* SU= 8 */
+static uchar bmul(uchar x,uchar y)
+{
+    /* x.y= AntiLog(Log(x) + Log(y)) */
+    if (x && y) return ptab[(ltab[x]+ltab[y])%255];
+    else return 0;
+}
+
+static unsign32 SubByte(unsign32 a)
+{
+    uchar b[4];
+    unpack(a,b);
+    b[0]=fbsub[b[0]];
+    b[1]=fbsub[b[1]];
+    b[2]=fbsub[b[2]];
+    b[3]=fbsub[b[3]];
+    return pack(b);
+}
+
+/* SU= 16 */
+static uchar product(unsign32 x,unsign32 y)
+{
+    /* dot product of two 4-byte arrays */
+    uchar xb[4],yb[4];
+    unpack(x,xb);
+    unpack(y,yb);
+    return 
bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
+}
+
+static unsign32 InvMixCol(unsign32 x)
+{
+    /* matrix Multiplication */
+    unsign32 y,m;
+    uchar b[4];
+
+    m=pack(InCo);
+    b[3]=product(m,x);
+    m=ROTL24(m);
+    b[2]=product(m,x);
+    m=ROTL24(m);
+    b[1]=product(m,x);
+    m=ROTL24(m);
+    b[0]=product(m,x);
+    y=pack(b);
+    return y;
+}
+
+/* SU= 8 */
+/* reset cipher */
+void AES_reset(amcl_aes *a,int mode,char *iv)
+{
+    /* reset mode, or reset iv */
+    int i;
+    a->mode=mode;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+    if (mode!=ECB && iv!=NULL)
+    {
+        for (i=0; i<4*NB; i++)
+            a->f[i]=iv[i];
+    }
+}
+
+void AES_getreg(amcl_aes *a,char *ir)
+{
+    int i;
+    for (i=0; i<4*NB; i++) ir[i]=a->f[i];
+}
+
+/* SU= 72 */
+/* Initialise cipher */
+int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
+{
+    /* Key length Nk=16, 24 or 32 bytes */
+    /* Key Scheduler. Create expanded encryption key */
+    int i,j,k,N,nr;
+    unsign32 CipherKey[8];
+
+    nk/=4;
+
+    if (nk!=4 && nk!=6 && nk!=8) return 0;
+
+    nr=6+nk;
+
+    a->Nk=nk;
+    a->Nr=nr;
+
+    AES_reset(a,mode,iv);
+
+    N=NB*(nr+1);
+
+    for (i=j=0; i<nk; i++,j+=4)
+    {
+        CipherKey[i]=pack((uchar *)&key[j]);
+    }
+    for (i=0; i<nk; i++) a->fkey[i]=CipherKey[i];
+    for (j=nk,k=0; j<N; j+=nk,k++)
+    {
+        a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
+        if (nk<=6)
+        {
+            for (i=1; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+        else
+        {
+            for (i=1; i<4 && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+            if ((j+4)<N) a->fkey[j+4]=a->fkey[j+4-nk]^SubByte(a->fkey[j+3]);
+            for (i=5; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+
+    }
+    /* now for the expanded decrypt key in reverse order */
+
+    for (j=0; j<NB; j++) a->rkey[j+N-NB]=a->fkey[j];
+    for (i=NB; i<N-NB; i+=NB)
+    {
+        k=N-NB-i;
+        for (j=0; j<NB; j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
+    }
+    for (j=N-NB; j<N; j++) a->rkey[j-N+NB]=a->fkey[j];
+    return 1;
+}
+
+/* SU= 80 */
+/* Encrypt a single block */
+void AES_ecb_encrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->fkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+
+        y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
+             ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(ftable[x[3]>>24]);
+        y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
+             ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(ftable[x[0]>>24]);
+        y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
+             ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(ftable[x[1]>>24]);
+        y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
+             ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(ftable[x[2]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+    /* Last Round */
+
+    y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)fbsub[x[3]>>24]);
+    y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)fbsub[x[0]>>24]);
+    y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)fbsub[x[1]>>24]);
+    y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)fbsub[x[2]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+}
+
+/* SU= 80 */
+/* Decrypt a single block */
+void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->rkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+        /* Nr is number of rounds. May be odd. */
+
+        y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
+             ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(rtable[x[1]>>24]);
+        y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
+             ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(rtable[x[2]>>24]);
+        y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
+             ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(rtable[x[3]>>24]);
+        y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
+             ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(rtable[x[0]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+
+    /* Last Round */
+    y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)rbsub[x[1]>>24]);
+    y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)rbsub[x[2]>>24]);
+    y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)rbsub[x[3]>>24]);
+    y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)rbsub[x[0]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+
+}
+
+/* simple default increment function */
+static void increment(char *f)
+{
+    int i;
+    for (i=0; i<16; i++)
+    {
+        f[i]++;
+        if (f[i]!=0) break;
+    }
+}
+
+/* SU= 40 */
+/* Encrypt using selected mode of operation */
+unsign32 AES_encrypt(amcl_aes* a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported Modes of Operation */
+
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_encrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++) buff[j]^=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++) a->f[j]=buff[j];
+        return 0;
+
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            buff[j]^=st[j];
+            a->f[16-bytes+j]=buff[j];
+        }
+        return fell_off;
+
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+        return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* SU= 40 */
+/* Decrypt using selected mode of operation */
+unsign32 AES_decrypt(amcl_aes *a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported modes of operation */
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_decrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++)
+        {
+            st[j]=a->f[j];
+            a->f[j]=buff[j];
+        }
+        AES_ecb_decrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++)
+        {
+            buff[j]^=st[j];
+            st[j]=0;
+        }
+        return 0;
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            a->f[16-bytes+j]=buff[j];
+            buff[j]^=st[j];
+        }
+        return fell_off;
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+        return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* Clean up and delete left-overs */
+void AES_end(amcl_aes *a)
+{
+    /* clean up */
+    int i;
+    for (i=0; i<NB*(a->Nr+1); i++)
+        a->fkey[i]=a->rkey[i]=0;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+}
+
+
+/*
+#include <stdio.h>
+
+#define KK 32
+
+int main()
+{
+    int i;
+    amcl_aes a;
+       unsign32 t;
+       uchar x,y;
+
+    char key[KK];
+    char block[16];
+    char iv[16];
+    for (i=0;i<KK;i++) key[i]=5;
+    key[0]=1;
+    for (i=0;i<16;i++) iv[i]=i;
+    for (i=0;i<16;i++) block[i]=i;
+
+    AES_init(&a,CTR16,KK,key,iv);
+
+    printf("Plain=   ");
+    for (i=0;i<16;i++) printf("%02x",block[i]);
+    printf("\n");
+    AES_encrypt(&a,block);
+    printf("Encrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+    AES_reset(&a,CTR16,iv);
+    AES_decrypt(&a,block);
+    printf("Decrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+
+    AES_end(&a);
+
+    return 0;
+}
+
+*/
+

http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version3/c/amcl.h
----------------------------------------------------------------------
diff --git a/version3/c/amcl.h b/version3/c/amcl.h
new file mode 100644
index 0000000..2558911
--- /dev/null
+++ b/version3/c/amcl.h
@@ -0,0 +1,590 @@
+/*
+       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.
+*/
+
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "arch.h"
+
+#ifdef CMAKE
+#define AMCL_VERSION_MAJOR @AMCL_VERSION_MAJOR@ /**< Major version of the 
library */
+#define AMCL_VERSION_MINOR @AMCL_VERSION_MINOR@ /**< Minor version of the 
library */
+#define AMCL_VERSION_PATCH @AMCL_VERSION_PATCH@ /**< Patch version of the 
library */
+#define OS "@OS@"                               /**< Build OS */
+#endif
+
+/* modulus types */
+
+#define NOT_SPECIAL 0         /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1      /**< Pseudo-mersenne modulus of form $2^n-c$  */
+#define MONTGOMERY_FRIENDLY 3  /**< Montgomery Friendly modulus of form 
$2^a(2^b-c)-1$  */
+#define GENERALISED_MERSENNE 2 /**< Generalised-mersenne modulus of form 
$2^n-2^m-1$, GOLDILOCKS only */
+
+
+/* Curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve  */
+#define EDWARDS 1     /**< Edwards or Twisted Edwards curve  */
+#define MONTGOMERY 2  /**< Montgomery form curve  */
+
+/* Pairing-Friendly types */
+
+#define NOT 0
+#define BN 1
+#define BLS 2
+
+#define D_TYPE 0
+#define M_TYPE 1
+
+/**
+ * @brief SHA256 hash function instance */
+typedef struct
+{
+    unsign32 length[2]; /**< 64-bit input length */
+    unsign32 h[8];      /**< Internal state */
+    unsign32 w[80];    /**< Internal state */
+    int hlen;          /**< Hash length in bytes */
+} hash256;
+
+/**
+ * @brief SHA384-512 hash function instance */
+typedef struct
+{
+    unsign64 length[2]; /**< 64-bit input length */
+    unsign64 h[8];      /**< Internal state */
+    unsign64 w[80];    /**< Internal state */
+    int hlen;           /**< Hash length in bytes */
+} hash512;
+
+/**
+ * @brief SHA384 hash function instance */
+typedef hash512 hash384;
+
+/**
+ * @brief SHA3 hash function instance */
+typedef struct
+{
+    unsign64 length;   /**< 64-bit input length */
+    unsign64 S[5][5];  /**< Internal state */
+    int rate;          /**< TODO */
+    int len;           /**< Hash length in bytes */
+} sha3;
+
+#define SHA256 32 /**< SHA-256 hashing */
+#define SHA384 48 /**< SHA-384 hashing */
+#define SHA512 64 /**< SHA-512 hashing */
+
+#define SHA3_HASH224 28 /**< SHA3 224 bit hash */
+#define SHA3_HASH256 32 /**< SHA3 256 bit hash */
+#define SHA3_HASH384 48 /**< SHA3 384 bit hash */
+#define SHA3_HASH512 64 /**< SHA3 512 bit hash */
+
+#define SHAKE128 16 /**< SHAKE128   hash */
+#define SHAKE256 32 /**< SHAKE256 hash */
+
+
+/* NewHope parameters */
+
+//q= 12289
+
+#define RLWE_PRIME 0x3001      // q in Hex
+#define RLWE_LGN 10                    // Degree n=2^LGN
+#define RLWE_ND 0xF7002FFF     // 1/(R-q) mod R
+#define RLWE_ONE 0x2AC8                // R mod q
+#define RLWE_R2MODP 0x1620     // R^2 mod q
+
+/* Symmetric Encryption AES structure */
+
+#define ECB   0  /**< Electronic Code Book */
+#define CBC   1  /**< Cipher Block Chaining */
+#define CFB1  2  /**< Cipher Feedback - 1 byte */
+#define CFB2  3  /**< Cipher Feedback - 2 bytes */
+#define CFB4  5  /**< Cipher Feedback - 4 bytes */
+#define OFB1  14 /**< Output Feedback - 1 byte */
+#define OFB2  15 /**< Output Feedback - 2 bytes */
+#define OFB4  17 /**< Output Feedback - 4 bytes */
+#define OFB8  21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+#define CTR1  30 /**< Counter Mode - 1 byte */
+#define CTR2  31 /**< Counter Mode - 2 bytes */
+#define CTR4  33 /**< Counter Mode - 4 bytes */
+#define CTR8  37 /**< Counter Mode - 8 bytes */
+#define CTR16 45 /**< Counter Mode - 16 bytes */
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/**
+       @brief AES instance
+*/
+
+
+typedef struct
+{
+    int Nk;            /**< AES Key Length */
+    int Nr;            /**< AES Number of rounds */
+    int mode;          /**< AES mode of operation */
+    unsign32 fkey[60]; /**< subkeys for encrypton */
+    unsign32 rkey[60]; /**< subkeys for decrypton */
+    char f[16];        /**< buffer for chaining vector */
+} amcl_aes;
+
+/* AES-GCM suppport.  */
+
+#define GCM_ACCEPTING_HEADER 0   /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1   /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3           /**< GCM status */
+#define GCM_ENCRYPTING 0         /**< GCM mode */
+#define GCM_DECRYPTING 1         /**< GCM mode */
+
+
+/**
+       @brief GCM mode instance, using AES internally
+*/
+
+typedef struct
+{
+    unsign32 table[128][4]; /**< 2k byte table */
+    uchar stateX[16];      /**< GCM Internal State */
+    uchar Y_0[16];         /**< GCM Internal State */
+    unsign32 lenA[2];      /**< GCM 64-bit length of header */
+    unsign32 lenC[2];      /**< GCM 64-bit length of ciphertext */
+    int status;                    /**< GCM Status */
+    amcl_aes a;                    /**< Internal Instance of AMCL_AES cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK   21 /**< PRNG constant */
+#define NJ   6  /**< PRNG constant */
+#define NV   8  /**< PRNG constant */
+
+
+/**
+       @brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct
+{
+    unsign32 ira[NK]; /**< random number array   */
+    int      rndptr;  /**< pointer into array */
+    unsign32 borrow;  /**<  borrow as a result of subtraction */
+    int pool_ptr;     /**< pointer into random pool */
+    char pool[32];    /**< random pool */
+} csprng;
+
+
+/**
+       @brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+    int len;   /**< length in bytes  */
+    int max;   /**< max length allowed - enforce truncation  */
+    char *val; /**< byte array  */
+} octet;
+
+
+/* Octet string handlers */
+/**    @brief Formats and outputs an octet to the console in hex
+ *
+       @param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/**    @brief Formats and outputs an octet to the console as a character string
+ *
+       @param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/**    @brief Wipe clean an octet
+ *
+       @param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/**    @brief Compare two octets
+ *
+       @param O first Octet to be compared
+       @param P second Octet to be compared
+       @return 1 if equal, else 0
+ */
+extern int  OCT_comp(octet *O,octet *P);
+/**    @brief Compare first n bytes of two octets
+ *
+       @param O first Octet to be compared
+       @param P second Octet to be compared
+       @param n number of bytes to compare
+       @return 1 if equal, else 0
+ */
+extern int  OCT_ncomp(octet *O,octet *P,int n);
+/**    @brief Join from a C string to end of an octet
+ *
+       Truncates if there is no room
+       @param O Octet to be written to
+       @param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/**    @brief Join bytes to end of an octet
+ *
+       Truncates if there is no room
+       @param O Octet to be written to
+       @param s bytes to be joined to end of octet
+       @param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/**    @brief Join single byte to end of an octet, repeated n times
+ *
+       Truncates if there is no room
+       @param O Octet to be written to
+       @param b byte to be joined to end of octet
+       @param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/**    @brief Join one octet to the end of another
+ *
+       Truncates if there is no room
+       @param O Octet to be written to
+       @param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/**    @brief XOR common bytes of a pair of Octets
+ *
+       @param O Octet - on exit = O xor P
+       @param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/**    @brief reset Octet to zero length
+ *
+       @param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/**    @brief Pad out an Octet to the given length
+ *
+       Padding is done by inserting leading zeros, so abcd becomes 00abcd
+       @param O Octet to be padded
+       @param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/**    @brief Convert an Octet to printable base64 number
+ *
+       @param b zero terminated byte array to take base64 conversion
+       @param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/**    @brief Populate an Octet from base64 number
+ *
+       @param O Octet to be populated
+       @param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/**    @brief Copy one Octet into another
+ *
+       @param O Octet to be copied to
+       @param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/**    @brief XOR every byte of an octet with input m
+ *
+       @param O Octet
+       @param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/**    @brief Chops Octet into two, leaving first n bytes in O, moving the 
rest to P
+ *
+       @param O Octet to be chopped
+       @param P new Octet to be created
+       @param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/**    @brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+       Typically n is 4 for a 32-bit integer
+       @param O Octet to be appended to
+       @param m integer to be appended to O
+       @param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/**    @brief Create an Octet from bytes taken from a random number generator
+ *
+       Truncates if there is no room
+       @param O Octet to be populated
+       @param R an instance of a Cryptographically Secure Random Number 
Generator
+       @param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/**    @brief Shifts Octet left by n bytes
+ *
+       Leftmost bytes disappear
+       @param O Octet to be shifted
+       @param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/**    @brief Convert a hex number to an Octet
+ *
+       @param dst Octet
+       @param src Hex string to be converted
+ */
+extern void OCT_fromHex(octet *dst,char *src);
+/**    @brief Convert an Octet to printable hex number
+ *
+       @param dst hex value
+       @param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/**    @brief Convert an Octet to string
+ *
+       @param dst string value
+       @param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+
+/* Hash function */
+/**    @brief Initialise an instance of SHA256
+ *
+       @param H an instance SHA256
+ */
+extern void HASH256_init(hash256 *H);
+/**    @brief Add a byte to the hash
+ *
+       @param H an instance SHA256
+       @param b byte to be included in hash
+ */
+extern void HASH256_process(hash256 *H,int b);
+/**    @brief Generate 32-byte hash
+ *
+       @param H an instance SHA256
+       @param h is the output 32-byte hash
+ */
+extern void HASH256_hash(hash256 *H,char *h);
+
+
+/**    @brief Initialise an instance of SHA384
+ *
+       @param H an instance SHA384
+ */
+extern void HASH384_init(hash384 *H);
+/**    @brief Add a byte to the hash
+ *
+       @param H an instance SHA384
+       @param b byte to be included in hash
+ */
+extern void HASH384_process(hash384 *H,int b);
+/**    @brief Generate 48-byte hash
+ *
+       @param H an instance SHA384
+       @param h is the output 48-byte hash
+ */
+extern void HASH384_hash(hash384 *H,char *h);
+
+
+/**    @brief Initialise an instance of SHA512
+ *
+       @param H an instance SHA512
+ */
+extern void HASH512_init(hash512 *H);
+/**    @brief Add a byte to the hash
+ *
+       @param H an instance SHA512
+       @param b byte to be included in hash
+ */
+extern void HASH512_process(hash512 *H,int b);
+/**    @brief Generate 64-byte hash
+ *
+       @param H an instance SHA512
+       @param h is the output 64-byte hash
+ */
+extern void HASH512_hash(hash512 *H,char *h);
+
+
+/**    @brief Initialise an instance of SHA3
+ *
+       @param H an instance SHA3
+       @param t the instance type
+ */
+extern void  SHA3_init(sha3 *H,int t);
+/**    @brief process a byte for SHA3
+ *
+       @param H an instance SHA3
+       @param b a byte of date to be processed
+ */
+extern void  SHA3_process(sha3 *H,int b);
+/**    @brief create fixed length hash output of SHA3
+ *
+       @param H an instance SHA3
+       @param h a byte array to take hash
+ */
+extern void  SHA3_hash(sha3 *H,char *h);
+/**    @brief create variable length hash output of SHA3
+ *
+       @param H an instance SHA3
+       @param h a byte array to take hash
+       @param len is the length of the hash
+ */
+extern void  SHA3_shake(sha3 *H,char *h,int len);
+/**    @brief generate further hash output of SHA3
+ *
+       @param H an instance SHA3
+       @param h a byte array to take hash
+       @param len is the length of the hash
+ */
+extern void  SHA3_squeeze(sha3 *H,char *h,int len);
+
+
+
+/* AES functions */
+/**    @brief Reset AES mode or IV
+ *
+       @param A an instance of the AMCL_AES
+       @param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+       @param iv the new Initialisation Vector
+ */
+extern void AES_reset(amcl_aes *A,int m,char *iv);
+/**    @brief Extract chaining vector from AMCL_AES instance
+ *
+       @param A an instance of the AMCL_AES
+       @param f the extracted chaining vector
+ */
+extern void AES_getreg(amcl_aes *A,char * f);
+/**    @brief Initialise an instance of AMCL_AES and its mode of operation
+ *
+       @param A an instance AMCL_AES
+       @param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+       @param n is the key length in bytes, 16, 24 or 32
+       @param k the AES key as an array of 16 bytes
+       @param iv the Initialisation Vector
+       @return 0 for invalid n
+ */
+extern int AES_init(amcl_aes *A,int m,int n,char *k,char *iv);
+/**    @brief Encrypt a single 16 byte block in ECB mode
+ *
+       @param A an instance of the AMCL_AES
+       @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(amcl_aes *A,uchar * b);
+/**    @brief Decrypt a single 16 byte block in ECB mode
+ *
+       @param A an instance of the AMCL_AES
+       @param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(amcl_aes *A,uchar * b);
+/**    @brief Encrypt a single 16 byte block in active mode
+ *
+       @param A an instance of the AMCL_AES
+       @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+       @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(amcl_aes *A,char *b );
+/**    @brief Decrypt a single 16 byte block in active mode
+ *
+       @param A an instance of the AMCL_AES
+       @param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+       @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(amcl_aes *A,char *b);
+/**    @brief Clean up after application of AES
+ *
+       @param A an instance of the AMCL_AES
+ */
+extern void AES_end(amcl_aes *A);
+
+
+/* AES-GCM functions */
+/**    @brief Initialise an instance of AES-GCM mode
+ *
+       @param G an instance AES-GCM
+       @param nk is the key length in bytes, 16, 24 or 32
+       @param k the AES key as an array of 16 bytes
+       @param n the number of bytes in the Initialisation Vector (IV)
+       @param iv the IV
+ */
+extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
+/**    @brief Add header (material to be authenticated but not encrypted)
+ *
+       Note that this function can be called any number of times with n a 
multiple of 16, and then one last time with any value for n
+       @param G an instance AES-GCM
+       @param b is the header material to be added
+       @param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/**    @brief Add plaintext and extract ciphertext
+ *
+       Note that this function can be called any number of times with n a 
multiple of 16, and then one last time with any value for n
+       @param G an instance AES-GCM
+       @param c is the ciphertext generated
+       @param p is the plaintext material to be added
+       @param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/**    @brief Add ciphertext and extract plaintext
+ *
+       Note that this function can be called any number of times with n a 
multiple of 16, and then one last time with any value for n
+       @param G an instance AES-GCM
+       @param p is the plaintext generated
+       @param c is the ciphertext material to be added
+       @param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/**    @brief Finish off and extract authentication tag (HMAC)
+ *
+       @param G is an active instance AES-GCM
+       @param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/**    @brief Seed a random number generator from an array of bytes
+ *
+       The provided seed should be truly random
+       @param R an instance of a Cryptographically Secure Random Number 
Generator
+       @param n the number of seed bytes provided
+       @param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/**    @brief Delete all internal state of a random number generator
+ *
+       @param R an instance of a Cryptographically Secure Random Number 
Generator
+ */
+extern void RAND_clean(csprng *R);
+/**    @brief Return a random byte from a random number generator
+ *
+       @param R an instance of a Cryptographically Secure Random Number 
Generator
+       @return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+
+
+#endif

Reply via email to