Page 1 of 2

broken c port of Ec25519 key exchange

Posted: Sat Feb 20, 2010 7:19 am
by idle
I can't seem to find whats wrong with my port from the topic.
http://www.purebasic.fr/english/viewtop ... 12&t=41157

possibly my offset calculations, loop bounds or just plain dumb

c source below

Code: Select all

Macro comment()
; /* Copyright 2008, Google Inc.
;  * All rights reserved.
;  *
;  * Redistribution And use in source And binary forms, With Or without
;  * modification, are permitted provided that the following conditions are
;  * met:
;  *
;  *     * Redistributions of source code must retain the above copyright
;  * notice, this List of conditions And the following disclaimer.
;  *     * Redistributions in binary form must reproduce the above
;  * copyright notice, this List of conditions And the following disclaimer
;  * in the documentation And/Or other materials provided With the
;  * distribution.
;  *     * Neither the name of Google Inc. nor the names of its
;  * contributors may be used To endorse Or promote products derived from
;  * this software without specific prior written permission.
;  *
;  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS And CONTRIBUTORS
;  * "AS IS" And ANY EXPRESS Or IMPLIED WARRANTIES, INCLUDING, BUT Not
;  * LIMITED To, THE IMPLIED WARRANTIES OF MERCHANTABILITY And FITNESS For
;  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;  * OWNER Or CONTRIBUTORS BE LIABLE For ANY DIRECT, INDIRECT, INCIDENTAL,
;  * SPECIAL, EXEMPLARY, Or CONSEQUENTIAL DAMAGES (INCLUDING, BUT Not
;  * LIMITED To, PROCUREMENT OF SUBSTITUTE GOODS Or SERVICES; LOSS OF USE,
;  * Data, Or PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, Or TORT
;  * (INCLUDING NEGLIGENCE Or OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;  * OF THIS SOFTWARE, EVEN If ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;  *
;  * curve25519-donna: Curve25519 elliptic curve, public key function
;  *
;  * http://code.google.com/p/curve25519-donna/
;  *
;  * Adam Langley <agl@imperialviolet.org>
;  *
;  * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.To>
;  *
;  * More information about curve25519 can be found here
;  *   http://cr.yp.To/ecdh.html
;  *
;  * djb's sample implementation of curve25519 is written in a special assembly
;  * language called qhasm And uses the floating point registers.
;  *
;  * This is, almost, a clean room reimplementation from the curve25519 paper. It
;  * uses many of the tricks described therein. Only the crecip function is taken
;  * from the sample implementation.
;  */
EndMacro

;EnableExplicit

Global *tA = AllocateMemory(19*8)
Global *tB = AllocateMemory(19*8)
Global over.q,over2.q  

Global *mysecret = AllocateMemory(32)
Global *mypublic = AllocateMemory(32)
Global *basepoint = AllocateMemory(32)
Global *hissecret = AllocateMemory(32)
Global *hispublic = AllocateMemory(32)
Global *myshared = AllocateMemory(32)
Global *hisshared = AllocateMemory(32)

Procedure dB(*mem,op.s)
  Protected len,st.s
  len = MemorySize(*mem)
  st = op + "   "
  For a = 0 To len-1 
   st+RSet(Hex(PeekA(*mem+a),#PB_Byte),2,"0")
  Next 
  Debug str$  
EndProcedure

Macro fsum(out,in)
 i=0
 While i < 80 
    ii=i+8
    PokeQ(out+i,(PeekQ(out+i) + PeekQ(in+i)))
    PokeQ(out+ii,(PeekQ(out+ii) + PeekQ(in+ii)))
    i+16
 Wend
 ;db(*out,"Sum")
EndMacro

Macro fdifference(out,in)
  i=0
  While i < 80
    PokeQ(out+i,(PeekQ(in+i) - PeekQ(out+i)));
    i+8
  Wend 
  ;db(*out,"difference")
EndMacro

Macro fscalar_product(out,in,scalar)
  
  i=0
  While i < 80 
    PokeQ(out+i,(PeekQ(in+i) * scalar))
    i+8
  Wend 
  ;db(*out,"scallar") 
EndMacro

Macro fproduct(out,im,in)
                          
  PokeQ(*out+0, PeekQ(*im+0) * PeekQ(*in+0));
  PokeQ(*out+8, PeekQ(*im+0) * PeekQ(*in+8) + PeekQ(*im+8) * PeekQ(*in+0));
  PokeQ(*out+16, 2 * PeekQ(*im+8) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+16) + PeekQ(*im+16) * PeekQ(*in+0));
  PokeQ(*out+24, PeekQ(*im+8) * PeekQ(*in+16) + PeekQ(*im+16) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+0));
  PokeQ(*out+32, PeekQ(*im+16) * PeekQ(*in+16) + 2 * (PeekQ(*im+8) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+8)) + PeekQ(*im+0) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+0));
  PokeQ(*out+40, PeekQ(*im+16) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+0));
  PokeQ(*out+48, 2 * (PeekQ(*im+24) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+0));
  PokeQ(*out+56, PeekQ(*im+24) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+0));
  PokeQ(*out+64, PeekQ(*im+32) * PeekQ(*in+32) + 2 * (PeekQ(*im+24) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+0));
  PokeQ(*out+72, PeekQ(*im+32) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+32) + PeekQ(*im+24) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+0));
  PokeQ(*out+80, 2 * (PeekQ(*im+40) * PeekQ(*in+40) + PeekQ(*im+24) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+8)) + PeekQ(*im+32) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+32) + PeekQ(*im+16) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+16));
  PokeQ(*out+88, PeekQ(*im+40) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+40) + PeekQ(*im+32) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+32) + PeekQ(*im+24) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+16));
  PokeQ(*out+96, PeekQ(*im+48) * PeekQ(*in+48) + 2 * (PeekQ(*im+40) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+40) + PeekQ(*im+24) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+24)) + PeekQ(*im+32) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+32));
  PokeQ(*out+104, PeekQ(*im+48) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+48) + PeekQ(*im+40) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+40) + PeekQ(*im+32) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+32));
  PokeQ(*out+112, 2 * (PeekQ(*im+56) * PeekQ(*in+56) + PeekQ(*im+40) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+40)) + PeekQ(*im+48) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+48));
  PokeQ(*out+120, PeekQ(*im+56) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+56) + PeekQ(*im+48) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+48));
  PokeQ(*out+128, PeekQ(*im+64) * PeekQ(*in+64) + 2 * (PeekQ(*im+56) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+56)));
  PokeQ(*out+136, PeekQ(*im+64) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+64));
  PokeQ(*out+144, 2 * PeekQ(*im+72) * PeekQ(*in+72));
  ;db(*out,"product")

EndMacro

Macro freduce_degree(out)
     
  PokeQ(*out+64,PeekQ(*out+64) + (19 * PeekQ(*out+144)));
  PokeQ(*out+56,PeekQ(*out+56) + (19 * PeekQ(*out+136)));
  PokeQ(*out+48,PeekQ(*out+48) + (19 * PeekQ(*out+128)));
  PokeQ(*out+40,PeekQ(*out+40) + (19 * PeekQ(*out+120)));
  PokeQ(*out+32,PeekQ(*out+32) + (19 * PeekQ(*out+112)));
  PokeQ(*out+24,PeekQ(*out+24) + (19 * PeekQ(*out+104)));
  PokeQ(*out+16,PeekQ(*out+16) + (19 * PeekQ(*out+96)));
  PokeQ(*out+8,PeekQ(*out+8) + (19 * PeekQ(*out+88)));
  PokeQ(*out+0,PeekQ(*out+0) + (19 * PeekQ(*out+80)));
  ;db(out,"degree")
EndMacro

Macro freduce_coefficients(out)
  
  Repeat 
    
    PokeQ(*out+80,0);
    i=0
    While i < 80 ;Step 2
      over = PeekQ(*out+i) / $2000000;
      over2 = (over + ((over >> 63) * 2) + 1) / 2;
      PokeQ(*out+i+8,((PeekQ(*out+i+8)) + over2));
      PokeQ(*out+i,((PeekQ(*out+i)) - (over2 * $4000000)))

      over = (PeekQ(*out+i+8)) / $2000000;
      PokeQ(*out+i+16,(PeekQ(*out+i+16) + over));
      PokeQ(*out+i+8,(PeekQ(*out+i+8)) - (over * $2000000));
      i+16
    
    Wend
    
    PokeQ(*out+0,((PeekQ(*out+0)) + (19 * (PeekQ(*out+80)))));
   
  
  Until Not PeekQ(*out+80) ;
  
  ;db(*out,"Coeff")
EndMacro
 
Macro fsquare_inner(out,in)
  
  PokeQ(*out+0, PeekQ(*in+0) * PeekQ(*in+0));
  PokeQ(*out+8, 2 * PeekQ(*in+0) * PeekQ(*in+8));
  PokeQ(*out+16, 2 * (PeekQ(*in+8) * PeekQ(*in+8) + PeekQ(*in+0) * PeekQ(*in+16)));
  PokeQ(*out+24, 2 * (PeekQ(*in+8) * PeekQ(*in+16) + PeekQ(*in+0) * PeekQ(*in+24)));
  PokeQ(*out+32, PeekQ(*in+16) * PeekQ(*in+16) + 4 * PeekQ(*in+8) * PeekQ(*in+24) + 2 * PeekQ(*in+0) * PeekQ(*in+32));
  PokeQ(*out+40, 2 * (PeekQ(*in+16) * PeekQ(*in+24) + PeekQ(*in+8) * PeekQ(*in+32) + PeekQ(*in+0) * PeekQ(*in+40)));
  PokeQ(*out+48, 2 * (PeekQ(*in+24) * PeekQ(*in+24) + PeekQ(*in+16) * PeekQ(*in+32) + PeekQ(*in+0) * PeekQ(*in+48) + 2 * PeekQ(*in+8) * PeekQ(*in+40)));
  PokeQ(*out+56, 2 * (PeekQ(*in+24) * PeekQ(*in+32) + PeekQ(*in+16) * PeekQ(*in+40) + PeekQ(*in+8) * PeekQ(*in+48) + PeekQ(*in+0) * PeekQ(*in+56)));
  PokeQ(*out+64, PeekQ(*in+32) * PeekQ(*in+32) + 2 * (PeekQ(*in+16) * PeekQ(*in+48) + PeekQ(*in+0) * PeekQ(*in+64) + 2 * (PeekQ(*in+8) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+40))));
  PokeQ(*out+72, 2 * (PeekQ(*in+32) * PeekQ(*in+40) + PeekQ(*in+24) * PeekQ(*in+48) + PeekQ(*in+16) * PeekQ(*in+56) + PeekQ(*in+8) * PeekQ(*in+64) + PeekQ(*in+0) * PeekQ(*in+72)));
  PokeQ(*out+80, 2 * (PeekQ(*in+40) * PeekQ(*in+40) + PeekQ(*in+32) * PeekQ(*in+48) + PeekQ(*in+16) * PeekQ(*in+64) + 2 * (PeekQ(*in+24) * PeekQ(*in+56) + PeekQ(*in+8) * PeekQ(*in+72))));
  PokeQ(*out+88, 2 * (PeekQ(*in+40) * PeekQ(*in+48) + PeekQ(*in+32) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+64) + PeekQ(*in+16) * PeekQ(*in+72)));
  PokeQ(*out+96, PeekQ(*in+48) * PeekQ(*in+48) + 2 * (PeekQ(*in+32) * PeekQ(*in+64) + 2 * (PeekQ(*in+40) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+72))));
  PokeQ(*out+104, 2 * (PeekQ(*in+48) * PeekQ(*in+56) + PeekQ(*in+40) * PeekQ(*in+64) + PeekQ(*in+32) * PeekQ(*in+72)));
  PokeQ(*out+112, 2 * (PeekQ(*in+56) * PeekQ(*in+56) + PeekQ(*in+48) * PeekQ(*in+64) + 2 * PeekQ(*in+40) * PeekQ(*in+72)));
  PokeQ(*out+120, 2 * (PeekQ(*in+56) * PeekQ(*in+64) + PeekQ(*in+48) * PeekQ(*in+72)));
  PokeQ(*out+128, PeekQ(*in+64) * PeekQ(*in+64) + 4 * PeekQ(*in+56) * PeekQ(*in+72));
  PokeQ(*out+136, 2 * PeekQ(*in+64) * PeekQ(*in+72));
  PokeQ(*out+144, 2 * PeekQ(*in+72) * PeekQ(*in+72));
  ;db(*out,"square inner")
EndMacro 

Macro fexpand(out,in) ;(quad,byte)
    
  PokeQ(out+0,(((PeekA(in+0)) | (PeekA(in+1)) << 8 | (PeekA(in+2)) << 16 | (PeekA(in+3)) << 24)) & $3ffffff);
  PokeQ(out+8,(((PeekA(in+3+0)) | (PeekA(in+3+1)) << 8 | (PeekA(in+3+2)) << 16 | (PeekA(in+3+3)) << 24) >> 2) & $1ffffff);
  PokeQ(out+16,(((PeekA(in+6+0)) | (PeekA(in+6+1)) << 8 | (PeekA(in+6+2)) << 16 | (PeekA(in+6+3)) << 24) >> 3) & $3ffffff);
  PokeQ(out+24,(((PeekA(in+9+0)) | (PeekA(in+9+1)) << 8 | (PeekA(in+9+2)) << 16 | (PeekA(in+9+3)) << 24) >> 5) & $1ffffff);
  PokeQ(out+32,(((PeekA(in+12+0)) | (PeekA(in+12+1)) << 8 | (PeekA(in+12+2)) << 16 | (PeekA(in+12+3)) << 24) >> 6) & $3ffffff);
  PokeQ(out+40,(((PeekA(in+16+0)) | (PeekA(in+16+1)) << 8 | (PeekA(in+16+2)) << 16 | (PeekA(in+16+3)) << 24)) & $1ffffff);
  PokeQ(out+48,(((PeekA(in+19+0)) | (PeekA(in+19+1)) << 8 | (PeekA(in+19+2)) << 16 | (PeekA(in+19+3)) << 24) >> 1) & $3ffffff);
  PokeQ(out+56,(((PeekA(in+22+0)) | (PeekA(in+22+1)) << 8 | (PeekA(in+22+2)) << 16 | (PeekA(in+22+3)) << 24) >> 3) & $1ffffff);
  PokeQ(out+64,(((PeekA(in+25+0)) | (PeekA(in+25+1)) << 8 | (PeekA(in+25+2)) << 16 | (PeekA(in+25+3)) << 24) >> 4) & $3ffffff);
  PokeQ(out+72,(((PeekA(in+28+0)) | (PeekA(in+28+1)) << 8 | (PeekA(in+28+2)) << 16 | (PeekA(in+28+3)) << 24) >> 6) & $1ffffff);
  
  ;db(*out,"Expand")
EndMacro

Macro FC(out,in,i,s)
    PokeA(out+s+0,(PeekA(out+s+0) | PeekQ(in+(i*8))) & $ff);
    PokeA(out+s+1,(PeekQ(in+(i*8)) >> 8) & $ff); \
    PokeA(out+s+2,(PeekQ(in+(i*8)) >> 16) & $ff); \
    PokeA(out+s+3,(PeekQ(in+(i*8)) >> 24) & $ff);
    PokeA(out+0,0);
    PokeA(out+16,0);
    ;db(*out,"FC")
EndMacro

Procedure fsquare(*out,*in)
  Protected i.i
  fsquare_inner(tB, in);
  freduce_degree(tB);
  freduce_coefficients(tB);
  CopyMemory(*tB,*out,80);
  FillMemory(*tb,19*8,0)
  db(*out,"Square")

EndProcedure

Procedure fmul(*out,*in,*in2)
  Protected i.i
  fproduct(tA,in,in2);
  freduce_degree(tA);
  freduce_coefficients(tA);
  CopyMemory(*tA,*out,80);
  FillMemory(*TA,19*8,0)
  ;db(*out,"mul")
EndProcedure

Procedure fcontract(*out,*in) 
  Protected a,i
  Repeat
    For a = 0 To 8 
      If (a & 1)  
       While PeekQ(*in+i) < 0
           PokeQ(*in+i,PeekQ(*in+i) + $2000000);
           PokeQ(*in+i+8,PeekQ(*in+i+8)-1);
        Wend
      Else 
        While PeekQ(*in+i) < 0  
          PokeQ(*in+i,PeekQ(*in+i) + $4000000);
          PokeQ(*in+i+8,PeekQ(*in+i+8)-1);
        Wend
      EndIf
      i+8
    Next
    While PeekQ(*in+72) < 0
      PokeQ(*in+72,PeekQ(*in+72) + $2000000);
      PokeQ(*in+0,PeekQ(*in+0) - 19);
    Wend
    Debug PeekQ(*in+0)
  Until PeekQ(*in+0) > 0;

  PokeQ(*in+8,PeekQ(*in+8) << 2);
  PokeQ(*in+16,PeekQ(*in+16) << 3);
  PokeQ(*in+24,PeekQ(*in+24) << 5);
  PokeQ(*in+32,PeekQ(*in+32) << 6);
  PokeQ(*in+48,PeekQ(*in+48) << 1);
  PokeQ(*in+56,PeekQ(*in+56) << 3);
  PokeQ(*in+64,PeekQ(*in+64) << 4);
  PokeQ(*in+72,PeekQ(*in+72) << 6);
  
   
  FC(*out,*in,0,0);
  FC(*out,*in,1,3);
  FC(*out,*in,2,6);
  FC(*out,*in,3,9);
  FC(*out,*in,4,12);
  FC(*out,*in,5,16);
  FC(*out,*in,6,19);
  FC(*out,*in,7,22);
  FC(*out,*in,8,25);
  FC(*out,*in,9,28);
  
  db(*out,"Contract")
  
EndProcedure

Procedure fmonty(*x2,*z2,*x3,*z3,*x,*z,*xprime,*zprime,*qmqp)
  
  Protected *origx = AllocateMemory(80)
  Protected *origxprime = AllocateMemory(80)
  Protected *zzz = AllocateMemory(8*19)
  Protected *xx = AllocateMemory(8*19)
  Protected *zz = AllocateMemory(8*19)
  Protected *xxprime = AllocateMemory(8*19)
  Protected *zzprime = AllocateMemory(8*19)
  Protected *zzzprime = AllocateMemory(8*19)
  Protected *xxxprime = AllocateMemory(8*19);
  Protected i,ii
   
  CopyMemory(*x,*origx,80) ;10 * SizeOf(felem));
  fsum(*x,*z);
  fdifference(*z,*origx);  // does x - z

  CopyMemory(*xprime,*origxprime,80); xprime, SizeOf(felem) * 10);
  fsum(*xprime, *zprime);
  fdifference(*zprime, *origxprime);
  fproduct(xxprime, xprime, z);
  fproduct(zzprime, x, zprime);
  freduce_degree(xxprime);
  freduce_coefficients(xxprime);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  CopyMemory(*xxprime,*origxprime,80); xxprime, SizeOf(felem) * 10);
  fsum(*xxprime, *zzprime);
  fdifference(*zzprime, *origxprime);
  fsquare(*xxxprime,*xxprime);
  fsquare(*zzzprime,*zzprime);
  fproduct(zzprime,zzzprime,qmqp);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  CopyMemory(*xxxprime,*x3,80); xxxprime, SizeOf(felem) * 10);
  CopyMemory(*zzprime,*z3,80); zzprime, SizeOf(felem) * 10);

  fsquare(*xx,*x);
  fsquare(*zz,*z);
  fproduct(x2,xx,zz);
  freduce_degree(x2);
  freduce_coefficients(x2);
  fdifference(*zz,*xx);  // does zz = xx - zz
  FillMemory(*zzz+80,72,0)
  Protected scal.q = 121665
  fscalar_product(*zzz,*zz,scal);
  freduce_degree(zzz);
  freduce_coefficients(zzz);
  fsum(*zzz,*xx);
  fproduct(z2,zz,zzz);
  freduce_degree(z2);
  freduce_coefficients(z2);
  
  FreeMemory(*origx) 
  FreeMemory(*origxprime) 
  FreeMemory(*zzz)  
  FreeMemory(*xx)  
  FreeMemory(*zz)  
  FreeMemory(*xxprime)  
  FreeMemory(*zzprime) 
  FreeMemory(*zzzprime)  
  FreeMemory(*xxxprime)  
  
