diff --git a/fhmqv.h b/fhmqv.h index d777c342..5d2f5135 100644 --- a/fhmqv.h +++ b/fhmqv.h @@ -1,11 +1,11 @@ -// fhmqv.h - written and placed in the public domain by Jeffrey Walton -// Shamelessly based upon Wei Dai's MQV source files +// fhmqv.h - written and placed in the public domain by Jeffrey Walton, Ray Clayton and Uri Blumenthal +// Shamelessly based upon Wei Dai's MQV source files #ifndef CRYPTOPP_FHMQV_H #define CRYPTOPP_FHMQV_H -/** \file -*/ +//! \file fhmqv.h +//! \brief Classes for Fully Hashed Menezes-Qu-Vanstone key agreement in GF(p) #include "gfpcrypt.h" #include "algebra.h" @@ -13,12 +13,12 @@ NAMESPACE_BEGIN(CryptoPP) -//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation, -/*! A Secure and Efficient Authenticated Diffie–Hellman Protocol - Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. -*/ +//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p) +//! \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's +//! A Secure and Efficient Authenticated Diffie-Hellman Protocol. +//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. template -class FHMQV_Domain: public AuthenticatedKeyAgreementDomain +class FHMQV_Domain : public AuthenticatedKeyAgreementDomain { public: typedef GROUP_PARAMETERS GroupParameters; @@ -54,46 +54,6 @@ public: : m_role(clientRole ? RoleClient : RoleServer) {m_groupParameters.Initialize(v1, v2, v3, v4);} -protected: - - inline void Hash(const Element* sigma, - const byte* e1, size_t e1len, const byte* e2, size_t e2len, - const byte* s1, size_t s1len, const byte* s2, size_t s2len, - byte* digest, size_t dlen) const - { - HASH hash; - size_t idx = 0, req = dlen; - size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); - - if(sigma) - { - Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); - SecByteBlock sbb(x.MinEncodedSize()); - x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); - hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); - } - - hash.Update(e1, e1len); - hash.Update(e2, e2len); - hash.Update(s1, s1len); - hash.Update(s2, s2len); - - hash.TruncatedFinal(digest, blk); - req -= blk; - - // All this to catch tail bytes for large curves and small hashes - while(req != 0) - { - hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); - - idx += (size_t)HASH::DIGESTSIZE; - blk = std::min(req, (size_t)HASH::DIGESTSIZE); - hash.TruncatedFinal(&digest[idx], blk); - - req -= blk; - } - } - public: const GroupParameters & GetGroupParameters() const {return m_groupParameters;} @@ -271,6 +231,46 @@ public: return true; } +protected: + + inline void Hash(const Element* sigma, + const byte* e1, size_t e1len, const byte* e2, size_t e2len, + const byte* s1, size_t s1len, const byte* s2, size_t s2len, + byte* digest, size_t dlen) const + { + HASH hash; + size_t idx = 0, req = dlen; + size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); + + if(sigma) + { + Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); + SecByteBlock sbb(x.MinEncodedSize()); + x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); + hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); + } + + hash.Update(e1, e1len); + hash.Update(e2, e2len); + hash.Update(s1, s1len); + hash.Update(s2, s2len); + + hash.TruncatedFinal(digest, blk); + req -= blk; + + // All this to catch tail bytes for large curves and small hashes + while(req != 0) + { + hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); + + idx += (size_t)HASH::DIGESTSIZE; + blk = std::min(req, (size_t)HASH::DIGESTSIZE); + hash.TruncatedFinal(&digest[idx], blk); + + req -= blk; + } + } + private: // The paper uses Initiator and Recipient - make it classical. @@ -279,14 +279,14 @@ private: DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;} - KeyAgreementRole m_role; GroupParameters m_groupParameters; + KeyAgreementRole m_role; }; -//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation, -/*! A Secure and Efficient Authenticated Diffie–Hellman Protocol - Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. -*/ +//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p) +//! \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's +//! A Secure and Efficient Authenticated Diffie-Hellman Protocol. +//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. typedef FHMQV_Domain FullyHashedMQV; NAMESPACE_END diff --git a/hmqv.h b/hmqv.h index d2c692a8..e44e0a24 100644 --- a/hmqv.h +++ b/hmqv.h @@ -1,11 +1,11 @@ // hmqv.h - written and placed in the public domain by Uri Blumenthal -// Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files +// Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files #ifndef CRYPTOPP_HMQV_H #define CRYPTOPP_HMQV_H -/** \file -*/ +//! \file hmqv.h +//! \brief Classes for Hashed Menezes-Qu-Vanstone key agreement in GF(p) #include "gfpcrypt.h" #include "algebra.h" @@ -13,10 +13,9 @@ NAMESPACE_BEGIN(CryptoPP) -//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation, -/*! HMQV: A High-Performance Secure Diffie-Hellman Protocol - Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately. -*/ +//! \brief Hashed Menezes-Qu-Vanstone in GF(p) +//! \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance +//! Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided. template class HMQV_Domain: public AuthenticatedKeyAgreementDomain { @@ -54,52 +53,6 @@ public: : m_role(clientRole ? RoleClient : RoleServer) {m_groupParameters.Initialize(v1, v2, v3, v4);} -protected: - // Hash invocation by client and server differ only in what keys - // each provides. - - inline void Hash(const Element* sigma, - const byte* e1, size_t e1len, // Ephemeral key and key length - const byte* s1, size_t s1len, // Static key and key length - byte* digest, size_t dlen) const - { - HASH hash; - size_t idx = 0, req = dlen; - size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); - - if(sigma) - { - if (e1len != 0 || s1len != 0) { - assert(0); - } - Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); - SecByteBlock sbb(x.MinEncodedSize()); - x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); - hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); - } else { - if (e1len == 0 || s1len == 0) { - assert(0); - } - hash.Update(e1, e1len); - hash.Update(s1, s1len); - } - - hash.TruncatedFinal(digest, blk); - req -= blk; - - // All this to catch tail bytes for large curves and small hashes - while(req != 0) - { - hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); - - idx += (size_t)HASH::DIGESTSIZE; - blk = std::min(req, (size_t)HASH::DIGESTSIZE); - hash.TruncatedFinal(&digest[idx], blk); - - req -= blk; - } - } - public: const GroupParameters & GetGroupParameters() const {return m_groupParameters;} @@ -225,7 +178,7 @@ public: if(!params.ValidateElement(3, VV2, NULL)) return false; -// const Integer& p = params.GetGroupOrder(); // not used, remove later + // const Integer& p = params.GetGroupOrder(); // not used, remove later const Integer& q = params.GetSubgroupOrder(); const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8); @@ -253,7 +206,7 @@ public: Element t1 = params.ExponentiateElement(A, d); Element t2 = m_groupParameters.MultiplyElements(X, t1); - // $\sigma_B}=(X \cdot A^{d})^{s_B} + // $\sigma_B}=(X \cdot A^{d})^{s_B} sigma = params.ExponentiateElement(t2, s_B); } else @@ -268,7 +221,7 @@ public: Element t1 = params.ExponentiateElement(B, e); Element t2 = m_groupParameters.MultiplyElements(Y, t1); - // $\sigma_A}=(Y \cdot B^{e})^{s_A} + // $\sigma_A}=(Y \cdot B^{e})^{s_A} sigma = params.ExponentiateElement(t2, s_A); } Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength()); @@ -280,6 +233,52 @@ public: return true; } +protected: + // Hash invocation by client and server differ only in what keys + // each provides. + + inline void Hash(const Element* sigma, + const byte* e1, size_t e1len, // Ephemeral key and key length + const byte* s1, size_t s1len, // Static key and key length + byte* digest, size_t dlen) const + { + HASH hash; + size_t idx = 0, req = dlen; + size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); + + if(sigma) + { + if (e1len != 0 || s1len != 0) { + assert(0); + } + Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); + SecByteBlock sbb(x.MinEncodedSize()); + x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); + hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); + } else { + if (e1len == 0 || s1len == 0) { + assert(0); + } + hash.Update(e1, e1len); + hash.Update(s1, s1len); + } + + hash.TruncatedFinal(digest, blk); + req -= blk; + + // All this to catch tail bytes for large curves and small hashes + while(req != 0) + { + hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); + + idx += (size_t)HASH::DIGESTSIZE; + blk = std::min(req, (size_t)HASH::DIGESTSIZE); + hash.TruncatedFinal(&digest[idx], blk); + + req -= blk; + } + } + private: // The paper uses Initiator and Recipient - make it classical. @@ -288,14 +287,13 @@ private: DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;} - KeyAgreementRole m_role; GroupParameters m_groupParameters; + KeyAgreementRole m_role; }; -//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation, -/*! HMQV: A High-Performance Secure Diffie-Hellman Protocol - Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately. -*/ +//! \brief Hashed Menezes-Qu-Vanstone in GF(p) +//! \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance +//! Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided. typedef HMQV_Domain HashedMQV; NAMESPACE_END