Key unwrapping implementation in TZ backend
[platform/core/security/key-manager.git] / misc / ckm_db_tool / decrypt.cpp
1 /*
2  *  Copyright (c) 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       decrypt.cpp
18  * @author     Mateusz Cegielka (m.cegielka@samsung.com)
19  * @version    1.0
20  */
21
22 #include "decrypt.h"
23 #include "ui.h"
24
25 #include <algorithm>
26 #include <iostream>
27 #include <stdexcept>
28
29 #include <credentials.h>
30 #include <generic-backend/gobj.h>
31
32 #include <unistd.h>
33
34 namespace {
35
36 int findColumnByName(const std::string &name, const CKM::Decrypt::Row &columns)
37 {
38         auto column = std::find(columns.begin(), columns.end(), name);
39         if (column == columns.end())
40                 return -1;
41
42         return column - columns.begin();
43 }
44
45 std::string fmtObject(const CKM::NameEntry &name)
46 {
47         return "'" + name.name + "'";
48 }
49
50 CKM::Password askObjectPassword(const std::string &displayName)
51 {
52         std::string password = CKM::UI::promptPassword(
53                 "enter password for object " + displayName + ":");
54         return CKM::Password(password.begin(), password.end());
55 }
56
57 } // anonymous namespace
58
59 namespace CKM {
60
61 Decrypt::Decrypt(const Row &columns, CKMLogicExt &logic, uid_t uid)
62         : m_logic(logic),
63           m_uid(uid),
64           m_columnData(-1),
65           m_columnDataType(-1),
66           m_columnIdx(-1)
67 {
68         m_columnData = findColumnByName("data", columns);
69         if (m_columnData == -1)
70                 return;
71         m_columnDataType = findColumnByName("dataType", columns);
72         m_columnIdx = findColumnByName("idx", columns);
73         if (m_columnDataType == -1 || m_columnIdx == -1)
74                 UI::warning() << "unable to decrypt, missing dataType or idx columns" << std::endl;
75 }
76
77 bool Decrypt::canDecryptQuery() const
78 {
79         return m_columnData != -1 && m_columnDataType != -1 && m_columnIdx != -1;
80 }
81
82 std::pair<std::string, bool> Decrypt::tryDecrypt(const Row &row) const
83 {
84         NameEntry nameEntry = getNameEntry(row);
85         std::string name = fmtObject(nameEntry);
86
87         try {
88                 return {decrypt(row, "", nameEntry), true};
89         } catch (const Exc::AuthenticationFailed &) {
90         }
91
92         while (true) {
93                 Password password = askObjectPassword(name);
94                 if (password.empty()) {
95                         UI::warning() << "skipped decrypting object " << name << std::endl;
96                         return {"", false};
97                 }
98
99                 try {
100                         return {decrypt(row, password, nameEntry), true};
101                 } catch (const Exc::AuthenticationFailed &) {
102                         UI::error() << "authentication failed for object " << name << std::endl;
103                 }
104         }
105 }
106
107 int Decrypt::getDataColumnIndex() const
108 {
109         return m_columnData;
110 }
111
112 NameEntry Decrypt::getNameEntry(const Row &row) const
113 {
114         int idx = std::stoi(row[m_columnIdx]);
115
116         return m_logic.getNameByIdx(m_uid, idx);
117 }
118
119 std::string Decrypt::decrypt(const Row &row, const Password &password,
120         const NameEntry& nameEntry) const
121 {
122         DataType dataType = static_cast<DataType::Type>(std::stoi(row[m_columnDataType]));
123         Credentials credentials(m_uid, nameEntry.owner);
124         Crypto::GObjUPtr obj;
125
126         int ret = m_logic.readDataHelperProtected(credentials, dataType, nameEntry.name,
127                 nameEntry.owner, password, obj);
128         if (ret != CKM_API_SUCCESS)
129                 throw std::logic_error("reading row data failed");
130
131         RawBuffer decrypted = obj->getBinary();
132         UI::info() << "decrypted object " << fmtObject(nameEntry) << std::endl;
133         return std::string(decrypted.begin(), decrypted.end());
134 }
135
136 } // namespace CKM