;   db(*x2,"fmonty x2")
;   db(*z2,"fmonty z2")  
 EndProcedure

Procedure cmult(*resultx,*resultz,*n,*q)
  
  Protected *a,*b,*c,*d,*e,*f,*g,*h,*t
  Protected *nqpqx,*nqpqz,*nqx,*nqz
  Protected *nqpqx2,*nqpqz2,*nqx2,*nqz2
  Protected byte.i,i,j
  
  *a = AllocateMemory(8*19)
  *b = AllocateMemory(8*19)
  *c = AllocateMemory(8*19)
  *d = AllocateMemory(8*19)
  
  PokeQ(*b,1) : PokeQ(*c,1)  
  *nqpqx = *a : *nqpqz = *b : *nqx = *c : *nqz =*d;
  
  *a = AllocateMemory(8*19)
  *b = AllocateMemory(8*19)
  *c = AllocateMemory(8*19)
  *d = AllocateMemory(8*19)  
  *e = AllocateMemory(8*19)
  *f = AllocateMemory(8*19)
  *g = AllocateMemory(8*19)
  *h = AllocateMemory(8*19)
  
  PokeQ(*f,1) : PokeQ(*h,1) 
  *nqpqx2 = *e : *nqpqz2 = *f : *nqx2 = *g : *nqz2 = *h;
  
  
  CopyMemory(*q,*nqpqx,80)
  
  db(*nqpqx,"nqpqx")
  
  For i = 0 To 31
    byte = PeekA(*n+(31-i)) & $FF
    For j = 0 To 7 
      If (byte & $80) 
        fmonty(*nqpqx2,*nqpqz2,*nqx2,*nqz2,*nqpqx,*nqpqz,*nqx,*nqz,*q);
      Else 
        fmonty(*nqx2,*nqz2,*nqpqx2,*nqpqz2,*nqx,*nqz,*nqpqx,*nqpqz,*q);
      EndIf

      *t = *nqx;
      *nqx = *nqx2;
      *nqx2 = *t;
      *t = *nqz;
      *nqz = *nqz2;
      *nqz2 = *t;
      *t = *nqpqx;
      *nqpqx = *nqpqx2;
      *nqpqx2 = *t;
      *t = *nqpqz;
      *nqpqz = *nqpqz2;
      *nqpqz2 = *t;
    
      byte << 1;
    
    Next
  Next 

  CopyMemory(*nqx,*resultx,80)
  CopyMemory(*nqz,*resultz,80)
  
  FreeMemory(*a)
  FreeMemory(*b)
  FreeMemory(*c)
  FreeMemory(*d)
  FreeMemory(*e)
  FreeMemory(*f)
  FreeMemory(*g)
  
  db(*resultx,"cmult result x")
  db(*resultx,"cmult result z")
  
EndProcedure

;// -----------------------------------------------------------------------------
;// Shamelessly copied from djb's code
;// -----------------------------------------------------------------------------
;Static void
Procedure crecip(*out,*z)
  
  Protected *z2,*z9,*z11,*z2_5_0,*z2_10_0,*z2_20_0,*z2_50_0,*z2_100_0,*t0,*t1
  Protected i
  *z2 = AllocateMemory(80);
  *z9 = AllocateMemory(80);
  *z11 = AllocateMemory(80);
  *z2_5_0 = AllocateMemory(80);
  *z2_10_0 = AllocateMemory(80);
  *z2_20_0 = AllocateMemory(80);
  *z2_50_0 = AllocateMemory(80);
  *z2_100_0 = AllocateMemory(80);
  *t0 = AllocateMemory(80);
  *t1 = AllocateMemory(80);
  
  fsquare(*z2,*z);
  fsquare(*t1,*z2);
  fsquare(*t0,*t1);
  fmul(*z9,*t0,*z);
  fmul(*z11,*z9,*z2);
  fsquare(*t0,*z11);
  fmul(*z2_5_0,*t0,*z9);

  fsquare(*t0,*z2_5_0);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fmul(*z2_10_0,*t0,*z2_5_0);

  fsquare(*t0,*z2_10_0);
  fsquare(*t1,*t0);
  i=2
  While i < 10 
     fsquare(*t0,*t1);
     fsquare(*t1,*t0); 
     i+2
  Wend
  
  
  fmul(*z2_20_0,*t1,*z2_10_0);
  fsquare(*t0,*z2_20_0);
  fsquare(*t1,*t0);
  i=2
  While i < 20 ;Step 2 
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2
  Wend    
  
  fmul(*t0,*t1,*z2_20_0);

  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  i=2
  While i < 10 ;Step 2
    fsquare(*t1,*t0)
    fsquare(*t0,*t1)
    i+2
  Wend 
  
  fmul(*z2_50_0,*t0,*z2_10_0);

  fsquare(*t0,*z2_50_0);
  fsquare(*t1,*t0);
  i=2
  While i < 50 ;Step 2 
    fsquare(*t0,*t1)
    fsquare(*t1,*t0)
    i+2
  Wend
  
  fmul(*z2_100_0,*t1,*z2_50_0);

  fsquare(*t1,*z2_100_0);
  fsquare(*t0,*t1);
  i=2
  While i < 100 ;Step 2
    fsquare(*t1,*t0)
    fsquare(*t0,*t1)
    i+2
  Wend 
  
  fmul(*t1,*t0,*z2_100_0);

  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  
  i=2 
  While i < 50
    fsquare(*t0,*t1)
    fsquare(*t1,*t0)
    i+2
  Wend   
  
  fmul(*t0,*t1,*z2_50_0);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fmul(*out,*t1,*z11);
  
  FreeMemory(*z2);
  FreeMemory(*z9) 
  FreeMemory(*z11)
  FreeMemory(*z2_5_0)
  FreeMemory(*z2_10_0)
  FreeMemory(*z2_20_0)
  FreeMemory(*z2_50_0)
  FreeMemory(*z2_100_0)
  FreeMemory(*t0) 
  FreeMemory(*t1) 
  
  db(*out,"Crecip")
  
EndProcedure

Procedure curve(*mypublic.i,*secret.i,*basepoint.i)
   
  Protected *bp,*x,*z,*zmone,*ee,i 
  *bp = AllocateMemory(80)
  *x = AllocateMemory(80)
  *z = AllocateMemory(80)
  *zmone = AllocateMemory(80)
  *ee = AllocateMemory(32);
  i=0
  While i < 32; ++i)
    PokeA(*ee+i,PeekA(*secret+i));
    Debug PeekA(*ee+i)
    i+1
  Wend 
  
  PokeA(*ee+0,(PeekA(*ee+0) & 248));
  PokeA(*ee+31,(PeekA(*ee+31) & 127));
  PokeA(*ee+31,(PeekA(*ee+31) | 64));

  db(*ee,"secret")
 
  fexpand(*bp,*basepoint);
  cmult(*x, *z, *ee, *bp);
  crecip(*zmone, *z);
  fmul(*z, *x, *zmone);
  fcontract(*mypublic,*z);
  
  FreeMemory(*bp)
  FreeMemory(*x)
  FreeMemory(*z)
  FreeMemory(*zmone)
  FreeMemory(*ee)
  
EndProcedure 

Define i 
For i=0 To 31 : PokeA(*mysecret+i,42) : Next

 PokeA(*mysecret+0, PeekA(*mysecret+0) & 248)
 PokeA(*mysecret+31, PeekA(*mysecret+31) & 127)
 PokeA(*mysecret+31, PeekA(*mysecret+31) | 64)

PokeA(*basepoint+0,9)

;-----

For i=0 To 31 : PokeA(*hissecret+i,11) : Next
   PokeA(*hissecret+0, PeekA(*hissecret+0) & 248)
   PokeA(*hissecret+31, PeekA(*hissecret+31) & 127)
   PokeA(*hissecret+31, PeekA(*hissecret+31) | 64)

;---



OpenConsole()
ConsoleTitle("Curve25519 Test")

str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mysecret+i),#PB_Byte),2,"0"): Next :   PrintN("mysecret : "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve(*mypublic, *mysecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mypublic+i),#PB_Byte),2,"0"): Next :   PrintN("mypublic : "+str$)
PrintN("")
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hissecret+i),#PB_Byte),2,"0"): Next :  PrintN("hissecret: "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve(*hispublic, *hissecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hispublic+i),#PB_Byte),2,"0"): Next :  PrintN("hispublic: "+str$)
PrintN("")
curve(*myshared, *mysecret, *hispublic)
curve(*hisshared, *hissecret, *mypublic)
str_myshared$="": For i=0 To 31: str_myshared$+RSet(Hex(PeekA(*myshared+i),#PB_Byte),2,"0"): Next :   PrintN("myshared : "+str_myshared$)
str_hisshared$="": For i=0 To 31: str_hisshared$+RSet(Hex(PeekA(*hisshared+i),#PB_Byte),2,"0"): Next :  PrintN("hisshared: "+str_hisshared$)
PrintN("")
If str_myshared$ = str_hisshared$
  PrintN("myshared = hisshared")
Else
  PrintN("myshared <> hisshared")
EndIf

PrintN("")
PrintN("")
PrintN("PRESS 'RETURN' TO QUIT.")
Input()
CloseConsole()

Code: Select all

/* Copyright 2008, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * curve25519-donna: Curve25519 elliptic curve, public key function
 *
 * http://code.google.com/p/curve25519-donna/
 *
 * Adam Langley <agl@imperialviolet.org>
 *
 * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
 *
 * More information about curve25519 can be found here
 *   http://cr.yp.to/ecdh.html
 *
 * djb's sample implementation of curve25519 is written in a special assembly
 * language called qhasm and uses the floating point registers.
 *
 * This is, almost, a clean room reimplementation from the curve25519 paper. It
 * uses many of the tricks described therein. Only the crecip function is taken
 * from the sample implementation.
 */

#include <string.h>
#include <stdint.h>

typedef uint8_t u8;
typedef int64_t felem;

/* Sum two numbers: output += in */
static void fsum(felem *output, const felem *in) {
  unsigned i;
  for (i = 0; i < 10; i += 2) {
    output[0+i] = (output[0+i] + in[0+i]);
    output[1+i] = (output[1+i] + in[1+i]);
  }
}

/* Find the difference of two numbers: output = in - output
 * (note the order of the arguments!)
 */
static void fdifference(felem *output, const felem *in) {
  unsigned i;
  for (i = 0; i < 10; ++i) {
    output[i] = (in[i] - output[i]);
  }
}

/* Multiply a number my a scalar: output = in * scalar */
static void fscalar_product(felem *output, const felem *in, const felem scalar) {
  unsigned i;
  for (i = 0; i < 10; ++i) {
    output[i] = in[i] * scalar;
  }
}

/* Multiply two numbers: output = in2 * in
 *
 * output must be distinct to both inputs. The inputs are reduced coefficient
 * form, the output is not.
 */
static void fproduct(felem *output, const felem *in2, const felem *in) {
  output[0] =      in2[0] * in[0];
  output[1] =      in2[0] * in[1] +
                   in2[1] * in[0];
  output[2] =  2 * in2[1] * in[1] +
                   in2[0] * in[2] +
                   in2[2] * in[0];
  output[3] =      in2[1] * in[2] +
                   in2[2] * in[1] +
                   in2[0] * in[3] +
                   in2[3] * in[0];
  output[4] =      in2[2] * in[2] +
               2 * (in2[1] * in[3] +
                    in2[3] * in[1]) +
                   in2[0] * in[4] +
                   in2[4] * in[0];
  output[5] =      in2[2] * in[3] +
                   in2[3] * in[2] +
                   in2[1] * in[4] +
                   in2[4] * in[1] +
                   in2[0] * in[5] +
                   in2[5] * in[0];
  output[6] =  2 * (in2[3] * in[3] +
                    in2[1] * in[5] +
                    in2[5] * in[1]) +
                   in2[2] * in[4] +
                   in2[4] * in[2] +
                   in2[0] * in[6] +
                   in2[6] * in[0];
  output[7] =      in2[3] * in[4] +
                   in2[4] * in[3] +
                   in2[2] * in[5] +
                   in2[5] * in[2] +
                   in2[1] * in[6] +
                   in2[6] * in[1] +
                   in2[0] * in[7] +
                   in2[7] * in[0];
  output[8] =      in2[4] * in[4] +
               2 * (in2[3] * in[5] +
                    in2[5] * in[3] +
                    in2[1] * in[7] +
                    in2[7] * in[1]) +
                   in2[2] * in[6] +
                   in2[6] * in[2] +
                   in2[0] * in[8] +
                   in2[8] * in[0];
  output[9] =      in2[4] * in[5] +
                   in2[5] * in[4] +
                   in2[3] * in[6] +
                   in2[6] * in[3] +
                   in2[2] * in[7] +
                   in2[7] * in[2] +
                   in2[1] * in[8] +
                   in2[8] * in[1] +
                   in2[0] * in[9] +
                   in2[9] * in[0];
  output[10] = 2 * (in2[5] * in[5] +
                    in2[3] * in[7] +
                    in2[7] * in[3] +
                    in2[1] * in[9] +
                    in2[9] * in[1]) +
                   in2[4] * in[6] +
                   in2[6] * in[4] +
                   in2[2] * in[8] +
                   in2[8] * in[2];
  output[11] =     in2[5] * in[6] +
                   in2[6] * in[5] +
                   in2[4] * in[7] +
                   in2[7] * in[4] +
                   in2[3] * in[8] +
                   in2[8] * in[3] +
                   in2[2] * in[9] +
                   in2[9] * in[2];
  output[12] =     in2[6] * in[6] +
               2 * (in2[5] * in[7] +
                    in2[7] * in[5] +
                    in2[3] * in[9] +
                    in2[9] * in[3]) +
                   in2[4] * in[8] +
                   in2[8] * in[4];
  output[13] =     in2[6] * in[7] +
                   in2[7] * in[6] +
                   in2[5] * in[8] +
                   in2[8] * in[5] +
                   in2[4] * in[9] +
                   in2[9] * in[4];
  output[14] = 2 * (in2[7] * in[7] +
                    in2[5] * in[9] +
                    in2[9] * in[5]) +
                   in2[6] * in[8] +
                   in2[8] * in[6];
  output[15] =     in2[7] * in[8] +
                   in2[8] * in[7] +
                   in2[6] * in[9] +
                   in2[9] * in[6];
  output[16] =     in2[8] * in[8] +
               2 * (in2[7] * in[9] +
                    in2[9] * in[7]);
  output[17] =     in2[8] * in[9] +
                   in2[9] * in[8];
  output[18] = 2 * in2[9] * in[9];
}

/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
static void freduce_degree(felem *output) {
  output[8] += 19 * output[18];
  output[7] += 19 * output[17];
  output[6] += 19 * output[16];
  output[5] += 19 * output[15];
  output[4] += 19 * output[14];
  output[3] += 19 * output[13];
  output[2] += 19 * output[12];
  output[1] += 19 * output[11];
  output[0] += 19 * output[10];
}

/* Reduce all coefficients of the short form input to be -2**25 <= x <= 2**25
 */
static void freduce_coefficients(felem *output) {
  unsigned i;
  do {
    output[10] = 0;

    for (i = 0; i < 10; i += 2) {
      felem over = output[i] / 0x2000000l;
      const felem over2 = (over + ((over >> 63) * 2) + 1) / 2;
      output[i+1] += over2;
      output[i] -= over2 * 0x4000000l;

      over = output[i+1] / 0x2000000;
      output[i+2] += over;
      output[i+1] -= over * 0x2000000;
    }
    output[0] += 19 * output[10];
  } while (output[10]);
}

/* A helpful wrapper around fproduct: output = in * in2.
 *
 * output must be distinct to both inputs. The output is reduced degree and
 * reduced coefficient.
 */
static void
fmul(felem *output, const felem *in, const felem *in2) {
  felem t[19];
  fproduct(t, in, in2);
  freduce_degree(t);
  freduce_coefficients(t);
  memcpy(output, t, sizeof(felem) * 10);
}

static void fsquare_inner(felem *output, const felem *in) {
  output[0] =      in[0] * in[0];
  output[1] =  2 * in[0] * in[1];
  output[2] =  2 * (in[1] * in[1] +
                    in[0] * in[2]);
  output[3] =  2 * (in[1] * in[2] +
                    in[0] * in[3]);
  output[4] =      in[2] * in[2] +
               4 * in[1] * in[3] +
               2 * in[0] * in[4];
  output[5] =  2 * (in[2] * in[3] +
                    in[1] * in[4] +
                    in[0] * in[5]);
  output[6] =  2 * (in[3] * in[3] +
                    in[2] * in[4] +
                    in[0] * in[6] +
                2 * in[1] * in[5]);
  output[7] =  2 * (in[3] * in[4] +
                    in[2] * in[5] +
                    in[1] * in[6] +
                    in[0] * in[7]);
  output[8] =      in[4] * in[4] +
               2 * (in[2] * in[6] +
                    in[0] * in[8] +
                2 * (in[1] * in[7] +
                     in[3] * in[5]));
  output[9] =  2 * (in[4] * in[5] +
                    in[3] * in[6] +
                    in[2] * in[7] +
                    in[1] * in[8] +
                    in[0] * in[9]);
  output[10] = 2 * (in[5] * in[5] +
                   in[4] * in[6] +
                   in[2] * in[8] +
                2 * (in[3] * in[7] +
                     in[1] * in[9]));
  output[11] = 2 * (in[5] * in[6] +
                    in[4] * in[7] +
                    in[3] * in[8] +
                    in[2] * in[9]);
  output[12] =     in[6] * in[6] +
               2 * (in[4] * in[8] +
                2 * (in[5] * in[7] +
                     in[3] * in[9]));
  output[13] = 2 * (in[6] * in[7] +
                    in[5] * in[8] +
                    in[4] * in[9]);
  output[14] = 2 * (in[7] * in[7] +
                    in[6] * in[8] +
                2 * in[5] * in[9]);
  output[15] = 2 * (in[7] * in[8] +
                    in[6] * in[9]);
  output[16] =     in[8] * in[8] +
               4 * in[7] * in[9];
  output[17] = 2 * in[8] * in[9];
  output[18] = 2 * in[9] * in[9];
}

static void
fsquare(felem *output, const felem *in) {
  felem t[19];
  fsquare_inner(t, in);
  freduce_degree(t);
  freduce_coefficients(t);
  memcpy(output, t, sizeof(felem) * 10);
}

/* Take a little-endian, 32-byte number and expand it into polynomial form */
static void
fexpand(felem *output, const u8 *input) {
#define F(n,start,shift,mask) \
  output[n] = ((((felem) input[start + 0]) | \
                ((felem) input[start + 1]) << 8 | \
                ((felem) input[start + 2]) << 16 | \
                ((felem) input[start + 3]) << 24) >> shift) & mask;
  F(0, 0, 0, 0x3ffffff);
  F(1, 3, 2, 0x1ffffff);
  F(2, 6, 3, 0x3ffffff);
  F(3, 9, 5, 0x1ffffff);
  F(4, 12, 6, 0x3ffffff);
  F(5, 16, 0, 0x1ffffff);
  F(6, 19, 1, 0x3ffffff);
  F(7, 22, 3, 0x1ffffff);
  F(8, 25, 4, 0x3ffffff);
  F(9, 28, 6, 0x1ffffff);
#undef F
}

/* Take a fully reduced polynomial form number and contract it into a
 * little-endian, 32-byte array
 */
static void
fcontract(u8 *output, felem *input) {
  int i;

  do {
    for (i = 0; i < 9; ++i) {
      if ((i & 1) == 1) {
        while (input[i] < 0) {
          input[i] += 0x2000000;
          input[i + 1]--;
        }
      } else {
        while (input[i] < 0) {
          input[i] += 0x4000000;
          input[i + 1]--;
        }
      }
    }
    while (input[9] < 0) {
      input[9] += 0x2000000;
      input[0] -= 19;
    }
  } while (input[0] < 0);

  input[1] <<= 2;
  input[2] <<= 3;
  input[3] <<= 5;
  input[4] <<= 6;
  input[6] <<= 1;
  input[7] <<= 3;
  input[8] <<= 4;
  input[9] <<= 6;
#define F(i, s) \
  output[s+0] |=  input[i] & 0xff; \
  output[s+1]  = (input[i] >> 8) & 0xff; \
  output[s+2]  = (input[i] >> 16) & 0xff; \
  output[s+3]  = (input[i] >> 24) & 0xff;
  output[0] = 0;
  output[16] = 0;
  F(0,0);
  F(1,3);
  F(2,6);
  F(3,9);
  F(4,12);
  F(5,16);
  F(6,19);
  F(7,22);
  F(8,25);
  F(9,28);
#undef F
}

/* Input: Q, Q', Q-Q'
 * Output: 2Q, Q+Q'
 *
 *   x2 z3: long form
 *   x3 z3: long form
 *   x z: short form, destroyed
 *   xprime zprime: short form, destroyed
 *   qmqp: short form, preserved
 */
static void fmonty(felem *x2, felem *z2,  /* output 2Q */
                   felem *x3, felem *z3,  /* output Q + Q' */
                   felem *x, felem *z,    /* input Q */
                   felem *xprime, felem *zprime,  /* input Q' */
                   const felem *qmqp /* input Q - Q' */) {
  felem origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
        zzprime[19], zzzprime[19], xxxprime[19];

  memcpy(origx, x, 10 * sizeof(felem));
  fsum(x, z);
  fdifference(z, origx);  // does x - z

  memcpy(origxprime, xprime, sizeof(felem) * 10);
  fsum(xprime, zprime);
  fdifference(zprime, origxprime);
  fproduct(xxprime, xprime, z);
  fproduct(zzprime, x, zprime);
  freduce_degree(xxprime);
  freduce_coefficients(xxprime);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  memcpy(origxprime, xxprime, sizeof(felem) * 10);
  fsum(xxprime, zzprime);
  fdifference(zzprime, origxprime);
  fsquare(xxxprime, xxprime);
  fsquare(zzzprime, zzprime);
  fproduct(zzprime, zzzprime, qmqp);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  memcpy(x3, xxxprime, sizeof(felem) * 10);
  memcpy(z3, zzprime, sizeof(felem) * 10);

  fsquare(xx, x);
  fsquare(zz, z);
  fproduct(x2, xx, zz);
  freduce_degree(x2);
  freduce_coefficients(x2);
  fdifference(zz, xx);  // does zz = xx - zz
  memset(zzz + 10, 0, sizeof(felem) * 9);
  fscalar_product(zzz, zz, 121665);
  freduce_degree(zzz);
  freduce_coefficients(zzz);
  fsum(zzz, xx);
  fproduct(z2, zz, zzz);
  freduce_degree(z2);
  freduce_coefficients(z2);
}

/* Calculates nQ where Q is the x-coordinate of a point on the curve
 *
 *   resultx/resultz: the x coordinate of the resulting curve point (short form)
 *   n: a little endian, 32-byte number
 *   q: a point of the curve (short form)
 */
static void
cmult(felem *resultx, felem *resultz, const u8 *n, const felem *q) {
  felem a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
  felem *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
  felem e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
  felem *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;

  unsigned i, j;

  memcpy(nqpqx, q, sizeof(felem) * 10);

  for (i = 0; i < 32; ++i) {
    u8 byte = n[31 - i];
    for (j = 0; j < 8; ++j) {
      if (byte & 0x80) {
        fmonty(nqpqx2, nqpqz2,
               nqx2, nqz2,
               nqpqx, nqpqz,
               nqx, nqz,
               q);
      } else {
        fmonty(nqx2, nqz2,
               nqpqx2, nqpqz2,
               nqx, nqz,
               nqpqx, nqpqz,
               q);
      }

      t = nqx;
      nqx = nqx2;
      nqx2 = t;
      t = nqz;
      nqz = nqz2;
      nqz2 = t;
      t = nqpqx;
      nqpqx = nqpqx2;
      nqpqx2 = t;
      t = nqpqz;
      nqpqz = nqpqz2;
      nqpqz2 = t;

      byte <<= 1;
    }
  }

  memcpy(resultx, nqx, sizeof(felem) * 10);
  memcpy(resultz, nqz, sizeof(felem) * 10);
}

// -----------------------------------------------------------------------------
// Shamelessly copied from djb's code
// -----------------------------------------------------------------------------
static void
crecip(felem *out, const felem *z) {
  felem z2[10];
  felem z9[10];
  felem z11[10];
  felem z2_5_0[10];
  felem z2_10_0[10];
  felem z2_20_0[10];
  felem z2_50_0[10];
  felem z2_100_0[10];
  felem t0[10];
  felem t1[10];
  int i;

  /* 2 */ fsquare(z2,z);
  /* 4 */ fsquare(t1,z2);
  /* 8 */ fsquare(t0,t1);
  /* 9 */ fmul(z9,t0,z);
  /* 11 */ fmul(z11,z9,z2);
  /* 22 */ fsquare(t0,z11);
  /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);

  /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
  /* 2^7 - 2^2 */ fsquare(t1,t0);
  /* 2^8 - 2^3 */ fsquare(t0,t1);
  /* 2^9 - 2^4 */ fsquare(t1,t0);
  /* 2^10 - 2^5 */ fsquare(t0,t1);
  /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);

  /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
  /* 2^12 - 2^2 */ fsquare(t1,t0);
  /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
  /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);

  /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
  /* 2^22 - 2^2 */ fsquare(t1,t0);
  /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
  /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);

  /* 2^41 - 2^1 */ fsquare(t1,t0);
  /* 2^42 - 2^2 */ fsquare(t0,t1);
  /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
  /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);

  /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
  /* 2^52 - 2^2 */ fsquare(t1,t0);
  /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
  /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);

  /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
  /* 2^102 - 2^2 */ fsquare(t0,t1);
  /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
  /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);

  /* 2^201 - 2^1 */ fsquare(t0,t1);
  /* 2^202 - 2^2 */ fsquare(t1,t0);
  /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
  /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);

  /* 2^251 - 2^1 */ fsquare(t1,t0);
  /* 2^252 - 2^2 */ fsquare(t0,t1);
  /* 2^253 - 2^3 */ fsquare(t1,t0);
  /* 2^254 - 2^4 */ fsquare(t0,t1);
  /* 2^255 - 2^5 */ fsquare(t1,t0);
  /* 2^255 - 21 */ fmul(out,t1,z11);
}

