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/rand.h>
19
20 using namespace AlibabaCloud::OSS;
21
toAlgorithmName(CipherAlgorithm algo)22 inline static std::string toAlgorithmName(CipherAlgorithm algo)
23 {
24 static const char* name[] = { "AES", "RSA"};
25 return name[static_cast<int>(algo) - static_cast<int>(CipherAlgorithm::AES)];
26 }
27
toModeName(CipherMode mode)28 inline static std::string toModeName(CipherMode mode)
29 {
30 static const char* name[] = { "NONE", "ECB", "CBC", "CTR"};
31 return name[static_cast<int>(mode) - static_cast<int>(CipherMode::NONE)];
32 }
33
toPaddingName(CipherPadding pad)34 inline static std::string toPaddingName(CipherPadding pad)
35 {
36 static const char* name[] = { "NoPadding", "PKCS1Padding", "PKCS5Padding", "PKCS7Padding", "ZeroPadding"};
37 return name[static_cast<int>(pad) - static_cast<int>(CipherPadding::NoPadding)];
38 }
39
SymmetricCipher(const std::string & impl,CipherAlgorithm algo,CipherMode mode,CipherPadding pad)40 SymmetricCipher::SymmetricCipher(const std::string& impl, CipherAlgorithm algo, CipherMode mode, CipherPadding pad):
41 impl_(impl),
42 algorithm_(algo),
43 mode_(mode),
44 padding_(pad),
45 blockSize_(16)
46 {
47 name_ = toAlgorithmName(algo);
48 name_.append("/");
49 name_.append(toModeName(mode));
50 name_.append("/");
51 name_.append(toPaddingName(pad));
52 }
53
GenerateIV(size_t length)54 ByteBuffer SymmetricCipher::GenerateIV(size_t length)
55 {
56 //use openssl rand func
57 ByteBuffer out = ByteBuffer(length);
58 RAND_bytes((unsigned char *)out.data(), length);
59 return out;
60 }
61
GenerateKey(size_t length)62 ByteBuffer SymmetricCipher::GenerateKey(size_t length)
63 {
64 //use openssl rand func
65 ByteBuffer out = ByteBuffer(length);
66 RAND_bytes((unsigned char *)out.data(), length);
67 return out;
68 }
69
70 template<class T>
71 typename std::enable_if<std::is_unsigned<T>::value, T>::type
bswap(T i,T j=0u,std::size_t n=0u)72 bswap(T i, T j = 0u, std::size_t n = 0u)
73 {
74 return n == sizeof(T) ? j :
75 bswap<T>(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1);
76 }
77
IncCTRCounter(const ByteBuffer & counter,uint64_t numberOfBlocks)78 ByteBuffer SymmetricCipher::IncCTRCounter(const ByteBuffer& counter, uint64_t numberOfBlocks)
79 {
80 ByteBuffer ctrCounter(counter);
81 uint64_t *ctrPtr = (uint64_t*)(ctrCounter.data() + ctrCounter.size() - sizeof(uint64_t));
82
83 uint64_t n = 1;
84 if (*(char *)&n) {
85 //little
86 *ctrPtr = bswap<uint64_t>(bswap<uint64_t>(*ctrPtr) + numberOfBlocks);
87 }
88 else {
89 //big
90 *ctrPtr += numberOfBlocks;
91 }
92
93 return ctrCounter;
94 }
95
CreateAES128_CTRImpl()96 std::shared_ptr<SymmetricCipher> SymmetricCipher::CreateAES128_CTRImpl()
97 {
98 return std::make_shared<SymmetricCipherOpenssl>(EVP_aes_128_ctr(),
99 CipherAlgorithm::AES, CipherMode::CTR, CipherPadding::NoPadding);
100 }
101
CreateAES128_CBCImpl()102 std::shared_ptr<SymmetricCipher> SymmetricCipher::CreateAES128_CBCImpl()
103 {
104 return std::make_shared<SymmetricCipherOpenssl>(EVP_aes_128_cbc(),
105 CipherAlgorithm::AES, CipherMode::CBC, CipherPadding::PKCS5Padding);
106 }
107
CreateAES256_CTRImpl()108 std::shared_ptr<SymmetricCipher> SymmetricCipher::CreateAES256_CTRImpl()
109 {
110 return std::make_shared<SymmetricCipherOpenssl>(EVP_aes_256_ctr(),
111 CipherAlgorithm::AES, CipherMode::CTR, CipherPadding::NoPadding);
112 }
113
114
115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116
AsymmetricCipher(const std::string & impl,CipherAlgorithm algo,CipherMode mode,CipherPadding pad)117 AsymmetricCipher::AsymmetricCipher(const std::string& impl, CipherAlgorithm algo, CipherMode mode, CipherPadding pad) :
118 impl_(impl),
119 algorithm_(algo),
120 mode_(mode),
121 padding_(pad)
122 {
123 name_ = toAlgorithmName(algo);
124 name_.append("/");
125 name_.append(toModeName(mode));
126 name_.append("/");
127 name_.append(toPaddingName(pad));
128 }
129
CreateRSA_NONEImpl()130 std::shared_ptr<AsymmetricCipher> AsymmetricCipher::CreateRSA_NONEImpl()
131 {
132 return std::make_shared<AsymmetricCipherOpenssl>(CipherAlgorithm::RSA, CipherMode::NONE, CipherPadding::PKCS1Padding);
133 }
134
135
136
137