From d86fcf64a74c86b5380199c2c5c3c413d1c9b41c Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 11 Feb 2019 12:29:04 -0500 Subject: [PATCH 1/4] Update documentation --- xed25519.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/xed25519.h b/xed25519.h index f581a586..8a4f2a64 100644 --- a/xed25519.h +++ b/xed25519.h @@ -545,9 +545,13 @@ struct ed25519Signer : public PK_Signer ed25519Signer(BufferedTransformation ¶ms); // DL_ObjectImplBase + /// \brief Retrieves a reference to a Private Key + /// \details AccessKey() retrieves a non-const reference to a private key. PrivateKey& AccessKey() { return m_key; } PrivateKey& AccessPrivateKey() { return m_key; } + /// \brief Retrieves a reference to a Private Key + /// \details AccessKey() retrieves a const reference to a private key. const PrivateKey& GetKey() const { return m_key; } const PrivateKey& GetPrivateKey() const { return m_key; } @@ -584,6 +588,7 @@ struct ed25519Signer : public PK_Signer /// \details ed25519 is a determinsitic signature scheme. IsProbabilistic() /// returns false and the random number generator can be NullRNG(). /// \pre COUNTOF(signature) == MaxSignatureLength() + /// \since Crypto++ 8.1 size_t SignStream (RandomNumberGenerator &rng, std::istream& stream, byte *signature) const; protected: @@ -723,9 +728,13 @@ struct ed25519Verifier : public PK_Verifier ed25519Verifier(const ed25519Signer& signer); // DL_ObjectImplBase + /// \brief Retrieves a reference to a Public Key + /// \details AccessKey() retrieves a non-const reference to a public key. PublicKey& AccessKey() { return m_key; } PublicKey& AccessPublicKey() { return m_key; } + /// \brief Retrieves a reference to a Public Key + /// \details GetKey() retrieves a const reference to a public key. const PublicKey& GetKey() const { return m_key; } const PublicKey& GetPublicKey() const { return m_key; } @@ -761,6 +770,7 @@ struct ed25519Verifier : public PK_Verifier /// \return true if the signature is valid, false otherwise /// \details VerifyStream() handles large streams. It was added for signing and verifying /// files that are too large for a memory allocation. + /// \since Crypto++ 8.1 bool VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const; DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const { @@ -776,7 +786,9 @@ protected: /// \since Crypto++ 8.0 struct ed25519 { + /// \brief ed25519 Signer typedef ed25519Signer Signer; + /// \brief ed25519 Verifier typedef ed25519Verifier Verifier; }; From 6befce1851e01977057331fb15de8474f6618a0a Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 11 Feb 2019 12:44:30 -0500 Subject: [PATCH 2/4] Update documentation --- xed25519.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/xed25519.h b/xed25519.h index 8a4f2a64..c0e0dd30 100644 --- a/xed25519.h +++ b/xed25519.h @@ -1,8 +1,8 @@ // xed25519.h - written and placed in public domain by Jeffrey Walton // Crypto++ specific implementation wrapped around Andrew // Moon's public domain curve25519-donna and ed25519-donna, -// https://github.com/floodyberry/curve25519-donna and -// https://github.com/floodyberry/ed25519-donna. +// http://github.com/floodyberry/curve25519-donna and +// http://github.com/floodyberry/ed25519-donna. // Typically the key agreement classes encapsulate their data more // than x25519 does below. They are a little more accessible @@ -23,15 +23,15 @@ /// clamed with 248. That is my_arr[0] &= 248 to mask the lower 3 bits. /// \details PKCS8 and X509 keys encoded using ASN.1 follow little endian /// arrays. The format is specified in draft-ietf-curdle-pkix. +/// "http:///tools.ietf.org/html/draft-ietf-curdle-pkix">draft-ietf-curdle-pkix. /// \details If you have a little endian array and you want to wrap it in /// an Integer using big endian then you can perform the following: ///
Integer x(my_arr, SECRET_KEYLENGTH, UNSIGNED, LITTLE_ENDIAN_ORDER);
/// \sa Andrew Moon's x22519 GitHub curve25519-donna, +/// HREF="http://github.com/floodyberry/curve25519-donna">curve25519-donna, /// ed22519 GitHub ed25519-donna, and -/// draft-ietf-curdle-pkix +/// HREF="http://github.com/floodyberry/ed25519-donna">ed25519-donna, and +/// draft-ietf-curdle-pkix /// \since Crypto++ 8.0 #ifndef CRYPTOPP_XED25519_H @@ -155,7 +155,7 @@ public: /// The default private key format is RFC 5208, which is the old format. /// The old format provides the best interop, and keys will work /// with OpenSSL. - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Save(BufferedTransformation &bt) const { DEREncode(bt, 0); @@ -174,7 +174,7 @@ public: /// the best interop, and keys will work with OpenSSL. The other /// option uses INTEGER 1. INTEGER 1 means RFC 5958 format, /// which is the new format. - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Save(BufferedTransformation &bt, bool v1) const { DEREncode(bt, v1 ? 0 : 1); @@ -182,7 +182,7 @@ public: /// \brief BER decode ASN.1 object /// \param bt BufferedTransformation object - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Load(BufferedTransformation &bt) { BERDecode(bt); @@ -378,7 +378,7 @@ struct ed25519PrivateKey : public PKCS8PrivateKey /// The default private key format is RFC 5208, which is the old format. /// The old format provides the best interop, and keys will work /// with OpenSSL. - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Save(BufferedTransformation &bt) const { DEREncode(bt, 0); @@ -397,7 +397,7 @@ struct ed25519PrivateKey : public PKCS8PrivateKey /// the best interop, and keys will work with OpenSSL. The other /// option uses INTEGER 1. INTEGER 1 means RFC 5958 format, /// which is the new format. - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Save(BufferedTransformation &bt, bool v1) const { DEREncode(bt, v1 ? 0 : 1); @@ -405,7 +405,7 @@ struct ed25519PrivateKey : public PKCS8PrivateKey /// \brief BER decode ASN.1 object /// \param bt BufferedTransformation object - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Load(BufferedTransformation &bt) { BERDecode(bt); @@ -583,8 +583,9 @@ struct ed25519Signer : public PK_Signer /// \param stream an std::istream derived class /// \param signature a block of bytes for the signature /// \return actual signature length - /// \details SignStream() handles large streams. It was added for signing and verifying - /// files that are too large for a memory allocation. + /// \details SignStream() handles large streams. The Stream functions were added to + /// ed25519 for signing and verifying files that are too large for a memory allocation. + /// The functions are not present in other library signers and verifiers. /// \details ed25519 is a determinsitic signature scheme. IsProbabilistic() /// returns false and the random number generator can be NullRNG(). /// \pre COUNTOF(signature) == MaxSignatureLength() @@ -640,7 +641,7 @@ struct ed25519PublicKey : public X509PublicKey /// \brief BER decode ASN.1 object /// \param bt BufferedTransformation object - /// \sa RFC 5958, Asymmetric + /// \sa RFC 5958, Asymmetric /// Key Packages void Load(BufferedTransformation &bt) { BERDecode(bt); @@ -768,8 +769,9 @@ struct ed25519Verifier : public PK_Verifier /// \param signature a pointer to the signature over the message /// \param signatureLen the size of the signature /// \return true if the signature is valid, false otherwise - /// \details VerifyStream() handles large streams. It was added for signing and verifying - /// files that are too large for a memory allocation. + /// \details VerifyStream() handles large streams. The Stream functions were added to + /// ed25519 for signing and verifying files that are too large for a memory allocation. + /// The functions are not present in other library signers and verifiers. /// \since Crypto++ 8.1 bool VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const; @@ -783,6 +785,7 @@ protected: }; /// \brief Ed25519 signature scheme +/// \sa Ed25519 on the Crypto++ wiki. /// \since Crypto++ 8.0 struct ed25519 { From a9eac2ce6ea615f611e1a0f2738f79e797efe074 Mon Sep 17 00:00:00 2001 From: asbai Date: Wed, 13 Feb 2019 04:05:39 +0800 Subject: [PATCH 3/4] Fix missing AlgorithmProvider() on PanamaHash (GH #801, PR #803) --- panama.h | 1 + 1 file changed, 1 insertion(+) diff --git a/panama.h b/panama.h index 69262606..04d2468b 100644 --- a/panama.h +++ b/panama.h @@ -50,6 +50,7 @@ public: unsigned int DigestSize() const {return DIGESTSIZE;} void TruncatedFinal(byte *hash, size_t size); CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == BIG_ENDIAN_ORDER ? "Panama-BE" : "Panama-LE";} + std::string AlgorithmProvider() const {return Panama::AlgorithmProvider();} // Fix https://github.com/weidai11/cryptopp/issues/801 protected: void Init() {Panama::Reset();} From e499131ea6ba23ce57f6a7e50d0c2ff3fb8eff62 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 12 Feb 2019 16:56:01 -0500 Subject: [PATCH 4/4] Latch previous ROUNDS in Salsa and ChaCha ciphers (GH #800, PR #804) --- chacha.cpp | 35 +++++++++++++++++++++-------------- chacha.h | 18 ++++++++++-------- salsa.cpp | 6 ++---- salsa.h | 2 ++ 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/chacha.cpp b/chacha.cpp index 9e0e3d37..e16a5008 100644 --- a/chacha.cpp +++ b/chacha.cpp @@ -345,9 +345,13 @@ void ChaCha_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32); CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length); - m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); - if (m_rounds != 20 && m_rounds != 12 && m_rounds != 8) - throw InvalidRounds(ChaCha::StaticAlgorithmName(), m_rounds); + // Use previous rounds as the default value + int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (rounds != 20 && rounds != 12 && rounds != 8) + throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds); + + // Latch a good value + m_rounds = rounds; // "expand 16-byte k" or "expand 32-byte k" m_state[0] = 0x61707865; @@ -425,9 +429,9 @@ void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke // the function, so we have to use the heavier-weight SetKey to change it. word64 block; if (params.GetValue("InitialBlock", block)) - m_state[CTR] = static_cast(block); + m_counter = static_cast(block); else - m_state[CTR] = 0; + m_counter = 0; // State words are defined in RFC 8439, Section 2.3. Key is 32-bytes. GetBlock get(key); @@ -449,7 +453,7 @@ void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV // State words are defined in RFC 8439, Section 2.3 GetBlock get(IV); - m_state[12] = m_state[CTR]; + m_state[12] = m_counter; get(m_state[13])(m_state[14])(m_state[15]); } @@ -506,16 +510,19 @@ void XChaCha20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke { CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32); - // XChaCha20 is always 20 rounds. Fetch Rounds() to avoid a spurious failure. - int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS); - if (rounds != 20) - throw InvalidRounds(XChaCha20::StaticAlgorithmName(), rounds); + // Use previous rounds as the default value + int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); + if (rounds != 20 && rounds != 12) + throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds); + + // Latch a good value + m_rounds = rounds; word64 block; if (params.GetValue("InitialBlock", block)) - m_state[CTR] = static_cast(block); + m_counter = static_cast(block); else - m_state[CTR] = 1; + m_counter = 1; // Stash key away for use in CipherResynchronize GetBlock get(key); @@ -548,7 +555,7 @@ void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; // Setup new IV - m_state[12] = m_state[CTR]; + m_state[12] = m_counter; m_state[13] = 0; m_state[14] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+16); m_state[15] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+20); @@ -575,7 +582,7 @@ void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) { ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13], - ROUNDS, output, input, iterationCount); + m_rounds, output, input, iterationCount); } NAMESPACE_END diff --git a/chacha.h b/chacha.h index 76aeb01b..0fab929a 100644 --- a/chacha.h +++ b/chacha.h @@ -58,7 +58,7 @@ class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy m_state; unsigned int m_rounds; }; @@ -114,7 +115,7 @@ class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy< { public: virtual ~ChaChaTLS_Policy() {} - ChaChaTLS_Policy() {} + ChaChaTLS_Policy() : m_counter(0) {} protected: void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); @@ -128,7 +129,8 @@ protected: std::string AlgorithmName() const; std::string AlgorithmProvider() const; - FixedSizeAlignedSecBlock m_state; + FixedSizeAlignedSecBlock m_state; + unsigned int m_counter; CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS) CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state @@ -161,7 +163,7 @@ struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation /// \brief XChaCha stream cipher information /// \since Crypto++ 8.1 -struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24>, FixedRounds<20> +struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24> { /// \brief The algorithm name /// \returns the algorithm name @@ -179,7 +181,7 @@ class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy< { public: virtual ~XChaCha20_Policy() {} - XChaCha20_Policy() {} + XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {} protected: void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); @@ -193,10 +195,10 @@ protected: std::string AlgorithmName() const; std::string AlgorithmProvider() const; - FixedSizeAlignedSecBlock m_state; - CRYPTOPP_CONSTANT(ROUNDS = XChaCha20_Info::ROUNDS) + FixedSizeAlignedSecBlock m_state; + unsigned int m_counter, m_rounds; + CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state - CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state }; /// \brief XChaCha stream cipher diff --git a/salsa.cpp b/salsa.cpp index c5330a9a..93f6293b 100644 --- a/salsa.cpp +++ b/salsa.cpp @@ -112,8 +112,7 @@ std::string Salsa20_Policy::AlgorithmProvider() const void Salsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) { - m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); - + m_rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20)) throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds); @@ -692,8 +691,7 @@ Salsa20_OperateKeystream ENDP void XSalsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) { - m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); - + m_rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds); if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20)) throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds); diff --git a/salsa.h b/salsa.h index a42d684b..31bb9a67 100644 --- a/salsa.h +++ b/salsa.h @@ -36,6 +36,7 @@ struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInter class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy { protected: + Salsa20_Policy() : m_rounds(ROUNDS) {} void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); @@ -49,6 +50,7 @@ protected: std::string AlgorithmProvider() const; + CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds FixedSizeAlignedSecBlock m_state; int m_rounds; };