int
curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
  felem bp[10], x[10], z[10], zmone[10];
  uint8_t e[32];
  int i;

  for (i = 0; i < 32; ++i) e[i] = secret[i];
  e[0] &= 248;
  e[31] &= 127;
  e[31] |= 64;

  fexpand(bp, basepoint);
  cmult(x, z, e, bp);
  crecip(zmone, z);
  fmul(z, x, zmone);
  fcontract(mypublic, z);
  return 0;
}

Re: broken c port of Ec25519 key exchange

Posted: Sat Feb 20, 2010 10:12 am
by Olliv

Code: Select all

// -----------------------------------------------------------------------------
// Shamelessly copied from djb's code
// -----------------------------------------------------------------------------
I have only one answer : 20 years is the duration I would need to understand totally this code.

I would start trying to send a mail to Dan Julius Bernstein. The first day in the first year, it's what I would do if I was interested...

Ollivier

Re: broken c port of Ec25519 key exchange

Posted: Sat Feb 20, 2010 5:04 pm
by Joakim Christiansen

Code: Select all

PokeQ(*out+64, PeekQ(*im+32) * PeekQ(*in+32) + 2 * (PeekQ(*im+24) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+0));
That is some sexy code! :D
Can't help you though, sorry...

Re: broken c port of Ec25519 key exchange

Posted: Sat Feb 20, 2010 8:35 pm
by idle
Joakim Christiansen wrote:

Code: Select all

PokeQ(*out+64, PeekQ(*im+32) * PeekQ(*in+32) + 2 * (PeekQ(*im+24) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+0));
That is some sexy code! :D
Can't help you though, sorry...
Sexy in a masochistic way :lol:

It's eventually going to be bunged into a network lib replacing the current DH which has the issue of generating suitably sized primes. So I'll spend another half day going cross eyed I guess

cheers

Re: broken c port of Ec25519 key exchange

Posted: Sun Feb 21, 2010 1:23 pm
by Fred
IMHO, the best idea is to compile your C program into a static lib and import it from PB.

Re: broken c port of Ec25519 key exchange

Posted: Sun Feb 21, 2010 5:54 pm
by djes
fsum seems broken, and in fcontract there's a pre incrementation of i (++i)

Re: broken c port of Ec25519 key exchange

Posted: Sun Feb 21, 2010 8:20 pm
by idle
javabean has already built a static lib but there's an issue with his lib where it's corrupting the stack if you call it from a procedure.
I built a dll version and that was fine but I wanted to provide it as source for the project so it's easier to share and maintain.

I had noticed the prefix iterators, though I don't think that has any effect on the bounds

Code: Select all

  for(int i=0;i<10;++i)
    {   
	printf("val of i : %lu :\n",i);
    }

     //value of i in loop is 0,1,2,3..9


thanks I will have a look at the fsum.

Re: broken c port of Ec25519 key exchange

Posted: Sun Feb 21, 2010 10:42 pm
by Olliv
Normally, in the addition of two huge numbers (I am sure there is a subject about huge numbers), there is a carry...

Code: Select all

Macro DWAdd(Offset, VarOut, VarIn)
!  MOV    eax, dword [v_#VarIn + Offset]
!  ADC    dword [v_#VarOut + Offset], eax ; ADdition with Carry
EndMacro

Macro FSum(VarOut, VarIn)
! CLC
DWAdd(0, VarOut, VarIn)
DWAdd(4, VarOut, VarIn)
DWAdd(8, VarOut, VarIn)
DWAdd(12, VarOut, VarIn)
DWAdd(16, VarOut, VarIn)
DWAdd(20, VarOut, VarIn)
DWAdd(24, VarOut, VarIn)
DWAdd(28, VarOut, VarIn)
DWAdd(32, VarOut, VarIn)
DWAdd(36, VarOut, VarIn)
DWAdd(40, VarOut, VarIn)
DWAdd(44, VarOut, VarIn)
DWAdd(48, VarOut, VarIn)
DWAdd(52, VarOut, VarIn)
DWAdd(56, VarOut, VarIn)
DWAdd(60, VarOut, VarIn)
DWAdd(64, VarOut, VarIn)
DWAdd(68, VarOut, VarIn)
DWAdd(72, VarOut, VarIn)
DWAdd(76, VarOut, VarIn)
EndMacro

; Test
Structure FElem
  Q.Q[10]
EndStructure
Define.FElem Q1, Q2
Q1\Q[8] = $8000000000000000 ; Set the bit #575 in Q1
Q2\Q[8] = $8000000000000000 ; Set the bit #575 in Q2
FSum(Q1, Q2)
Debug Q1\Q[9] ; Return the bit #576 set, exactly as %1 + %1 = %10

Re: broken c port of Ec25519 key exchange

Posted: Thu Mar 21, 2013 11:48 pm
by PeterH
Insanely hard to do without PB but finally I'm sure where the problem is and I sent it to a friend who verified it to be working. Unfortunately it cannot be used to securely sign stuff for validation, so I'm still waiting for a working (in acceptable speed) 2048+ bit RSA before buying PB. Enjoy the working Curve25519-Donna anyway:

The FC macro had two lines that should've been outside the macro (before the macro was invoked) nulling the 1st and 17th byte of *out.

Code: Select all

Macro comment()
; /* Copyright 2008, Google Inc.
;  * All rights reserved.
;  *
;  * Redistribution And use in source And binary forms, With Or without
;  * modification, are permitted provided that the following conditions are
;  * met:
;  *
;  *     * Redistributions of source code must retain the above copyright
;  * notice, this List of conditions And the following disclaimer.
;  *     * Redistributions in binary form must reproduce the above
;  * copyright notice, this List of conditions And the following disclaimer
;  * in the documentation And/Or other materials provided With the
;  * distribution.
;  *     * Neither the name of Google Inc. nor the names of its
;  * contributors may be used To endorse Or promote products derived from
;  * this software without specific prior written permission.
;  *
;  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS And CONTRIBUTORS
;  * "AS IS" And ANY EXPRESS Or IMPLIED WARRANTIES, INCLUDING, BUT Not
;  * LIMITED To, THE IMPLIED WARRANTIES OF MERCHANTABILITY And FITNESS For
;  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;  * OWNER Or CONTRIBUTORS BE LIABLE For ANY DIRECT, INDIRECT, INCIDENTAL,
;  * SPECIAL, EXEMPLARY, Or CONSEQUENTIAL DAMAGES (INCLUDING, BUT Not
;  * LIMITED To, PROCUREMENT OF SUBSTITUTE GOODS Or SERVICES; LOSS OF USE,
;  * Data, Or PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, Or TORT
;  * (INCLUDING NEGLIGENCE Or OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;  * OF THIS SOFTWARE, EVEN If ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;  *
;  * curve25519-donna: Curve25519 elliptic curve, public key function
;  *
;  * http://code.google.com/p/curve25519-donna/
;  *
;  * Adam Langley <agl@imperialviolet.org>
;  *
;  * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.To>
;  *
;  * More information about curve25519 can be found here
;  *   http://cr.yp.To/ecdh.html
;  *
;  * djb's sample implementation of curve25519 is written in a special assembly
;  * language called qhasm And uses the floating point registers.
;  *
;  * This is, almost, a clean room reimplementation from the curve25519 paper. It
;  * uses many of the tricks described therein. Only the crecip function is taken
;  * from the sample implementation.
;  */
EndMacro

;EnableExplicit

Global *tA = AllocateMemory(19*8)
Global *tB = AllocateMemory(19*8)
Global over.q,over2.q  

Global *mysecret = AllocateMemory(32)
Global *mypublic = AllocateMemory(32)
Global *basepoint = AllocateMemory(32)
Global *hissecret = AllocateMemory(32)
Global *hispublic = AllocateMemory(32)
Global *myshared = AllocateMemory(32)
Global *hisshared = AllocateMemory(32)

Procedure dB(*mem,op.s)
  Protected len,st.s
  len = MemorySize(*mem)
  st = op + "   "
  For a = 0 To len-1 
   st+RSet(Hex(PeekA(*mem+a),#PB_Byte),2,"0")
  Next 
  Debug str$  
EndProcedure

Macro fsum(out,in)
 i=0
 While i < 80 
    ii=i+8
    PokeQ(out+i,(PeekQ(out+i) + PeekQ(in+i)))
    PokeQ(out+ii,(PeekQ(out+ii) + PeekQ(in+ii)))
    i+16
 Wend
 ;db(*out,"Sum")
EndMacro

Macro fdifference(out,in)
  i=0
  While i < 80
    PokeQ(out+i,(PeekQ(in+i) - PeekQ(out+i)));
    i+8
  Wend 
  ;db(*out,"difference")
EndMacro

Macro fscalar_product(out,in,scalar)
  
  i=0
  While i < 80 
    PokeQ(out+i,(PeekQ(in+i) * scalar))
    i+8
  Wend 
  ;db(*out,"scallar") 
EndMacro

Macro fproduct(out,im,in)
                          
  PokeQ(*out+0, PeekQ(*im+0) * PeekQ(*in+0));
  PokeQ(*out+8, PeekQ(*im+0) * PeekQ(*in+8) + PeekQ(*im+8) * PeekQ(*in+0));
  PokeQ(*out+16, 2 * PeekQ(*im+8) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+16) + PeekQ(*im+16) * PeekQ(*in+0));
  PokeQ(*out+24, PeekQ(*im+8) * PeekQ(*in+16) + PeekQ(*im+16) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+0));
  PokeQ(*out+32, PeekQ(*im+16) * PeekQ(*in+16) + 2 * (PeekQ(*im+8) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+8)) + PeekQ(*im+0) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+0));
  PokeQ(*out+40, PeekQ(*im+16) * PeekQ(*in+24) + PeekQ(*im+24) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+0));
  PokeQ(*out+48, 2 * (PeekQ(*im+24) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+0));
  PokeQ(*out+56, PeekQ(*im+24) * PeekQ(*in+32) + PeekQ(*im+32) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+0));
  PokeQ(*out+64, PeekQ(*im+32) * PeekQ(*in+32) + 2 * (PeekQ(*im+24) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+0));
  PokeQ(*out+72, PeekQ(*im+32) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+32) + PeekQ(*im+24) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+16) + PeekQ(*im+8) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+8) + PeekQ(*im+0) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+0));
  PokeQ(*out+80, 2 * (PeekQ(*im+40) * PeekQ(*in+40) + PeekQ(*im+24) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+8)) + PeekQ(*im+32) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+32) + PeekQ(*im+16) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+16));
  PokeQ(*out+88, PeekQ(*im+40) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+40) + PeekQ(*im+32) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+32) + PeekQ(*im+24) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+24) + PeekQ(*im+16) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+16));
  PokeQ(*out+96, PeekQ(*im+48) * PeekQ(*in+48) + 2 * (PeekQ(*im+40) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+40) + PeekQ(*im+24) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+24)) + PeekQ(*im+32) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+32));
  PokeQ(*out+104, PeekQ(*im+48) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+48) + PeekQ(*im+40) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+40) + PeekQ(*im+32) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+32));
  PokeQ(*out+112, 2 * (PeekQ(*im+56) * PeekQ(*in+56) + PeekQ(*im+40) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+40)) + PeekQ(*im+48) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+48));
  PokeQ(*out+120, PeekQ(*im+56) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+56) + PeekQ(*im+48) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+48));
  PokeQ(*out+128, PeekQ(*im+64) * PeekQ(*in+64) + 2 * (PeekQ(*im+56) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+56)));
  PokeQ(*out+136, PeekQ(*im+64) * PeekQ(*in+72) + PeekQ(*im+72) * PeekQ(*in+64));
  PokeQ(*out+144, 2 * PeekQ(*im+72) * PeekQ(*in+72));
  ;db(*out,"product")

