Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
matrix-org
Olm
Commits
6c56bcf2
Commit
6c56bcf2
authored
Feb 26, 2015
by
Mark Haines
Browse files
Merge commit '
e50ac707
' as 'lib/curve25519-donna'
parents
09d8e84c
e50ac707
Changes
23
Expand all
Hide whitespace changes
Inline
Side-by-side
lib/curve25519-donna/.gitignore
0 → 100644
View file @
6c56bcf2
/curve25519-donna-c64.a
/curve25519-donna.a
/test-curve25519-donna
/speed-curve25519-donna
/test-curve25519-donna-c64
/speed-curve25519-donna-c64
/test-sc-curve25519-donna-c64
/build
*.o
*.pyc
/dist
/MANIFEST
lib/curve25519-donna/LICENSE.md
0 → 100644
View file @
6c56bcf2
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.
lib/curve25519-donna/Makefile
0 → 100644
View file @
6c56bcf2
CFLAGS
=
-Wmissing-prototypes
-Wdeclaration-after-statement
-O2
-Wall
CFLAGS_32
=
-m32
targets
:
curve25519-donna.a curve25519-donna-c64.a
test
:
test-donna test-donna-c64
clean
:
rm
-f
*
.o
*
.a
*
.pp test-curve25519-donna test-curve25519-donna-c64 speed-curve25519-donna speed-curve25519-donna-c64 test-noncanon-curve25519-donna test-noncanon-curve25519-donna-c64
curve25519-donna.a
:
curve25519-donna.o
ar
-rc
curve25519-donna.a curve25519-donna.o
ranlib curve25519-donna.a
curve25519-donna.o
:
curve25519-donna.c
gcc
-c
curve25519-donna.c
$(CFLAGS)
$(CFLAGS_32)
curve25519-donna-c64.a
:
curve25519-donna-c64.o
ar
-rc
curve25519-donna-c64.a curve25519-donna-c64.o
ranlib curve25519-donna-c64.a
curve25519-donna-c64.o
:
curve25519-donna-c64.c
gcc
-c
curve25519-donna-c64.c
$(CFLAGS)
test-donna
:
test-curve25519-donna
./test-curve25519-donna |
head
-123456
|
tail
-1
test-donna-c64
:
test-curve25519-donna-c64
./test-curve25519-donna-c64 |
head
-123456
|
tail
-1
test-curve25519-donna
:
test-curve25519.c curve25519-donna.a
gcc
-o
test-curve25519-donna test-curve25519.c curve25519-donna.a
$(CFLAGS)
$(CFLAGS_32)
test-curve25519-donna-c64
:
test-curve25519.c curve25519-donna-c64.a
gcc
-o
test-curve25519-donna-c64 test-curve25519.c curve25519-donna-c64.a
$(CFLAGS)
speed-curve25519-donna
:
speed-curve25519.c curve25519-donna.a
gcc
-o
speed-curve25519-donna speed-curve25519.c curve25519-donna.a
$(CFLAGS)
$(CFLAGS_32)
speed-curve25519-donna-c64
:
speed-curve25519.c curve25519-donna-c64.a
gcc
-o
speed-curve25519-donna-c64 speed-curve25519.c curve25519-donna-c64.a
$(CFLAGS)
test-sc-curve25519-donna-c64
:
test-sc-curve25519.c curve25519-donna-c64.a
gcc
-o
test-sc-curve25519-donna-c64
-O
test-sc-curve25519.c curve25519-donna-c64.a test-sc-curve25519.s
$(CFLAGS)
test-noncanon-donna
:
test-noncanon-curve25519-donna
./test-noncanon-curve25519-donna
test-noncanon-donna-c64
:
test-noncanon-curve25519-donna-c64
./test-noncanon-curve25519-donna-c64
test-noncanon-curve25519-donna
:
test-noncanon.c curve25519-donna.a
gcc
-o
test-noncanon-curve25519-donna test-noncanon.c curve25519-donna.a
$(CFLAGS)
$(CFLAGS_32)
test-noncanon-curve25519-donna-c64
:
test-noncanon.c curve25519-donna-c64.a
gcc
-o
test-noncanon-curve25519-donna-c64 test-noncanon.c curve25519-donna-c64.a
$(CFLAGS)
lib/curve25519-donna/README
0 → 100644
View file @
6c56bcf2
See http://code.google.com/p/curve25519-donna/ for details.
BUILDING:
If you run `make`, two .a archives will be built, similar to djb's curve25519
code. Alternatively, read on:
The C implementation is contained within curve25519-donna.c. It has no external
dependancies and is BSD licenced. You can copy/include/link it directly in with
your program. Recommended C flags: -O2
The x86-64 bit implementation is contained within curve25519-donna-x86-64.c and
curve25519-donna-x86-64.s. Build like this:
% cpp curve25519-donna-x86-64.s > curve25519-donna-x86-64.s.pp
% as -o curve25519-donna-x86-64.s.o curve25519-donna-x86-64.s.pp
% gcc -O2 -c curve25519-donna-x86-64.c
Then the two .o files can be linked in
USAGE:
The usage is exactly the same as djb's code (as described at
http://cr.yp.to/ecdh.html) expect that the function is called curve25519_donna.
In short,
To generate a private key just generate 32 random bytes.
To generate the public key, just do:
static const uint8_t basepoint[32] = {9};
curve25519_donna(mypublic, mysecret, basepoint);
To generate an agreed key do:
uint8_t shared_key[32];
curve25519_donna(shared_key, mysecret, theirpublic);
And hash the shared_key with a cryptographic hash function before using.
lib/curve25519-donna/contrib/Curve25519Donna.c
0 → 100644
View file @
6c56bcf2
/*
James Robson
Public domain.
*/
#include "Curve25519Donna.h"
#include <stdio.h>
#include <stdlib.h>
extern
void
curve25519_donna
(
unsigned
char
*
output
,
const
unsigned
char
*
a
,
const
unsigned
char
*
b
);
unsigned
char
*
as_unsigned_char_array
(
JNIEnv
*
env
,
jbyteArray
array
,
int
*
len
);
jbyteArray
as_byte_array
(
JNIEnv
*
env
,
unsigned
char
*
buf
,
int
len
);
jbyteArray
as_byte_array
(
JNIEnv
*
env
,
unsigned
char
*
buf
,
int
len
)
{
jbyteArray
array
=
(
*
env
)
->
NewByteArray
(
env
,
len
);
(
*
env
)
->
SetByteArrayRegion
(
env
,
array
,
0
,
len
,
(
jbyte
*
)
buf
);
//int i;
//for (i = 0;i < len;++i) printf("%02x",(unsigned int) buf[i]); printf(" ");
//printf("\n");
return
array
;
}
unsigned
char
*
as_unsigned_char_array
(
JNIEnv
*
env
,
jbyteArray
array
,
int
*
len
)
{
*
len
=
(
*
env
)
->
GetArrayLength
(
env
,
array
);
unsigned
char
*
buf
=
(
unsigned
char
*
)
calloc
(
*
len
+
1
,
sizeof
(
char
));
(
*
env
)
->
GetByteArrayRegion
(
env
,
array
,
0
,
*
len
,
(
jbyte
*
)
buf
);
return
buf
;
}
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_curve25519Donna
(
JNIEnv
*
env
,
jobject
obj
,
jbyteArray
a
,
jbyteArray
b
)
{
unsigned
char
o
[
32
]
=
{
0
};
int
l1
,
l2
;
unsigned
char
*
a1
=
as_unsigned_char_array
(
env
,
a
,
&
l1
);
unsigned
char
*
b1
=
as_unsigned_char_array
(
env
,
b
,
&
l2
);
if
(
!
(
l1
==
32
&&
l2
==
32
)
)
{
fprintf
(
stderr
,
"Error, must be length 32"
);
return
NULL
;
}
curve25519_donna
(
o
,
(
const
unsigned
char
*
)
a1
,
(
const
unsigned
char
*
)
b1
);
free
(
a1
);
free
(
b1
);
return
as_byte_array
(
env
,
(
unsigned
char
*
)
o
,
32
);
}
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_makePrivate
(
JNIEnv
*
env
,
jobject
obj
,
jbyteArray
secret
)
{
int
len
;
unsigned
char
*
k
=
as_unsigned_char_array
(
env
,
secret
,
&
len
);
if
(
len
!=
32
)
{
fprintf
(
stderr
,
"Error, must be length 32"
);
return
NULL
;
}
k
[
0
]
&=
248
;
k
[
31
]
&=
127
;
k
[
31
]
|=
64
;
return
as_byte_array
(
env
,
k
,
32
);
}
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_getPublic
(
JNIEnv
*
env
,
jobject
obj
,
jbyteArray
privkey
)
{
int
len
;
unsigned
char
*
private
=
as_unsigned_char_array
(
env
,
privkey
,
&
len
);
if
(
len
!=
32
)
{
fprintf
(
stderr
,
"Error, must be length 32"
);
return
NULL
;
}
unsigned
char
pubkey
[
32
];
unsigned
char
basepoint
[
32
]
=
{
9
};
curve25519_donna
(
pubkey
,
private
,
basepoint
);
return
as_byte_array
(
env
,
(
unsigned
char
*
)
pubkey
,
32
);
}
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_makeSharedSecret
(
JNIEnv
*
env
,
jobject
obj
,
jbyteArray
privkey
,
jbyteArray
their_pubkey
)
{
unsigned
char
shared_secret
[
32
];
int
l1
,
l2
;
unsigned
char
*
private
=
as_unsigned_char_array
(
env
,
privkey
,
&
l1
);
unsigned
char
*
pubkey
=
as_unsigned_char_array
(
env
,
their_pubkey
,
&
l2
);
if
(
!
(
l1
==
32
&&
l2
==
32
)
)
{
fprintf
(
stderr
,
"Error, must be length 32"
);
return
NULL
;
}
curve25519_donna
(
shared_secret
,
private
,
pubkey
);
return
as_byte_array
(
env
,
(
unsigned
char
*
)
shared_secret
,
32
);
}
JNIEXPORT
void
JNICALL
Java_Curve25519Donna_helowrld
(
JNIEnv
*
env
,
jobject
obj
)
{
printf
(
"helowrld
\n
"
);
}
lib/curve25519-donna/contrib/Curve25519Donna.h
0 → 100644
View file @
6c56bcf2
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Curve25519Donna */
#ifndef _Included_Curve25519Donna
#define _Included_Curve25519Donna
#ifdef __cplusplus
extern
"C"
{
#endif
/*
* Class: Curve25519Donna
* Method: curve25519Donna
* Signature: ([B[B)[B
*/
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_curve25519Donna
(
JNIEnv
*
,
jobject
,
jbyteArray
,
jbyteArray
);
/*
* Class: Curve25519Donna
* Method: makePrivate
* Signature: ([B)[B
*/
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_makePrivate
(
JNIEnv
*
,
jobject
,
jbyteArray
);
/*
* Class: Curve25519Donna
* Method: getPublic
* Signature: ([B)[B
*/
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_getPublic
(
JNIEnv
*
,
jobject
,
jbyteArray
);
/*
* Class: Curve25519Donna
* Method: makeSharedSecret
* Signature: ([B[B)[B
*/
JNIEXPORT
jbyteArray
JNICALL
Java_Curve25519Donna_makeSharedSecret
(
JNIEnv
*
,
jobject
,
jbyteArray
,
jbyteArray
);
/*
* Class: Curve25519Donna
* Method: helowrld
* Signature: ()V
*/
JNIEXPORT
void
JNICALL
Java_Curve25519Donna_helowrld
(
JNIEnv
*
,
jobject
);
#ifdef __cplusplus
}
#endif
#endif
lib/curve25519-donna/contrib/Curve25519Donna.java
0 → 100644
View file @
6c56bcf2
/*
James Robson
Public domain.
*/
public
class
Curve25519Donna
{
final
protected
static
char
[]
hexArray
=
"0123456789ABCDEF"
.
toCharArray
();
public
static
String
bytesToHex
(
byte
[]
bytes
)
{
char
[]
hexChars
=
new
char
[
bytes
.
length
*
2
];
int
v
;
for
(
int
j
=
0
;
j
<
bytes
.
length
;
j
++
)
{
v
=
bytes
[
j
]
&
0xFF
;
hexChars
[
j
*
2
]
=
hexArray
[
v
>>>
4
];
hexChars
[
j
*
2
+
1
]
=
hexArray
[
v
&
0x0F
];
}
return
new
String
(
hexChars
);
}
public
native
byte
[]
curve25519Donna
(
byte
[]
a
,
byte
[]
b
);
public
native
byte
[]
makePrivate
(
byte
[]
secret
);
public
native
byte
[]
getPublic
(
byte
[]
privkey
);
public
native
byte
[]
makeSharedSecret
(
byte
[]
privkey
,
byte
[]
theirPubKey
);
public
native
void
helowrld
();
// Uncomment if your Java is 32-bit:
//static { System.loadLibrary("Curve25519Donna"); }
// Otherwise, load this 64-bit .jnilib:
static
{
System
.
loadLibrary
(
"Curve25519Donna_64"
);
}
/*
To give the old tires a kick (OSX):
java -cp `pwd` Curve25519Donna
*/
public
static
void
main
(
String
[]
args
)
{
Curve25519Donna
c
=
new
Curve25519Donna
();
// These should be 32 bytes long
byte
[]
user1Secret
=
"abcdefghijklmnopqrstuvwxyz123456"
.
getBytes
();
byte
[]
user2Secret
=
"654321zyxwvutsrqponmlkjihgfedcba"
.
getBytes
();
// You can use the curve function directly...
//byte[] o = c.curve25519Donna(a, b);
//System.out.println("o = " + bytesToHex(o));
// ... but it's not really necessary. Just use the following
// convenience methods:
byte
[]
privKey
=
c
.
makePrivate
(
user1Secret
);
byte
[]
pubKey
=
c
.
getPublic
(
privKey
);
byte
[]
privKey2
=
c
.
makePrivate
(
user2Secret
);
byte
[]
pubKey2
=
c
.
getPublic
(
privKey2
);
System
.
out
.
println
(
"'user1' privKey = "
+
bytesToHex
(
privKey
));
System
.
out
.
println
(
"'user1' pubKey = "
+
bytesToHex
(
pubKey
));
System
.
out
.
println
(
"==================================================="
);
System
.
out
.
println
(
"'user2' privKey = "
+
bytesToHex
(
privKey2
));
System
.
out
.
println
(
"'user2' pubKey = "
+
bytesToHex
(
pubKey2
));
System
.
out
.
println
(
"==================================================="
);
byte
[]
ss1
=
c
.
makeSharedSecret
(
privKey
,
pubKey2
);
System
.
out
.
println
(
"'user1' computes shared secret: "
+
bytesToHex
(
ss1
));
byte
[]
ss2
=
c
.
makeSharedSecret
(
privKey2
,
pubKey
);
System
.
out
.
println
(
"'user2' computes shared secret: "
+
bytesToHex
(
ss2
));
}
}
lib/curve25519-donna/contrib/make-snippets
0 → 100644
View file @
6c56bcf2
CFLAGS=-Wmissing-prototypes -Wdeclaration-after-statement -O2 -Wall
CC=clang
targets: curve25519-donna.a curve25519-donna-c64.a
test: test-donna test-donna-c64
clean:
rm -f java-src/*.class java-src/*.jnilib *.dylib *.o *.a *.pp test-curve25519-donna test-curve25519-donna-c64 speed-curve25519-donna speed-curve25519-donna-c64
curve25519-donna.a: curve25519-donna.o
ar -rc curve25519-donna.a curve25519-donna.o
ranlib curve25519-donna.a
##### OSX dynamic library (32- & 64-bit)
curve25519donna.dylib: curve25519-donna.a curve25519-donna-c64.a
$(CC) -m32 -fpic -shared -Wl,-all_load curve25519-donna.a -Wl,-all_load -o libcurve25519donna.dylib
$(CC) -fpic -shared -Wl,-all_load curve25519-donna-c64.a -Wl,-all_load -o libcurve25519donna_64.dylib
##### OSX/Java section hence
# Java JNI - compiled for OSX (32- & 64-bit)
Curve25519Donna.class:
cd java-src; javah -jni Curve25519Donna; cd ..
cd java-src; javac Curve25519Donna.java; cd ..
Curve25519Donna.jnilib: curve25519-donna.a curve25519-donna-c64.a Curve25519Donna.class
@echo "Building 32-bit..."
clang -o java-src/libCurve25519Donna.jnilib $(CFLAGS) -lc -shared -m32 -I /System/Library/Frameworks/JavaVM.framework/Headers curve25519-donna.o java-src/Curve25519Donna.c
@echo "Building 64-bit..."
clang -o java-src/libCurve25519Donna_64.jnilib $(CFLAGS) -lc -shared -I /System/Library/Frameworks/JavaVM.framework/Headers curve25519-donna-c64.o java-src/Curve25519Donna.c
##### OSX/Java section end
curve25519-donna.o: curve25519-donna.c
$(CC) -c curve25519-donna.c $(CFLAGS) -m32
curve25519-donna-c64.a: curve25519-donna-c64.o
ar -rc curve25519-donna-c64.a curve25519-donna-c64.o
ranlib curve25519-donna-c64.a
curve25519-donna-c64.o: curve25519-donna-c64.c
$(CC) -c curve25519-donna-c64.c $(CFLAGS)
test-donna: test-curve25519-donna
./test-curve25519-donna | head -123456 | tail -1
test-donna-c64: test-curve25519-donna-c64
./test-curve25519-donna-c64 | head -123456 | tail -1
test-curve25519-donna: test-curve25519.c curve25519-donna.a
$(CC) -o test-curve25519-donna test-curve25519.c curve25519-donna.a $(CFLAGS) -m32
test-curve25519-donna-c64: test-curve25519.c curve25519-donna-c64.a
$(CC) -o test-curve25519-donna-c64 test-curve25519.c curve25519-donna-c64.a $(CFLAGS)
speed-curve25519-donna: speed-curve25519.c curve25519-donna.a
$(CC) -o speed-curve25519-donna speed-curve25519.c curve25519-donna.a $(CFLAGS) -m32
speed-curve25519-donna-c64: speed-curve25519.c curve25519-donna-c64.a
$(CC) -o speed-curve25519-donna-c64 speed-curve25519.c curve25519-donna-c64.a $(CFLAGS)
test-sc-curve25519-donna-c64: test-sc-curve25519.c curve25519-donna-c64.a
$(CC) -o test-sc-curve25519-donna-c64 -O test-sc-curve25519.c curve25519-donna-c64.a test-sc-curve25519.s $(CFLAGS)
lib/curve25519-donna/curve25519-donna-c64.c
0 → 100644
View file @
6c56bcf2
/* Copyright 2008, Google Inc.
* All rights reserved.
*
* Code released into the public domain.
*
* 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
uint64_t
limb
;
typedef
limb
felem
[
5
];
// This is a special gcc mode for 128-bit integers. It's implemented on 64-bit
// platforms only as far as I know.
typedef
unsigned
uint128_t
__attribute__
((
mode
(
TI
)));
#undef force_inline
#define force_inline __attribute__((always_inline))
/* Sum two numbers: output += in */
static
inline
void
force_inline
fsum
(
limb
*
output
,
const
limb
*
in
)
{
output
[
0
]
+=
in
[
0
];
output
[
1
]
+=
in
[
1
];
output
[
2
]
+=
in
[
2
];
output
[
3
]
+=
in
[
3
];
output
[
4
]
+=
in
[
4
];
}
/* Find the difference of two numbers: output = in - output
* (note the order of the arguments!)
*
* Assumes that out[i] < 2**52
* On return, out[i] < 2**55
*/
static
inline
void
force_inline
fdifference_backwards
(
felem
out
,
const
felem
in
)
{
/* 152 is 19 << 3 */
static
const
limb
two54m152
=
(((
limb
)
1
)
<<
54
)
-
152
;
static
const
limb
two54m8
=
(((
limb
)
1
)
<<
54
)
-
8
;
out
[
0
]
=
in
[
0
]
+
two54m152
-
out
[
0
];
out
[
1
]
=
in
[
1
]
+
two54m8
-
out
[
1
];
out
[
2
]
=
in
[
2
]
+
two54m8
-
out
[
2
];
out
[
3
]
=
in
[
3
]
+
two54m8
-
out
[
3
];
out
[
4
]
=
in
[
4
]
+
two54m8
-
out
[
4
];
}
/* Multiply a number by a scalar: output = in * scalar */
static
inline
void
force_inline
fscalar_product
(
felem
output
,
const
felem
in
,
const
limb
scalar
)
{
uint128_t
a
;
a
=
((
uint128_t
)
in
[
0
])
*
scalar
;
output
[
0
]
=
((
limb
)
a
)
&
0x7ffffffffffff
;
a
=
((
uint128_t
)
in
[
1
])
*
scalar
+
((
limb
)
(
a
>>
51
));
output
[
1
]
=
((
limb
)
a
)
&
0x7ffffffffffff
;
a
=
((
uint128_t
)
in
[
2
])
*
scalar
+
((
limb
)
(
a
>>
51
));
output
[
2
]
=
((
limb
)
a
)
&
0x7ffffffffffff
;
a
=
((
uint128_t
)
in
[
3
])
*
scalar
+
((
limb
)
(
a
>>
51
));
output
[
3
]
=
((
limb
)
a
)
&
0x7ffffffffffff
;
a
=
((
uint128_t
)
in
[
4
])
*
scalar
+
((
limb
)
(
a
>>
51
));
output
[
4
]
=
((
limb
)
a
)
&
0x7ffffffffffff
;
output
[
0
]
+=
(
a
>>
51
)
*
19
;
}
/* Multiply two numbers: output = in2 * in
*
* output must be distinct to both inputs. The inputs are reduced coefficient
* form, the output is not.
*
* Assumes that in[i] < 2**55 and likewise for in2.
* On return, output[i] < 2**52
*/
static
inline
void
force_inline
fmul
(
felem
output
,
const
felem
in2
,
const
felem
in
)
{
uint128_t
t
[
5
];
limb
r0
,
r1
,
r2
,
r3
,
r4
,
s0
,
s1
,
s2
,
s3
,
s4
,
c
;
r0
=
in
[
0
];
r1
=
in
[
1
];
r2
=
in
[
2
];
r3
=
in
[
3
];
r4
=
in
[
4
];
s0
=
in2
[
0
];
s1
=
in2
[
1
];
s2
=
in2
[
2
];
s3
=
in2
[
3
];
s4
=
in2
[
4
];
t
[
0
]
=
((
uint128_t
)
r0
)
*
s0
;
t
[
1
]
=
((
uint128_t
)
r0
)
*
s1
+
((
uint128_t
)
r1
)
*
s0
;
t
[
2
]
=
((
uint128_t
)
r0
)
*
s2
+
((
uint128_t
)
r2
)
*
s0
+
((
uint128_t
)
r1
)
*
s1
;
t
[
3
]
=
((
uint128_t
)
r0
)
*
s3
+
((
uint128_t
)
r3
)
*
s0
+
((
uint128_t
)
r1
)
*
s2
+
((
uint128_t
)
r2
)
*
s1
;
t
[
4
]
=
((
uint128_t
)
r0
)
*
s4
+
((
uint128_t
)
r4
)
*
s0
+
((
uint128_t
)
r3
)
*
s1
+
((
uint128_t
)
r1
)
*
s3
+
((
uint128_t
)
r2
)
*
s2
;
r4
*=
19
;
r1
*=
19
;
r2
*=
19
;
r3
*=
19
;