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
16 * @file generic-key.cpp
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>
36 #include <generic-key.h>
41 //void printDER(const RawBuffer &key) {
42 // std::stringstream ss;
43 // for (auto &e : key) {
44 // ss << std::hex << " " << (int)e;
47 // LogError(ss.str());
50 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
52 int passcb(char *buff, int size, int rwflag, void *userdata) {
54 std::string *ptr = static_cast<std::string*>(userdata);
59 if (static_cast<int>(ptr->size()) > size)
61 memcpy(buff, ptr->c_str(), ptr->size());
65 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
67 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
68 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
71 LogDebug("You are trying to read empty key!");
75 if (NULL == bio.get()) {
76 LogError("Error in memory allocation! Function: BIO_new.");
80 if (1 != fun(bio.get(), pkey)) {
81 LogError("Error in conversion EVP_PKEY to der");
85 CKM::RawBuffer output(8196);
87 int size = BIO_read(bio.get(), output.data(), output.size());
90 LogError("Error in BIO_read: " << size);
98 } // anonymous namespace
100 GenericKey::GenericKey()
101 : m_pkey(NULL, EVP_PKEY_free)
102 , m_type(KeyType::KEY_NONE)
105 GenericKey::GenericKey(const GenericKey &second) {
106 m_pkey = second.m_pkey;
107 m_type = second.m_type;
110 GenericKey::GenericKey(const RawBuffer &buf, const std::string &pass)
111 : m_pkey(NULL, EVP_PKEY_free)
112 , m_type(KeyType::KEY_NONE)
114 bool isPrivate = false;
115 EVP_PKEY *pkey = NULL;
116 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
118 LogDebug("Start to parse key:");
122 BIO_write(bio.get(), buf.data(), buf.size());
123 pkey = d2i_PUBKEY_bio(bio.get(), NULL);
125 LogDebug("Trying d2i_PUBKEY_bio Status: " << (void*)pkey);
128 if (!pkey && buf[0] != '-') {
129 BIO_reset(bio.get());
130 BIO_write(bio.get(), buf.data(), buf.size());
131 pkey = d2i_PrivateKey_bio(bio.get(), NULL);
133 LogDebug("Trying d2i_PrivateKey_bio Status: " << (void*)pkey);
136 if (!pkey && buf[0] == '-') {
137 BIO_reset(bio.get());
138 BIO_write(bio.get(), buf.data(), buf.size());
139 pkey = PEM_read_bio_PUBKEY(bio.get(), NULL, passcb, const_cast<std::string*>(&pass));
141 LogDebug("PEM_read_bio_PUBKEY Status: " << (void*)pkey);
144 if (!pkey && buf[0] == '-') {
145 BIO_reset(bio.get());
146 BIO_write(bio.get(), buf.data(), buf.size());
147 pkey = PEM_read_bio_PrivateKey(bio.get(), NULL, passcb, const_cast<std::string*>(&pass));
149 LogDebug("PEM_read_bio_PrivateKey Status: " << (void*)pkey);
153 LogError("Failed to parse key");
157 m_pkey.reset(pkey, EVP_PKEY_free);
159 int type = EVP_PKEY_type(pkey->type);
161 if (type == EVP_PKEY_RSA) {
162 m_type = isPrivate ? KeyType::KEY_RSA_PRIVATE : KeyType::KEY_RSA_PUBLIC;
165 if (type == EVP_PKEY_EC) {
166 m_type = isPrivate ? KeyType::KEY_ECDSA_PRIVATE : KeyType::KEY_ECDSA_PUBLIC;
168 LogDebug("KeyType is: " << (int)m_type << " isPrivate: " << isPrivate);
171 GenericKey::GenericKey(EvpShPtr pkey, KeyType type)
175 if (type == KeyType::KEY_RSA_PRIVATE || type == KeyType::KEY_RSA_PUBLIC)
176 if (EVP_PKEY_RSA != EVP_PKEY_type(pkey->type)) {
178 m_type = KeyType::KEY_NONE;
180 if (type == KeyType::KEY_ECDSA_PRIVATE || type == KeyType::KEY_ECDSA_PUBLIC)
181 if (EVP_PKEY_EC != EVP_PKEY_type(pkey->type)) {
183 m_type = KeyType::KEY_NONE;
187 bool GenericKey::empty() const {
188 return m_pkey.get() == NULL;
191 GenericKey::EvpShPtr GenericKey::getEvpShPtr() const {
195 KeyType GenericKey::getType() const {
199 RawBuffer GenericKey::getDERPRV() const {
200 return i2d(i2d_PrivateKey_bio, m_pkey.get());
203 RawBuffer GenericKey::getDERPUB() const {
204 return i2d(i2d_PUBKEY_bio, m_pkey.get());
207 RawBuffer GenericKey::getDER() const {
208 if (m_type == KeyType::KEY_ECDSA_PRIVATE || m_type == KeyType::KEY_RSA_PRIVATE) {
210 } else if (m_type == KeyType::KEY_RSA_PUBLIC || m_type == KeyType::KEY_ECDSA_PUBLIC) {
216 // if (m_type == KeyType::KEY_ECDSA_PRIVATE || m_type == KeyType::KEY_RSA_PRIVATE) {
217 // output = getDERPRV();
218 // } else if (m_type == KeyType::KEY_RSA_PUBLIC || m_type == KeyType::KEY_ECDSA_PUBLIC) {
219 // output = getDERPUB();
221 // LogError("Key::getDER");
226 KeyShPtr Key::create(const RawBuffer &raw, const std::string &password) {
227 KeyShPtr output(new GenericKey(raw, password));