2 * Copyright (c) 2015 - 2021 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 Lukasz Kostyra (l.kostyra@samsung.com)
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>
28 #include <message-buffer.h>
36 // internal SW encryption scheme flags
37 enum EncryptionScheme {
42 RawBuffer unpackData(const RawBuffer &packed)
45 buffer.Push(RawBuffer(packed));
48 buffer.Deserialize(scheme);
51 buffer.Deserialize(data);
57 Store::Store(CryptoBackend backendId) :
62 GObjUPtr Store::getObject(const Token &token, const Password &pass)
68 unpack(token.data, pass, scheme, id, iv, tag);
70 if (token.dataType.isKeyPrivate() || token.dataType.isKeyPublic())
71 return make<AKey>(scheme, std::move(id), Pwd(pass, iv, tag), token.dataType);
73 if (token.dataType.isSymmetricKey())
74 return make<SKey>(scheme, std::move(id), Pwd(pass, iv, tag));
76 if (token.dataType.isCertificate() || token.dataType.isChainCert())
77 return make<Cert>(scheme, std::move(id), Pwd(pass, iv, tag), token.dataType);
79 auto pwd = Pwd(pass, iv, tag);
80 RawBuffer raw = Internals::getData(id, pwd, token.dataType);
82 if (token.dataType.isBinaryData())
83 return make<BData>(scheme, std::move(id), std::move(pwd), std::move(raw));
85 ThrowErr(Exc::Crypto::DataTypeNotSupported,
86 "This type of data is not supported by trustzone backend: ", token.dataType);
89 TokenPair Store::generateAKey(const CryptoAlgorithm &alg, const Password &privPass,
90 const Password &pubPass, const RawBuffer &hashPriv, const RawBuffer &hashPub)
92 RawBuffer pubIv, privIv;
93 RawBuffer pubTag, privTag;
94 if (!pubPass.empty()) {
95 pubIv = Internals::generateIV();
97 if (!privPass.empty()) {
98 privIv = Internals::generateIV();
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);
108 else if(keyType == AlgoType::DSA_GEN){
109 pubType= DataType(KeyType::KEY_DSA_PUBLIC);
110 privType = DataType(KeyType::KEY_DSA_PRIVATE);
112 else if(keyType == AlgoType::ECDSA_GEN){
113 pubType= DataType(KeyType::KEY_ECDSA_PUBLIC);
114 privType = DataType(KeyType::KEY_ECDSA_PRIVATE);
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))
123 Token Store::generateSKey(const CryptoAlgorithm &alg,
124 const Password &pass,
125 const RawBuffer &hash)
130 // IV is needed for key encryption
131 iv = Internals::generateIV();
134 Internals::generateSKey(alg, pass, iv, tag, hash);
135 return Token(m_backendId, DataType(KeyType::KEY_AES), pack(hash, pass, iv, tag));
138 Token Store::import(const Data &data, const Password &pass, const EncryptionParams &e,
139 const RawBuffer &hash)
141 if (!data.type.isBinaryData() && !data.type.isKey())
142 ThrowErr(Exc::Crypto::DataTypeNotSupported, "Invalid data provided for import");
148 // IV is needed for data encryption with pwd
149 passIV = Internals::generateIV();
152 Internals::importData(data, e, pass, passIV, tag, hash);
153 return Token(m_backendId, data.type, pack(hash, pass, passIV, tag));
156 void Store::destroy(const Token &token)
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);
164 Internals::destroyKey(id);
167 RawBuffer Store::pack(const RawBuffer &keyId,
170 const RawBuffer &tag)
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;
176 if (scheme == EncryptionScheme::PASSWORD) {
177 return SerializeMessage(scheme, keyId, iv, tag);
179 return SerializeMessage(scheme, keyId);
183 void Store::unpack(const RawBuffer &packed,
184 const Password& password,
190 MessageBuffer buffer;
191 buffer.Push(RawBuffer(packed));
193 buffer.Deserialize(scheme);
195 if (scheme == EncryptionScheme::PASSWORD) {
196 buffer.Deserialize(data, iv, tag);
198 buffer.Deserialize(data);
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");
210 size_t Store::maxChunkSize() const
212 return Internals::maxChunkSize();
216 } // namespace Crypto