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
/* based on Wei Dai's rsa.cpp from CryptoPP */
21
#include "runtime.hpp"
24
#include "modarith.hpp"
31
Integer RSA_PublicKey::ApplyFunction(const Integer& x) const
33
return a_exp_b_mod_c(x, e_, n_);
37
RSA_PublicKey::RSA_PublicKey(Source& source)
43
void RSA_PublicKey::Initialize(Source& source)
45
RSA_Public_Decoder decoder(source);
46
decoder.Decode(*this);
50
Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng,
51
const Integer& x) const
53
ModularArithmetic modn(n_);
55
Integer r(rng, Integer::One(), n_ - Integer::One());
56
Integer re = modn.Exponentiate(r, e_);
57
re = modn.Multiply(re, x); // blind
59
// here we follow the notation of PKCS #1 and let u=q inverse mod p
60
// but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
62
Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_);
63
y = modn.Divide(y, r); // unblind
64
assert(modn.Exponentiate(y, e_) == x); // check
70
RSA_PrivateKey::RSA_PrivateKey(Source& source)
76
void RSA_PrivateKey::Initialize(Source& source)
78
RSA_Private_Decoder decoder(source);
79
decoder.Decode(*this);
83
void RSA_BlockType2::Pad(const byte *input, word32 inputLen, byte *pkcsBlock,
84
word32 pkcsBlockLen, RandomNumberGenerator& rng) const
86
// convert from bit length to byte length
87
if (pkcsBlockLen % 8 != 0)
94
pkcsBlock[0] = 2; // block type 2
96
// pad with non-zero random bytes
97
word32 padLen = pkcsBlockLen - inputLen - 1;
98
rng.GenerateBlock(&pkcsBlock[1], padLen);
99
for (word32 i = 1; i < padLen; i++)
100
if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
102
pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
103
memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
106
word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
109
bool invalid = false;
110
unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
112
// convert from bit length to byte length
113
if (pkcsBlockLen % 8 != 0)
115
invalid = (pkcsBlock[0] != 0) || invalid;
120
// Require block type 2.
121
invalid = (pkcsBlock[0] != 2) || invalid;
123
// skip past the padding until we find the separator
125
while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
127
assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
129
unsigned int outputLen = pkcsBlockLen - i;
130
invalid = (outputLen > maxOutputLen) || invalid;
135
memcpy (output, pkcsBlock+i, outputLen);
140
void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock,
141
word32 pkcsBlockLen, RandomNumberGenerator&) const
143
// convert from bit length to byte length
144
if (pkcsBlockLen % 8 != 0)
151
pkcsBlock[0] = 1; // block type 1 for SSL
153
// pad with 0xff bytes
154
memset(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
156
pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
157
memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
161
word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen,
164
bool invalid = false;
165
unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
167
// convert from bit length to byte length
168
if (pkcsBlockLen % 8 != 0)
170
invalid = (pkcsBlock[0] != 0) || invalid;
175
// Require block type 1 for SSL.
176
invalid = (pkcsBlock[0] != 1) || invalid;
178
// skip past the padding until we find the separator
180
while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
182
assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
184
unsigned int outputLen = pkcsBlockLen - i;
185
invalid = (outputLen > maxOutputLen) || invalid;
190
memcpy(output, pkcsBlock+i, outputLen);
195
word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain)
197
PK_Lengths lengths(key.GetModulus());
199
ByteBlock paddedBlock(BitsToBytes(lengths.PaddedBlockBitLength()));
200
Integer x = key.ApplyFunction(Integer(sig,
201
lengths.FixedCiphertextLength()));
202
if (x.ByteCount() > paddedBlock.size())
204
x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
205
return RSA_BlockType1().UnPad(paddedBlock.get_buffer(),
206
lengths.PaddedBlockBitLength(), plain);