Add context cleanup command for TZ
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / store.cpp
1 /*
2  *  Copyright (c) 2015 - 2021 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       store.cpp
18  * @author     Lukasz Kostyra (l.kostyra@samsung.com)
19  * @version    1.0
20  */
21
22 #include <generic-backend/exception.h>
23 #include <generic-backend/crypto-params.h>
24 #include <tz-backend/obj.h>
25 #include <tz-backend/store.h>
26 #include <tz-backend/internals.h>
27
28 #include <message-buffer.h>
29
30 namespace CKM {
31 namespace Crypto {
32 namespace TZ {
33
34 namespace {
35
36 // internal SW encryption scheme flags
37 enum EncryptionScheme {
38         NONE = 0,
39         PASSWORD = 1 << 0
40 };
41
42 RawBuffer unpackData(const RawBuffer &packed)
43 {
44         MessageBuffer buffer;
45         buffer.Push(RawBuffer(packed));
46
47         int scheme;
48         buffer.Deserialize(scheme);
49
50         RawBuffer data;
51         buffer.Deserialize(data);
52         return data;
53 }
54
55 } // namespace
56
57 Store::Store(CryptoBackend backendId) :
58         GStore(backendId)
59 {
60 }
61
62 GObjUPtr Store::getObject(const Token &token, const Password &pass)
63 {
64         int scheme;
65         RawBuffer id;
66         RawBuffer iv;
67         RawBuffer tag;
68         unpack(token.data, pass, scheme, id, iv, tag);
69
70         if (token.dataType.isKeyPrivate() || token.dataType.isKeyPublic())
71                 return make<AKey>(scheme, std::move(id), Pwd(pass, iv, tag), token.dataType);
72
73         if (token.dataType.isSymmetricKey())
74                 return make<SKey>(scheme, std::move(id), Pwd(pass, iv, tag));
75
76         if (token.dataType.isCertificate() || token.dataType.isChainCert())
77                 return make<Cert>(scheme, std::move(id), Pwd(pass, iv, tag), token.dataType);
78
79         auto pwd = Pwd(pass, iv, tag);
80         RawBuffer raw = Internals::getData(id, pwd, token.dataType);
81
82         if (token.dataType.isBinaryData())
83                 return make<BData>(scheme, std::move(id), std::move(pwd), std::move(raw));
84
85         ThrowErr(Exc::Crypto::DataTypeNotSupported,
86                          "This type of data is not supported by trustzone backend: ", token.dataType);
87 }
88
89 TokenPair Store::generateAKey(const CryptoAlgorithm &alg, const Password &privPass,
90                                                           const Password &pubPass, const RawBuffer &hashPriv, const RawBuffer &hashPub)
91 {
92         RawBuffer pubIv, privIv;
93         RawBuffer pubTag, privTag;
94         if (!pubPass.empty()) {
95                 pubIv = Internals::generateIV();
96         }
97         if (!privPass.empty()) {
98                 privIv = Internals::generateIV();
99         }
100
101         AlgoType keyType;
102         DataType pubType, privType;
103         keyType = Internals::generateAKey(alg, pubPass, privPass, pubIv, privIv, pubTag, privTag, hashPriv, hashPub);
104         if(keyType == AlgoType::RSA_GEN){
105                 pubType = DataType(KeyType::KEY_RSA_PUBLIC);
106                 privType = DataType(KeyType::KEY_RSA_PRIVATE);
107         }
108         else if(keyType == AlgoType::DSA_GEN){
109                 pubType= DataType(KeyType::KEY_DSA_PUBLIC);
110                 privType = DataType(KeyType::KEY_DSA_PRIVATE);
111         }
112         else if(keyType == AlgoType::ECDSA_GEN){
113                 pubType= DataType(KeyType::KEY_ECDSA_PUBLIC);
114                 privType = DataType(KeyType::KEY_ECDSA_PRIVATE);
115         }
116
117         return std::make_pair<Token, Token>(
118                 Token(m_backendId, privType, pack(hashPriv, privPass, privIv, privTag)),
119                 Token(m_backendId, pubType, pack(hashPub, pubPass, pubIv, pubTag))
120         );
121 }
122
123 Token Store::generateSKey(const CryptoAlgorithm &alg,
124                                                   const Password &pass,
125                                                   const RawBuffer &hash)
126 {
127         RawBuffer iv;
128         RawBuffer tag;
129         if (!pass.empty()) {
130                 // IV is needed for key encryption
131                 iv = Internals::generateIV();
132         }
133
134         Internals::generateSKey(alg, pass, iv, tag, hash);
135         return Token(m_backendId, DataType(KeyType::KEY_AES), pack(hash, pass, iv, tag));
136 }
137
138 Token Store::import(const Data &data, const Password &pass, const EncryptionParams &e,
139                                                                    const RawBuffer &hash)
140 {
141         if (!data.type.isBinaryData() && !data.type.isKey())
142                 ThrowErr(Exc::Crypto::DataTypeNotSupported, "Invalid data provided for import");
143
144         RawBuffer passIV;
145         RawBuffer tag;
146
147         if (!pass.empty()) {
148                 // IV is needed for data encryption with pwd
149                 passIV = Internals::generateIV();
150         }
151
152         Internals::importData(data, e, pass, passIV, tag, hash);
153         return Token(m_backendId, data.type, pack(hash, pass, passIV, tag));
154 }
155
156 void Store::destroy(const Token &token)
157 {
158         RawBuffer id = unpackData(token.data);
159         if (token.dataType.isBinaryData()) {
160                 // TODO this should be a generic "destroy persistent memory object" once
161                 // serialization in key-manager-ta is unified
162                 Internals::destroyData(id);
163         }
164         Internals::destroyKey(id);
165 }
166
167 RawBuffer Store::pack(const RawBuffer &keyId,
168                                           const Password &pwd,
169                                           const RawBuffer &iv,
170                                           const RawBuffer &tag)
171 {
172         // determine whether the key is password protected and store schema info
173         // we don't need to additionally encrypt key ID
174         int scheme = pwd.empty() ? EncryptionScheme::NONE : EncryptionScheme::PASSWORD;
175
176         if (scheme == EncryptionScheme::PASSWORD) {
177                 return SerializeMessage(scheme, keyId, iv, tag);
178         } else {
179                 return SerializeMessage(scheme, keyId);
180         }
181 }
182
183 void Store::unpack(const RawBuffer &packed,
184                                    const Password& password,
185                                    int &scheme,
186                                    RawBuffer &data,
187                                    RawBuffer &iv,
188                                    RawBuffer &tag)
189 {
190         MessageBuffer buffer;
191         buffer.Push(RawBuffer(packed));
192
193         buffer.Deserialize(scheme);
194
195         if (scheme == EncryptionScheme::PASSWORD) {
196                 buffer.Deserialize(data, iv, tag);
197         } else {
198                 buffer.Deserialize(data);
199         }
200
201         if ((scheme & EncryptionScheme::PASSWORD) && password.empty()) {
202                 ThrowErr(Exc::Crypto::AuthenticationFailed,
203                                  "This token is protected with password and none passed");
204         } else if (!(scheme & EncryptionScheme::PASSWORD) && !password.empty()) {
205                 ThrowErr(Exc::Crypto::AuthenticationFailed,
206                                  "This token is not protected with password but passed one");
207         }
208 }
209
210 size_t Store::maxChunkSize() const
211 {
212         return Internals::maxChunkSize();
213 }
214
215 } // namespace TZ
216 } // namespace Crypto
217 } // namespace CKM