Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

openssl_rsa.cpp
Go to the documentation of this file.
1 /*
2 * RSA operations provided by OpenSSL
3 * (C) 2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/internal/openssl.h>
9
10 #if defined(BOTAN_HAS_RSA)
11
12 #include <botan/rsa.h>
13 #include <botan/internal/pk_ops_impl.h>
14 #include <botan/internal/ct_utils.h>
15
16 #include <functional>
17 #include <memory>
18
19 #include <openssl/rsa.h>
20 #include <openssl/x509.h>
21 #include <openssl/err.h>
22
23 namespace Botan {
24
25 namespace {
26
27 std::pair<int, size_t> get_openssl_enc_pad(const std::string& eme)
28 {
29 ERR_load_crypto_strings();
30 if(eme == "Raw")
31 return std::make_pair(RSA_NO_PADDING, 0);
32 else if(eme == "EME-PKCS1-v1_5")
33 return std::make_pair(RSA_PKCS1_PADDING, 11);
34 else if(eme == "OAEP(SHA-1)" || eme == "EME1(SHA-1)")
35 return std::make_pair(RSA_PKCS1_OAEP_PADDING, 41);
36 else
37 throw Lookup_Error("OpenSSL RSA does not support EME " + eme);
38 }
39
40 class OpenSSL_RSA_Encryption_Operation : public PK_Ops::Encryption
41 {
42 public:
43
44 OpenSSL_RSA_Encryption_Operation(const RSA_PublicKey& rsa, int pad, size_t pad_overhead) :
45 m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad)
46 {
47 const std::vector<uint8_t> der = rsa.public_key_bits();
48 const uint8_t* der_ptr = der.data();
49 m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size()));
50 if(!m_openssl_rsa)
51 throw OpenSSL_Error("d2i_RSAPublicKey");
52
53 m_bits = 8 * (n_size() - pad_overhead) - 1;
54 }
55
56 size_t max_input_bits() const override { return m_bits; };
57
58 secure_vector<uint8_t> encrypt(const uint8_t msg[], size_t msg_len,
59 RandomNumberGenerator&) override
60 {
61 const size_t mod_sz = n_size();
62
63 if(msg_len > mod_sz)
64 throw Invalid_Argument("Input too large for RSA key");
65
66 secure_vector<uint8_t> outbuf(mod_sz);
67
68 secure_vector<uint8_t> inbuf;
69
70 if(m_padding == RSA_NO_PADDING)
71 {
72 inbuf.resize(mod_sz);
73 copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len);
74 }
75 else
76 {
77 inbuf.assign(msg, msg + msg_len);
78 }
79
80 int rc = ::RSA_public_encrypt(inbuf.size(), inbuf.data(), outbuf.data(),
81 m_openssl_rsa.get(), m_padding);
82 if(rc < 0)
83 throw OpenSSL_Error("RSA_public_encrypt");
84
85 return outbuf;
86 }
87
88 private:
89 size_t n_size() const { return ::RSA_size(m_openssl_rsa.get()); }
90 std::unique_ptr<RSA, std::function<void (RSA*)>> m_openssl_rsa;
91 size_t m_bits = 0;
92 int m_padding = 0;
93 };
94
95 class OpenSSL_RSA_Decryption_Operation : public PK_Ops::Decryption
96 {
97 public:
98
99 OpenSSL_RSA_Decryption_Operation(const RSA_PrivateKey& rsa, int pad) :
100 m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad)
101 {
102 const secure_vector<uint8_t> der = rsa.private_key_bits();
103 const uint8_t* der_ptr = der.data();
104 m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size()));
105 if(!m_openssl_rsa)
106 throw OpenSSL_Error("d2i_RSAPrivateKey");
107 }
108
109 secure_vector<uint8_t> decrypt(uint8_t& valid_mask,
110 const uint8_t msg[], size_t msg_len) override
111 {
112 secure_vector<uint8_t> buf(::RSA_size(m_openssl_rsa.get()));
113 int rc = ::RSA_private_decrypt(msg_len, msg, buf.data(), m_openssl_rsa.get(), m_padding);
114 if(rc < 0 || static_cast<size_t>(rc) > buf.size())
115 {
116 valid_mask = 0;
117 buf.resize(0);
118 }
119 else
120 {
121 valid_mask = 0xFF;
122 buf.resize(rc);
123 }
124
125 if(m_padding == RSA_NO_PADDING)
126 {
127 return CT::strip_leading_zeros(buf);
128 }
129
130 return buf;
131 }
132
133 private:
134 std::unique_ptr<RSA, std::function<void (RSA*)>> m_openssl_rsa;
135 int m_padding = 0;
136 };
137
138 class OpenSSL_RSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
139 {
140 public:
141
142 OpenSSL_RSA_Verification_Operation(const RSA_PublicKey& rsa, const std::string& emsa) :
143 PK_Ops::Verification_with_EMSA(emsa),
144 m_openssl_rsa(nullptr, ::RSA_free)
145 {
146 const std::vector<uint8_t> der = rsa.public_key_bits();
147 const uint8_t* der_ptr = der.data();
148 m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size()));
149 }
150
151 size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; }
152
153 bool with_recovery() const override { return true; }
154
155 secure_vector<uint8_t> verify_mr(const uint8_t msg[], size_t msg_len) override
156 {
157 const size_t mod_sz = ::RSA_size(m_openssl_rsa.get());
158
159 if(msg_len > mod_sz)
160 throw Invalid_Argument("OpenSSL RSA verify input too large");
161
162 secure_vector<uint8_t> inbuf(mod_sz);
163 copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len);
164
165 secure_vector<uint8_t> outbuf(mod_sz);
166
167 int rc = ::RSA_public_decrypt(inbuf.size(), inbuf.data(), outbuf.data(),
168 m_openssl_rsa.get(), RSA_NO_PADDING);
169 if(rc < 0)
170 throw Invalid_Argument("RSA_public_decrypt");
171
172 return CT::strip_leading_zeros(outbuf);
173 }
174 private:
175 std::unique_ptr<RSA, std::function<void (RSA*)>> m_openssl_rsa;
176 };
177
178 class OpenSSL_RSA_Signing_Operation : public PK_Ops::Signature_with_EMSA
179 {
180 public:
181
182 OpenSSL_RSA_Signing_Operation(const RSA_PrivateKey& rsa, const std::string& emsa) :
183 PK_Ops::Signature_with_EMSA(emsa),
184 m_openssl_rsa(nullptr, ::RSA_free)
185 {
186 const secure_vector<uint8_t> der = rsa.private_key_bits();
187 const uint8_t* der_ptr = der.data();
188 m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size()));
189 if(!m_openssl_rsa)
190 throw OpenSSL_Error("d2i_RSAPrivateKey");
191 }
192
193 secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
194 RandomNumberGenerator&) override
195 {
196 const size_t mod_sz = ::RSA_size(m_openssl_rsa.get());
197
198 if(msg_len > mod_sz)
199 throw Invalid_Argument("OpenSSL RSA sign input too large");
200
201 secure_vector<uint8_t> inbuf(mod_sz);
202 copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len);
203
204 secure_vector<uint8_t> outbuf(mod_sz);
205
206 int rc = ::RSA_private_encrypt(inbuf.size(), inbuf.data(), outbuf.data(),
207 m_openssl_rsa.get(), RSA_NO_PADDING);
208 if(rc < 0)
209 throw OpenSSL_Error("RSA_private_encrypt");
210
211 return outbuf;
212 }
213
214 size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; }
215
216 private:
217 std::unique_ptr<RSA, std::function<void (RSA*)>> m_openssl_rsa;
218 };
219
220 }
221
222 std::unique_ptr<PK_Ops::Encryption>
223 make_openssl_rsa_enc_op(const RSA_PublicKey& key, const std::string& params)
224 {
225 auto pad_info = get_openssl_enc_pad(params);
226 return std::unique_ptr<PK_Ops::Encryption>(
227 new OpenSSL_RSA_Encryption_Operation(key, pad_info.first, pad_info.second));
228 }
229
230 std::unique_ptr<PK_Ops::Decryption>
231 make_openssl_rsa_dec_op(const RSA_PrivateKey& key, const std::string& params)
232 {
233 auto pad_info = get_openssl_enc_pad(params);
234 return std::unique_ptr<PK_Ops::Decryption>(new OpenSSL_RSA_Decryption_Operation(key, pad_info.first));
235 }
236
237 std::unique_ptr<PK_Ops::Verification>
238 make_openssl_rsa_ver_op(const RSA_PublicKey& key, const std::string& params)
239 {
240 return std::unique_ptr<PK_Ops::Verification>(new OpenSSL_RSA_Verification_Operation(key, params));
241 }
242
243 std::unique_ptr<PK_Ops::Signature>
244 make_openssl_rsa_sig_op(const RSA_PrivateKey& key, const std::string& params)
245 {
246 return std::unique_ptr<PK_Ops::Signature>(new OpenSSL_RSA_Signing_Operation(key, params));
247 }
248
249 }
250
251 #endif // BOTAN_HAS_RSA
Botan::CryptoBox::encrypt
std::string encrypt(const uint8_t input[], size_t input_len, const std::string &passphrase, RandomNumberGenerator &rng)
Definition: cryptobox.cpp:42
Botan::CryptoBox::decrypt
std::string decrypt(const uint8_t input[], size_t input_len, const std::string &passphrase)
Definition: cryptobox.cpp:102
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Botan
Definition: alg_id.cpp:13
Botan::CT::strip_leading_zeros
secure_vector< uint8_t > strip_leading_zeros(const uint8_t in[], size_t length)
Definition: ct_utils.h:186