EndMacro

Macro freduce_degree(out)
     
  PokeQ(*out+64,PeekQ(*out+64) + (19 * PeekQ(*out+144)));
  PokeQ(*out+56,PeekQ(*out+56) + (19 * PeekQ(*out+136)));
  PokeQ(*out+48,PeekQ(*out+48) + (19 * PeekQ(*out+128)));
  PokeQ(*out+40,PeekQ(*out+40) + (19 * PeekQ(*out+120)));
  PokeQ(*out+32,PeekQ(*out+32) + (19 * PeekQ(*out+112)));
  PokeQ(*out+24,PeekQ(*out+24) + (19 * PeekQ(*out+104)));
  PokeQ(*out+16,PeekQ(*out+16) + (19 * PeekQ(*out+96)));
  PokeQ(*out+8,PeekQ(*out+8) + (19 * PeekQ(*out+88)));
  PokeQ(*out+0,PeekQ(*out+0) + (19 * PeekQ(*out+80)));
  ;db(out,"degree")
EndMacro

Macro freduce_coefficients(out)
  
  Repeat 
    
    PokeQ(*out+80,0);
    i=0
    While i < 80 ;Step 2
      over = PeekQ(*out+i) / $2000000;
      over2 = (over + ((over >> 63) * 2) + 1) / 2;
      PokeQ(*out+i+8,((PeekQ(*out+i+8)) + over2));
      PokeQ(*out+i,((PeekQ(*out+i)) - (over2 * $4000000)))

      over = (PeekQ(*out+i+8)) / $2000000;
      PokeQ(*out+i+16,(PeekQ(*out+i+16) + over));
      PokeQ(*out+i+8,(PeekQ(*out+i+8)) - (over * $2000000));
      i+16
    
    Wend
    
    PokeQ(*out+0,((PeekQ(*out+0)) + (19 * (PeekQ(*out+80)))));
   
  
  Until Not PeekQ(*out+80) ;
  
  ;db(*out,"Coeff")
EndMacro
 
Macro fsquare_inner(out,in)
  
  PokeQ(*out+0, PeekQ(*in+0) * PeekQ(*in+0));
  PokeQ(*out+8, 2 * PeekQ(*in+0) * PeekQ(*in+8));
  PokeQ(*out+16, 2 * (PeekQ(*in+8) * PeekQ(*in+8) + PeekQ(*in+0) * PeekQ(*in+16)));
  PokeQ(*out+24, 2 * (PeekQ(*in+8) * PeekQ(*in+16) + PeekQ(*in+0) * PeekQ(*in+24)));
  PokeQ(*out+32, PeekQ(*in+16) * PeekQ(*in+16) + 4 * PeekQ(*in+8) * PeekQ(*in+24) + 2 * PeekQ(*in+0) * PeekQ(*in+32));
  PokeQ(*out+40, 2 * (PeekQ(*in+16) * PeekQ(*in+24) + PeekQ(*in+8) * PeekQ(*in+32) + PeekQ(*in+0) * PeekQ(*in+40)));
  PokeQ(*out+48, 2 * (PeekQ(*in+24) * PeekQ(*in+24) + PeekQ(*in+16) * PeekQ(*in+32) + PeekQ(*in+0) * PeekQ(*in+48) + 2 * PeekQ(*in+8) * PeekQ(*in+40)));
  PokeQ(*out+56, 2 * (PeekQ(*in+24) * PeekQ(*in+32) + PeekQ(*in+16) * PeekQ(*in+40) + PeekQ(*in+8) * PeekQ(*in+48) + PeekQ(*in+0) * PeekQ(*in+56)));
  PokeQ(*out+64, PeekQ(*in+32) * PeekQ(*in+32) + 2 * (PeekQ(*in+16) * PeekQ(*in+48) + PeekQ(*in+0) * PeekQ(*in+64) + 2 * (PeekQ(*in+8) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+40))));
  PokeQ(*out+72, 2 * (PeekQ(*in+32) * PeekQ(*in+40) + PeekQ(*in+24) * PeekQ(*in+48) + PeekQ(*in+16) * PeekQ(*in+56) + PeekQ(*in+8) * PeekQ(*in+64) + PeekQ(*in+0) * PeekQ(*in+72)));
  PokeQ(*out+80, 2 * (PeekQ(*in+40) * PeekQ(*in+40) + PeekQ(*in+32) * PeekQ(*in+48) + PeekQ(*in+16) * PeekQ(*in+64) + 2 * (PeekQ(*in+24) * PeekQ(*in+56) + PeekQ(*in+8) * PeekQ(*in+72))));
  PokeQ(*out+88, 2 * (PeekQ(*in+40) * PeekQ(*in+48) + PeekQ(*in+32) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+64) + PeekQ(*in+16) * PeekQ(*in+72)));
  PokeQ(*out+96, PeekQ(*in+48) * PeekQ(*in+48) + 2 * (PeekQ(*in+32) * PeekQ(*in+64) + 2 * (PeekQ(*in+40) * PeekQ(*in+56) + PeekQ(*in+24) * PeekQ(*in+72))));
  PokeQ(*out+104, 2 * (PeekQ(*in+48) * PeekQ(*in+56) + PeekQ(*in+40) * PeekQ(*in+64) + PeekQ(*in+32) * PeekQ(*in+72)));
  PokeQ(*out+112, 2 * (PeekQ(*in+56) * PeekQ(*in+56) + PeekQ(*in+48) * PeekQ(*in+64) + 2 * PeekQ(*in+40) * PeekQ(*in+72)));
  PokeQ(*out+120, 2 * (PeekQ(*in+56) * PeekQ(*in+64) + PeekQ(*in+48) * PeekQ(*in+72)));
  PokeQ(*out+128, PeekQ(*in+64) * PeekQ(*in+64) + 4 * PeekQ(*in+56) * PeekQ(*in+72));
  PokeQ(*out+136, 2 * PeekQ(*in+64) * PeekQ(*in+72));
  PokeQ(*out+144, 2 * PeekQ(*in+72) * PeekQ(*in+72));
  ;db(*out,"square inner")
EndMacro 

Macro fexpand(out,in) ;(quad,byte)
    
  PokeQ(out+0,(((PeekA(in+0)) | (PeekA(in+1)) << 8 | (PeekA(in+2)) << 16 | (PeekA(in+3)) << 24)) & $3ffffff);
  PokeQ(out+8,(((PeekA(in+3+0)) | (PeekA(in+3+1)) << 8 | (PeekA(in+3+2)) << 16 | (PeekA(in+3+3)) << 24) >> 2) & $1ffffff);
  PokeQ(out+16,(((PeekA(in+6+0)) | (PeekA(in+6+1)) << 8 | (PeekA(in+6+2)) << 16 | (PeekA(in+6+3)) << 24) >> 3) & $3ffffff);
  PokeQ(out+24,(((PeekA(in+9+0)) | (PeekA(in+9+1)) << 8 | (PeekA(in+9+2)) << 16 | (PeekA(in+9+3)) << 24) >> 5) & $1ffffff);
  PokeQ(out+32,(((PeekA(in+12+0)) | (PeekA(in+12+1)) << 8 | (PeekA(in+12+2)) << 16 | (PeekA(in+12+3)) << 24) >> 6) & $3ffffff);
  PokeQ(out+40,(((PeekA(in+16+0)) | (PeekA(in+16+1)) << 8 | (PeekA(in+16+2)) << 16 | (PeekA(in+16+3)) << 24)) & $1ffffff);
  PokeQ(out+48,(((PeekA(in+19+0)) | (PeekA(in+19+1)) << 8 | (PeekA(in+19+2)) << 16 | (PeekA(in+19+3)) << 24) >> 1) & $3ffffff);
  PokeQ(out+56,(((PeekA(in+22+0)) | (PeekA(in+22+1)) << 8 | (PeekA(in+22+2)) << 16 | (PeekA(in+22+3)) << 24) >> 3) & $1ffffff);
  PokeQ(out+64,(((PeekA(in+25+0)) | (PeekA(in+25+1)) << 8 | (PeekA(in+25+2)) << 16 | (PeekA(in+25+3)) << 24) >> 4) & $3ffffff);
  PokeQ(out+72,(((PeekA(in+28+0)) | (PeekA(in+28+1)) << 8 | (PeekA(in+28+2)) << 16 | (PeekA(in+28+3)) << 24) >> 6) & $1ffffff);
  
  ;db(*out,"Expand")
EndMacro

Macro FC(out,in,i,s)
    PokeA(out+s+0,(PeekA(out+s+0) | PeekQ(in+(i*8))) & $ff);
    PokeA(out+s+1,(PeekQ(in+(i*8)) >> 8) & $ff); \
    PokeA(out+s+2,(PeekQ(in+(i*8)) >> 16) & $ff); \
    PokeA(out+s+3,(PeekQ(in+(i*8)) >> 24) & $ff);
;    PokeA(out+0,0)   ;Let's move these two to line 275
;    PokeA(out+16,0)
    ;db(*out,"FC")
EndMacro

Procedure fsquare(*out,*in)
  Protected i.i
  fsquare_inner(tB, in);
  freduce_degree(tB);
  freduce_coefficients(tB);
  CopyMemory(*tB,*out,80);
  FillMemory(*tb,19*8,0)
  db(*out,"Square")

EndProcedure

Procedure fmul(*out,*in,*in2)
  Protected i.i
  fproduct(tA,in,in2);
  freduce_degree(tA);
  freduce_coefficients(tA);
  CopyMemory(*tA,*out,80);
  FillMemory(*TA,19*8,0)
  ;db(*out,"mul")
EndProcedure

Procedure fcontract(*out,*in) 
  Protected a,i
  Repeat
    For a = 0 To 8 
      If (a & 1)  
       While PeekQ(*in+i) < 0
           PokeQ(*in+i,PeekQ(*in+i) + $2000000);
           PokeQ(*in+i+8,PeekQ(*in+i+8)-1);
        Wend
      Else 
        While PeekQ(*in+i) < 0  
          PokeQ(*in+i,PeekQ(*in+i) + $4000000);
          PokeQ(*in+i+8,PeekQ(*in+i+8)-1);
        Wend
      EndIf
      i+8
    Next
    While PeekQ(*in+72) < 0
      PokeQ(*in+72,PeekQ(*in+72) + $2000000);
      PokeQ(*in+0,PeekQ(*in+0) - 19);
    Wend
    Debug PeekQ(*in+0)
  Until PeekQ(*in+0) > 0;

  PokeQ(*in+8,PeekQ(*in+8) << 2);
  PokeQ(*in+16,PeekQ(*in+16) << 3);
  PokeQ(*in+24,PeekQ(*in+24) << 5);
  PokeQ(*in+32,PeekQ(*in+32) << 6);
  PokeQ(*in+48,PeekQ(*in+48) << 1);
  PokeQ(*in+56,PeekQ(*in+56) << 3);
  PokeQ(*in+64,PeekQ(*in+64) << 4);
  PokeQ(*in+72,PeekQ(*in+72) << 6);
  
  PokeA(*out+0,0);
  PokeA(*out+16,0);   
  FC(*out,*in,0,0);
  FC(*out,*in,1,3);
  FC(*out,*in,2,6);
  FC(*out,*in,3,9);
  FC(*out,*in,4,12);
  FC(*out,*in,5,16);
  FC(*out,*in,6,19);
  FC(*out,*in,7,22);
  FC(*out,*in,8,25);
  FC(*out,*in,9,28);
  
  db(*out,"Contract")
  
EndProcedure

Procedure fmonty(*x2,*z2,*x3,*z3,*x,*z,*xprime,*zprime,*qmqp)
  
  Protected *origx = AllocateMemory(80)
  Protected *origxprime = AllocateMemory(80)
  Protected *zzz = AllocateMemory(8*19)
  Protected *xx = AllocateMemory(8*19)
  Protected *zz = AllocateMemory(8*19)
  Protected *xxprime = AllocateMemory(8*19)
  Protected *zzprime = AllocateMemory(8*19)
  Protected *zzzprime = AllocateMemory(8*19)
  Protected *xxxprime = AllocateMemory(8*19);
  Protected i,ii
   
  CopyMemory(*x,*origx,80) ;10 * SizeOf(felem));
  fsum(*x,*z);
  fdifference(*z,*origx);  // does x - z

  CopyMemory(*xprime,*origxprime,80); xprime, SizeOf(felem) * 10);
  fsum(*xprime, *zprime);
  fdifference(*zprime, *origxprime);
  fproduct(xxprime, xprime, z);
  fproduct(zzprime, x, zprime);
  freduce_degree(xxprime);
  freduce_coefficients(xxprime);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  CopyMemory(*xxprime,*origxprime,80); xxprime, SizeOf(felem) * 10);
  fsum(*xxprime, *zzprime);
  fdifference(*zzprime, *origxprime);
  fsquare(*xxxprime,*xxprime);
  fsquare(*zzzprime,*zzprime);
  fproduct(zzprime,zzzprime,qmqp);
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  CopyMemory(*xxxprime,*x3,80); xxxprime, SizeOf(felem) * 10);
  CopyMemory(*zzprime,*z3,80); zzprime, SizeOf(felem) * 10);

  fsquare(*xx,*x);
  fsquare(*zz,*z);
  fproduct(x2,xx,zz);
  freduce_degree(x2);
  freduce_coefficients(x2);
  fdifference(*zz,*xx);  // does zz = xx - zz
  FillMemory(*zzz+80,72,0)
  Protected scal.q = 121665
  fscalar_product(*zzz,*zz,scal);
  freduce_degree(zzz);
  freduce_coefficients(zzz);
  fsum(*zzz,*xx);
  fproduct(z2,zz,zzz);
  freduce_degree(z2);
  freduce_coefficients(z2);
  
  FreeMemory(*origx) 
  FreeMemory(*origxprime) 
  FreeMemory(*zzz)  
  FreeMemory(*xx)  
  FreeMemory(*zz)  
  FreeMemory(*xxprime)  
  FreeMemory(*zzprime) 
  FreeMemory(*zzzprime)  
  FreeMemory(*xxxprime)  
  
;   db(*x2,"fmonty x2")
;   db(*z2,"fmonty z2")  
 EndProcedure

Procedure cmult(*resultx,*resultz,*n,*q)
  
  Protected *a,*b,*c,*d,*e,*f,*g,*h,*t
  Protected *nqpqx,*nqpqz,*nqx,*nqz
  Protected *nqpqx2,*nqpqz2,*nqx2,*nqz2
  Protected byte.i,i,j
  
  *a = AllocateMemory(8*19)
  *b = AllocateMemory(8*19)
  *c = AllocateMemory(8*19)
  *d = AllocateMemory(8*19)
  
  PokeQ(*b,1) : PokeQ(*c,1)  
  *nqpqx = *a : *nqpqz = *b : *nqx = *c : *nqz =*d;
  
  *a = AllocateMemory(8*19)
  *b = AllocateMemory(8*19)
  *c = AllocateMemory(8*19)
  *d = AllocateMemory(8*19)  
  *e = AllocateMemory(8*19)
  *f = AllocateMemory(8*19)
  *g = AllocateMemory(8*19)
  *h = AllocateMemory(8*19)
  
  PokeQ(*f,1) : PokeQ(*h,1) 
  *nqpqx2 = *e : *nqpqz2 = *f : *nqx2 = *g : *nqz2 = *h;
  
  
  CopyMemory(*q,*nqpqx,80)
  
  db(*nqpqx,"nqpqx")
  
  For i = 0 To 31
    byte = PeekA(*n+(31-i)) & $FF
    For j = 0 To 7 
      If (byte & $80) 
        fmonty(*nqpqx2,*nqpqz2,*nqx2,*nqz2,*nqpqx,*nqpqz,*nqx,*nqz,*q);
      Else 
        fmonty(*nqx2,*nqz2,*nqpqx2,*nqpqz2,*nqx,*nqz,*nqpqx,*nqpqz,*q);
      EndIf

      *t = *nqx;
      *nqx = *nqx2;
      *nqx2 = *t;
      *t = *nqz;
      *nqz = *nqz2;
      *nqz2 = *t;
      *t = *nqpqx;
      *nqpqx = *nqpqx2;
      *nqpqx2 = *t;
      *t = *nqpqz;
      *nqpqz = *nqpqz2;
      *nqpqz2 = *t;
    
      byte << 1;
    
    Next
  Next 

  CopyMemory(*nqx,*resultx,80)
  CopyMemory(*nqz,*resultz,80)
  
  FreeMemory(*a)
  FreeMemory(*b)
  FreeMemory(*c)
  FreeMemory(*d)
  FreeMemory(*e)
  FreeMemory(*f)
  FreeMemory(*g)
  
  db(*resultx,"cmult result x")
  db(*resultx,"cmult result z")
  
EndProcedure

;// -----------------------------------------------------------------------------
;// Shamelessly copied from djb's code
;// -----------------------------------------------------------------------------
;Static void
Procedure crecip(*out,*z)
  
  Protected *z2,*z9,*z11,*z2_5_0,*z2_10_0,*z2_20_0,*z2_50_0,*z2_100_0,*t0,*t1
  Protected i
  *z2 = AllocateMemory(80);
  *z9 = AllocateMemory(80);
  *z11 = AllocateMemory(80);
  *z2_5_0 = AllocateMemory(80);
  *z2_10_0 = AllocateMemory(80);
  *z2_20_0 = AllocateMemory(80);
  *z2_50_0 = AllocateMemory(80);
  *z2_100_0 = AllocateMemory(80);
  *t0 = AllocateMemory(80);
  *t1 = AllocateMemory(80);
  
  fsquare(*z2,*z);
  fsquare(*t1,*z2);
  fsquare(*t0,*t1);
  fmul(*z9,*t0,*z);
  fmul(*z11,*z9,*z2);
  fsquare(*t0,*z11);
  fmul(*z2_5_0,*t0,*z9);

  fsquare(*t0,*z2_5_0);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fmul(*z2_10_0,*t0,*z2_5_0);

  fsquare(*t0,*z2_10_0);
  fsquare(*t1,*t0);
  i=2
  While i < 10 
     fsquare(*t0,*t1);
     fsquare(*t1,*t0); 
     i+2
  Wend
  
  
  fmul(*z2_20_0,*t1,*z2_10_0);
  fsquare(*t0,*z2_20_0);
  fsquare(*t1,*t0);
  i=2
  While i < 20 ;Step 2 
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2
  Wend    
  
  fmul(*t0,*t1,*z2_20_0);

  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  i=2
  While i < 10 ;Step 2
    fsquare(*t1,*t0)
    fsquare(*t0,*t1)
    i+2
  Wend 
  
  fmul(*z2_50_0,*t0,*z2_10_0);

  fsquare(*t0,*z2_50_0);
  fsquare(*t1,*t0);
  i=2
  While i < 50 ;Step 2 
    fsquare(*t0,*t1)
    fsquare(*t1,*t0)
    i+2
  Wend
  
  fmul(*z2_100_0,*t1,*z2_50_0);

  fsquare(*t1,*z2_100_0);
  fsquare(*t0,*t1);
  i=2
  While i < 100 ;Step 2
    fsquare(*t1,*t0)
    fsquare(*t0,*t1)
    i+2
  Wend 
  
  fmul(*t1,*t0,*z2_100_0);

  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  
  i=2 
  While i < 50
    fsquare(*t0,*t1)
    fsquare(*t1,*t0)
    i+2
  Wend   
  
  fmul(*t0,*t1,*z2_50_0);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fmul(*out,*t1,*z11);
  
  FreeMemory(*z2);
  FreeMemory(*z9) 
  FreeMemory(*z11)
  FreeMemory(*z2_5_0)
  FreeMemory(*z2_10_0)
  FreeMemory(*z2_20_0)
  FreeMemory(*z2_50_0)
  FreeMemory(*z2_100_0)
  FreeMemory(*t0) 
  FreeMemory(*t1) 
  
  db(*out,"Crecip")
  
