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