f9b6b1e4b384fa029f96b1e03c9d2068c232ce3c
[platform/core/security/key-manager.git] / src / manager / common / generic-key.cpp
1 /* Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
2  *
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
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
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
14  *
15  *
16  * @file        generic-key.cpp
17  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
18  * @version     1.0
19  * @brief       Key implementation.
20  */
21 #include <string.h>
22
23 #include <functional>
24 #include <memory>
25 #include <sstream>
26 #include <ios>
27
28 #include <openssl/bio.h>
29 #include <openssl/evp.h>
30 #include <openssl/pem.h>
31 #include <openssl/x509.h>
32
33 #include <dpl/log/log.h>
34
35 #include <ckm/ckm-type.h>
36 #include <generic-key.h>
37
38 namespace CKM {
39 namespace {
40
41 //void printDER(const RawBuffer &key) {
42 //    std::stringstream ss;
43 //    for (auto &e : key) {
44 //        ss << std::hex << " " << (int)e;
45 //    }
46 //    ss << std::dec;
47 //    LogError(ss.str());
48 //}
49
50 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
51
52 int passcb(char *buff, int size, int rwflag, void *userdata) {
53     (void) rwflag;
54     std::string *ptr = static_cast<std::string*>(userdata);
55     if (ptr == NULL)
56         return 0;
57     if (ptr->empty())
58         return 0;
59     if (static_cast<int>(ptr->size()) > size)
60         return 0;
61     memcpy(buff, ptr->c_str(), ptr->size());
62     return ptr->size();
63 }
64
65 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
66
67 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
68     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
69
70     if (NULL == pkey) {
71         LogDebug("You are trying to read empty key!");
72         return RawBuffer();
73     }
74
75     if (NULL == bio.get()) {
76         LogError("Error in memory allocation! Function: BIO_new.");
77         return RawBuffer();
78     }
79
80     if (1 != fun(bio.get(), pkey)) {
81         LogError("Error in conversion EVP_PKEY to der");
82         return RawBuffer();
83     }
84
85     CKM::RawBuffer output(8196);
86
87     int size = BIO_read(bio.get(), output.data(), output.size());
88
89     if (size <= 0) {
90         LogError("Error in BIO_read: " << size);
91         return RawBuffer();
92     }
93
94     output.resize(size);
95     return output;
96 }
97
98 } // anonymous namespace
99
100 GenericKey::GenericKey()
101   : m_pkey(NULL, EVP_PKEY_free)
102   , m_type(KeyType::KEY_NONE)
103 {}
104
105 GenericKey::GenericKey(const GenericKey &second) {
106     m_pkey = second.m_pkey;
107     m_type = second.m_type;
108 }
109
110 GenericKey::GenericKey(const RawBuffer &buf, const std::string &pass)
111   : m_pkey(NULL, EVP_PKEY_free)
112   , m_type(KeyType::KEY_NONE)
113 {
114     bool isPrivate = false;
115     EVP_PKEY *pkey = NULL;
116     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
117
118     LogDebug("Start to parse key:");
119 //    printDER(buf);
120
121     if (buf[0] != '-') {
122         BIO_write(bio.get(), buf.data(), buf.size());
123         pkey = d2i_PUBKEY_bio(bio.get(), NULL);
124         isPrivate = false;
125         LogDebug("Trying d2i_PUBKEY_bio Status: " << (void*)pkey);
126     }
127
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);
132         isPrivate = true;
133         LogDebug("Trying d2i_PrivateKey_bio Status: " << (void*)pkey);
134     }
135
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));
140         isPrivate = false;
141         LogDebug("PEM_read_bio_PUBKEY Status: " << (void*)pkey);
142     }
143
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));
148         isPrivate = true;
149         LogDebug("PEM_read_bio_PrivateKey Status: " << (void*)pkey);
150     }
151
152     if (!pkey) {
153         LogError("Failed to parse key");
154         return;
155     }
156
157     m_pkey.reset(pkey, EVP_PKEY_free);
158
159     int type = EVP_PKEY_type(pkey->type);
160
161     if (type == EVP_PKEY_RSA) {
162         m_type = isPrivate ? KeyType::KEY_RSA_PRIVATE : KeyType::KEY_RSA_PUBLIC;
163     }
164
165     if (type == EVP_PKEY_EC) {
166         m_type = isPrivate ? KeyType::KEY_ECDSA_PRIVATE : KeyType::KEY_ECDSA_PUBLIC;
167     }
168     LogDebug("KeyType is: " << (int)m_type << " isPrivate: " << isPrivate);
169 }
170
171 GenericKey::GenericKey(EvpShPtr pkey, KeyType type)
172   : m_pkey(pkey)
173   , m_type(type)
174 {
175     if (type == KeyType::KEY_RSA_PRIVATE || type == KeyType::KEY_RSA_PUBLIC)
176         if (EVP_PKEY_RSA != EVP_PKEY_type(pkey->type)) {
177             m_pkey.reset();
178             m_type = KeyType::KEY_NONE;
179         }
180     if (type == KeyType::KEY_ECDSA_PRIVATE || type == KeyType::KEY_ECDSA_PUBLIC)
181         if (EVP_PKEY_EC != EVP_PKEY_type(pkey->type)) {
182             m_pkey.reset();
183             m_type = KeyType::KEY_NONE;
184         }
185 }
186
187 bool GenericKey::empty() const {
188     return m_pkey.get() == NULL;
189 }
190
191 GenericKey::EvpShPtr GenericKey::getEvpShPtr() const {
192     return m_pkey;
193 }
194
195 KeyType GenericKey::getType() const {
196     return m_type;
197 }
198
199 RawBuffer GenericKey::getDERPRV() const {
200     return i2d(i2d_PrivateKey_bio, m_pkey.get());
201 }
202
203 RawBuffer GenericKey::getDERPUB() const {
204     return i2d(i2d_PUBKEY_bio, m_pkey.get());
205 }
206
207 RawBuffer GenericKey::getDER() const {
208     if (m_type == KeyType::KEY_ECDSA_PRIVATE || m_type == KeyType::KEY_RSA_PRIVATE) {
209         return getDERPRV();
210     } else if (m_type == KeyType::KEY_RSA_PUBLIC || m_type == KeyType::KEY_ECDSA_PUBLIC) {
211         return getDERPUB();
212     }
213     return RawBuffer();
214
215 //    RawBuffer output;
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();
220 //    } 
221 //    LogError("Key::getDER");
222 //    printDER(output);
223 //    return output;
224 }
225
226 KeyShPtr Key::create(const RawBuffer &raw, const std::string &password) {
227     KeyShPtr output(new GenericKey(raw, password));
228     if (output->empty())
229         output.reset();
230     return output;
231 }
232
233 } // namespace CKM
234