2
Copyright (C) 2000-2007 MySQL AB
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; version 2 of the License.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program; see the file COPYING. If not, write to the
15
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19
/* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify
22
#ifndef TAO_CRYPT_RSA_HPP
23
#define TAO_CRYPT_RSA_HPP
25
#include "integer.hpp"
34
// Public Key Length helper
36
const Integer& image_;
38
explicit PK_Lengths(const Integer& i) : image_(i) {}
40
word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;}
41
word32 PaddedBlockByteLength() const
42
{return BitsToBytes(PaddedBlockBitLength());}
44
word32 FixedCiphertextLength() const {return image_.ByteCount();}
45
word32 FixedMaxPlaintextLength() const
46
{return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); }
57
explicit RSA_PublicKey(Source&);
59
void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;}
60
void Initialize(Source&);
62
Integer ApplyFunction(const Integer& x) const;
64
const Integer& GetModulus() const {return n_;}
65
const Integer& GetPublicExponent() const {return e_;}
67
void SetModulus(const Integer& n) {n_ = n;}
68
void SetPublicExponent(const Integer& e) {e_ = e;}
70
word32 FixedCiphertextLength()
72
return PK_Lengths(n_).FixedCiphertextLength();
75
RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {}
76
RSA_PublicKey& operator=(const RSA_PublicKey& that)
78
RSA_PublicKey tmp(that);
83
void Swap(RSA_PublicKey& other)
92
class RSA_PrivateKey : public RSA_PublicKey {
101
explicit RSA_PrivateKey(Source&);
103
void Initialize(const Integer& n, const Integer& e, const Integer& d,
104
const Integer& p, const Integer& q, const Integer& dp,
105
const Integer& dq, const Integer& u)
106
{n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;}
107
void Initialize(Source&);
109
Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const;
111
const Integer& GetPrime1() const {return p_;}
112
const Integer& GetPrime2() const {return q_;}
113
const Integer& GetPrivateExponent() const {return d_;}
114
const Integer& GetModPrime1PrivateExponent() const {return dp_;}
115
const Integer& GetModPrime2PrivateExponent() const {return dq_;}
116
const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const
119
void SetPrime1(const Integer& p) {p_ = p;}
120
void SetPrime2(const Integer& q) {q_ = q;}
121
void SetPrivateExponent(const Integer& d) {d_ = d;}
122
void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;}
123
void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;}
124
void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;}
126
RSA_PrivateKey(const RSA_PrivateKey&); // hide copy
127
RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign
131
// block type 2 padding
132
class RSA_BlockType2 {
134
void Pad(const byte*, word32, byte*, word32,
135
RandomNumberGenerator&) const;
136
word32 UnPad(const byte*, word32, byte*) const;
140
// block type 1 padding
141
class RSA_BlockType1 {
143
void Pad(const byte*, word32, byte*, word32,
144
RandomNumberGenerator&) const;
145
word32 UnPad(const byte*, word32, byte*) const;
149
// RSA Encryptor, can use any padding
150
template<class Pad = RSA_BlockType2>
151
class RSA_Encryptor {
152
const RSA_PublicKey& key_;
155
explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {}
157
void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&);
158
bool SSL_Verify(const byte* msg, word32 sz, const byte* sig);
162
// RSA Decryptor, can use any padding
163
template<class Pad = RSA_BlockType2>
164
class RSA_Decryptor {
165
const RSA_PrivateKey& key_;
168
explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {}
170
word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&);
171
void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&);
177
void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher,
178
RandomNumberGenerator& rng)
180
PK_Lengths lengths(key_.GetModulus());
181
assert(sz <= lengths.FixedMaxPlaintextLength());
183
ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
184
padding_.Pad(plain, sz, paddedBlock.get_buffer(),
185
lengths.PaddedBlockBitLength(), rng);
187
key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())).
188
Encode(cipher, lengths.FixedCiphertextLength());
194
word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain,
195
RandomNumberGenerator& rng)
197
PK_Lengths lengths(key_.GetModulus());
198
assert(sz == lengths.FixedCiphertextLength());
200
if (sz != lengths.FixedCiphertextLength())
203
ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
204
Integer x = key_.CalculateInverse(rng, Integer(cipher,
205
lengths.FixedCiphertextLength()).Ref());
206
if (x.ByteCount() > paddedBlock.size())
207
x = Integer::Zero(); // don't return false, prevents timing attack
208
x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
209
return padding_.UnPad(paddedBlock.get_buffer(),
210
lengths.PaddedBlockBitLength(), plain);
214
// Private SSL type (block 1) Encrypt
216
void RSA_Decryptor<Pad>::SSL_Sign(const byte* message, word32 sz, byte* sig,
217
RandomNumberGenerator& rng)
219
RSA_PublicKey inverse;
220
inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent());
221
RSA_Encryptor<RSA_BlockType1> enc(inverse); // SSL Type
222
enc.Encrypt(message, sz, sig, rng);
226
word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain);
229
// Public SSL type (block 1) Decrypt
231
bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz,
234
ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength());
235
if (SSL_Decrypt(key_, sig, plain.get_buffer()) != sz)
236
return false; // not right justified or bad padding
238
if ( (memcmp(plain.get_buffer(), message, sz)) == 0)
244
typedef RSA_Encryptor<> RSAES_Encryptor;
245
typedef RSA_Decryptor<> RSAES_Decryptor;
250
#endif // TAO_CRYPT_RSA_HPP