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