EndProcedure

Procedure curve(*mypublic.i,*secret.i,*basepoint.i)
   
  Protected *bp,*x,*z,*zmone,*ee,i 
  *bp = AllocateMemory(80)
  *x = AllocateMemory(80)
  *z = AllocateMemory(80)
  *zmone = AllocateMemory(80)
  *ee = AllocateMemory(32);
  i=0
  While i < 32; ++i)
    PokeA(*ee+i,PeekA(*secret+i));
    Debug PeekA(*ee+i)
    i+1
  Wend 
  
  PokeA(*ee+0,(PeekA(*ee+0) & 248));
  PokeA(*ee+31,(PeekA(*ee+31) & 127));
  PokeA(*ee+31,(PeekA(*ee+31) | 64));

  db(*ee,"secret")
 
  fexpand(*bp,*basepoint);
  cmult(*x, *z, *ee, *bp);
  crecip(*zmone, *z);
  fmul(*z, *x, *zmone);
  fcontract(*mypublic,*z);
  
  FreeMemory(*bp)
  FreeMemory(*x)
  FreeMemory(*z)
  FreeMemory(*zmone)
  FreeMemory(*ee)
  
EndProcedure 

Define i 
For i=0 To 31 : PokeA(*mysecret+i,42) : Next

 PokeA(*mysecret+0, PeekA(*mysecret+0) & 248)
 PokeA(*mysecret+31, PeekA(*mysecret+31) & 127)
 PokeA(*mysecret+31, PeekA(*mysecret+31) | 64)

PokeA(*basepoint+0,9)

;-----

For i=0 To 31 : PokeA(*hissecret+i,11) : Next
   PokeA(*hissecret+0, PeekA(*hissecret+0) & 248)
   PokeA(*hissecret+31, PeekA(*hissecret+31) & 127)
   PokeA(*hissecret+31, PeekA(*hissecret+31) | 64)

;---



OpenConsole()
ConsoleTitle("Curve25519 Test")

