mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-12 04:42:36 -03:00
Added constant time methods to FieldElem class.
This commit is contained in:
parent
b358450114
commit
8803181c61
2 changed files with 65 additions and 4 deletions
59
field.cpp
59
field.cpp
|
@ -33,8 +33,11 @@ FieldElem::FieldElem(const unsigned char *b32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldElem::Normalize() {
|
void FieldElem::Normalize() {
|
||||||
|
#ifdef CONSTANT_TIME
|
||||||
|
NormalizeCT();
|
||||||
|
return;
|
||||||
|
#else
|
||||||
uint64_t c;
|
uint64_t c;
|
||||||
#ifndef CONSTANT_TIME
|
|
||||||
if (n[0] > 0xFFFFFFFFFFFFFULL || n[1] > 0xFFFFFFFFFFFFFULL || n[2] > 0xFFFFFFFFFFFFFULL || n[3] > 0xFFFFFFFFFFFFFULL || n[4] > 0xFFFFFFFFFFFFULL) {
|
if (n[0] > 0xFFFFFFFFFFFFFULL || n[1] > 0xFFFFFFFFFFFFFULL || n[2] > 0xFFFFFFFFFFFFFULL || n[3] > 0xFFFFFFFFFFFFFULL || n[4] > 0xFFFFFFFFFFFFULL) {
|
||||||
c = n[0];
|
c = n[0];
|
||||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
||||||
|
@ -69,7 +72,14 @@ void FieldElem::Normalize() {
|
||||||
n[1] = 0;
|
n[1] = 0;
|
||||||
n[0] -= 0xFFFFEFFFFFC2FULL;
|
n[0] -= 0xFFFFEFFFFFC2FULL;
|
||||||
}
|
}
|
||||||
#else
|
#ifdef VERIFY_MAGNITUDE
|
||||||
|
magnitude = 1;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldElem::NormalizeCT() {
|
||||||
|
uint64_t c;
|
||||||
c = n[0];
|
c = n[0];
|
||||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
||||||
c = (c >> 52) + n[1];
|
c = (c >> 52) + n[1];
|
||||||
|
@ -106,8 +116,7 @@ void FieldElem::Normalize() {
|
||||||
n[2] &= mask;
|
n[2] &= mask;
|
||||||
n[1] &= mask;
|
n[1] &= mask;
|
||||||
n[0] -= (~mask & 0xFFFFEFFFFFC2FULL);
|
n[0] -= (~mask & 0xFFFFEFFFFFC2FULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VERIFY_MAGNITUDE
|
#ifdef VERIFY_MAGNITUDE
|
||||||
magnitude = 1;
|
magnitude = 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -118,12 +127,23 @@ bool inline FieldElem::IsZero() {
|
||||||
return (n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0);
|
return (n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool inline FieldElem::IsZeroCT() {
|
||||||
|
NormalizeCT();
|
||||||
|
return (n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool inline operator==(FieldElem &a, FieldElem &b) {
|
bool inline operator==(FieldElem &a, FieldElem &b) {
|
||||||
a.Normalize();
|
a.Normalize();
|
||||||
b.Normalize();
|
b.Normalize();
|
||||||
return (a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]);
|
return (a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool inline EqualCT(FieldElem &a, FieldElem &b) {
|
||||||
|
a.NormalizeCT();
|
||||||
|
b.NormalizeCT();
|
||||||
|
return (a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]);
|
||||||
|
}
|
||||||
|
|
||||||
void FieldElem::GetBytes(unsigned char *o) {
|
void FieldElem::GetBytes(unsigned char *o) {
|
||||||
Normalize();
|
Normalize();
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
|
@ -137,6 +157,19 @@ void FieldElem::GetBytes(unsigned char *o) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FieldElem::GetBytesCT(unsigned char *o) {
|
||||||
|
NormalizeCT();
|
||||||
|
for (int i=0; i<32; i++) {
|
||||||
|
int c = 0;
|
||||||
|
for (int j=0; j<2; j++) {
|
||||||
|
int limb = (8*i+4*j)/52;
|
||||||
|
int shift = (8*i+4*j)%52;
|
||||||
|
c |= ((n[limb] >> shift) & 0xF) << (4 * j);
|
||||||
|
}
|
||||||
|
o[31-i] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FieldElem::SetBytes(const unsigned char *in) {
|
void FieldElem::SetBytes(const unsigned char *in) {
|
||||||
n[0] = n[1] = n[2] = n[3] = n[4] = 0;
|
n[0] = n[1] = n[2] = n[3] = n[4] = 0;
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
|
@ -329,6 +362,11 @@ bool FieldElem::IsOdd() {
|
||||||
return n[0] & 1;
|
return n[0] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FieldElem::IsOddCT() {
|
||||||
|
NormalizeCT();
|
||||||
|
return n[0] & 1;
|
||||||
|
}
|
||||||
|
|
||||||
std::string FieldElem::ToString() {
|
std::string FieldElem::ToString() {
|
||||||
unsigned char tmp[32];
|
unsigned char tmp[32];
|
||||||
GetBytes(tmp);
|
GetBytes(tmp);
|
||||||
|
@ -341,6 +379,18 @@ std::string FieldElem::ToString() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FieldElem::ToStringCT() {
|
||||||
|
unsigned char tmp[32];
|
||||||
|
GetBytesCT(tmp);
|
||||||
|
std::string ret;
|
||||||
|
for (int i=0; i<32; i++) {
|
||||||
|
static const char *c = "0123456789ABCDEF";
|
||||||
|
ret += c[(tmp[i] >> 4) & 0xF];
|
||||||
|
ret += c[(tmp[i]) & 0xF];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void FieldElem::SetHex(const std::string &str) {
|
void FieldElem::SetHex(const std::string &str) {
|
||||||
unsigned char tmp[32] = {};
|
unsigned char tmp[32] = {};
|
||||||
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||||
|
@ -378,6 +428,7 @@ const FieldConstants &GetFieldConst() {
|
||||||
return field_const;
|
return field_const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nonbuiltin Field Inverse is not constant time.
|
||||||
void FieldElem::SetInverse(FieldElem &a) {
|
void FieldElem::SetInverse(FieldElem &a) {
|
||||||
#if defined(USE_FIELDINVERSE_BUILTIN)
|
#if defined(USE_FIELDINVERSE_BUILTIN)
|
||||||
// calculate a^p, with p={45,63,1019,1023}
|
// calculate a^p, with p={45,63,1019,1023}
|
||||||
|
|
10
field.h
10
field.h
|
@ -18,6 +18,10 @@ namespace secp256k1 {
|
||||||
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
|
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
|
||||||
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their
|
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their
|
||||||
* output.
|
* output.
|
||||||
|
*
|
||||||
|
* There are two implementations of the Normalize method, NormalizeCT executing in constant time.
|
||||||
|
* Similarly, a second version of all the other methods that call Normalize have been added which
|
||||||
|
* NormalizeCT instead to prevent sidechannel leaks.
|
||||||
*/
|
*/
|
||||||
class FieldElem {
|
class FieldElem {
|
||||||
private:
|
private:
|
||||||
|
@ -36,13 +40,17 @@ public:
|
||||||
|
|
||||||
/** Normalizes the internal representation entries. Magnitude=1 */
|
/** Normalizes the internal representation entries. Magnitude=1 */
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
void NormalizeCT();
|
||||||
|
|
||||||
bool IsZero();
|
bool IsZero();
|
||||||
|
bool IsZeroCT();
|
||||||
|
|
||||||
bool friend operator==(FieldElem &a, FieldElem &b);
|
bool friend operator==(FieldElem &a, FieldElem &b);
|
||||||
|
bool friend EqualCT(FieldElem &a, FieldElem &b);
|
||||||
|
|
||||||
/** extract as 32-byte big endian array */
|
/** extract as 32-byte big endian array */
|
||||||
void GetBytes(unsigned char *o);
|
void GetBytes(unsigned char *o);
|
||||||
|
void GetBytesCT(unsigned char *o);
|
||||||
|
|
||||||
/** set value of 32-byte big endian array */
|
/** set value of 32-byte big endian array */
|
||||||
void SetBytes(const unsigned char *in);
|
void SetBytes(const unsigned char *in);
|
||||||
|
@ -65,11 +73,13 @@ public:
|
||||||
void SetSquareRoot(const FieldElem &a);
|
void SetSquareRoot(const FieldElem &a);
|
||||||
|
|
||||||
bool IsOdd();
|
bool IsOdd();
|
||||||
|
bool IsOddCT();
|
||||||
|
|
||||||
/** Set this to be the (modular) inverse of another FieldElem. Magnitude=1 */
|
/** Set this to be the (modular) inverse of another FieldElem. Magnitude=1 */
|
||||||
void SetInverse(FieldElem &a);
|
void SetInverse(FieldElem &a);
|
||||||
|
|
||||||
std::string ToString();
|
std::string ToString();
|
||||||
|
std::string ToStringCT();
|
||||||
|
|
||||||
void SetHex(const std::string &str);
|
void SetHex(const std::string &str);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue