Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/gfpcrypt.cpp
Line
Count
Source (jump to first uncovered line)
1
// dsa.cpp - originally written and placed in the public domain by Wei Dai
2
3
#include "pch.h"
4
#include "config.h"
5
6
// TODO: fix the C4589 warnings
7
#if CRYPTOPP_MSC_VERSION
8
# pragma warning(disable: 4189 4589)
9
#endif
10
11
#ifndef CRYPTOPP_IMPORTS
12
13
#include "gfpcrypt.h"
14
#include "nbtheory.h"
15
#include "modarith.h"
16
#include "integer.h"
17
#include "asn.h"
18
#include "oids.h"
19
#include "misc.h"
20
21
NAMESPACE_BEGIN(CryptoPP)
22
23
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
24
void TestInstantiations_gfpcrypt()
25
{
26
  GDSA<SHA1>::Signer test;
27
  GDSA<SHA1>::Verifier test1;
28
  DSA::Signer test5(NullRNG(), 100);
29
  DSA::Signer test2(test5);
30
  NR<SHA1>::Signer test3;
31
  NR<SHA1>::Verifier test4;
32
  DLIES<>::Encryptor test6;
33
  DLIES<>::Decryptor test7;
34
}
35
#endif
36
37
void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
38
0
{
39
0
  Integer p, q, g;
40
41
0
  if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
42
0
  {
43
0
    q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
44
0
    Initialize(p, q, g);
45
0
  }
46
0
  else
47
0
  {
48
0
    int modulusSize = 2048, defaultSubgroupOrderSize;
49
0
    alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
50
51
0
    switch (modulusSize)
52
0
    {
53
0
    case 1024:
54
0
      defaultSubgroupOrderSize = 160;
55
0
      break;
56
0
    case 2048:
57
0
      defaultSubgroupOrderSize = 224;
58
0
      break;
59
0
    case 3072:
60
0
      defaultSubgroupOrderSize = 256;
61
0
      break;
62
0
    default:
63
0
      throw InvalidArgument("DSA: not a valid prime length");
64
0
    }
65
66
0
    DL_GroupParameters_GFP::GenerateRandom(rng, CombinedNameValuePairs(alg, MakeParameters(Name::SubgroupOrderSize(), defaultSubgroupOrderSize, false)));
67
0
  }
68
0
}
69
70
bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
71
0
{
72
0
  bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level);
73
0
  CRYPTOPP_ASSERT(pass);
74
75
0
  const int pSize = GetModulus().BitCount(), qSize = GetSubgroupOrder().BitCount();
76
0
  pass = pass && ((pSize==1024 && qSize==160) || (pSize==2048 && qSize==224) || (pSize==2048 && qSize==256) || (pSize==3072 && qSize==256));
77
0
  CRYPTOPP_ASSERT(pass);
78
79
0
  return pass;
80
0
}
81
82
void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng,
83
  const byte *recoverableMessage, size_t recoverableMessageLength,
84
  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
85
  byte *representative, size_t representativeBitLength) const
86
0
{
87
0
  CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength);
88
0
  CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
89
0
  CRYPTOPP_ASSERT(recoverableMessageLength == 0);
90
0
  CRYPTOPP_ASSERT(hashIdentifier.second == 0);
91
92
0
  const size_t representativeByteLength = BitsToBytes(representativeBitLength);
93
0
  const size_t digestSize = hash.DigestSize();
94
0
  const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
95
96
0
  std::memset(representative, 0, paddingLength);
97
0
  hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
98
99
0
  if (digestSize*8 > representativeBitLength)
100
0
  {
101
0
    Integer h(representative, representativeByteLength);
102
0
    h >>= representativeByteLength*8 - representativeBitLength;
103
0
    h.Encode(representative, representativeByteLength);
104
0
  }
105
0
}
106
107
void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng,
108
  const byte *recoverableMessage, size_t recoverableMessageLength,
