summaryrefslogtreecommitdiff
path: root/xed25519.cpp
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2018-12-12 03:56:09 -0500
committerJeffrey Walton <noloader@gmail.com>2018-12-12 03:56:09 -0500
commite97d6d0ff5c5ae428d70954116f1587d09227772 (patch)
treebbb40e52b26e377000155db35414812534c8ca33 /xed25519.cpp
parent80776453f8187ad704e69886b856ee65115d3b25 (diff)
downloadcryptopp-git-e97d6d0ff5c5ae428d70954116f1587d09227772.tar.gz
Fix failed self test when NO_OS_DEPENDENCE (GH #761)
Add is_clamped for secret key validation. Cleanup paramter names in Donna::curve25519 to follow function. Overload Donna::curve25519 to implicitly use base point if not provided. Add additional asserts to let the code debug itself. Update documentation.
Diffstat (limited to 'xed25519.cpp')
-rw-r--r--xed25519.cpp82
1 files changed, 63 insertions, 19 deletions
diff --git a/xed25519.cpp b/xed25519.cpp
index b97182e4..f00347f3 100644
--- a/xed25519.cpp
+++ b/xed25519.cpp
@@ -63,6 +63,11 @@ int is_small_order(const byte s[32])
return (int) ((k >> 8) & 1);
}
+int is_clamped(const byte s[32])
+{
+ return (s[0] & 248) == s[0] && (s[31] & 127) == s[31] && (s[31] | 64) == s[31];
+}
+
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
@@ -71,12 +76,18 @@ x25519::x25519(const byte y[32], const byte x[32])
{
std::memcpy(m_pk, y, 32);
std::memcpy(m_sk, x, 32);
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
x25519::x25519(const byte x[32])
{
std::memcpy(m_sk, x, 32);
GeneratePublicKey(NullRNG(), m_sk, m_pk);
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
x25519::x25519(const Integer &y, const Integer &x)
@@ -86,6 +97,9 @@ x25519::x25519(const Integer &y, const Integer &x)
ArraySink xs(m_sk, 32);
x.Encode(xs, 32);
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
x25519::x25519(const Integer &x)
@@ -93,46 +107,72 @@ x25519::x25519(const Integer &x)
ArraySink xs(m_sk, 32);
x.Encode(xs, 32);
GeneratePublicKey(NullRNG(), m_sk, m_pk);
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
x25519::x25519(RandomNumberGenerator &rng)
{
GeneratePrivateKey(rng, m_sk);
GeneratePublicKey(NullRNG(), m_sk, m_pk);
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
x25519::x25519(BufferedTransformation &params)
{
- // TODO: Fix the on-disk format once we know what it is.
+ // TODO: Fix the on-disk format once we determine what it is.
BERSequenceDecoder seq(params);
- BERGeneralDecoder x(seq, BIT_STRING);
- if (!x.IsDefiniteLength() || x.MaxRetrievable() < 32)
- BERDecodeError();
- x.Get(m_sk, 32);
- x.MessageEnd();
+ size_t read; byte unused;
+
+ BERSequenceDecoder sk(seq, BIT_STRING);
+ read = sk.Get(unused); // unused bits
+ CRYPTOPP_ASSERT(read == 1 && unused == 0);
+
+ CRYPTOPP_ASSERT(sk.MaxRetrievable() >= 32);
+ read = sk.Get(m_sk, 32);
+ sk.MessageEnd();
+
+ if (read != 32)
+ throw BERDecodeErr();
- BERGeneralDecoder y(seq, OCTET_STRING);
- if (!y.IsDefiniteLength() || y.MaxRetrievable() < 32)
- BERDecodeError();
- y.Get(m_pk, 32);
- y.MessageEnd();
+ if (seq.EndReached())
+ {
+ GeneratePublicKey(NullRNG(), m_sk, m_pk);
+ }
+ else
+ {
+ BERSequenceDecoder pk(seq, OCTET_STRING);
+ CRYPTOPP_ASSERT(pk.MaxRetrievable() >= 32);
+ read = pk.Get(m_pk, 32);
+ pk.MessageEnd();
+
+ if (read != 32)
+ throw BERDecodeErr();
+ }
seq.MessageEnd();
+
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
}
void x25519::DEREncode(BufferedTransformation &params) const
{
- // TODO: Fix the on-disk format once we know what it is.
+ // TODO: Fix the on-disk format once we determine what it is.
DERSequenceEncoder seq(params);
- DERSequenceEncoder x(seq, BIT_STRING);
- x.Put(m_sk, 32);
- x.MessageEnd();
+ DERSequenceEncoder sk(seq, BIT_STRING);
+ sk.Put((byte)0); // unused bits
+ sk.Put(m_sk, 32);
+ sk.MessageEnd();
- DERSequenceEncoder y(seq, OCTET_STRING);
- y.Put(m_pk, 32);
- y.MessageEnd();
+ DERSequenceEncoder pk(seq, OCTET_STRING);
+ pk.Put(m_pk, 32);
+ pk.MessageEnd();
seq.MessageEnd();
}
@@ -140,8 +180,12 @@ void x25519::DEREncode(BufferedTransformation &params) const
bool x25519::Validate(RandomNumberGenerator &rng, unsigned int level) const
{
CRYPTOPP_UNUSED(rng);
+ CRYPTOPP_ASSERT(is_clamped(m_sk) != 0);
+ CRYPTOPP_ASSERT(is_small_order(m_pk) == 0);
- if (level >= 2 && is_small_order(m_pk) != 0)
+ if (level >= 1 && is_clamped(m_sk) == 0)
+ return false;
+ else if (level >= 2 && is_small_order(m_pk) != 0)
return false;
return true;