str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mysecret+i),#PB_Byte),2,"0"): Next :   PrintN("mysecret : "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve(*mypublic, *mysecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mypublic+i),#PB_Byte),2,"0"): Next :   PrintN("mypublic : "+str$)
PrintN("")
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hissecret+i),#PB_Byte),2,"0"): Next :  PrintN("hissecret: "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve(*hispublic, *hissecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hispublic+i),#PB_Byte),2,"0"): Next :  PrintN("hispublic: "+str$)
PrintN("")
curve(*myshared, *mysecret, *hispublic)
curve(*hisshared, *hissecret, *mypublic)
str_myshared$="": For i=0 To 31: str_myshared$+RSet(Hex(PeekA(*myshared+i),#PB_Byte),2,"0"): Next :   PrintN("myshared : "+str_myshared$)
str_hisshared$="": For i=0 To 31: str_hisshared$+RSet(Hex(PeekA(*hisshared+i),#PB_Byte),2,"0"): Next :  PrintN("hisshared: "+str_hisshared$)
PrintN("")
If str_myshared$ = str_hisshared$
  PrintN("myshared = hisshared")
Else
  PrintN("myshared <> hisshared")
EndIf

PrintN("")
PrintN("")
PrintN("PRESS 'RETURN' TO QUIT.")
Input()
CloseConsole()

Re: broken c port of Ec25519 key exchange

Posted: Fri Mar 22, 2013 7:17 am
by Danilo
idle wrote:... but I wanted to provide it as source for the project so it's easier to share and maintain.
How is this maintainable?

Code: Select all

PokeQ(*out+64, PeekQ(*im+32) * PeekQ(*in+32) + 2 * (PeekQ(*im+24) * PeekQ(*in+40) + PeekQ(*im+40) * PeekQ(*in+24) + PeekQ(*im+8) * PeekQ(*in+56) + PeekQ(*im+56) * PeekQ(*in+8)) + PeekQ(*im+16) * PeekQ(*in+48) + PeekQ(*im+48) * PeekQ(*in+16) + PeekQ(*im+0) * PeekQ(*in+64) + PeekQ(*im+64) * PeekQ(*in+0));
For me the following style looks much more like the C code (not full translation):

Code: Select all

EnableExplicit

Structure felem
    q.q[0]
EndStructure


; /* Sum two numbers: output += in */
; static void fsum(felem *output, const felem *in) {
;   unsigned i;
;   for (i = 0; i < 10; i += 2) {
;     output[0+i] = (output[0+i] + in[0+i]);
;     output[1+i] = (output[1+i] + in[1+i]);
;   }
; }
Procedure fsum(*output.felem, *in.felem)
  Protected i
  While i < 10
    *output\q[  i] = (*output\q[  i] + *in\q[  i])
    *output\q[1+i] = (*output\q[1+i] + *in\q[1+i])
    i + 2
  Wend
EndProcedure


; /* Find the difference of two numbers: output = in - output
;  * (note the order of the arguments!)
;  */
; static void fdifference(felem *output, const felem *in) {
;   unsigned i;
;   for (i = 0; i < 10; ++i) {
;     output[i] = (in[i] - output[i]);
;   }
; }
Procedure fdifference(*output.felem, *in.felem)
  Protected i
  While i < 10
      *output\q[i] = (*in\q[i] - *output\q[i])
      i + 1
  Wend
EndProcedure


; /* Multiply a number my a scalar: output = in * scalar */
; static void fscalar_product(felem *output, const felem *in, const felem scalar) {
;   unsigned i;
;   for (i = 0; i < 10; ++i) {
;     output[i] = in[i] * scalar;
;   }
; }
Procedure fscalar_product(*output.felem, *in.felem, scalar.q)
  Protected i
  While i < 10
      *output\q[i] = *in\q[i] * scalar
      i + 1
  Wend
EndProcedure


;/* Multiply two numbers: output = in2 * in
; *
; * output must be distinct to both inputs. The inputs are reduced coefficient
; * form, the output is not.
; */
Procedure fproduct(*output.felem, *in2.felem, *in.felem)
  *output\q[0] =       *in2\q[0] * *in\q[0]
  *output\q[1] =       *in2\q[0] * *in\q[1] +
                       *in2\q[1] * *in\q[0]
  *output\q[2] =  2 *  *in2\q[1] * *in\q[1] +
                       *in2\q[0] * *in\q[2] +
                       *in2\q[2] * *in\q[0]
  *output\q[3] =       *in2\q[1] * *in\q[2] +
                       *in2\q[2] * *in\q[1] +
                       *in2\q[0] * *in\q[3] +
                       *in2\q[3] * *in\q[0]
  *output\q[4] =       *in2\q[2] * *in\q[2] +
                  2 * (*in2\q[1] * *in\q[3] +
                       *in2\q[3] * *in\q[1]) +
                       *in2\q[0] * *in\q[4] +
                       *in2\q[4] * *in\q[0]
  *output\q[5] =       *in2\q[2] * *in\q[3] +
                       *in2\q[3] * *in\q[2] +
                       *in2\q[1] * *in\q[4] +
                       *in2\q[4] * *in\q[1] +
                       *in2\q[0] * *in\q[5] +
                       *in2\q[5] * *in\q[0]
  *output\q[6] =  2 * (*in2\q[3] * *in\q[3] +
                       *in2\q[1] * *in\q[5] +
                       *in2\q[5] * *in\q[1]) +
                       *in2\q[2] * *in\q[4] +
                       *in2\q[4] * *in\q[2] +
                       *in2\q[0] * *in\q[6] +
                       *in2\q[6] * *in\q[0]
  *output\q[7] =       *in2\q[3] * *in\q[4] +
                       *in2\q[4] * *in\q[3] +
                       *in2\q[2] * *in\q[5] +
                       *in2\q[5] * *in\q[2] +
                       *in2\q[1] * *in\q[6] +
                       *in2\q[6] * *in\q[1] +
                       *in2\q[0] * *in\q[7] +
                       *in2\q[7] * *in\q[0]
  *output\q[8] =       *in2\q[4] * *in\q[4] +
                  2 * (*in2\q[3] * *in\q[5] +
                       *in2\q[5] * *in\q[3] +
                       *in2\q[1] * *in\q[7] +
                       *in2\q[7] * *in\q[1]) +
                       *in2\q[2] * *in\q[6] +
                       *in2\q[6] * *in\q[2] +
                       *in2\q[0] * *in\q[8] +
                       *in2\q[8] * *in\q[0]
  *output\q[9] =       *in2\q[4] * *in\q[5] +
                       *in2\q[5] * *in\q[4] +
                       *in2\q[3] * *in\q[6] +
                       *in2\q[6] * *in\q[3] +
                       *in2\q[2] * *in\q[7] +
                       *in2\q[7] * *in\q[2] +
                       *in2\q[1] * *in\q[8] +
                       *in2\q[8] * *in\q[1] +
                       *in2\q[0] * *in\q[9] +
                       *in2\q[9] * *in\q[0]
  *output\q[10] = 2 * (*in2\q[5] * *in\q[5] +
                       *in2\q[3] * *in\q[7] +
                       *in2\q[7] * *in\q[3] +
                       *in2\q[1] * *in\q[9] +
                       *in2\q[9] * *in\q[1]) +
                       *in2\q[4] * *in\q[6] +
                       *in2\q[6] * *in\q[4] +
                       *in2\q[2] * *in\q[8] +
                       *in2\q[8] * *in\q[2]
  *output\q[11] =      *in2\q[5] * *in\q[6] +
                       *in2\q[6] * *in\q[5] +
                       *in2\q[4] * *in\q[7] +
                       *in2\q[7] * *in\q[4] +
                       *in2\q[3] * *in\q[8] +
                       *in2\q[8] * *in\q[3] +
                       *in2\q[2] * *in\q[9] +
                       *in2\q[9] * *in\q[2]
  *output\q[12] =      *in2\q[6] * *in\q[6] +
                  2 * (*in2\q[5] * *in\q[7] +
                       *in2\q[7] * *in\q[5] +
                       *in2\q[3] * *in\q[9] +
                       *in2\q[9] * *in\q[3]) +
                       *in2\q[4] * *in\q[8] +
                       *in2\q[8] * *in\q[4]
  *output\q[13] =      *in2\q[6] * *in\q[7] +
                       *in2\q[7] * *in\q[6] +
                       *in2\q[5] * *in\q[8] +
                       *in2\q[8] * *in\q[5] +
                       *in2\q[4] * *in\q[9] +
                       *in2\q[9] * *in\q[4]
  *output\q[14] = 2 * (*in2\q[7] * *in\q[7] +
                       *in2\q[5] * *in\q[9] +
                       *in2\q[9] * *in\q[5]) +
                       *in2\q[6] * *in\q[8] +
                       *in2\q[8] * *in\q[6]
  *output\q[15] =      *in2\q[7] * *in\q[8] +
                       *in2\q[8] * *in\q[7] +
                       *in2\q[6] * *in\q[9] +
                       *in2\q[9] * *in\q[6]
  *output\q[16] =      *in2\q[8] * *in\q[8] +
                  2 * (*in2\q[7] * *in\q[9] +
                       *in2\q[9] * *in\q[7])
  *output\q[17] =      *in2\q[8] * *in\q[9] +
                       *in2\q[9] * *in\q[8]
  *output\q[18] = 2 *  *in2\q[9] * *in\q[9]
EndProcedure


;/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
Procedure freduce_degree(*output.felem)
  *output\q[8] + 19 * *output\q[18]
  *output\q[7] + 19 * *output\q[17]
  *output\q[6] + 19 * *output\q[16]
  *output\q[5] + 19 * *output\q[15]
  *output\q[4] + 19 * *output\q[14]
  *output\q[3] + 19 * *output\q[13]
  *output\q[2] + 19 * *output\q[12]
  *output\q[1] + 19 * *output\q[11]
  *output\q[0] + 19 * *output\q[10]
EndProcedure


;/* Reduce all coefficients of the short form input to be -2**25 <= x <= 2**25
Procedure freduce_coefficients(*output.felem)
  Protected i, over.q, over2.q ; over and over2 = felem
  Repeat
    *output\q[10] = 0

    While i < 10
      over = *output\q[i] / $2000000
      over2 = (over + ((over >> 63) * 2) + 1) / 2
      *output\q[i+1] + over2
      *output\q[i] - over2 * $4000000

      over = *output\q[i+1] / $2000000
      *output\q[i+2] + over
      *output\q[i+1] - over * $2000000
      i + 2
    Wend
    *output\q[0] + 19 * *output\q[10]
  Until *output\q[10] = 0
EndProcedure


;/* A helpful wrapper around fproduct: output = in * in2.
; *
; * output must be distinct to both inputs. The output is reduced degree and
; * reduced coefficient.
; */
Procedure fmul(*output.felem, *in.felem, *in2.felem)
  Dim t.q(19) ; felem
  fproduct(@t(), *in, *in2);
  freduce_degree(@t())
  freduce_coefficients(@t())
  CopyMemory(@t(), *output, SizeOf(Quad) * 10) ; SizeOf(felem)
EndProcedure

; ...

Re: broken c port of Ec25519 key exchange

Posted: Fri Mar 22, 2013 8:35 am
by idle
Danilo, Peter H said he fixed it.

I had tried to redo the code via structures so it was identical to the c code but it didn't work!
If you can take peter's code and make that work without the peeks and pokes that would be great.
I tried and failed!

doesn't work!

Code: Select all

; /* Copyright 2008, Google Inc.
;  * All rights reserved.
;  *
;  * Redistribution And use in source And binary forms, With Or without
;  * modification, are permitted provided that the following conditions are
;  * met:
;  *
;  *     * Redistributions of source code must retain the above copyright
;  * notice, this List of conditions And the following disclaimer.
;  *     * Redistributions in binary form must reproduce the above
;  * copyright notice, this List of conditions And the following disclaimer
;  * in the documentation And/Or other materials provided With the
;  * distribution.
;  *     * Neither the name of Google Inc. nor the names of its
;  * contributors may be used To endorse Or promote products derived from
;  * this software without specific prior written permission.
;  *
;  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS And CONTRIBUTORS
;  * "AS IS" And ANY EXPRESS Or IMPLIED WARRANTIES, INCLUDING, BUT Not
;  * LIMITED To, THE IMPLIED WARRANTIES OF MERCHANTABILITY And FITNESS For
;  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;  * OWNER Or CONTRIBUTORS BE LIABLE For ANY DIRECT, INDIRECT, INCIDENTAL,
;  * SPECIAL, EXEMPLARY, Or CONSEQUENTIAL DAMAGES (INCLUDING, BUT Not
;  * LIMITED To, PROCUREMENT OF SUBSTITUTE GOODS Or SERVICES; LOSS OF USE,
;  * Data, Or PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, Or TORT
;  * (INCLUDING NEGLIGENCE Or OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;  * OF THIS SOFTWARE, EVEN If ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;  *
;  * curve25519-donna: Curve25519 elliptic curve, public key function
;  *
;  * http://code.google.com/p/curve25519-donna/
;  *
;  * Adam Langley <agl@imperialviolet.org>
;  *
;  * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.To>
;  *
;  * More information about curve25519 can be found here
;  *   http://cr.yp.To/ecdh.html
;  *
;  * djb's sample implementation of curve25519 is written in a special assembly
;  * language called qhasm And uses the floating point registers.
;  *
;  * This is, almost, a clean room reimplementation from the curve25519 paper. It
;  * uses many of the tricks described therein. Only the crecip function is taken
;  * from the sample implementation.
;  */
; 
; #include <string.h>
; #include <stdint.h>
EnableExplicit

Structure felem;
   ele.q[0]
EndStructure    

Structure u8 
   ele.a[0]
EndStructure   

Procedure dB(*mem,op.s)
  Protected a,len,st.s
  len = MemorySize(*mem)
  st = op + "   "
  For a = 0 To len-1 
   st+RSet(Hex(PeekA(*mem+a),#PB_Byte),2,"0")
  Next 
  Debug st  
EndProcedure
;/* Sum two numbers: output += in */
Procedure fsum(*output.felem,*in.felem) 
  Protected i;
  While i < 10  
    *output\ele[i] + *in\ele[i];
    *output\ele[1+i] = *output\ele[1+i] + *in\ele[1+i]
    i+2    
  Wend  
EndProcedure 

;/* Find the difference of two numbers: output = in - output
; * (note the order of the arguments!)
; */
Procedure fdifference(*output.felem,*in.felem) 
  Protected i;
  While i < 10; 
     *output\ele[i] = *in\ele[i] - *output\ele[i]
     i+1
  Wend  
EndProcedure 

;/* Multiply a number my a scalar: output = in * scalar */
Procedure fscalar_product(*output.felem,*in.felem,scalar.q) 
  Protected i;
  While i < 10 ; i < 10; ++i) {
     *output\ele[i] = *in\ele[i] * scalar;
     i+1
  Wend  
EndProcedure 

;/* Multiply two numbers: output = in2 * in
; *
; * output must be distinct To both inputs. The inputs are reduced coefficient
; * form, the output is Not.
; */
Procedure fproduct(*output.felem,*in2.felem,*in.felem) 
  *output\ele[0] =      *in2\ele[0] * *in\ele[0];
  *output\ele[1] =      *in2\ele[0] * *in\ele[1] + *in2\ele[1] * *in\ele[0];
  *output\ele[2] =  2 * *in2\ele[1] * *in\ele[1] + *in2\ele[0] * *in\ele[2] + *in2\ele[2] * *in\ele[0];
  *output\ele[3] =      *in2\ele[1] * *in\ele[2] + *in2\ele[2] * *in\ele[1] + *in2\ele[0] * *in\ele[3] + *in2\ele[3] * *in\ele[0];
  *output\ele[4] =      *in2\ele[2] * *in\ele[2] + 2 * (*in2\ele[1] * *in\ele[3] + *in2\ele[3] * *in\ele[1]) + *in2\ele[0] * *in\ele[4] + *in2\ele[4] * *in\ele[0];
  *output\ele[5] =      *in2\ele[2] * *in\ele[3] + *in2\ele[3] * *in\ele[2] + *in2\ele[1] * *in\ele[4] + *in2\ele[4] * *in\ele[1] + *in2\ele[0] * *in\ele[5] + *in2\ele[5] * *in\ele[0];
  *output\ele[6] =  2 * (*in2\ele[3] * *in\ele[3] + *in2\ele[1] * *in\ele[5] + *in2\ele[5] * *in\ele[1]) + *in2\ele[2] * *in\ele[4] + *in2\ele[4] * *in\ele[2] + *in2\ele[0] * *in\ele[6] + *in2\ele[6] * *in\ele[0];
  *output\ele[7] =      *in2\ele[3] * *in\ele[4] + *in2\ele[4] * *in\ele[3] +  *in2\ele[2] * *in\ele[5] + *in2\ele[5] * *in\ele[2] + *in2\ele[1] * *in\ele[6] + *in2\ele[6] * *in\ele[1] +  *in2\ele[0] * *in\ele[7] + *in2\ele[7] * *in\ele[0];
  *output\ele[8] =      *in2\ele[4] * *in\ele[4] + 2 * (*in2\ele[3] * *in\ele[5] + *in2\ele[5] * *in\ele[3] + *in2\ele[1] * *in\ele[7] + *in2\ele[7] * *in\ele[1]) + *in2\ele[2] * *in\ele[6] + *in2\ele[6] * *in\ele[2] + *in2\ele[0] * *in\ele[8] + *in2\ele[8] * *in\ele[0];
  *output\ele[9] =      *in2\ele[4] * *in\ele[5] + *in2\ele[5] * *in\ele[4] + *in2\ele[3] * *in\ele[6] + *in2\ele[6] * *in\ele[3] + *in2\ele[2] * *in\ele[7] + *in2\ele[7] * *in\ele[2] + *in2\ele[1] * *in\ele[8] + *in2\ele[8] * *in\ele[1] + *in2\ele[0] * *in\ele[9] + *in2\ele[9] * *in\ele[0];
  *output\ele[10] = 2 * (*in2\ele[5] * *in\ele[5] + *in2\ele[3] * *in\ele[7] + *in2\ele[7] * *in\ele[3] + *in2\ele[1] * *in\ele[9] + *in2\ele[9] * *in\ele[1]) + *in2\ele[4] * *in\ele[6] + *in2\ele[6] * *in\ele[4] + *in2\ele[2] * *in\ele[8] + *in2\ele[8] * *in\ele[2];
  *output\ele[11] =     *in2\ele[5] * *in\ele[6] + *in2\ele[6] * *in\ele[5] + *in2\ele[4] * *in\ele[7] + *in2\ele[7] * *in\ele[4] + *in2\ele[3] * *in\ele[8] + *in2\ele[8] * *in\ele[3] + *in2\ele[2] * *in\ele[9] + *in2\ele[9] * *in\ele[2];
  *output\ele[12] =     *in2\ele[6] * *in\ele[6] + 2 * (*in2\ele[5] * *in\ele[7] + *in2\ele[7] * *in\ele[5] + *in2\ele[3] * *in\ele[9] + *in2\ele[9] * *in\ele[3]) + *in2\ele[4] * *in\ele[8] + *in2\ele[8] * *in\ele[4];
  *output\ele[13] =     *in2\ele[6] * *in\ele[7] + *in2\ele[7] * *in\ele[6] + *in2\ele[5] * *in\ele[8] + *in2\ele[8] * *in\ele[5] + *in2\ele[4] * *in\ele[9] + *in2\ele[9] * *in\ele[4];
  *output\ele[14] = 2 * (*in2\ele[7] * *in\ele[7] + *in2\ele[5] * *in\ele[9] + *in2\ele[9] * *in\ele[5]) + *in2\ele[6] * *in\ele[8] + *in2\ele[8] * *in\ele[6];
  *output\ele[15] =     *in2\ele[7] * *in\ele[8] + *in2\ele[8] * *in\ele[7] + *in2\ele[6] * *in\ele[9] + *in2\ele[9] * *in\ele[6]; 
  *output\ele[16] =     *in2\ele[8] * *in\ele[8] + 2 * (*in2\ele[7] * *in\ele[9] + *in2\ele[9] * *in\ele[7]);
  *output\ele[17] =     *in2\ele[8] * *in\ele[9] + *in2\ele[9] * *in\ele[8];
  *output\ele[18] = 2 * *in2\ele[9] * *in\ele[9];
EndProcedure 

;/* Reduce a long form To a short form by taking the input mod 2^255 - 19. */
Procedure freduce_degree(*output.felem)
  *output\ele[8] = *output\ele[8] + (19 * *output\ele[18]);
  *output\ele[7] = *output\ele[7] + (19 * *output\ele[17]);
  *output\ele[6] = *output\ele[6] + (19 * *output\ele[16]);
  *output\ele[5] = *output\ele[5] + (19 * *output\ele[15]);
  *output\ele[4] = *output\ele[4] + (19 * *output\ele[14]);
  *output\ele[3] = *output\ele[3] + (19 * *output\ele[13]);
  *output\ele[2] = *output\ele[2] + (19 * *output\ele[12]);
  *output\ele[1] = *output\ele[1] + (19 * *output\ele[11]);
  *output\ele[0] = *output\ele[0] + (19 * *output\ele[10]);
EndProcedure 

;/* Reduce all coefficients of the short form input To be -2**25 <= x <= 2**25
; */
Procedure freduce_coefficients(*output.felem)
  Protected i,over.q,over2.q;
  Repeat
    *output\ele[10] = 0;
    i=0
    While i < 10 ; Step 2 
      over = *output\ele[i] / $2000000
      over2 = (over + ((over >> 63) * 2) + 1) / 2;
      *output\ele[i+1] = *output\ele[i+1] + over2;
      *output\ele[i] = *output\ele[i] - (over2 * $4000000);

      over = *output\ele[i+1] / $2000000;
      *output\ele[i+2] = *output\ele[i+2] + over;
      *output\ele[i+1] = *output\ele[i+1] - (over * $2000000);
      i+2   
   Wend  
   *output\ele[0] = *output\ele[0] + (19 * *output\ele[10]);
  Until *output\ele[10] = 0;
EndProcedure 

; /* A helpful wrapper around fproduct: output = in * in2.
;  *
;  * output must be distinct To both inputs. The output is reduced degree And
;  * reduced coefficient.
;  */
; Static void
Procedure fmul(*output.felem,*in.felem,*in2.felem)
  Protected *t.felem 
  *t = AllocateMemory(19 * SizeOf(quad));
  fproduct(*t, *in, *in2);
  freduce_degree(*t);
  freduce_coefficients(*t);
  CopyMemory(*t,*output,SizeOf(quad) * 10);
  FreeMemory(*t) 
EndProcedure 

Procedure fsquare_inner(*output.felem,*in.felem)
  *output\ele[0] =      *in\ele[0] * *in\ele[0];
  *output\ele[1] =  2 * *in\ele[0] * *in\ele[1];
  *output\ele[2] =  2 * (*in\ele[1] * *in\ele[1] + *in\ele[0] * *in\ele[2]);
  *output\ele[3] =  2 * (*in\ele[1] * *in\ele[2] + *in\ele[0] * *in\ele[3]);
  *output\ele[4] =      *in\ele[2] * *in\ele[2] + 4 * *in\ele[1] * *in\ele[3] + 2 * *in\ele[0] * *in\ele[4];
  *output\ele[5] =  2 * (*in\ele[2] * *in\ele[3] + *in\ele[1] * *in\ele[4] + *in\ele[0] * *in\ele[5]);
  *output\ele[6] =  2 * (*in\ele[3] * *in\ele[3] + *in\ele[2] * *in\ele[4] + *in\ele[0] * *in\ele[6] + 2 * *in\ele[1] * *in\ele[5]);
  *output\ele[7] =  2 * (*in\ele[3] * *in\ele[4] + *in\ele[2] * *in\ele[5] + *in\ele[1] * *in\ele[6] + *in\ele[0] * *in\ele[7]);
  *output\ele[8] =      *in\ele[4] * *in\ele[4] + 2 * (*in\ele[2] * *in\ele[6] + *in\ele[0] * *in\ele[8] + 2 * (*in\ele[1] * *in\ele[7] + *in\ele[3] * *in\ele[5]));
  *output\ele[9] =  2 * (*in\ele[4] * *in\ele[5] + *in\ele[3] * *in\ele[6] + *in\ele[2] * *in\ele[7] + *in\ele[1] * *in\ele[8] + *in\ele[0] * *in\ele[9]);
  *output\ele[10] = 2 * (*in\ele[5] * *in\ele[5] + *in\ele[4] * *in\ele[6] + *in\ele[2] * *in\ele[8] + 2 * (*in\ele[3] * *in\ele[7] + *in\ele[1] * *in\ele[9]));
  *output\ele[11] = 2 * (*in\ele[5] * *in\ele[6] + *in\ele[4] * *in\ele[7] + *in\ele[3] * *in\ele[8] + *in\ele[2] * *in\ele[9]);
  *output\ele[12] =     *in\ele[6] * *in\ele[6] + 2 * (*in\ele[4] * *in\ele[8] + 2 * (*in\ele[5] * *in\ele[7] + *in\ele[3] * *in\ele[9]));
  *output\ele[13] = 2 * (*in\ele[6] * *in\ele[7] + *in\ele[5] * *in\ele[8] + *in\ele[4] * *in\ele[9]);
  *output\ele[14] = 2 * (*in\ele[7] * *in\ele[7] + *in\ele[6] * *in\ele[8] + 2 * *in\ele[5] * *in\ele[9]);
  *output\ele[15] = 2 * (*in\ele[7] * *in\ele[8] + *in\ele[6] * *in\ele[9]);
  *output\ele[16] =     *in\ele[8] * *in\ele[8] + 4 * *in\ele[7] * *in\ele[9];
  *output\ele[17] = 2 * *in\ele[8] * *in\ele[9];
  *output\ele[18] = 2 * *in\ele[9] * *in\ele[9];
EndProcedure 

;Static void
Procedure fsquare(*output.felem,*in.felem) 
  Protected *t.felem 
  *t = AllocateMemory(19 * SizeOf(quad));
  fsquare_inner(*t, *in);
  freduce_degree(*t);
  freduce_coefficients(*t);
  CopyMemory(*t,*output,SizeOf(quad) * 10);
  FreeMemory(*t)
EndProcedure 

;/* Take a little-endian, 32-byte number And expand it into polynomial form */
;Static void

Macro Fe(n,start,shift,mask) 
  *output\ele[n] = (((*input\ele[start] | *input\ele[start+1] << 8 | *input\ele[start+2] << 16 | *input\ele[start+3] << 24) >> shift) & mask);
EndMacro                 


Procedure fexpand(*output.felem,*input.u8)
  Fe(0, 0, 0, $3ffffff);
  Fe(1, 3, 2, $1ffffff);
  Fe(2, 6, 3, $3ffffff);
  Fe(3, 9, 5, $1ffffff);
  Fe(4, 12, 6, $3ffffff);
  Fe(5, 16, 0, $1ffffff);
  Fe(6, 19, 1, $3ffffff);
  Fe(7, 22, 3, $1ffffff);
  Fe(8, 25, 4, $3ffffff);
  Fe(9, 28, 6, $1ffffff);
EndProcedure 

Macro Fc(i, s) 
  *output\ele[s+0] = (*output\ele[s+0] | *input\ele[i]) & $ff;
  *output\ele[s+1] = (*input\ele[i] >> 8) & $ff; 
  *output\ele[s+2] = (*input\ele[i] >> 16) & $ff; 
  *output\ele[s+3] = (*input\ele[i] >> 24) & $ff;
  
EndMacro   
;/* Take a fully reduced polynomial form number And contract it into a
; * little-endian, 32-byte Array
; */
;Static void
Procedure fcontract(*output.u8,*input.felem)
  Protected i,j

  Repeat 
    For i = 0 To 8
       j = i & 1
       If j 
        While *input\ele[i] < 0 
          *input\ele[i] + $2000000;
          *input\ele[i + 1]- 1;
        Wend
      Else 
        While *input\ele[i] < 0 
          *input\ele[i] + $4000000;
          *input\ele[i + 1] - 1;
        Wend
     EndIf
    Next   
    While *input\ele[9] < 0 
      *input\ele[9] + $2000000;
      *input\ele[0] - 19;
    Wend
    
  Until *input\ele[0] >= 0;

  *input\ele[1] << 2;
  *input\ele[2] << 3;
  *input\ele[3] << 5;
  *input\ele[4] << 6;
  *input\ele[6] << 1;
  *input\ele[7] << 3;
  *input\ele[8] << 4;
  *input\ele[9] << 6;
  
  *output\ele[0] = 0;
  *output\ele[16] = 0;
  
  Fc(0,0);
  Fc(1,3);
  Fc(2,6);
  Fc(3,9);
  Fc(4,12);
  Fc(5,16);
  Fc(6,19);
  Fc(7,22);
  Fc(8,25);
  Fc(9,28);
EndProcedure 

;/* Input: Q, Q', Q-Q'
; * Output: 2Q, Q+Q'
; *
; *   x2 z3: long form
; *   x3 z3: long form
; *   x z: short form, destroyed
; *   xprime zprime: short form, destroyed
; *   qmqp: short form, preserved
; */
Procedure fmonty(*x2.felem,*z2.felem,*x3.felem,*z3.felem,*x.felem,*z.felem,*xprime.felem,*zprime.felem,*qmqp.felem)
   Protected *origx.felem,*origxprime.felem,*zzz.felem,*xx.felem,*zz.felem,*xxprime.felem,*zzprime.felem
   Protected *zzzprime.felem,*xxxprime.felem 
   
   *origx = AllocateMemory(10 * SizeOf(quad))
   *origxprime = AllocateMemory(10 * SizeOf(quad))
   *zzz = AllocateMemory(19 * SizeOf(quad))
   *xx = AllocateMemory(19 * SizeOf(quad))
   *zz = AllocateMemory(19 * SizeOf(quad))
   *xxprime = AllocateMemory(19 * SizeOf(quad))
   *zzprime = AllocateMemory(19 * SizeOf(quad))
   *zzzprime = AllocateMemory(19 * SizeOf(quad))
   *xxxprime = AllocateMemory(19 * SizeOf(quad));
   
   CopyMemory(*x,*origx,10 * SizeOf(quad));
   fsum(*x,*z);
   fdifference(*z,*origx);  // does x - z

  CopyMemory(*xprime,*origxprime,SizeOf(quad) * 10);
  fsum(*xprime,*zprime);
  fdifference(*zprime, *origxprime);
  fproduct(*xxprime,*xprime, *z);
  fproduct(*zzprime,*x,*zprime);
  freduce_degree(*xxprime);
  freduce_coefficients(*xxprime);
  freduce_degree(*zzprime);
  freduce_coefficients(*zzprime);
  CopyMemory(*xxprime,*origxprime,SizeOf(quad) * 10);
  fsum(*xxprime,*zzprime);
  fdifference(*zzprime,*origxprime);
  fsquare(*xxxprime,*xxprime);
  fsquare(*zzzprime,*zzprime);
  fproduct(*zzprime,*zzzprime,*qmqp);
  freduce_degree(*zzprime);
  freduce_coefficients(*zzprime);
  CopyMemory(*xxxprime,*x3, SizeOf(quad) * 10);
  CopyMemory(*zzprime,*z3, SizeOf(quad) * 10);

  fsquare(*xx,*x);
  fsquare(*zz,*z);
  fproduct(*x2, *xx,*zz);
  freduce_degree(*x2);
  freduce_coefficients(*x2);
  fdifference(*zz,*xx);  // does zz = xx - zz
  FillMemory(@*zzz\ele[10],SizeOf(quad) * 9,0);
  fscalar_product(*zzz,*zz,121665);
  freduce_degree(*zzz);
  freduce_coefficients(*zzz);
  fsum(*zzz,*xx);
  fproduct(*z2,*zz,*zzz);
  freduce_degree(*z2);
  freduce_coefficients(*z2);
  
  FreeMemory(*origx) 
  FreeMemory(*origxprime) 
  FreeMemory(*zzz)  
  FreeMemory(*xx)  
  FreeMemory(*zz)  
  FreeMemory(*xxprime)  
  FreeMemory(*zzprime) 
  FreeMemory(*zzzprime)  
  FreeMemory(*xxxprime)
  
EndProcedure

; /* Calculates nQ where Q is the x-coordinate of a point on the curve
;  *
;  *   resultx/resultz: the x coordinate of the resulting curve Point (short form)
;  *   n: a little endian, 32-byte number
;  *   q: a point of the curve (short form)
;  */
; Static void
Procedure cmult(*resultx.felem,*resultz.felem,*n.u8,*q.felem)
   
   Protected *a,*b,*c,*d,*e,*f,*g,*h
   Protected *nqpqx.felem,*nqpqz.felem,*nqx.felem,*nqz.felem,*t
   Protected *nqpqx2.felem, *nqpqz2.felem, *nqx2.felem, *nqz2.felem
   
   *a = AllocateMemory(19 * SizeOf(quad))
   *b = AllocateMemory(19 * SizeOf(quad))
   *c = AllocateMemory(19 * SizeOf(quad))
   *d = AllocateMemory(19 * SizeOf(quad))
   *e = AllocateMemory(19 * SizeOf(quad))
   *f = AllocateMemory(19 * SizeOf(quad))
   *g = AllocateMemory(19 * SizeOf(quad))
   *h = AllocateMemory(19 * SizeOf(quad))
   
   *nqpqx = *a : *nqpqz = *b : *nqx = *c : *nqz = *d
   *nqpqx\ele[19] = 0 : *nqpqz\ele[19] = 1 :  *nqx\ele[19] = 1 : *nqz\ele[19] = 0;
   
   *nqpqx2 = *e : *nqpqz2 = *f : *nqx2 = *g : *nqz2 = *h 
   *nqpqx2\ele[19] = 0 : *nqpqz2\ele[19] = 1 : *nqx2\ele[19] = 0 : *nqz2\ele[19] = 1
  
  Protected i, j,byte.a,r;
   
  CopyMemory(*q,*nqpqx,SizeOf(quad) * 10);
  
  For i = 0 To 31 ; i < 32; ++i) {
    byte = *n\ele[31-i] & $FF
     
    For j = 0 To 7 ; j < 8; ++j) {
      r = byte & $80
      If r ;byte & $80 
        fmonty(*nqpqx2, *nqpqz2,*nqx2, *nqz2, *nqpqx, *nqpqz, *nqx, *nqz, *q);
      Else 
        fmonty(*nqx2, *nqz2,*nqpqx2, *nqpqz2,*nqx, *nqz,*nqpqx, *nqpqz,*q);
      EndIf 

      *t = *nqx;
      *nqx = *nqx2;
      *nqx2 = *t;
      *t = *nqz;
      *nqz = *nqz2;
      *nqz2 = *t;
      *t = *nqpqx;
      *nqpqx = *nqpqx2;
      *nqpqx2 = *t;
      *t = *nqpqz;
      *nqpqz = *nqpqz2;
      *nqpqz2 = *t;

      byte << 1;
      
    Next  
  Next   

  CopyMemory(*nqx,*resultx, SizeOf(quad) * 10);
  CopyMemory(*nqz,*resultz,SizeOf(quad) * 10);
  
  FreeMemory(*a)  
  FreeMemory(*b)  
  FreeMemory(*c)  
  FreeMemory(*d)  
  FreeMemory(*e)  
  FreeMemory(*f)  
  FreeMemory(*g)  
  FreeMemory(*h) 
    
EndProcedure 

;// -----------------------------------------------------------------------------
;// Shamelessly copied from djb's code
;// -----------------------------------------------------------------------------
;Static void
Procedure crecip(*out.felem,*z.felem)
  Protected *z2.felem,*z9.felem,*z11.felem,*z2_5_0.felem, *z2_10_0.felem
  Protected *z2_20_0.felem,*z2_50_0.felem,*z2_100_0.felem,*t0.felem,*t1.felem 
  Protected i  
  
  *z2 = AllocateMemory(10*SizeOf(quad));
  *z9 = AllocateMemory(10*SizeOf(quad))
  *z11 = AllocateMemory(10*SizeOf(quad))
  *z2_5_0 = AllocateMemory(10*SizeOf(quad))
  *z2_10_0 = AllocateMemory(10*SizeOf(quad))
  *z2_20_0 = AllocateMemory(10*SizeOf(quad))
  *z2_50_0 = AllocateMemory(10*SizeOf(quad))
  *z2_100_0 = AllocateMemory(10*SizeOf(quad))
  *t0 = AllocateMemory(10*SizeOf(quad))
  *t1 = AllocateMemory(10*SizeOf(quad))
  
  fsquare(*z2,*z);
  fsquare(*t1,*z2);
  fsquare(*t0,*t1);
  fmul(*z9,*t0,*z);
  fmul(*z11,*z9,*z2);
  fsquare(*t0,*z11);
  fmul(*z2_5_0,*t0,*z9);

  fsquare(*t0,*z2_5_0);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fmul(*z2_10_0,*t0,*z2_5_0);

  fsquare(*t0,*z2_10_0);
  fsquare(*t1,*t0);
  i=2
  While i< 10 ; i < 10;i += 2)
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2    
  Wend     
     
  fmul(*z2_20_0,*t1,*z2_10_0);

  fsquare(*t0,*z2_20_0);
  fsquare(*t1,*t0);
  i=2
  While i < 20 ;i < 20;i += 2)
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2   
  Wend  
  fmul(*t0,*t1,*z2_20_0);

  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  i=2
  While i < 10 ;i<10;i += 2)
     fsquare(*t1,*t0)
     fsquare(*t0,*t1)
     i+2
  Wend  
  fmul(*z2_50_0,*t0,*z2_10_0);

  fsquare(*t0,*z2_50_0);
  fsquare(*t1,*t0);
  i=2
  While i< 50 ;i<50;i += 2) 
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2
  Wend  
  fmul(*z2_100_0,*t1,*z2_50_0);

  fsquare(*t1,*z2_100_0);
  fsquare(*t0,*t1);
  i=2
  While i < 100 ;i < 100;i += 2)
     fsquare(*t1,*t0)
     fsquare(*t0,*t1)
     i+2
  Wend  
  fmul(*t1,*t0,*z2_100_0);

  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  i=2
  While i < 50 ;i < 50;i += 2) 
     fsquare(*t0,*t1)
     fsquare(*t1,*t0)
     i+2
  Wend  
  fmul(*t0,*t1,*z2_50_0);

  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fsquare(*t0,*t1);
  fsquare(*t1,*t0);
  fmul(*out,*t1,*z11);
  
  FreeMemory(*z2) 
  FreeMemory(*z9) 
  FreeMemory(*z11)
  FreeMemory(*z2_5_0)
  FreeMemory(*z2_10_0)
  FreeMemory(*z2_20_0)
  FreeMemory(*z2_50_0)
  FreeMemory(*z2_100_0)
  FreeMemory(*t0)
  FreeMemory(*t1)  
  
EndProcedure 


Procedure curve25519_donna(*public.u8,*secret.u8,*basepoint.u8) 
   Protected *bp.felem,*x.felem,*z.felem,*zmone.felem,*e.u8 
   Protected i 
   *bp = AllocateMemory(19*SizeOf(quad))
   *x = AllocateMemory(19*SizeOf(quad))
   *z = AllocateMemory(19*SizeOf(quad))
   *zmone = AllocateMemory(19*SizeOf(quad))
   *e = AllocateMemory(32);
  
   For i = 0 To 31 ;i < 32; ++i)
      *e\ele[i] = *secret\ele[i];
      i+1
   Next      
   
   *e\ele[0] & 248;
   *e\ele[31] & 127;
   *e\ele[31] | 64;

  fexpand(*bp,*basepoint);
  db(*bp,"after fexpand")
  cmult(*x, *z, *e, *bp);
  db(*x,"after cmult")
  crecip(*zmone, *z);
  fmul(*z, *x, *zmone);
  fcontract(*public,*z);
     
EndProcedure 


DisableExplicit;EnableExplicit
Global str$

Global *mysecret.u8 = AllocateMemory(32)
Global *mypublic.u8 = AllocateMemory(32)
Global *basepoint.u8 = AllocateMemory(32)
Global *hissecret.u8 = AllocateMemory(32)
Global *hispublic.u8 = AllocateMemory(32)
Global *myshared.u8 = AllocateMemory(32)
Global *hisshared.u8 = AllocateMemory(32)

Define i 

For i=0 To 31 
   *mysecret\ele[i] = 42
Next

*mysecret\ele[0] & 248 
*mysecret\ele[31] & 127
*mysecret\ele[31] | 64
*basepoint\ele[0] = 9

;-----

For i=0 To 31
   *hissecret\ele[i] = 11
Next
*hissecret\ele[0] & 248
*hissecret\ele[31] & 127
*hissecret\ele[31] | 64

;---


OpenConsole()
ConsoleTitle("Curve25519 Test")

