Migrate ss data to both of system/admin user db
[platform/core/security/key-manager.git] / src / manager / service / ss-crypto.cpp
1 /*
2  *  Copyright (c) 2016 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        ss-crypto.cpp
18  * @author      Kyungwook Tak (k.tak@samsung.com)
19  * @version     1.0
20  * @brief       Decrypt old secure-storage data for migration
21  */
22 #include <ss-crypto.h>
23
24 #include <memory>
25 #include <cstring>
26
27 #include <openssl/sha.h>
28 #include <openssl/evp.h>
29 #include <openssl/hmac.h>
30
31 #include <dpl/log/log.h>
32
33 namespace CKM {
34
35 namespace {
36
37 const int SALT_SIZE = 32;
38 const int KEY_SIZE = 16;
39
40 RawBuffer _get_key(const std::string &id)
41 {
42         unsigned char salt[SALT_SIZE];
43
44         ::memset(salt, 0xFF, SALT_SIZE);
45
46         RawBuffer duk(KEY_SIZE);
47
48         if (::PKCS5_PBKDF2_HMAC_SHA1(id.c_str(), id.length(), salt, SALT_SIZE, 1, duk.size(),
49                         duk.data()) != 1) {
50                 LogError("Failed to pkcs5_pkbdf_hmac_sha1.");
51                 return RawBuffer();
52         }
53
54         return duk;
55 }
56
57 RawBuffer _get_iv(const RawBuffer &src)
58 {
59         RawBuffer iv(KEY_SIZE);
60         size_t ivlen = iv.size();
61
62         if (::EVP_Digest(src.data(), src.size(), iv.data(), &ivlen, ::EVP_sha1(), nullptr)
63                         != 1) {
64                 LogError("Failed to get iv");
65                 return RawBuffer();
66         }
67
68         return iv;
69 }
70
71 RawBuffer _decrypt(const RawBuffer &key, const RawBuffer &iv, const RawBuffer &ciphertext)
72 {
73         auto algo = ::EVP_aes_128_cbc();
74         int tmp_len = (ciphertext.size() / algo->block_size + 1) * algo->block_size;
75
76         RawBuffer plaintext(tmp_len, 0);
77
78         std::unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX *)> ctxptr(
79                         ::EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
80
81         if (ctxptr == nullptr)
82                 throw std::bad_alloc();
83
84         auto ctx = ctxptr.get();
85
86         int ec = ::EVP_CIPHER_CTX_set_padding(ctx, 1);
87         if (ec != 1) {
88                 LogError("Failed to evp ctx set padding. ec: " << ec);
89                 return RawBuffer();
90         }
91
92         ec = ::EVP_CipherInit(ctx, algo, key.data(), iv.data(), 0 /* decrypt flag */);
93         if (ec != 1) {
94                 LogError("Failed to evp cipher init. ec: " << ec);
95                 return RawBuffer();
96         }
97
98         int plaintext_len = 0;
99         ec = ::EVP_CipherUpdate(ctx, plaintext.data(), &plaintext_len,
100                         ciphertext.data(), ciphertext.size());
101         if (ec != 1) {
102                 LogError("Failed to evp cipher update. ec: " << ec);
103                 return RawBuffer();
104         }
105
106         int final_len = 0;
107         ec = EVP_CipherFinal(ctx, plaintext.data() + plaintext_len, &final_len);
108         if (ec != 1) {
109                 LogError("Failed to evp cipher final. ec: " << ec);
110                 return RawBuffer();
111         }
112
113         plaintext_len += final_len;
114
115         plaintext.resize(plaintext_len);
116
117         return plaintext;
118 }
119
120 } // namespace anonymous
121
122 namespace SsMigration {
123
124 RawBuffer decrypt(const std::string &seed, const RawBuffer &ciphertext)
125 {
126         auto key = _get_key(seed);
127         auto iv = _get_iv(key);
128
129         return _decrypt(key, iv, ciphertext);
130 }
131
132 } // namespace SsMigration
133
134 } // namespace CKM