109
  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
110
  byte *representative, size_t representativeBitLength) const
111
0
{
112
0
  CRYPTOPP_UNUSED(rng);CRYPTOPP_UNUSED(recoverableMessage); CRYPTOPP_UNUSED(recoverableMessageLength);
113
0
  CRYPTOPP_UNUSED(hash); CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(messageEmpty);
114
0
  CRYPTOPP_UNUSED(representative); CRYPTOPP_UNUSED(representativeBitLength);
115
116
0
  CRYPTOPP_ASSERT(recoverableMessageLength == 0);
117
0
  CRYPTOPP_ASSERT(hashIdentifier.second == 0);
118
0
  const size_t representativeByteLength = BitsToBytes(representativeBitLength);
119
0
  const size_t digestSize = hash.DigestSize();
120
0
  const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
121
122
0
  std::memset(representative, 0, paddingLength);
123
0
  hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
124
125
0
  if (digestSize*8 >= representativeBitLength)
126
0
  {
127
0
    Integer h(representative, representativeByteLength);
128
0
    h >>= representativeByteLength*8 - representativeBitLength + 1;
129
0
    h.Encode(representative, representativeByteLength);
130
0
  }
131
0
}
132
133
bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
134
0
{
135
0
  const Integer &p = GetModulus(), &q = GetSubgroupOrder();
136
0
  bool pass = true;
137
138
0
  CRYPTOPP_ASSERT(p > Integer::One() && p.IsOdd());
139
0
  pass = pass && p > Integer::One() && p.IsOdd();
140
141
0
  CRYPTOPP_ASSERT(q > Integer::One() && q.IsOdd());
142
0
  pass = pass && q > Integer::One() && q.IsOdd();
143
144
0
  if (level >= 1)
145
0
  {
146
0
    CRYPTOPP_ASSERT(GetCofactor() > Integer::One());
147
0
    CRYPTOPP_ASSERT(GetGroupOrder() % q == Integer::Zero());
148
149
0
    pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero();
150
0
  }
151
0
  if (level >= 2)
152
0
  {
153
0
    CRYPTOPP_ASSERT(VerifyPrime(rng, q, level-2));
154
0
    CRYPTOPP_ASSERT(VerifyPrime(rng, p, level-2));
155
156
0
    pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2);
157
0
  }
158
159
0
  return pass;
160
0
}
161
162
bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation<Integer> *gpc) const
163
0
{
164
0
  const Integer &p = GetModulus(), &q = GetSubgroupOrder();
165
0
  bool pass = true;
166
167
0
  CRYPTOPP_ASSERT(GetFieldType() == 1 ? g.IsPositive() : g.NotNegative());
168
0
  pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative();
169
170
0
  CRYPTOPP_ASSERT(g < p && !IsIdentity(g));
171
0
  pass = pass && g < p && !IsIdentity(g);
172
173
0
  if (level >= 1)
174
0
  {
175
0
    if (gpc)
176
0
    {
177
0
      CRYPTOPP_ASSERT(gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g);
178
0
      pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g;
179
0
    }
180
0
  }
181
0
  if (level >= 2)
182
0
  {
183
0
    if (GetFieldType() == 2)
184
0
    {
185
0
      CRYPTOPP_ASSERT(Jacobi(g*g-4, p)==-1);
186
0
      pass = pass && Jacobi(g*g-4, p)==-1;
187
0
    }
188
189
    // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly
190
    // and at most 1 bit is leaked if it's false
191
0
    bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable();
192
193
0
    if (fullValidate && pass)
194
0
    {
195
0
      Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q);
196
0
      CRYPTOPP_ASSERT(IsIdentity(gp));
197
0
      pass = pass && IsIdentity(gp);
198
0
    }
199
0
    else if (GetFieldType() == 1)
200
0
    {
201
0
      CRYPTOPP_ASSERT(Jacobi(g, p) == 1);
202
0
      pass = pass && Jacobi(g, p) == 1;
203
0
    }
204
0
  }