str$="": For i=0 To 31: str$+RSet(Hex(*mysecret\ele[i],#PB_Byte),2,"0"): Next :   PrintN("mysecret : "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(*basepoint\ele[i],#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve25519_donna(*mypublic, *mysecret, *basepoint)

str$="": For i=0 To 31: str$+RSet(Hex(*mypublic\ele[i],#PB_Byte),2,"0"): Next :   PrintN("mypublic : "+str$)
PrintN("")
str$="": For i=0 To 31: str$+RSet(Hex(*hissecret\ele[i],#PB_Byte),2,"0"): Next :  PrintN("hissecret: "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(*basepoint\ele[i],#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve25519_donna(*hispublic, *hissecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(*hispublic\ele[i],#PB_Byte),2,"0"): Next :  PrintN("hispublic: "+str$)
PrintN("")
curve25519_donna(*myshared, *mysecret, *hispublic)
curve25519_donna(*hisshared, *hissecret, *mypublic)
str_myshared$="": For i=0 To 31: str_myshared$+RSet(Hex(*myshared\ele[i],#PB_Byte),2,"0"): Next :   PrintN("myshared : "+str_myshared$)
str_hisshared$="": For i=0 To 31: str_hisshared$+RSet(Hex(*hisshared\ele[i],#PB_Byte),2,"0"): Next :  PrintN("hisshared: "+str_hisshared$)
PrintN("")
If str_myshared$ = str_hisshared$
  PrintN("myshared = hisshared")
Else
  PrintN("myshared <> hisshared")
EndIf

PrintN("")
PrintN("")
PrintN("PRESS 'RETURN' TO QUIT.")
Input()
CloseConsole()


Re: broken c port of Ec25519 key exchange

Posted: Sat Mar 23, 2013 9:51 pm
by PeterH
idle wrote:Danilo, Peter H said he fixed it.

I had tried to redo the code via structures so it was identical to the c code but it didn't work!
If you can take peter's code and make that work without the peeks and pokes that would be great.
I tried and failed!
I second that. I'd be very grateful for a version that can compile on linux x64 as well. I'm gonna buy a box of energy drinks and make an attempt on ECDSA if I manage to figure out how to get that stuff working properly.

Re: broken c port of Ec25519 key exchange

Posted: Sun Mar 24, 2013 1:40 am
by Danilo
idle wrote:Danilo, Peter H said he fixed it.

I had tried to redo the code via structures so it was identical to the c code but it didn't work!
If you can take peter's code and make that work without the peeks and pokes that would be great.
I tried and failed!

doesn't work!
I did port directly from the C source in your first posting and it works:

Code: Select all

; /* Copyright 2008, Google Inc.
;  * All rights reserved.
;  *
;  * Redistribution And use in source And binary forms, With Or without
;  * modification, are permitted provided that the following conditions are
;  * met:
;  *
;  *     * Redistributions of source code must retain the above copyright
;  *       notice, this List of conditions And the following disclaimer.
;  *     * Redistributions in binary form must reproduce the above
;  *       copyright notice, this List of conditions And the following disclaimer
;  *       in the documentation And/Or other materials provided With the
;  *       distribution.
;  *     * Neither the name of Google Inc. nor the names of its
;  *       contributors may be used To endorse Or promote products derived from
;  *       this software without specific prior written permission.
;  *
;  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS And CONTRIBUTORS
;  * "AS IS" And ANY EXPRESS Or IMPLIED WARRANTIES, INCLUDING, BUT Not
;  * LIMITED To, THE IMPLIED WARRANTIES OF MERCHANTABILITY And FITNESS For
;  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;  * OWNER Or CONTRIBUTORS BE LIABLE For ANY DIRECT, INDIRECT, INCIDENTAL,
;  * SPECIAL, EXEMPLARY, Or CONSEQUENTIAL DAMAGES (INCLUDING, BUT Not
;  * LIMITED To, PROCUREMENT OF SUBSTITUTE GOODS Or SERVICES; LOSS OF USE,
;  * Data, Or PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, Or TORT
;  * (INCLUDING NEGLIGENCE Or OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;  * OF THIS SOFTWARE, EVEN If ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;  *
;  * curve25519-donna: Curve25519 elliptic curve, public key function
;  *
;  * http://code.google.com/p/curve25519-donna/
;  *
;  * Adam Langley <agl@imperialviolet.org>
;  *
;  * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.To>
;  *
;  * More information about curve25519 can be found here
;  *   http://cr.yp.To/ecdh.html
;  *
;  * djb's sample implementation of curve25519 is written in a special assembly
;  * language called qhasm And uses the floating point registers.
;  *
;  * This is, almost, a clean room reimplementation from the curve25519 paper. It
;  * uses many of the tricks described therein. Only the crecip function is taken
;  * from the sample implementation.
;  */

EnableExplicit

Structure felem
    q.q[0]
EndStructure

Structure u8
    a.a[0]
EndStructure

Macro Comment(a) : EndMacro

; /* Sum two numbers: output += in */
Procedure fsum(*output.felem, *in.felem)
  Protected i
  While i < 10
    *output\q[  i] = (*output\q[  i] + *in\q[  i])
    *output\q[1+i] = (*output\q[1+i] + *in\q[1+i])
    i + 2
  Wend
EndProcedure


; /* Find the difference of two numbers: output = in - output
;  * (note the order of the arguments!)
;  */
Procedure fdifference(*output.felem, *in.felem)
  Protected i
  While i < 10
      *output\q[i] = (*in\q[i] - *output\q[i])
      i + 1
  Wend
EndProcedure


; /* Multiply a number my a scalar: output = in * scalar */
Procedure fscalar_product(*output.felem, *in.felem, scalar.q)
  Protected i
  While i < 10
      *output\q[i] = *in\q[i] * scalar
      i + 1
  Wend
EndProcedure


;/* Multiply two numbers: output = in2 * in
; *
; * output must be distinct to both inputs. The inputs are reduced coefficient
; * form, the output is not.
; */
Procedure fproduct(*output.felem, *in2.felem, *in.felem)
  *output\q[0] =       *in2\q[0] * *in\q[0]
  *output\q[1] =       *in2\q[0] * *in\q[1] +
                       *in2\q[1] * *in\q[0]
  *output\q[2] =  2 *  *in2\q[1] * *in\q[1] +
                       *in2\q[0] * *in\q[2] +
                       *in2\q[2] * *in\q[0]
  *output\q[3] =       *in2\q[1] * *in\q[2] +
                       *in2\q[2] * *in\q[1] +
                       *in2\q[0] * *in\q[3] +
                       *in2\q[3] * *in\q[0]
  *output\q[4] =       *in2\q[2] * *in\q[2] +
                  2 * (*in2\q[1] * *in\q[3] +
                       *in2\q[3] * *in\q[1]) +
                       *in2\q[0] * *in\q[4] +
                       *in2\q[4] * *in\q[0]
  *output\q[5] =       *in2\q[2] * *in\q[3] +
                       *in2\q[3] * *in\q[2] +
                       *in2\q[1] * *in\q[4] +
                       *in2\q[4] * *in\q[1] +
                       *in2\q[0] * *in\q[5] +
                       *in2\q[5] * *in\q[0]
  *output\q[6] =  2 * (*in2\q[3] * *in\q[3] +
                       *in2\q[1] * *in\q[5] +
                       *in2\q[5] * *in\q[1]) +
                       *in2\q[2] * *in\q[4] +
                       *in2\q[4] * *in\q[2] +
                       *in2\q[0] * *in\q[6] +
                       *in2\q[6] * *in\q[0]
  *output\q[7] =       *in2\q[3] * *in\q[4] +
                       *in2\q[4] * *in\q[3] +
                       *in2\q[2] * *in\q[5] +
                       *in2\q[5] * *in\q[2] +
                       *in2\q[1] * *in\q[6] +
                       *in2\q[6] * *in\q[1] +
                       *in2\q[0] * *in\q[7] +
                       *in2\q[7] * *in\q[0]
  *output\q[8] =       *in2\q[4] * *in\q[4] +
                  2 * (*in2\q[3] * *in\q[5] +
                       *in2\q[5] * *in\q[3] +
                       *in2\q[1] * *in\q[7] +
                       *in2\q[7] * *in\q[1]) +
                       *in2\q[2] * *in\q[6] +
                       *in2\q[6] * *in\q[2] +
                       *in2\q[0] * *in\q[8] +
                       *in2\q[8] * *in\q[0]
  *output\q[9] =       *in2\q[4] * *in\q[5] +
                       *in2\q[5] * *in\q[4] +
                       *in2\q[3] * *in\q[6] +
                       *in2\q[6] * *in\q[3] +
                       *in2\q[2] * *in\q[7] +
                       *in2\q[7] * *in\q[2] +
                       *in2\q[1] * *in\q[8] +
                       *in2\q[8] * *in\q[1] +
                       *in2\q[0] * *in\q[9] +
                       *in2\q[9] * *in\q[0]
  *output\q[10] = 2 * (*in2\q[5] * *in\q[5] +
                       *in2\q[3] * *in\q[7] +
                       *in2\q[7] * *in\q[3] +
                       *in2\q[1] * *in\q[9] +
                       *in2\q[9] * *in\q[1]) +
                       *in2\q[4] * *in\q[6] +
                       *in2\q[6] * *in\q[4] +
                       *in2\q[2] * *in\q[8] +
                       *in2\q[8] * *in\q[2]
  *output\q[11] =      *in2\q[5] * *in\q[6] +
                       *in2\q[6] * *in\q[5] +
                       *in2\q[4] * *in\q[7] +
                       *in2\q[7] * *in\q[4] +
                       *in2\q[3] * *in\q[8] +
                       *in2\q[8] * *in\q[3] +
                       *in2\q[2] * *in\q[9] +
                       *in2\q[9] * *in\q[2]
  *output\q[12] =      *in2\q[6] * *in\q[6] +
                  2 * (*in2\q[5] * *in\q[7] +
                       *in2\q[7] * *in\q[5] +
                       *in2\q[3] * *in\q[9] +
                       *in2\q[9] * *in\q[3]) +
                       *in2\q[4] * *in\q[8] +
                       *in2\q[8] * *in\q[4]
  *output\q[13] =      *in2\q[6] * *in\q[7] +
                       *in2\q[7] * *in\q[6] +
                       *in2\q[5] * *in\q[8] +
                       *in2\q[8] * *in\q[5] +
                       *in2\q[4] * *in\q[9] +
                       *in2\q[9] * *in\q[4]
  *output\q[14] = 2 * (*in2\q[7] * *in\q[7] +
                       *in2\q[5] * *in\q[9] +
                       *in2\q[9] * *in\q[5]) +
                       *in2\q[6] * *in\q[8] +
                       *in2\q[8] * *in\q[6]
  *output\q[15] =      *in2\q[7] * *in\q[8] +
                       *in2\q[8] * *in\q[7] +
                       *in2\q[6] * *in\q[9] +
                       *in2\q[9] * *in\q[6]
  *output\q[16] =      *in2\q[8] * *in\q[8] +
                  2 * (*in2\q[7] * *in\q[9] +
                       *in2\q[9] * *in\q[7])
  *output\q[17] =      *in2\q[8] * *in\q[9] +
                       *in2\q[9] * *in\q[8]
  *output\q[18] = 2 *  *in2\q[9] * *in\q[9]
EndProcedure


;/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
Procedure freduce_degree(*output.felem)
  *output\q[8] + (19 * *output\q[18])
  *output\q[7] + (19 * *output\q[17])
  *output\q[6] + (19 * *output\q[16])
  *output\q[5] + (19 * *output\q[15])
  *output\q[4] + (19 * *output\q[14])
  *output\q[3] + (19 * *output\q[13])
  *output\q[2] + (19 * *output\q[12])
  *output\q[1] + (19 * *output\q[11])
  *output\q[0] + (19 * *output\q[10])
EndProcedure


;/* Reduce all coefficients of the short form input to be -2**25 <= x <= 2**25
Procedure freduce_coefficients(*output.felem)
  Protected i, over.q, over2.q ; over and over2 = felem
  Repeat
    *output\q[10] = 0
    
    i=0
    While i < 10
      over = *output\q[i] / $2000000
      over2 = (over + ((over >> 63) * 2) + 1) / 2
      *output\q[i+1] + over2
      *output\q[i] - (over2 * $4000000)

      over = *output\q[i+1] / $2000000
      *output\q[i+2] + over
      *output\q[i+1] - (over * $2000000)
      i + 2
    Wend
    *output\q[0] + (19 * *output\q[10])
  Until Not *output\q[10]
EndProcedure


;/* A helpful wrapper around fproduct: output = in * in2.
; *
; * output must be distinct to both inputs. The output is reduced degree and
; * reduced coefficient.
; */
Procedure fmul(*output.felem, *in.felem, *in2.felem)
  Dim t.q(19) ; felem
  fproduct(@t(), *in, *in2);
  freduce_degree(@t())
  freduce_coefficients(@t())
  CopyMemory(@t(), *output, SizeOf(Quad) * 10) ; SizeOf(felem)
EndProcedure


Procedure fsquare_inner(*output.felem, *in.felem)
  *output\q[0] =       *in\q[0] * *in\q[0]
  *output\q[1] =  2 *  *in\q[0] * *in\q[1]
  *output\q[2] =  2 * (*in\q[1] * *in\q[1] +
                       *in\q[0] * *in\q[2])
  *output\q[3] =  2 * (*in\q[1] * *in\q[2] +
                       *in\q[0] * *in\q[3])
  *output\q[4] =       *in\q[2] * *in\q[2] +
                  4 *  *in\q[1] * *in\q[3] +
                  2 *  *in\q[0] * *in\q[4]
  *output\q[5] =  2 * (*in\q[2] * *in\q[3] +
                       *in\q[1] * *in\q[4] +
                       *in\q[0] * *in\q[5])
  *output\q[6] =  2 * (*in\q[3] * *in\q[3] +
                       *in\q[2] * *in\q[4] +
                       *in\q[0] * *in\q[6] +
                  2 *  *in\q[1] * *in\q[5])
  *output\q[7] =  2 * (*in\q[3] * *in\q[4] +
                       *in\q[2] * *in\q[5] +
                       *in\q[1] * *in\q[6] +
                       *in\q[0] * *in\q[7])
  *output\q[8] =       *in\q[4] * *in\q[4] +
                  2 * (*in\q[2] * *in\q[6] +
                       *in\q[0] * *in\q[8] +
                  2 * (*in\q[1] * *in\q[7] +
                       *in\q[3] * *in\q[5]))
  *output\q[9] =  2 * (*in\q[4] * *in\q[5] +
                       *in\q[3] * *in\q[6] +
                       *in\q[2] * *in\q[7] +
                       *in\q[1] * *in\q[8] +
                       *in\q[0] * *in\q[9])
  *output\q[10] = 2 * (*in\q[5] * *in\q[5] +
                       *in\q[4] * *in\q[6] +
                       *in\q[2] * *in\q[8] +
                  2 * (*in\q[3] * *in\q[7] +
                       *in\q[1] * *in\q[9]))
  *output\q[11] = 2 * (*in\q[5] * *in\q[6] +
                       *in\q[4] * *in\q[7] +
                       *in\q[3] * *in\q[8] +
                       *in\q[2] * *in\q[9])
  *output\q[12] =      *in\q[6] * *in\q[6] +
                  2 * (*in\q[4] * *in\q[8] +
                  2 * (*in\q[5] * *in\q[7] +
                       *in\q[3] * *in\q[9]))
  *output\q[13] = 2 * (*in\q[6] * *in\q[7] +
                       *in\q[5] * *in\q[8] +
                       *in\q[4] * *in\q[9])
  *output\q[14] = 2 * (*in\q[7] * *in\q[7] +
                       *in\q[6] * *in\q[8] +
                  2 *  *in\q[5] * *in\q[9])
  *output\q[15] = 2 * (*in\q[7] * *in\q[8] +
                       *in\q[6] * *in\q[9])
  *output\q[16] =      *in\q[8] * *in\q[8] +
                  4 *  *in\q[7] * *in\q[9]
  *output\q[17] = 2 *  *in\q[8] * *in\q[9]
  *output\q[18] = 2 *  *in\q[9] * *in\q[9]
EndProcedure


Procedure fsquare(*output.felem, *in.felem)
  Dim t.q(19) ; felem
  fsquare_inner(@t(), *in)
  freduce_degree(@t())
  freduce_coefficients(@t())
  CopyMemory(@t(),*output, SizeOf(Quad) * 10) ; SizeOf(felem)
EndProcedure


;/* Take a little-endian, 32-byte number and expand it into polynomial form */
Procedure fexpand(*output.felem, *input.u8)
  Protected q1.q, q2.q, q3.q, q4.q
  Macro F(n,start,shift,mask)
    q1 = (*input\a[start + 0] & $FF)
    q2 = (*input\a[start + 1] & $FF) : q2 << 8
    q3 = (*input\a[start + 2] & $FF) : q3 << 16
    q4 = (*input\a[start + 3] & $FF) : q4 << 24
    *output\q[n] = ((q1 | q2 | q3 | q4 ) >> shift) & mask
  EndMacro
      F(0, 0, 0, $3ffffff)
      F(1, 3, 2, $1ffffff)
      F(2, 6, 3, $3ffffff)
      F(3, 9, 5, $1ffffff)
      F(4, 12, 6, $3ffffff)
      F(5, 16, 0, $1ffffff)
      F(6, 19, 1, $3ffffff)
      F(7, 22, 3, $1ffffff)
      F(8, 25, 4, $3ffffff)
      F(9, 28, 6, $1ffffff)
  UndefineMacro F
EndProcedure



;/* Take a fully reduced polynomial form number and contract it into a
; * little-endian, 32-byte array
; */
Procedure fcontract(*output.u8, *input.felem)
  Protected i

  Repeat
    i = 0
    While i < 9
      If ((i & 1) = 1)
        While (*input\q[i] < 0)
          *input\q[i] + $2000000
          *input\q[i + 1] - 1
        Wend
      Else
        While (*input\q[i] < 0)
          *input\q[i] + $4000000
          *input\q[i + 1] - 1
        Wend
      EndIf
      i + 1
    Wend
    While (*input\q[9] < 0)
      *input\q[9] + $2000000
      *input\q[0] - 19
    Wend
  Until *input\q[0] >= 0

  *input\q[1] << 2
  *input\q[2] << 3
  *input\q[3] << 5
  *input\q[4] << 6
  *input\q[6] << 1
  *input\q[7] << 3
  *input\q[8] << 4
  *input\q[9] << 6
  
  Macro F(i, s)
      *output\a[s+0] | (*input\q[i] & $ff)
      *output\a[s+1] = ((*input\q[i] >>  8) & $ff)
      *output\a[s+2] = ((*input\q[i] >> 16) & $ff)
      *output\a[s+3] = ((*input\q[i] >> 24) & $ff)
  EndMacro
  
  *output\a[0]  = 0
  *output\a[16] = 0
  F(0,0)
  F(1,3)
  F(2,6)
  F(3,9)
  F(4,12)
  F(5,16)
  F(6,19)
  F(7,22)
  F(8,25)
  F(9,28)
  
  UndefineMacro F
  
EndProcedure


;/* Input: Q, Q', Q-Q'
; * Output: 2Q, Q+Q'
; *
; *   x2 z3: long form
; *   x3 z3: long form
; *   x z: short form, destroyed
; *   xprime zprime: short form, destroyed
; *   qmqp: short form, preserved
; */
Procedure fmonty(*x2.felem, *z2.felem          Comment("/* output 2Q     */") ,
                 *x3.felem, *z3.felem          Comment("/* output Q + Q' */") ,
                 *x.felem , *z.felem           Comment("/* input Q       */") ,
                 *xprime.felem, *zprime.felem  Comment("/* input Q'      */") ,
                 *qmqp.felem                   Comment("/* input Q - Q'  */") )
  ; following Dim's are all of type felem
  Dim origx.q(10)   : Dim origxprime.q(10)
  Dim zzz.q(19)     : Dim xx.q(19)         : Dim zz.q(19)
  Dim xxprime.q(19) : Dim zzprime.q(19)    : Dim zzzprime.q(19) : Dim xxxprime.q(19)

  CopyMemory(*x, @origx(), 10 * SizeOf(Quad)) ; SizeOf(felem)
  fsum(*x, *z)
  fdifference(*z, @origx())  ; does x - z

  CopyMemory(*xprime, @origxprime(), SizeOf(Quad) * 10) ; SizeOf(felem)
  fsum(*xprime, *zprime)
  fdifference(*zprime, @origxprime())
  fproduct(@xxprime(), *xprime, *z)
  fproduct(@zzprime(), *x, *zprime)
  freduce_degree(@xxprime())
  freduce_coefficients(@xxprime())
  freduce_degree(@zzprime())
  freduce_coefficients(@zzprime())
  CopyMemory(@xxprime(), @origxprime(), SizeOf(Quad) * 10) ; SizeOf(felem)
  fsum(@xxprime(), @zzprime())
  fdifference(@zzprime(), @origxprime())
  fsquare(@xxxprime(), @xxprime())
  fsquare(@zzzprime(), @zzprime())
  fproduct(@zzprime(), @zzzprime(), *qmqp)
  freduce_degree(@zzprime())
  freduce_coefficients(@zzprime())
  CopyMemory(@xxxprime(), *x3, SizeOf(Quad) * 10) ; SizeOf(felem)
  CopyMemory(@zzprime() , *z3, SizeOf(Quad) * 10) ; SizeOf(felem)

  fsquare(@xx(), *x)
  fsquare(@zz(), *z)
  fproduct(*x2, @xx(), @zz())
  freduce_degree(*x2)
  freduce_coefficients(*x2)
  fdifference(@zz(), @xx())  ; does zz = xx - zz
  FillMemory(@zzz()+10*SizeOf(Quad), SizeOf(Quad) * 9, 0, #PB_Byte) ; SizeOf(felem)
  fscalar_product(@zzz(), @zz(), 121665)
  freduce_degree(@zzz())
  freduce_coefficients(@zzz())
  fsum(@zzz(), @xx())
  fproduct(*z2, @zz(), @zzz())
  freduce_degree(*z2)
  freduce_coefficients(*z2)
EndProcedure


;/* Calculates nQ where Q is the x-coordinate of a point on the curve
; *
; *   resultx/resultz: the x coordinate of the resulting curve Point (short form)
; *   n: a little endian, 32-byte number
; *   q: a point of the curve (short form)
; */
Procedure cmult(*resultx.felem, *resultz.felem, *n.u8, *q.felem)
  Protected i, j, byte.a
    
  ; all of type felem
  Dim a.q(19)
  Dim b.q(19) : b(0) = 1
  Dim c.q(19) : c(0) = 1
  Dim d.q(19)
  
  Protected *nqpqx.felem = @a(), *nqpqz.felem = @b(), *nqx.felem = @c(), *nqz.felem = @d()  ;, *t.felem
  
  Dim e.q(19)
  Dim f.q(19) : f(0) = 1
  Dim g.q(19)
  Dim h.q(19) : h(0) = 1

  Protected *nqpqx2.felem = @e(), *nqpqz2.felem = @f(), *nqx2.felem = @g(), *nqz2.felem = @h()

  CopyMemory(*q, *nqpqx, SizeOf(Quad) * 10) ; Sizeof(felem)
  
  i = 0
  While i < 32
    byte = *n\a[31 - i] & $FF ; byte = type u8
    j = 0
    While j < 8
      If (byte & $80)
        fmonty(*nqpqx2, *nqpqz2,
               *nqx2, *nqz2,
               *nqpqx, *nqpqz,
               *nqx, *nqz,
               *q)
      Else
        fmonty(*nqx2, *nqz2,
               *nqpqx2, *nqpqz2,
               *nqx, *nqz,
               *nqpqx, *nqpqz,
               *q)
      EndIf
      
      ;*t = *nqx           ; can be replaced with Swap in PB
      ;*nqx = *nqx2
      ;*nqx2 = *t
      Swap *nqx, *nqx2
      
      ;*t = *nqz
      ;*nqz = *nqz2
      ;*nqz2 = *t
      Swap *nqz, *nqz2
      
      ;*t = *nqpqx
      ;*nqpqx = *nqpqx2
      ;*nqpqx2 = *t
      Swap *nqpqx, *nqpqx2
      
      ;*t = *nqpqz
      ;*nqpqz = *nqpqz2
      ;*nqpqz2 = *t
      Swap *nqpqz, *nqpqz2

      byte = (byte << 1)
      j + 1
    Wend
    i + 1
  Wend

  CopyMemory(*nqx, *resultx, SizeOf(Quad) * 10) ; SizeOf(felem)
  CopyMemory(*nqz, *resultz, SizeOf(Quad) * 10) ; SizeOf(felem)
EndProcedure


;// -----------------------------------------------------------------------------
;// Shamelessly copied from djb's code
;// -----------------------------------------------------------------------------
Procedure crecip(*out.felem, *z.felem)
  ; all Dim of type felem:
  Dim z2.q(10)
  Dim z9.q(10)
  Dim z11.q(10)
  Dim z2_5_0.q(10)
  Dim z2_10_0.q(10)
  Dim z2_20_0.q(10)
  Dim z2_50_0.q(10)
  Dim z2_100_0.q(10)
  Dim t0.q(10)
  Dim t1.q(10)
  
  Protected i

  Comment("/* 2              */") fsquare(@z2(),*z)
  Comment("/* 4              */") fsquare(@t1(),@z2())
  Comment("/* 8              */") fsquare(@t0(),@t1())
  Comment("/* 9              */") fmul(@z9(),@t0(),*z)
  Comment("/* 11             */") fmul(@z11(),@z9(),@z2())
  Comment("/* 22             */") fsquare(@t0(),@z11())
  Comment("/* 2^5 - 2^0 = 31 */") fmul(@z2_5_0(),@t0(),@z9())

  Comment("/* 2^6 - 2^1      */") fsquare(@t0(),@z2_5_0())
  Comment("/* 2^7 - 2^2      */") fsquare(@t1(),@t0())
  Comment("/* 2^8 - 2^3      */") fsquare(@t0(),@t1())
  Comment("/* 2^9 - 2^4      */") fsquare(@t1(),@t0())
  Comment("/* 2^10 - 2^5     */") fsquare(@t0(),@t1())
  Comment("/* 2^10 - 2^0     */") fmul(@z2_10_0(),@t0(),@z2_5_0())

  Comment("/* 2^11 - 2^1     */") fsquare(@t0(),@z2_10_0())
  Comment("/* 2^12 - 2^2     */") fsquare(@t1(),@t0())
  Comment("/* 2^20 - 2^10    */") i=2 : While i < 10 : fsquare(@t0(),@t1()) : fsquare(@t1(),@t0()) : i + 2 : Wend
  Comment("/* 2^20 - 2^0     */") fmul(@z2_20_0(),@t1(),@z2_10_0())

  Comment("/* 2^21 - 2^1     */") fsquare(@t0(),@z2_20_0())
  Comment("/* 2^22 - 2^2     */") fsquare(@t1(),@t0())
  Comment("/* 2^40 - 2^20    */") i=2 : While i < 20 : fsquare(@t0(),@t1()) : fsquare(@t1(),@t0()) : i + 2 : Wend
  Comment("/* 2^40 - 2^0     */") fmul(@t0(),@t1(),@z2_20_0())

  Comment("/* 2^41 - 2^1     */") fsquare(@t1(),@t0())
  Comment("/* 2^42 - 2^2     */") fsquare(@t0(),@t1())
  Comment("/* 2^50 - 2^10    */") i=2 : While i < 10 : fsquare(@t1(),@t0()) : fsquare(@t0(),@t1()) : i + 2 : Wend
  Comment("/* 2^50 - 2^0     */") fmul(@z2_50_0(),@t0(),@z2_10_0())

  Comment("/* 2^51 - 2^1     */") fsquare(@t0(),@z2_50_0())
  Comment("/* 2^52 - 2^2     */") fsquare(@t1(),@t0())
  Comment("/* 2^100 - 2^50   */") i=2 : While i < 50 : fsquare(@t0(),@t1()) : fsquare(@t1(),@t0()) : i + 2 : Wend
  Comment("/* 2^100 - 2^0    */") fmul(@z2_100_0(),@t1(),@z2_50_0())

  Comment("/* 2^101 - 2^1    */") fsquare(@t1(),@z2_100_0())
  Comment("/* 2^102 - 2^2    */") fsquare(@t0(),@t1())
  Comment("/* 2^200 - 2^100  */") i=2 : While i < 100 : fsquare(@t1(),@t0()) : fsquare(@t0(),@t1()): i + 2 : Wend
  Comment("/* 2^200 - 2^0    */") fmul(@t1(),@t0(),@z2_100_0())

  Comment("/* 2^201 - 2^1    */") fsquare(@t0(),@t1())
  Comment("/* 2^202 - 2^2    */") fsquare(@t1(),@t0())
  Comment("/* 2^250 - 2^50   */") i=2 : While i < 50 : fsquare(@t0(),@t1()) : fsquare(@t1(),@t0()) : i + 2 : Wend
  Comment("/* 2^250 - 2^0    */") fmul(@t0(),@t1(),@z2_50_0())

  Comment("/* 2^251 - 2^1    */") fsquare(@t1(),@t0())
  Comment("/* 2^252 - 2^2    */") fsquare(@t0(),@t1())
  Comment("/* 2^253 - 2^3    */") fsquare(@t1(),@t0())
  Comment("/* 2^254 - 2^4    */") fsquare(@t0(),@t1())
  Comment("/* 2^255 - 2^5    */") fsquare(@t1(),@t0())
  Comment("/* 2^255 - 21     */") fmul(*out,@t1(),@z11())
EndProcedure

Procedure.i curve25519_donna(*mypublic.u8, *secret.u8, *basepoint.u8)
  ; Dim of type felem:
  Dim bp.q(10)
  Dim x.q(10)
  Dim z.q(10)
  Dim zmone.q(10)
  
  ; Dim of type uint8_t
  Dim e.a(32)
  
  Protected i

  i = 0
  While i < 32
      e(i) = *secret\a[i]
      i + 1
  Wend
      
  e(0)  & 248
  e(31) & 127
  e(31) | 64

  fexpand(@bp(), *basepoint)
  cmult(@x(), @z(), @e(), @bp())
  crecip(@zmone(), @z())
  fmul(@z(), @x(), @zmone())
  fcontract(*mypublic, @z())
  ProcedureReturn 0
EndProcedure




;----------------------------------------------------------------------------------
; test code by idle
;----------------------------------------------------------------------------------




Procedure.s dB(*mem,len)
  Protected a,st.s
  st = ""
  For a = 0 To len-1
   st+RSet(Hex(PeekA(*mem+a),#PB_Byte),2,"0")
  Next 
  ProcedureReturn st
EndProcedure



;Global *tA = AllocateMemory(19*8)
;Global *tB = AllocateMemory(19*8)

Global *mysecret = AllocateMemory(32)
Global *mypublic = AllocateMemory(32)
Global *basepoint = AllocateMemory(32)
Global *hissecret = AllocateMemory(32)
Global *hispublic = AllocateMemory(32)
Global *myshared = AllocateMemory(32)
Global *hisshared = AllocateMemory(32)

Define i 
For i=0 To 31 : PokeA(*mysecret+i,42) : Next

 PokeA(*mysecret+0, PeekA(*mysecret+0) & 248)
 PokeA(*mysecret+31, PeekA(*mysecret+31) & 127)
 PokeA(*mysecret+31, PeekA(*mysecret+31) | 64)

PokeA(*basepoint+0,9)

;-----

For i=0 To 31 : PokeA(*hissecret+i,11) : Next
   PokeA(*hissecret+0, PeekA(*hissecret+0) & 248)
   PokeA(*hissecret+31, PeekA(*hissecret+31) & 127)
   PokeA(*hissecret+31, PeekA(*hissecret+31) | 64)

;---

Define str$, str_myshared$, str_hisshared$

OpenConsole()
ConsoleTitle("Curve25519 Test")

str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mysecret+i),#PB_Byte),2,"0"): Next :   PrintN("mysecret : "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve25519_donna(*mypublic, *mysecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*mypublic+i),#PB_Byte),2,"0"): Next :   PrintN("mypublic : "+str$)
PrintN("")
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hissecret+i),#PB_Byte),2,"0"): Next :  PrintN("hissecret: "+str$)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*basepoint+i),#PB_Byte),2,"0"): Next :  PrintN("basepoint: "+str$)
curve25519_donna(*hispublic, *hissecret, *basepoint)
str$="": For i=0 To 31: str$+RSet(Hex(PeekA(*hispublic+i),#PB_Byte),2,"0"): Next :  PrintN("hispublic: "+str$)
PrintN("")
curve25519_donna(*myshared, *mysecret, *hispublic)
curve25519_donna(*hisshared, *hissecret, *mypublic)
str_myshared$="": For i=0 To 31: str_myshared$+RSet(Hex(PeekA(*myshared+i),#PB_Byte),2,"0"): Next :   PrintN("myshared : "+str_myshared$)
str_hisshared$="": For i=0 To 31: str_hisshared$+RSet(Hex(PeekA(*hisshared+i),#PB_Byte),2,"0"): Next :  PrintN("hisshared: "+str_hisshared$)
PrintN("")
If str_myshared$ = str_hisshared$
  PrintN("myshared = hisshared")
Else
  PrintN("myshared <> hisshared")
EndIf

PrintN("")
PrintN("")
PrintN("PRESS 'RETURN' TO QUIT.")
Input()
CloseConsole()

Re: broken c port of Ec25519 key exchange

Posted: Sun Mar 24, 2013 2:55 am
by PeterH
If I had ovaries you would be the future father of my children. Safe key exchange - check. Safe DSA in pure PB - maybe soon. :)

Re: broken c port of Ec25519 key exchange

Posted: Sun Mar 24, 2013 5:24 am
by idle
Danilo wrote: I did port directly from the C source in your first posting and it works:
Thanks.