1 /* Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License
17 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19 * @brief Key implementation.
28 #include <openssl/bio.h>
29 #include <openssl/evp.h>
30 #include <openssl/pem.h>
31 #include <openssl/x509.h>
33 #include <dpl/log/log.h>
35 #include <ckm/ckm-type.h>
41 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
43 int passcb(char *buff, int size, int rwflag, void *userdata) {
45 Password *ptr = static_cast<Password*>(userdata);
50 if (static_cast<int>(ptr->size()) > size)
52 memcpy(buff, ptr->c_str(), ptr->size());
56 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
58 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
59 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
62 LogDebug("You are trying to read empty key!");
66 if (NULL == bio.get()) {
67 LogError("Error in memory allocation! Function: BIO_new.");
71 if (1 != fun(bio.get(), pkey)) {
72 LogError("Error in conversion EVP_PKEY to der");
76 CKM::RawBuffer output(8196);
78 int size = BIO_read(bio.get(), output.data(), output.size());
81 LogError("Error in BIO_read: " << size);
89 } // anonymous namespace
92 : m_pkey(NULL, EVP_PKEY_free)
93 , m_type(KeyType::KEY_NONE)
96 KeyImpl::KeyImpl(const KeyImpl &second) {
97 m_pkey = second.m_pkey;
98 m_type = second.m_type;
101 KeyImpl &KeyImpl::operator=(const KeyImpl &second) {
105 m_pkey = second.m_pkey;
106 m_type = second.m_type;
111 KeyImpl::KeyImpl(const RawBuffer &buf, const Password &password)
112 : m_pkey(NULL, EVP_PKEY_free)
113 , m_type(KeyType::KEY_NONE)
115 bool isPrivate = false;
116 EVP_PKEY *pkey = NULL;
117 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
119 LogDebug("Start to parse key:");
123 BIO_write(bio.get(), buf.data(), buf.size());
124 pkey = d2i_PUBKEY_bio(bio.get(), NULL);
126 LogDebug("Trying d2i_PUBKEY_bio Status: " << (void*)pkey);
129 if (!pkey && buf[0] != '-') {
130 (void)BIO_reset(bio.get());
131 BIO_write(bio.get(), buf.data(), buf.size());
132 pkey = d2i_PrivateKey_bio(bio.get(), NULL);
134 LogDebug("Trying d2i_PrivateKey_bio Status: " << (void*)pkey);
137 if (!pkey && buf[0] == '-') {
138 (void)BIO_reset(bio.get());
139 BIO_write(bio.get(), buf.data(), buf.size());
140 pkey = PEM_read_bio_PUBKEY(bio.get(), NULL, passcb, const_cast<Password*>(&password));
142 LogDebug("PEM_read_bio_PUBKEY Status: " << (void*)pkey);
145 if (!pkey && buf[0] == '-') {
146 (void)BIO_reset(bio.get());
147 BIO_write(bio.get(), buf.data(), buf.size());
148 pkey = PEM_read_bio_PrivateKey(bio.get(), NULL, passcb, const_cast<Password*>(&password));
150 LogDebug("PEM_read_bio_PrivateKey Status: " << (void*)pkey);
154 LogError("Failed to parse key");
158 m_pkey.reset(pkey, EVP_PKEY_free);
160 switch(EVP_PKEY_type(pkey->type))
163 m_type = isPrivate ? KeyType::KEY_RSA_PRIVATE : KeyType::KEY_RSA_PUBLIC;
167 m_type = isPrivate ? KeyType::KEY_DSA_PRIVATE : KeyType::KEY_DSA_PUBLIC;
171 m_type = isPrivate ? KeyType::KEY_ECDSA_PRIVATE : KeyType::KEY_ECDSA_PUBLIC;
174 LogDebug("KeyType is: " << (int)m_type << " isPrivate: " << isPrivate);
177 KeyImpl::KeyImpl(EvpShPtr pkey, KeyType type) : m_pkey(pkey), m_type(type)
179 int expected_type = EVP_PKEY_NONE;
182 case KeyType::KEY_RSA_PRIVATE:
183 case KeyType::KEY_RSA_PUBLIC:
184 expected_type = EVP_PKEY_RSA;
187 case KeyType::KEY_DSA_PRIVATE:
188 case KeyType::KEY_DSA_PUBLIC:
189 expected_type = EVP_PKEY_DSA;
192 case KeyType::KEY_AES:
193 LogError("Error, AES keys are not supported yet.");
196 case KeyType::KEY_ECDSA_PRIVATE:
197 case KeyType::KEY_ECDSA_PUBLIC:
198 expected_type = EVP_PKEY_EC;
202 LogError("Unknown key type provided.");
206 // verify if actual key type matches the expected tpe
207 int given_key_type = EVP_PKEY_type(pkey->type);
208 if(given_key_type==EVP_PKEY_NONE || expected_type!=given_key_type)
211 m_type = KeyType::KEY_NONE;
215 bool KeyImpl::empty() const {
216 return m_pkey.get() == NULL;
219 KeyImpl::EvpShPtr KeyImpl::getEvpShPtr() const {
223 KeyType KeyImpl::getType() const {
227 RawBuffer KeyImpl::getDERPRV() const {
228 return i2d(i2d_PrivateKey_bio, m_pkey.get());
231 RawBuffer KeyImpl::getDERPUB() const {
232 return i2d(i2d_PUBKEY_bio, m_pkey.get());
235 RawBuffer KeyImpl::getDER() const {
238 case KeyType::KEY_RSA_PRIVATE:
239 case KeyType::KEY_DSA_PRIVATE:
240 case KeyType::KEY_ECDSA_PRIVATE:
243 case KeyType::KEY_RSA_PUBLIC:
244 case KeyType::KEY_DSA_PUBLIC:
245 case KeyType::KEY_ECDSA_PUBLIC:
254 KeyShPtr Key::create(const RawBuffer &raw, const Password &password) {
256 KeyShPtr output = std::make_shared<KeyImpl>(raw, password);
260 } catch (const std::bad_alloc &) {
261 LogDebug("Bad alloc was catch during KeyImpl creation");
263 LogError("Critical error: Unknown exception was caught during KeyImpl creation");