File indexing completed on 2025-01-18 09:55:02
0001
0002
0003
0004 #ifndef CRYPTOPP_FHMQV_H
0005 #define CRYPTOPP_FHMQV_H
0006
0007
0008
0009
0010
0011 #include "gfpcrypt.h"
0012 #include "algebra.h"
0013 #include "sha.h"
0014
0015 NAMESPACE_BEGIN(CryptoPP)
0016
0017
0018
0019
0020
0021
0022
0023 template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
0024 class FHMQV_Domain : public AuthenticatedKeyAgreementDomain
0025 {
0026 public:
0027 typedef GROUP_PARAMETERS GroupParameters;
0028 typedef typename GroupParameters::Element Element;
0029 typedef FHMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain;
0030
0031 virtual ~FHMQV_Domain() {}
0032
0033
0034
0035
0036
0037 FHMQV_Domain(bool clientRole = true)
0038 : m_role(clientRole ? RoleClient : RoleServer) {}
0039
0040
0041
0042
0043
0044
0045 FHMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
0046 : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
0047
0048
0049
0050
0051
0052
0053 FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
0054 : m_role(clientRole ? RoleClient : RoleServer)
0055 {m_groupParameters.BERDecode(bt);}
0056
0057
0058
0059
0060
0061
0062
0063
0064 template <class T1>
0065 FHMQV_Domain(T1 v1, bool clientRole = true)
0066 : m_role(clientRole ? RoleClient : RoleServer)
0067 {m_groupParameters.Initialize(v1);}
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 template <class T1, class T2>
0079 FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
0080 : m_role(clientRole ? RoleClient : RoleServer)
0081 {m_groupParameters.Initialize(v1, v2);}
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 template <class T1, class T2, class T3>
0095 FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
0096 : m_role(clientRole ? RoleClient : RoleServer)
0097 {m_groupParameters.Initialize(v1, v2, v3);}
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 template <class T1, class T2, class T3, class T4>
0113 FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
0114 : m_role(clientRole ? RoleClient : RoleServer)
0115 {m_groupParameters.Initialize(v1, v2, v3, v4);}
0116
0117 public:
0118
0119
0120
0121 const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
0122
0123
0124
0125 GroupParameters & AccessGroupParameters() {return m_groupParameters;}
0126
0127
0128
0129 CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
0130
0131
0132
0133
0134
0135
0136
0137 unsigned int AgreedValueLength() const
0138 {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
0139
0140
0141
0142
0143 unsigned int StaticPrivateKeyLength() const
0144 {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
0145
0146
0147
0148
0149
0150
0151
0152 unsigned int StaticPublicKeyLength() const
0153 {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
0154
0155
0156
0157
0158
0159
0160
0161 void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
0162 {
0163 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
0164 x.Encode(privateKey, StaticPrivateKeyLength());
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
0176 {
0177 CRYPTOPP_UNUSED(rng);
0178 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
0179 Integer x(privateKey, StaticPrivateKeyLength());
0180 Element y = params.ExponentiateBase(x);
0181 params.EncodeElement(true, y, publicKey);
0182 }
0183
0184
0185
0186
0187
0188 unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
0189
0190
0191
0192
0193
0194 unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
0195
0196
0197
0198
0199
0200 void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
0201 {
0202 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
0203 Integer x(rng, Integer::One(), params.GetMaxExponent());
0204 x.Encode(privateKey, StaticPrivateKeyLength());
0205 Element y = params.ExponentiateBase(x);
0206 params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
0207 }
0208
0209
0210
0211
0212
0213
0214 void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
0215 {
0216 CRYPTOPP_UNUSED(rng);
0217 std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
0218 }
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 bool Agree(byte *agreedValue,
0244 const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
0245 const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
0246 bool validateStaticOtherPublicKey=true) const
0247 {
0248 const byte *XX = NULLPTR, *YY = NULLPTR, *AA = NULLPTR, *BB = NULLPTR;
0249 size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
0250
0251
0252
0253 SecByteBlock tt(StaticPublicKeyLength());
0254
0255 try
0256 {
0257 this->GetMaterial().DoQuickSanityCheck();
0258 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
0259
0260 if(m_role == RoleServer)
0261 {
0262 Integer b(staticPrivateKey, StaticPrivateKeyLength());
0263 Element B = params.ExponentiateBase(b);
0264 params.EncodeElement(true, B, tt);
0265
0266 XX = ephemeralOtherPublicKey;
0267 xxs = EphemeralPublicKeyLength();
0268 YY = ephemeralPrivateKey + StaticPrivateKeyLength();
0269 yys = EphemeralPublicKeyLength();
0270 AA = staticOtherPublicKey;
0271 aas = StaticPublicKeyLength();
0272 BB = tt.BytePtr();
0273 bbs = tt.SizeInBytes();
0274 }
0275 else
0276 {
0277 Integer a(staticPrivateKey, StaticPrivateKeyLength());
0278 Element A = params.ExponentiateBase(a);
0279 params.EncodeElement(true, A, tt);
0280
0281 XX = ephemeralPrivateKey + StaticPrivateKeyLength();
0282 xxs = EphemeralPublicKeyLength();
0283 YY = ephemeralOtherPublicKey;
0284 yys = EphemeralPublicKeyLength();
0285 AA = tt.BytePtr();
0286 aas = tt.SizeInBytes();
0287 BB = staticOtherPublicKey;
0288 bbs = StaticPublicKeyLength();
0289 }
0290
0291 Element VV1 = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
0292 Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, true);
0293
0294 const Integer& q = params.GetSubgroupOrder();
0295 const unsigned int len = (((q.BitCount()+1)/2 +7)/8);
0296 SecByteBlock dd(len), ee(len);
0297
0298 Hash(NULLPTR, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
0299 Integer d(dd.BytePtr(), dd.SizeInBytes());
0300
0301 Hash(NULLPTR, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes());
0302 Integer e(ee.BytePtr(), ee.SizeInBytes());
0303
0304 Element sigma;
0305 if(m_role == RoleServer)
0306 {
0307 Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
0308 Integer b(staticPrivateKey, StaticPrivateKeyLength());
0309 Integer s_B = (y + e * b) % q;
0310
0311 Element A = params.DecodeElement(AA, false);
0312 Element X = params.DecodeElement(XX, false);
0313
0314 Element t1 = params.ExponentiateElement(A, d);
0315 Element t2 = m_groupParameters.MultiplyElements(X, t1);
0316
0317 sigma = params.ExponentiateElement(t2, s_B);
0318 }
0319 else
0320 {
0321 Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
0322 Integer a(staticPrivateKey, StaticPrivateKeyLength());
0323 Integer s_A = (x + d * a) % q;
0324
0325 Element B = params.DecodeElement(BB, false);
0326 Element Y = params.DecodeElement(YY, false);
0327
0328 Element t1 = params.ExponentiateElement(B, e);
0329 Element t2 = m_groupParameters.MultiplyElements(Y, t1);
0330
0331 sigma = params.ExponentiateElement(t2, s_A);
0332 }
0333
0334 Hash(&sigma, XX, xxs, YY, yys, AA, aas, BB, bbs, agreedValue, AgreedValueLength());
0335 }
0336 catch (DL_BadElement &)
0337 {
0338 CRYPTOPP_ASSERT(0);
0339 return false;
0340 }
0341 return true;
0342 }
0343
0344 protected:
0345
0346 inline void Hash(const Element* sigma,
0347 const byte* e1, size_t e1len, const byte* e2, size_t e2len,
0348 const byte* s1, size_t s1len, const byte* s2, size_t s2len,
0349 byte* digest, size_t dlen) const
0350 {
0351 HASH hash;
0352 size_t idx = 0, req = dlen;
0353 size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE);
0354
0355 if(sigma)
0356 {
0357
0358
0359
0360 SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
0361 GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
0362 hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
0363 }
0364
0365 hash.Update(e1, e1len);
0366 hash.Update(e2, e2len);
0367 hash.Update(s1, s1len);
0368 hash.Update(s2, s2len);
0369
0370 hash.TruncatedFinal(digest, blk);
0371 req -= blk;
0372
0373
0374 while(req != 0)
0375 {
0376 hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
0377
0378 idx += (size_t)HASH::DIGESTSIZE;
0379 blk = STDMIN(req, (size_t)HASH::DIGESTSIZE);
0380 hash.TruncatedFinal(&digest[idx], blk);
0381
0382 req -= blk;
0383 }
0384 }
0385
0386 private:
0387
0388
0389 enum KeyAgreementRole { RoleServer = 1, RoleClient };
0390
0391 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
0392 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
0393
0394 GroupParameters m_groupParameters;
0395 KeyAgreementRole m_role;
0396 };
0397
0398
0399
0400
0401
0402
0403
0404 typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FHMQV;
0405
0406 NAMESPACE_END
0407
0408 #endif