Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/pubkey.cpp
Line
Count
Source (jump to first uncovered line)
1
// pubkey.cpp - originally written and placed in the public domain by Wei Dai
2
3
#include "pch.h"
4
#include "config.h"
5
6
#ifndef CRYPTOPP_IMPORTS
7
8
#include "pubkey.h"
9
#include "integer.h"
10
#include "filters.h"
11
12
NAMESPACE_BEGIN(CryptoPP)
13
14
void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart)
15
0
{
16
0
  ArraySink *sink;
17
0
  HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
18
0
  word32 counter = counterStart;
19
0
  while (sink->AvailableSize() > 0)
20
0
  {
21
0
    filter.Put(input, inputLength);
22
0
    filter.PutWord32(counter++);
23
0
    filter.Put(derivationParams, derivationParamsLength);
24
0
    filter.MessageEnd();
25
0
  }
26
0
}
27
28
bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
29
  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
30
  byte *representative, size_t representativeBitLength) const
31
0
{
32
0
  SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
33
0
  ComputeMessageRepresentative(NullRNG(), NULLPTR, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
34
0
  return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
35
0
}
36
37
bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
38
  HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
39
  byte *representative, size_t representativeBitLength) const
40
0
{
41
0
  SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
42
0
  DecodingResult result = RecoverMessageFromRepresentative(
43
0
    hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
44
0
  return result.isValidCoding && result.messageLength == 0;
45
0
}
46
47
void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
48
0
{
49
0
  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
50
0
  HashIdentifier id = GetHashIdentifier();
51
0
  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
52
53
0
  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
54
0
    throw PK_SignatureScheme::KeyTooShort();
55
56
0
  size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
57
58
0
  if (maxRecoverableLength == 0)
59
0
    {throw NotImplemented("TF_SignerBase: this algorithm does not support message recovery or the key is too short");}
60
0
  if (recoverableMessageLength > maxRecoverableLength)
61
0
    throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
62
63
0
  ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
64
0
  encoding.ProcessRecoverableMessage(
65
0
    ma.AccessHash(),
66
0
    recoverableMessage, recoverableMessageLength,
67
0
    NULLPTR, 0, ma.m_semisignature);
68
0
}
69
70
size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
71
0
{
72
0
  CRYPTOPP_UNUSED(restart);
73
74
0
  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
75
0
  HashIdentifier id = GetHashIdentifier();
76
0
  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
77
78
0
  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
79
0
    throw PK_SignatureScheme::KeyTooShort();
80
81
0
  SecByteBlock representative(MessageRepresentativeLength());
82
0
  encoding.ComputeMessageRepresentative(rng,
83
0
    ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
84
0
    ma.AccessHash(), id, ma.m_empty,
85
0
    representative, MessageRepresentativeBitLength());
86
0
  ma.m_empty = true;
87
88
0
  Integer r(representative, representative.size());
89
0
  size_t signatureLength = SignatureLength();
90
0
  GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
91
0
  return signatureLength;
92
0
}
93
94
void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
95
0
{
96
0
  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
97
0
  HashIdentifier id = GetHashIdentifier();
98
0
  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
99
100
0
  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
101
0
    throw PK_SignatureScheme::KeyTooShort();
102
103
0
  ma.m_representative.New(MessageRepresentativeLength());
104
0
  Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
105
0
  if (x.BitCount() > MessageRepresentativeBitLength())
106
0
    x = Integer::Zero(); // don't return false here to prevent timing attack
107
0
  x.Encode(ma.m_representative, ma.m_representative.size());
108
0
}
109
110
bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
111
0
{
112
0
  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
113
0
  HashIdentifier id = GetHashIdentifier();
114
0
  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
115
116
0
  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
117
0
    throw PK_SignatureScheme::KeyTooShort();
118
119
0
  bool result = encoding.VerifyMessageRepresentative(
120
0
    ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
121
0
  ma.m_empty = true;
122
0
  return result;
123
0
}
124
125
DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
126
0
{
127
0
  PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
128
0
  HashIdentifier id = GetHashIdentifier();
129
0
  const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
130
131
0
  if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
132
0
    throw PK_SignatureScheme::KeyTooShort();
133
134
0
  DecodingResult result = encoding.RecoverMessageFromRepresentative(
135
0
    ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
136
0
  ma.m_empty = true;
137
0
  return result;
138
0
}
139
140
DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
141
0
{
142
0
  if (ciphertextLength != FixedCiphertextLength())
143
0
      throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key");
144
145
0
  SecByteBlock paddedBlock(PaddedBlockByteLength());
146
0
  Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength));
147
0
  if (x.ByteCount() > paddedBlock.size())
148
0
    x = Integer::Zero(); // don't return false here to prevent timing attack
149
0
  x.Encode(paddedBlock, paddedBlock.size());
150
0
  return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
151
0
}
152
153
void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
154
0
{
155
0
  if (plaintextLength > FixedMaxPlaintextLength())
156
0
  {
157
0
    if (FixedMaxPlaintextLength() < 1)
158
0
      throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
159
0
    else
160
0
      throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
161
0
  }
162
163
0
  SecByteBlock paddedBlock(PaddedBlockByteLength());
164
0
  GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
165
0
  GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
166
0
}
167
168
NAMESPACE_END
169
170
#endif