205
206
0
  return pass;
207
0
}
208
209
void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
210
0
{
211
0
  Integer p, q, g;
212
213
0
  if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
214
0
  {
215
0
    q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
216
0
  }
217
0
  else
218
0
  {
219
0
    int modulusSize, subgroupOrderSize;
220
221
0
    if (!alg.GetIntValue("ModulusSize", modulusSize))
222
0
      modulusSize = alg.GetIntValueWithDefault("KeySize", 2048);
223
224
0
    if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize))
225
0
      subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize);
226
227
0
    PrimeAndGenerator pg;
228
0
    pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize);
229
0
    p = pg.Prime();
230
0
    q = pg.SubPrime();
231
0
    g = pg.Generator();
232
0
  }
233
234
0
  Initialize(p, q, g);
235
0
}
236
237
void DL_GroupParameters_IntegerBased::EncodeElement(bool reversible, const Element &element, byte *encoded) const
238
0
{
239
0
  CRYPTOPP_UNUSED(reversible);
240
0
  element.Encode(encoded, GetModulus().ByteCount());
241
0
}
242
243
unsigned int DL_GroupParameters_IntegerBased::GetEncodedElementSize(bool reversible) const
244
0
{
245
0
  CRYPTOPP_UNUSED(reversible);
246
0
  return GetModulus().ByteCount();
247
0
}
248
249
Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const
250
0
{
251
0
  CRYPTOPP_UNUSED(checkForGroupMembership);
252
0
  Integer g(encoded, GetModulus().ByteCount());
253
0
  if (!ValidateElement(1, g, NULLPTR))
254
0
    throw DL_BadElement();
255
0
  return g;
256
0
}
257
258
void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt)
259
0
{
260
0
  BERSequenceDecoder parameters(bt);
261
0
    Integer p(parameters);
262
0
    Integer q(parameters);
263
0
    Integer g;
264
0
    if (parameters.EndReached())
265
0
    {
266
0
      g = q;
267
0
      q = ComputeGroupOrder(p) / 2;
268
0
    }
269
0
    else
270
0
      g.BERDecode(parameters);
271
0
  parameters.MessageEnd();
272
273
0
  SetModulusAndSubgroupGenerator(p, g);
274
0
  SetSubgroupOrder(q);
275
0
}
276
277
void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const
278
0
{
279
0
  DERSequenceEncoder parameters(bt);
280
0
    GetModulus().DEREncode(parameters);
281
0
    m_q.DEREncode(parameters);
282
0
    GetSubgroupGenerator().DEREncode(parameters);
283
0
  parameters.MessageEnd();
284
0
}
285
286
bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
287
0
{
288
0
  return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue)
289
0
    CRYPTOPP_GET_FUNCTION_ENTRY(Modulus);
290
0
}
291
292
void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source)
293
0
{
294
0
  AssignFromHelper(this, source)
295
0
    CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator)
296
0
    CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
297
0
    ;
298
0
}
299
300
OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const
301
0
{
302
0
  return ASN1::id_dsa();
303
0
}
304
305
void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
306
0
{
307
0
  ModularArithmetic ma(GetModulus());
308
0
  ma.SimultaneousExponentiate(results, base, exponents, exponentsCount);
309
0
}
310
311
DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const
312
0
{
313
0
  return a_times_b_mod_c(a, b, GetModulus());
314
0
}
315
316
DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
317
0
{
318
0
  ModularArithmetic ma(GetModulus());
319
0
  return ma.CascadeExponentiate(element1, exponent1, element2, exponent2);
320
0
}
321
322
Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const
323
0
{
324
0
  return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount())));
325
0
}
326
327
unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const
328
0
{
329
0
  return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize);
330
0
}
331
332
NAMESPACE_END
333
334
#endif