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