Change code formatting in import/export wrapped key
[platform/core/security/key-manager.git] / src / manager / crypto / sw-backend / obj.cpp
1 /*
2  *  Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. 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  * @file       obj.cpp
18  * @author     BartÅ‚omiej Grzelewski (b.grzelewski@samsung.com)
19  * @version    1.0
20  */
21 #include <openssl/bio.h>
22 #include <openssl/evp.h>
23 #include <openssl/x509.h>
24
25 #include <dpl/log/log.h>
26 #include <utils.h>
27
28 #include <generic-backend/exception.h>
29 #include <sw-backend/obj.h>
30 #include <sw-backend/store.h>
31 #include <sw-backend/internals.h>
32 #include <ckm/ckm-key.h>
33
34 namespace CKM {
35 namespace Crypto {
36 namespace SW {
37
38 namespace {
39
40 AlgoType key2algo(DataType type)
41 {
42         switch (type) {
43         case DataType::KEY_RSA_PRIVATE:
44         case DataType::KEY_RSA_PUBLIC:
45                 return AlgoType::RSA_SV;
46
47         case DataType::KEY_DSA_PRIVATE:
48         case DataType::KEY_DSA_PUBLIC:
49                 return AlgoType::DSA_SV;
50
51         case DataType::KEY_ECDSA_PRIVATE:
52         case DataType::KEY_ECDSA_PUBLIC:
53                 return AlgoType::ECDSA_SV;
54
55         default:
56                 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
57         }
58 }
59
60 } // namespace anonymous
61
62 Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &)
63 {
64         auto data = Internals::deriveKBKDF(getBinary(), alg);
65
66         return Token(backendId(), data.type, Store::pack(data.buffer, pass));
67 }
68
69 Token Key::unwrap(const CryptoAlgorithm &params,
70                                   const Data &wrappedKey,
71                                   const Password &pass,
72                                   const RawBuffer &)
73 {
74         auto decrypted = decrypt(params, wrappedKey.data);
75
76         if (!wrappedKey.type.isKey()) {
77                 ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a key");
78         }
79
80         // validate the decrypted key
81         if (wrappedKey.type.isSKey()) {
82                 auto tmp = CKM::Key::createAES(decrypted);
83                 if (!tmp)
84                         ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid AES key");
85         } else {
86                 auto tmp = CKM::Key::create(decrypted);
87                 if (!tmp)
88                         ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid asymmetric key");
89
90                 if (wrappedKey.type != DataType(tmp->getType()))
91                         ThrowErr(Exc::Crypto::InputParam, "Wrapped key type does not match the required one");
92         }
93
94         return Token(backendId(), wrappedKey.type, Store::pack(decrypted, pass));
95 }
96
97 RawBuffer Key::wrap(const CryptoAlgorithm &params,
98                                         const Token &keyToWrap,
99                                         const Password &keyToWrapPass)
100 {
101         RawBuffer data = Store::unpack(keyToWrap.data, keyToWrapPass);
102         return encrypt(params, data);
103 }
104
105
106 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
107 {
108         return Internals::symmetricEncrypt(getBinary(), alg, data);
109 }
110 RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
111 {
112         return Internals::symmetricDecrypt(getBinary(), alg, cipher);
113 }
114
115 RawBuffer AKey::sign(
116         const CryptoAlgorithm &alg,
117         const RawBuffer &message)
118 {
119         CryptoAlgorithm algWithType(alg);
120         algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
121         return Internals::sign(getEvpShPtr().get(), algWithType, message);
122 }
123
124 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
125                                  const RawBuffer &sign)
126 {
127         CryptoAlgorithm algWithType(alg);
128         EVP_PKEY *evp = getEvpShPtr().get();
129         AlgoType type;
130
131         // setup algorithm type basing on evp key type if it doesn't exist
132         if (!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
133                 int subType = EVP_PKEY_type(EVP_PKEY_id(evp));
134
135                 switch (subType) {
136                 case EVP_PKEY_RSA:
137                         type = AlgoType::RSA_SV;
138                         break;
139
140                 case EVP_PKEY_DSA:
141                         type = AlgoType::DSA_SV;
142                         break;
143
144                 case EVP_PKEY_EC:
145                         type = AlgoType::ECDSA_SV;
146                         break;
147
148                 default:
149                         ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
150                 }
151
152                 algWithType.setParam(ParamName::ALGO_TYPE, type);
153         }
154
155         return Internals::verify(evp, algWithType, message, sign);
156 }
157
158 RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
159 {
160         return Internals::asymmetricEncrypt(getEvpShPtr(), alg, data);
161 }
162
163 RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
164 {
165         return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
166 }
167
168 Token AKey::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer & /* digest */)
169 {
170         auto data = Internals::deriveECDH(getEvpShPtr(), alg);
171
172         return Token(backendId(), data.type, Store::pack(data.buffer, pass));
173 }
174
175 EvpShPtr AKey::getEvpShPtr()
176 {
177         if (m_evp)
178                 return m_evp;
179
180         EVP_PKEY *pkey = NULL;
181         auto bio = uptr<BIO_free_all>(BIO_new(BIO_s_mem()));
182
183         LogDebug("Start to parse key:");
184
185         if (!pkey) {
186                 (void)BIO_reset(bio.get());
187                 BIO_write(bio.get(), m_raw.data(), m_raw.size());
188                 pkey = d2i_PrivateKey_bio(bio.get(), NULL);
189                 LogDebug("Trying d2i_PrivateKey_bio Status: " << (void *)pkey);
190         }
191
192         if (!pkey) {
193                 (void)BIO_reset(bio.get());
194                 BIO_write(bio.get(), m_raw.data(), m_raw.size());
195                 pkey = d2i_PUBKEY_bio(bio.get(), NULL);
196                 LogDebug("Trying d2i_PUBKEY_bio Status: " << (void *)pkey);
197         }
198
199         if (!pkey)
200                 ThrowErr(Exc::Crypto::InternalError, "Failed to parse key");
201
202         m_evp.reset(pkey, EVP_PKEY_free);
203         return m_evp;
204 }
205
206 EvpShPtr Cert::getEvpShPtr()
207 {
208         if (m_evp)
209                 return m_evp;
210
211         int size = static_cast<int>(m_raw.size());
212         const unsigned char *ptr = reinterpret_cast<const unsigned char *>
213                                                            (m_raw.data());
214
215         X509 *x509 = d2i_X509(NULL, &ptr, size);
216
217         if (!x509)
218                 ThrowErr(Exc::Crypto::InternalError, "Failed to parse certificate.");
219
220         m_evp.reset(X509_get_pubkey(x509), EVP_PKEY_free);
221         X509_free(x509);
222         return m_evp;
223 }
224
225 Token Cert::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &)
226 {
227         ThrowErr(Exc::Crypto::OperationNotSupported);
228 }
229
230 Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, const RawBuffer &)
231 {
232         ThrowErr(Exc::Crypto::OperationNotSupported);
233 }
234
235 RawBuffer Cert::wrap(const CryptoAlgorithm &, const Token &, const Password &)
236 {
237         ThrowErr(Exc::Crypto::OperationNotSupported);
238 }
239
240 } // namespace SW
241 } // namespace Crypto
242 } // namespace CKM