2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
18 * @author Kyungwook Tak (k.tak@samsung.com)
20 * @brief Decrypt old secure-storage data for migration
22 #include <ss-crypto.h>
27 #include <openssl/sha.h>
28 #include <openssl/evp.h>
29 #include <openssl/hmac.h>
31 #include <dpl/log/log.h>
37 const int SALT_SIZE = 32;
38 const int KEY_SIZE = 16;
40 RawBuffer _get_key(const std::string &id)
42 unsigned char salt[SALT_SIZE];
44 ::memset(salt, 0xFF, SALT_SIZE);
46 RawBuffer duk(KEY_SIZE);
48 if (::PKCS5_PBKDF2_HMAC_SHA1(id.c_str(), id.length(), salt, SALT_SIZE, 1, duk.size(),
50 LogError("Failed to pkcs5_pkbdf_hmac_sha1.");
57 RawBuffer _get_iv(const RawBuffer &src)
59 RawBuffer iv(KEY_SIZE);
60 size_t ivlen = iv.size();
62 if (::EVP_Digest(src.data(), src.size(), iv.data(), &ivlen, ::EVP_sha1(), nullptr)
64 LogError("Failed to get iv");
71 RawBuffer _decrypt(const RawBuffer &key, const RawBuffer &iv, const RawBuffer &ciphertext)
73 auto algo = ::EVP_aes_128_cbc();
74 int tmp_len = (ciphertext.size() / algo->block_size + 1) * algo->block_size;
76 RawBuffer plaintext(tmp_len, 0);
78 std::unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX *)> ctxptr(
79 ::EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
81 if (ctxptr == nullptr)
82 throw std::bad_alloc();
84 auto ctx = ctxptr.get();
86 int ec = ::EVP_CIPHER_CTX_set_padding(ctx, 1);
88 LogError("Failed to evp ctx set padding. ec: " << ec);
92 ec = ::EVP_CipherInit(ctx, algo, key.data(), iv.data(), 0 /* decrypt flag */);
94 LogError("Failed to evp cipher init. ec: " << ec);
98 int plaintext_len = 0;
99 ec = ::EVP_CipherUpdate(ctx, plaintext.data(), &plaintext_len,
100 ciphertext.data(), ciphertext.size());
102 LogError("Failed to evp cipher update. ec: " << ec);
107 ec = EVP_CipherFinal(ctx, plaintext.data() + plaintext_len, &final_len);
109 LogError("Failed to evp cipher final. ec: " << ec);
113 plaintext_len += final_len;
115 plaintext.resize(plaintext_len);
120 } // namespace anonymous
122 namespace SsMigration {
124 RawBuffer decrypt(const std::string &seed, const RawBuffer &ciphertext)
126 auto key = _get_key(seed);
127 auto iv = _get_iv(key);
129 return _decrypt(key, iv, ciphertext);
132 } // namespace SsMigration