cf15ed8f227dbeb56b43207f357bc6b18faaf347
[platform/core/security/key-manager.git] / src / manager / service / key-provider.cpp
1 /*
2  *  Copyright (c) 2014-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 #include <array>
18
19 #include <openssl/rand.h>
20 #include <openssl/err.h>
21 #include <openssl/evp.h>
22 #include <openssl/sha.h>
23
24 #include <key-provider.h>
25 #include <ckm/ckm-zero-memory.h>
26 #include <utils.h>
27 #include <string.h>
28
29 #include <crypto-backend.h>
30 #ifdef SE_BACKEND_ENABLED
31 #include <se-backend/internals.h>
32 #endif
33 using namespace CKM;
34
35 namespace {
36
37 constexpr int PBKDF2_ITERATIONS = 4096;
38 constexpr uint32_t KEYCOMPONENT_VERSION = 2;
39 constexpr int OPENSSL_ENGINE_ERROR = -4;
40
41 template<typename T>
42 RawBuffer toRawBuffer(const T &data)
43 {
44         RawBuffer output;
45         const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
46         output.assign(ptr, ptr + sizeof(T));
47         return output;
48 }
49
50 // You cannot use toRawBuffer template with pointers
51 template<typename T>
52 RawBuffer toRawBuffer(T *)
53 {
54         class NoPointerAllowed {
55                 NoPointerAllowed() {}
56         };
57         NoPointerAllowed a;
58         return RawBuffer();
59 }
60
61 int encryptAes256Gcm(const unsigned char *plaintext,
62                      int plaintext_len, const unsigned char *key, const unsigned char *iv,
63                      unsigned char *ciphertext, unsigned char *tag)
64 {
65         int len;
66         int ciphertext_len = 0;
67
68         auto ctx = uptr<EVP_CIPHER_CTX_free>(EVP_CIPHER_CTX_new());
69         if (!ctx)
70                 return OPENSSL_ENGINE_ERROR;
71
72         if (!EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL, NULL, NULL))
73                 return OPENSSL_ENGINE_ERROR;
74
75         if (!EVP_EncryptInit_ex(ctx.get(), NULL, NULL, key, iv))
76                 return OPENSSL_ENGINE_ERROR;
77
78         if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
79                 return OPENSSL_ENGINE_ERROR;
80
81         if (!EVP_EncryptUpdate(ctx.get(), ciphertext, &len, plaintext, plaintext_len))
82                 return OPENSSL_ENGINE_ERROR;
83
84         ciphertext_len = len;
85
86         if (!EVP_EncryptFinal_ex(ctx.get(), ciphertext + len, &len))
87                 return OPENSSL_ENGINE_ERROR;
88
89         ciphertext_len += len;
90
91         if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
92                 return OPENSSL_ENGINE_ERROR;
93
94         return ciphertext_len;
95 }
96
97 int decryptAes256Gcm(const unsigned char *ciphertext,
98                      int ciphertext_len, unsigned char *tag, const unsigned char *key,
99                      const unsigned char *iv, unsigned char *plaintext)
100 {
101         int len;
102         int plaintext_len;
103         int ret;
104
105         auto ctx = uptr<EVP_CIPHER_CTX_free>(EVP_CIPHER_CTX_new());
106         if (!ctx)
107                 return OPENSSL_ENGINE_ERROR;
108
109         if (!EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL, NULL, NULL))
110                 return OPENSSL_ENGINE_ERROR;
111
112         if (!EVP_DecryptInit_ex(ctx.get(), NULL, NULL, key, iv))
113                 return OPENSSL_ENGINE_ERROR;
114
115         if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
116                 return OPENSSL_ENGINE_ERROR;
117
118         if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
119                 return OPENSSL_ENGINE_ERROR;
120
121         if (!EVP_DecryptUpdate(ctx.get(), plaintext, &len, ciphertext, ciphertext_len))
122                 return OPENSSL_ENGINE_ERROR;
123
124         plaintext_len = len;
125
126         if (!(ret = EVP_DecryptFinal_ex(ctx.get(), plaintext + len, &len)))
127                 return OPENSSL_ENGINE_ERROR;
128
129         if (ret > 0) {
130                 plaintext_len += len;
131                 return plaintext_len;
132         } else {
133                 return -1;
134         }
135 }
136
137 typedef std::array<uint8_t, MAX_KEY_SIZE> KeyData;
138
139 KeyData PBKDF(const std::string& pass, const unsigned char *salt, int saltlen)
140 {
141         KeyData key;
142         if (!PKCS5_PBKDF2_HMAC_SHA1(pass.c_str(),
143                                     pass.size(),
144                                     salt,
145                                     saltlen,
146                                     PBKDF2_ITERATIONS,
147                                     key.size(),
148                                     key.data())) {
149                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
150         }
151         return key;
152 }
153
154 // derives a key used for DomainKEK encryption (aka PKEK1) from random salt & user password
155 KeyData makePKEK1(const DomainKEKInfo& domainKEKInfo, const Password &password)
156 {
157         std::string concatPasswordClient(password.c_str());
158         concatPasswordClient += std::string(domainKEKInfo.client);
159
160         if (domainKEKInfo.version != KEYCOMPONENT_VERSION)
161                 ThrowErr(Exc::InternalError, "It's not expected version");
162
163         RawBuffer salt;
164         if (domainKEKInfo.backend == (int)CryptoBackend::SecureElement) {
165 #if SE_BACKEND_ENABLED
166                 salt = Crypto::SE::Internals::encryptWithDbpKey((unsigned char*)domainKEKInfo.salt,
167                                                                 MAX_SALT_SIZE,
168                                                                 (unsigned char*)domainKEKInfo.iv,
169                                                                 MAX_IV_SIZE);
170 #else
171                 ThrowErr(Exc::InternalError, "It's not expected backend");
172 #endif
173         } else if (domainKEKInfo.backend == (int)CryptoBackend::OpenSSL) {
174                 salt = RawBuffer(domainKEKInfo.salt, domainKEKInfo.salt + MAX_SALT_SIZE);
175         } else {
176                 ThrowErr(Exc::InternalError, "It's not expected backend");
177         }
178
179         return PBKDF(concatPasswordClient, salt.data(), salt.size());
180 }
181
182 // derives a key (PKEK2) from DomainKEK and custom client string (may be a client id or uid)
183 KeyData makePKEK2(const uint8_t *domainKEK, const std::string &client)
184 {
185         return PBKDF(client, domainKEK, MAX_SALT_SIZE);
186 }
187
188 void unwrapDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
189                      const Password &password,
190                      DomainKEKAndInfo &domainKEK)
191 {
192         DomainKEKAndInfo wrappedDomainKEK(wrappedDomainKEKbuffer);
193         KeyData PKEK1 = makePKEK1(wrappedDomainKEK.info, password);
194
195         int keyLength;
196         if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.key,
197                                               wrappedDomainKEK.info.keyLength,
198                                               wrappedDomainKEK.info.tag,
199                                               PKEK1.data(),
200                                               wrappedDomainKEK.info.iv,
201                                               domainKEK.key)))
202                 ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
203
204         domainKEK.setKeyInfo(wrappedDomainKEK.info);
205         domainKEK.info.keyLength = static_cast<uint32_t>(keyLength);
206 }
207
208 RawBuffer wrapDomainKEK(DomainKEKAndInfo &domainKEK, const Password &password)
209 {
210         KeyData PKEK1 = makePKEK1(domainKEK.info, password);
211
212         DomainKEKAndInfo wrappedDomainKEK;
213         wrappedDomainKEK.setKeyInfo(domainKEK.info);
214
215         int wrappedLength;
216         if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.key,
217                                                   domainKEK.info.keyLength,
218                                                   PKEK1.data(),
219                                                   domainKEK.info.iv,
220                                                   wrappedDomainKEK.key,
221                                                   wrappedDomainKEK.info.tag)))
222                 ThrowErr(Exc::InternalError, "DomainKEK encryption failed");
223
224         wrappedDomainKEK.info.keyLength = static_cast<uint32_t>(wrappedLength);
225         return toRawBuffer(wrappedDomainKEK);
226 }
227
228 template <size_t N>
229 bool randomize(uint8_t (&array)[N])
230 {
231         return RAND_bytes(array, N) == 1;
232 }
233
234 } // anonymous namespace
235
236 KeyProvider::KeyProvider() :
237         m_domainKEK(NULL),
238         m_isInitialized(false)
239 {
240         LogDebug("Created empty KeyProvider");
241 }
242
243 KeyProvider::KeyProvider(
244         const RawBuffer &domainKEKInWrapForm,
245         const Password &password) :
246         m_domainKEK(new DomainKEKAndInfo()),
247         m_isInitialized(true)
248 {
249         if (domainKEKInWrapForm.size() != sizeof(DomainKEKAndInfo)) {
250                 LogWarning("Input size:" << domainKEKInWrapForm.size()
251                            << " Expected: " << sizeof(DomainKEKAndInfo));
252                 LogWarning("Buffer doesn't have proper size to store DomainKEKAndInfo in KeyProvider"
253                            "Constructor");
254                 m_isInitialized = false;
255                 return;
256         }
257
258         unwrapDomainKEK(domainKEKInWrapForm, password, *m_domainKEK);
259 }
260
261 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
262 {
263         LogDebug("Moving KeyProvider");
264
265         if (this == &second)
266                 return *this;
267
268         m_isInitialized = second.m_isInitialized;
269         m_domainKEK = second.m_domainKEK;
270         second.m_isInitialized = false;
271         second.m_domainKEK = NULL;
272         return *this;
273 }
274
275 KeyProvider::KeyProvider(KeyProvider &&second)
276 {
277         LogDebug("Moving KeyProvider");
278         m_isInitialized = second.m_isInitialized;
279         m_domainKEK = second.m_domainKEK;
280         second.m_isInitialized = false;
281         second.m_domainKEK = NULL;
282 }
283
284 bool KeyProvider::isInitialized() const
285 {
286         return m_isInitialized;
287 }
288
289 RawBuffer KeyProvider::getPureDomainKEK() const
290 {
291         if (!m_isInitialized)
292                 ThrowErr(Exc::InternalError, "Object not initialized!");
293
294         // TODO secure
295         return RawBuffer(m_domainKEK->key, m_domainKEK->key + m_domainKEK->info.keyLength);
296 }
297
298 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password) const
299 {
300         if (!m_isInitialized)
301                 ThrowErr(Exc::InternalError, "Object not initialized!");
302
303         return wrapDomainKEK(*m_domainKEK, password);
304 }
305
306 RawBuffer KeyProvider::getPureDEK(const RawBuffer &wrappedDEKbuffer) const
307 {
308         if (!m_isInitialized)
309                 ThrowErr(Exc::InternalError, "Object not initialized!");
310
311         if (wrappedDEKbuffer.size() != sizeof(DEKAndInfo)) {
312                 LogError("input size:" << wrappedDEKbuffer.size() << " Expected: " << sizeof(DEKAndInfo));
313
314                 ThrowErr(Exc::InternalError,
315                          "buffer doesn't have proper size to store KeyAndInfo in KeyProvider::getPureDEK");
316         }
317
318         DEKAndInfo DEK;
319         DEKAndInfo wrappedDEK(wrappedDEKbuffer);
320
321         KeyData PKEK2 = makePKEK2(m_domainKEK->key, wrappedDEK.info.client);
322
323         int keyLength;
324         if (0 > (keyLength = decryptAes256Gcm(wrappedDEK.key,
325                                               wrappedDEK.info.keyLength,
326                                               wrappedDEK.info.tag,
327                                               PKEK2.data(),
328                                               wrappedDEK.info.iv,
329                                               DEK.key)))
330                 ThrowErr(Exc::InternalError, "UnwrapDEK Failed in KeyProvider::getPureDEK");
331
332         DEK.info.keyLength = static_cast<uint32_t>(keyLength);
333
334         LogDebug("getPureDEK SUCCESS");
335         return RawBuffer(DEK.key, DEK.key + DEK.info.keyLength);
336 }
337
338 RawBuffer KeyProvider::generateDEK(const std::string &client) const
339 {
340         if (!m_isInitialized)
341                 ThrowErr(Exc::InternalError, "Object not initialized!");
342
343         DEKAndInfo wrappedDEK;
344         std::string resized_client;
345
346         if (client.length() < MAX_CLIENT_ID_SIZE)
347                 resized_client = client;
348         else
349                 resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
350
351         uint8_t DEK[MAX_KEY_SIZE];
352
353         if (!randomize(DEK) || !randomize(wrappedDEK.info.iv))
354                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
355
356         KeyData PKEK2 = makePKEK2(m_domainKEK->key, resized_client);
357
358         int wrappedKeyLength;
359         if (0 > (wrappedKeyLength = encryptAes256Gcm(DEK,
360                                                      sizeof(DEK),
361                                                      PKEK2.data(),
362                                                      wrappedDEK.info.iv,
363                                                      wrappedDEK.key,
364                                                      wrappedDEK.info.tag)))
365                 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
366
367         wrappedDEK.info.keyLength = static_cast<uint32_t>(wrappedKeyLength);
368         wrappedDEK.setKeyInfoClient(resized_client);
369
370         LogDebug("GenerateDEK Success");
371         return toRawBuffer(wrappedDEK);
372 }
373
374 void KeyProvider::migrateDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
375                                    const Password &password)
376 {
377         DEKAndInfo wrappedOldDomainKEK(wrappedDomainKEKbuffer);
378
379         std::string concatPasswordClient(password.c_str());
380         concatPasswordClient += std::string(wrappedOldDomainKEK.info.client);
381
382         KeyData PKEK1 = PBKDF(concatPasswordClient, wrappedOldDomainKEK.info.salt, MAX_SALT_SIZE);
383
384         int keyLength;
385         if (0 > (keyLength = decryptAes256Gcm(wrappedOldDomainKEK.key,
386                                               wrappedOldDomainKEK.info.keyLength,
387                                               wrappedOldDomainKEK.info.tag,
388                                               PKEK1.data(),
389                                               wrappedOldDomainKEK.info.iv,
390                                               m_domainKEK->key)))
391                 ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
392
393         DomainKEKInfo info(wrappedOldDomainKEK.info);
394         info.version = KEYCOMPONENT_VERSION;
395         info.backend = static_cast<uint32_t>(CryptoBackend::OpenSSL);
396 #ifdef SE_BACKEND_ENABLED
397         info.backend = static_cast<uint32_t>(CryptoBackend::SecureElement);
398 #endif
399         m_domainKEK->setKeyInfo(info);
400
401         m_domainKEK->info.keyLength = static_cast<uint32_t>(keyLength);
402         m_isInitialized = true;
403         LogDebug("Migrate DomainKEK Success");
404 }
405
406 RawBuffer KeyProvider::generateDomainKEK(const std::string &user, const Password &userPassword)
407 {
408         DomainKEKAndInfo domainKEK;
409
410         if (!randomize(domainKEK.info.salt) ||
411             !randomize(domainKEK.key) ||
412             !randomize(domainKEK.info.iv)) {
413                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
414         }
415
416         domainKEK.info.version = KEYCOMPONENT_VERSION;
417         domainKEK.info.backend = static_cast<uint32_t>(CryptoBackend::OpenSSL);
418 #ifdef SE_BACKEND_ENABLED
419         domainKEK.info.backend = static_cast<uint32_t>(CryptoBackend::SecureElement);
420 #endif
421         domainKEK.info.keyLength = sizeof(domainKEK.key);
422         domainKEK.setKeyInfoClient(user);
423
424         return wrapDomainKEK(domainKEK, userPassword);
425 }