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