1 /*
2 * Copyright 2009-2017 Alibaba Cloud All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "CipherOpenssl.h"
18 #include <openssl/evp.h>
19 #include <openssl/rand.h>
20 #include <openssl/engine.h>
21 #include <openssl/rsa.h>
22 #include <openssl/pem.h>
23 #include <cstring>
24
25 using namespace AlibabaCloud::OSS;
26
SymmetricCipherOpenssl(const EVP_CIPHER * cipher,CipherAlgorithm algo,CipherMode mode,CipherPadding pad)27 SymmetricCipherOpenssl::SymmetricCipherOpenssl(const EVP_CIPHER* cipher, CipherAlgorithm algo, CipherMode mode, CipherPadding pad):
28 SymmetricCipher("openssl-impl", algo, mode, pad),
29 encryptCtx_(nullptr),
30 decryptCtx_(nullptr),
31 cipher_(cipher)
32 {
33 blockSize_ = EVP_CIPHER_block_size(cipher_);
34 }
35
~SymmetricCipherOpenssl()36 SymmetricCipherOpenssl::~SymmetricCipherOpenssl()
37 {
38 if (encryptCtx_) {
39 EVP_CIPHER_CTX_cleanup(encryptCtx_);
40 EVP_CIPHER_CTX_free(encryptCtx_);
41 encryptCtx_ = nullptr;
42 }
43
44 if (decryptCtx_) {
45 EVP_CIPHER_CTX_cleanup(decryptCtx_);
46 EVP_CIPHER_CTX_free(decryptCtx_);
47 decryptCtx_ = nullptr;
48 }
49 }
50
EncryptInit(const ByteBuffer & key,const ByteBuffer & iv)51 void SymmetricCipherOpenssl::EncryptInit(const ByteBuffer& key, const ByteBuffer& iv)
52 {
53 if (!encryptCtx_) {
54 encryptCtx_ = EVP_CIPHER_CTX_new();
55 }
56
57 EVP_EncryptInit_ex(encryptCtx_, cipher_, nullptr, key.data(), iv.data());
58 }
59
Encrypt(const ByteBuffer & data)60 ByteBuffer SymmetricCipherOpenssl::Encrypt(const ByteBuffer& data)
61 {
62 if (data.empty()) {
63 return ByteBuffer();
64 }
65
66 int outlen = static_cast<int>(data.size() + EVP_MAX_BLOCK_LENGTH);
67 ByteBuffer out(static_cast<size_t>(outlen));
68
69 if (!EVP_EncryptUpdate(encryptCtx_, out.data(), &outlen, data.data(), static_cast<int>(data.size()))) {
70 return ByteBuffer();
71 }
72 out.resize(outlen);
73 return out;
74 }
75
Encrypt(unsigned char * dst,int dstLen,const unsigned char * src,int srcLen)76 int SymmetricCipherOpenssl::Encrypt(unsigned char* dst, int dstLen, const unsigned char* src, int srcLen)
77 {
78 if (!dst || !src) {
79 return -1;
80 }
81
82 if (!EVP_EncryptUpdate(encryptCtx_, dst, &dstLen, src, srcLen)) {
83 return -1;
84 }
85
86 return dstLen;
87 }
88
89
EncryptFinish()90 ByteBuffer SymmetricCipherOpenssl::EncryptFinish()
91 {
92 ByteBuffer out(EVP_MAX_BLOCK_LENGTH);
93 int outlen = 0;
94 if (!EVP_EncryptFinal_ex(encryptCtx_, out.data(), &outlen)) {
95 return ByteBuffer();
96 }
97 out.resize(static_cast<size_t>(outlen));
98 return out;
99 }
100
DecryptInit(const ByteBuffer & key,const ByteBuffer & iv)101 void SymmetricCipherOpenssl::DecryptInit(const ByteBuffer& key, const ByteBuffer& iv)
102 {
103 if (!decryptCtx_) {
104 decryptCtx_ = EVP_CIPHER_CTX_new();
105 }
106
107 EVP_DecryptInit_ex(decryptCtx_, cipher_, nullptr, key.data(), iv.data());
108 }
109
Decrypt(const ByteBuffer & data)110 ByteBuffer SymmetricCipherOpenssl::Decrypt(const ByteBuffer& data)
111 {
112 if (data.empty()) {
113 return ByteBuffer();
114 }
115
116 int outlen = static_cast<int>(data.size() + EVP_MAX_BLOCK_LENGTH);
117 ByteBuffer out(static_cast<size_t>(outlen));
118
119 if (!EVP_DecryptUpdate(decryptCtx_, out.data(), &outlen, data.data(), static_cast<int>(data.size()))) {
120 return ByteBuffer();
121 }
122 out.resize(outlen);
123 return out;
124 }
125
Decrypt(unsigned char * dst,int dstLen,const unsigned char * src,int srcLen)126 int SymmetricCipherOpenssl::Decrypt(unsigned char * dst, int dstLen, const unsigned char* src, int srcLen)
127 {
128 if (!dst || !src) {
129 return -1;
130 }
131
132 if (!EVP_DecryptUpdate(decryptCtx_, dst, &dstLen, (const unsigned char *)src, srcLen)) {
133 return -1;
134 }
135
136 return dstLen;
137 }
138
DecryptFinish()139 ByteBuffer SymmetricCipherOpenssl::DecryptFinish()
140 {
141 ByteBuffer out(EVP_MAX_BLOCK_LENGTH);
142 int outlen = 0;
143 if (!EVP_DecryptFinal_ex(decryptCtx_, (unsigned char *)out.data(), &outlen)) {
144 return ByteBuffer();
145 }
146 out.resize(static_cast<size_t>(outlen));
147 return out;
148 }
149
150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151
AsymmetricCipherOpenssl(CipherAlgorithm algo,CipherMode mode,CipherPadding pad)152 AsymmetricCipherOpenssl::AsymmetricCipherOpenssl(CipherAlgorithm algo, CipherMode mode, CipherPadding pad) :
153 AsymmetricCipher("openssl-impl", algo, mode, pad)
154 {
155 }
156
~AsymmetricCipherOpenssl()157 AsymmetricCipherOpenssl::~AsymmetricCipherOpenssl()
158 {
159 }
160
Encrypt(const ByteBuffer & data)161 ByteBuffer AsymmetricCipherOpenssl::Encrypt(const ByteBuffer& data)
162 {
163 RSA* rsa = NULL;
164 BIO* bio = NULL;
165 EVP_PKEY* pkey = NULL;
166 ByteBuffer enc;
167 do {
168 if (data.empty()) {
169 break;
170 }
171
172 bio = BIO_new(BIO_s_mem());
173 BIO_puts(bio, PublicKey().c_str());
174
175 if (strncmp("-----BEGIN RSA", PublicKey().c_str(), 14) == 0) {
176 rsa = PEM_read_bio_RSAPublicKey(bio, &rsa, NULL, NULL);
177 }
178 else {
179 pkey = PEM_read_bio_PUBKEY(bio, &pkey, NULL, NULL);
180 rsa = pkey? EVP_PKEY_get1_RSA(pkey) : NULL;
181 }
182
183 if (rsa == NULL) {
184 break;
185 }
186
187 int rsa_len = RSA_size(rsa);
188 enc.resize(rsa_len, 0);
189
190 if (RSA_public_encrypt(data.size(), (unsigned char*)data.data(), (unsigned char*)enc.data(), rsa, RSA_PKCS1_PADDING) < 0) {
191 enc.resize(0);
192 }
193
194 } while (0);
195
196 if (bio) {
197 BIO_free(bio);
198 }
199
200 if (pkey) {
201 EVP_PKEY_free(pkey);
202 }
203
204 if (rsa) {
205 RSA_free(rsa);
206 }
207
208 return enc;
209 }
210
Decrypt(const ByteBuffer & data)211 ByteBuffer AsymmetricCipherOpenssl::Decrypt(const ByteBuffer& data)
212 {
213 RSA* rsa = NULL;
214 BIO* bio = NULL;
215 EVP_PKEY* pkey = NULL;
216 ByteBuffer dec;
217 do {
218 if (data.empty()) {
219 break;
220 }
221
222 bio = BIO_new(BIO_s_mem());
223 BIO_puts(bio, PrivateKey().c_str());
224
225 if (strncmp("-----BEGIN RSA", PublicKey().c_str(), 14) == 0) {
226 rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL);
227 }
228 else {
229 pkey = PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL);
230 rsa = pkey ? EVP_PKEY_get1_RSA(pkey) : NULL;
231 }
232
233 if (rsa == NULL) {
234 break;
235 }
236
237 int rsa_len = RSA_size(rsa);
238 dec.resize(rsa_len, 0);
239
240 auto dec_len = RSA_private_decrypt(rsa_len, (unsigned char*)data.data(), (unsigned char*)dec.data(), rsa, RSA_PKCS1_PADDING);
241 dec.resize(dec_len < 0 ? 0 : static_cast<size_t>(dec_len));
242
243 } while (0);
244
245 if (bio) {
246 BIO_free(bio);
247 }
248
249 if (pkey) {
250 EVP_PKEY_free(pkey);
251 }
252
253 if (rsa) {
254 RSA_free(rsa);
255 }
256
257 return dec;
258 }
259