Implement public key extraction in TZ backend
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / obj.cpp
1 /*
2  *  Copyright (c) 2015 - 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       obj.cpp
18  * @author     Lukasz Kostyra (l.kostyra@samsung.com)
19  * @version    1.0
20  */
21 #include <memory>
22 #include <utility>
23 #include <generic-backend/exception.h>
24 #include <generic-backend/algo-validation.h>
25 #include <tz-backend/obj.h>
26 #include <tz-backend/ctx.h>
27 #include <tz-backend/store.h>
28 #include <tz-backend/internals.h>
29
30 namespace CKM {
31 namespace Crypto {
32 namespace TZ {
33
34 namespace {
35 AlgoType key2algo(DataType type)
36 {
37         switch (type) {
38         case DataType::KEY_RSA_PRIVATE:
39         case DataType::KEY_RSA_PUBLIC:
40                 return AlgoType::RSA_SV;
41
42         case DataType::KEY_DSA_PRIVATE:
43         case DataType::KEY_DSA_PUBLIC:
44                 return AlgoType::DSA_SV;
45
46         case DataType::KEY_ECDSA_PRIVATE:
47         case DataType::KEY_ECDSA_PUBLIC:
48                 return AlgoType::ECDSA_SV;
49
50         default:
51                 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
52         }
53 }
54 } // namespace anonymous
55
56 Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &hash)
57 {
58         auto algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
59         if (algo != AlgoType::KBKDF)
60                 ThrowErr(Exc::Crypto::InputParam, "Wrong algorithm");
61
62         RawBuffer iv;
63         RawBuffer tag;
64         if (!pass.empty()) {
65                 // IV is needed for key encryption
66                 iv = Internals::generateIV();
67         }
68
69         Internals::deriveKBKDF(getId(), alg, pass, iv, tag, hash);
70
71         return Token(backendId(), DataType(KeyType::KEY_AES), Store::pack(hash, pass, iv, tag));
72 }
73
74 Token Key::unwrap(const CryptoAlgorithm &params,
75                                   const Data &encryptedKey,
76                                   const Password &pass,
77                                   const RawBuffer &hash)
78 {
79
80         if (!encryptedKey.type.isKey() || encryptedKey.type.isEllipticCurve())
81                 ThrowErr(Exc::Crypto::DataTypeNotSupported, "Invalid data provided for import");
82
83         RawBuffer passIV;
84         RawBuffer tag;
85
86         if (!pass.empty()) {
87                 // IV is needed for data encryption with pwd
88                 passIV = Internals::generateIV();
89         }
90
91         Internals::importWrappedKey(getId(),
92                                                                 getPassword(),
93                                                                 params,
94                                                                 encryptedKey,
95                                                                 pass,
96                                                                 passIV,
97                                                                 tag,
98                                                                 hash);
99
100         return Token(backendId(), encryptedKey.type, Store::pack(hash, pass, passIV, tag));
101 }
102
103 RawBuffer Key::wrap(const CryptoAlgorithm &alg,
104                                         const Token &keyToWrap,
105                                         const Password &keyToWrapPass)
106 {
107         int keyToWrapScheme;
108         RawBuffer keyToWrapId;
109         RawBuffer keyToWrapIV;
110         RawBuffer keyToWrapTag;
111         Store::unpack(keyToWrap.data,
112                                   keyToWrapPass,
113                                   keyToWrapScheme,
114                                   keyToWrapId,
115                                   keyToWrapIV,
116                                   keyToWrapTag);
117
118         return Internals::exportWrappedKey(getId(),
119                                                                            getPassword(),
120                                                                            alg,
121                                                                            keyToWrapId,
122                                                                            Pwd(keyToWrapPass, keyToWrapIV, keyToWrapTag));
123 }
124
125 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
126 {
127     return Internals::symmetricEncrypt(getId(), getPassword(), alg, data);
128 }
129
130 RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
131 {
132     return Internals::symmetricDecrypt(getId(), getPassword(), alg, cipher);
133 }
134
135 GCtxShPtr SKey::initContext(const CryptoAlgorithm &alg, bool onward)
136 {
137         auto opId = Internals::initCipher(getId(), getPassword(), alg, onward);
138
139         return std::make_shared<CipherCtx>(opId);
140 }
141
142 RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
143 {
144         return Internals::asymmetricEncrypt(getId(), getPassword(), alg, data);
145 }
146
147 RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
148 {
149         return Internals::asymmetricDecrypt(getId(), getPassword(), alg, cipher);
150 }
151
152 Token AKey::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &hash)
153 {
154         if (m_type != DataType::KEY_ECDSA_PRIVATE)
155                 ThrowErr(Exc::Crypto::InputParam, "ECDH requires EC private key");
156
157         auto algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
158         if (algo != AlgoType::ECDH)
159                 ThrowErr(Exc::Crypto::InputParam, "Wrong algorithm");
160
161         auto pubKey = unpack<RawBuffer>(alg, ParamName::ECDH_PUBKEY);
162
163         RawBuffer iv;
164         RawBuffer tag;
165         if (!pass.empty()) {
166                 // IV is needed for key encryption
167                 iv = Internals::generateIV();
168         }
169
170         Internals::deriveECDH(getId(), getPassword(), pubKey, pass, iv, tag, hash);
171
172         return Token(backendId(), DataType::BINARY_DATA, Store::pack(hash, pass, iv, tag));
173 }
174
175 GCtxShPtr AKey::initContext(const CryptoAlgorithm &, bool)
176 {
177         ThrowErr(Exc::Crypto::OperationNotSupported);
178 }
179
180 RawBuffer AKey::sign(
181         const CryptoAlgorithm &alg,
182         const RawBuffer &message)
183 {
184         CryptoAlgorithm algWithType(alg);
185         algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
186         return Internals::sign(getId(), getPassword(), algWithType, message);
187 }
188
189 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
190                                  const RawBuffer &sign)
191 {
192         CryptoAlgorithm algWithType(alg);
193         AlgoType type;
194
195         // setup algorithm type basing on key type if it doesn't exist
196         if (!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
197                 algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
198         }
199
200         return Internals::verify(getId(), getPassword(), algWithType, message, sign);
201 }
202
203 Token Cert::unwrap(const CryptoAlgorithm &,
204                                    const Data &,
205                                    const Password &,
206                                    const RawBuffer &)
207 {
208         ThrowErr(Exc::Crypto::OperationNotSupported);
209 }
210
211 RawBuffer Cert::wrap(const CryptoAlgorithm &,
212                                          const Token &,
213                                          const Password &)
214 {
215         ThrowErr(Exc::Crypto::OperationNotSupported);
216 }
217
218 } // namespace TZ
219 } // namespace Crypto
220 } // namespace CKM
221