2 * Copyright (c) 2017 - 2019 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 Krzysztof Dynowski (k.dynowski@samsung.com)
19 * @author Lukasz Kostyra (l.kostyra@samsung.com)
23 #include <generic-backend/exception.h>
24 #include <generic-backend/algo-validation.h>
25 #include <generic-backend/crypto-params.h>
26 #include <dpl/log/log.h>
27 #include <openssl/evp.h>
28 #include <openssl/dsa.h>
29 #include <openssl/bio.h>
30 #include <openssl/bn.h>
32 #include <tz-backend/internals.h>
33 #include <tz-backend/tz-context.h>
34 #include <openssl-error-handler.h>
35 #include <km_ta_defines.h>
41 using DSAPtr = std::unique_ptr<DSA, std::function<void(DSA*)>>;
43 CKM::RawBuffer extractBignumData(BIGNUM* bn)
45 size_t size = static_cast<size_t>(BN_num_bytes(bn));
47 CKM::RawBuffer result(size);
48 int ret = BN_bn2bin(bn, result.data());
49 if (ret != static_cast<int>(size)) {
50 ThrowErr(CKM::Exc::Crypto::InternalError,
51 "Error while converting bignums - expected "
52 + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
58 void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
59 CKM::RawBuffer &subprime, CKM::RawBuffer &base)
61 DSAPtr dsa(DSA_new(), DSA_free);
63 ThrowErr(CKM::Exc::Crypto::InternalError,
64 "Failed to create DSA context for parameter gen");
67 if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
68 ThrowErr(CKM::Exc::Crypto::InternalError,
69 "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
72 // at this stage dsa->p, dsa->q & dsa->r should contain our params
73 // extract them into buffers
74 prime = extractBignumData(dsa->p);
75 subprime = extractBignumData(dsa->q);
76 base = extractBignumData(dsa->g);
86 tz_algo_type getGenSKeyType(AlgoType type)
90 case AlgoType::AES_GEN: return ALGO_AES_GEN;
91 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
95 tz_algo_type getAlgType(AlgoType type)
99 case AlgoType::AES_CBC: return ALGO_AES_CBC;
100 case AlgoType::AES_CTR: return ALGO_AES_CTR;
101 case AlgoType::AES_CFB: return ALGO_AES_CFB;
102 case AlgoType::AES_GCM: return ALGO_AES_GCM;
103 case AlgoType::RSA_OAEP: return ALGO_RSA;
104 case AlgoType::RSA_SV: return ALGO_RSA_SV;
105 case AlgoType::DSA_SV: return ALGO_DSA_SV;
106 case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
107 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
111 tz_algo_type getAlgType(KeyType keyType)
115 case KeyType::KEY_AES:
117 case KeyType::KEY_RSA_PUBLIC:
118 case KeyType::KEY_RSA_PRIVATE:
120 case KeyType::KEY_DSA_PUBLIC:
121 case KeyType::KEY_DSA_PRIVATE:
123 case KeyType::KEY_ECDSA_PUBLIC:
124 case KeyType::KEY_ECDSA_PRIVATE:
125 return ALGO_ECDSA_GEN;
127 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
131 tz_hash_type getHashType(HashAlgorithm hash)
135 case HashAlgorithm::SHA1: return HASH_SHA1;
136 case HashAlgorithm::SHA256: return HASH_SHA256;
137 case HashAlgorithm::SHA384: return HASH_SHA384;
138 case HashAlgorithm::SHA512: return HASH_SHA512;
140 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
144 RawBuffer generateIV()
147 TrustZoneContext::Instance().generateIV(result);
151 Data generateSKey(const CryptoAlgorithm &alg,
156 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
157 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
160 keyData.type = DataType(KeyType::KEY_AES);
164 ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
167 RawBuffer pwdBuf(pwd.begin(), pwd.end());
168 TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
172 TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
179 DataPair generateAKey(const CryptoAlgorithm &alg,
180 const Password &pubPwd,
181 const Password &privPwd,
182 const RawBuffer &pubPwdIv,
183 const RawBuffer &privPwdIv,
187 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
188 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
195 pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
197 RawBuffer privPwdBuf;
198 if (!privPwd.empty())
199 privPwdBuf.assign(privPwd.begin(), privPwd.end());
202 case AlgoType::RSA_GEN: {
203 pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
204 privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
206 TrustZoneContext::Instance().generateRSAKey(keyBits,
217 case AlgoType::DSA_GEN: {
218 pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
219 privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
224 generateDSAParams(keyBits, prime, subprime, base);
225 TrustZoneContext::Instance().generateDSAKey(keyBits,
240 ThrowErr(Exc::Crypto::InputParam,
241 "Invalid algo type provided for generateAKey function");
245 return DataPair(pubKeyData, privKeyData);
248 void destroyKey(const RawBuffer &key)
250 TrustZoneContext::Instance().executeDestroy(key);
253 RawBuffer importData(const Data &data,
254 const EncryptionParams &encData,
256 const RawBuffer &pwdIV,
262 if (data.type.isSKey()) {
263 dataType = TYPE_SKEY;
264 } else if (data.type.isBinaryData()) {
265 dataType = TYPE_GENERIC_SECRET;
266 } else if (data.type.isKeyPrivate()) {
267 dataType = TYPE_AKEY_PRIVATE;
268 } else if (data.type.isKeyPublic()) {
269 dataType = TYPE_AKEY_PUBLIC;
271 ThrowErr(Exc::Crypto::DataTypeNotSupported,
272 "Data type could not be impoted by tz-backend");
277 RawBuffer pwdBuf(pwd.begin(), pwd.end());
278 uint32_t keySizeBits = data.data.size() * 8;
279 TrustZoneContext::Instance().importData(dataType,
285 Params::DERIVED_KEY_LENGTH_BITS,
291 RawBuffer getData(const RawBuffer &dataId,
295 TrustZoneContext::Instance().getData(dataId,
301 void destroyData(const RawBuffer &dataId)
303 TrustZoneContext::Instance().destroyData(dataId);
306 BufferPair encryptDataAesGcm(const RawBuffer &key,
310 const RawBuffer &data,
311 const RawBuffer &aad)
316 TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
317 aad, data, result, tag);
319 return std::make_pair(result, tag);
322 RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
326 const RawBuffer &data,
327 const RawBuffer &aad)
329 auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
330 std::copy(pair.second.begin(), pair.second.end(),
331 std::back_inserter(pair.first));
335 RawBuffer decryptDataAesGcm(const RawBuffer &key,
339 const RawBuffer &tag,
340 const RawBuffer &data,
341 const RawBuffer &aad)
345 TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
346 tag, aad, data, result);
351 RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
355 const RawBuffer &data,
356 const RawBuffer &aad)
358 int tagSizeBytes = tagSizeBits / 8;
359 if (tagSizeBytes > static_cast<int>(data.size()))
360 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
362 auto tagPos = data.data() + data.size() - tagSizeBytes;
363 return decryptDataAesGcm(key,
367 RawBuffer(tagPos, data.data() + data.size()),
368 RawBuffer(data.data(), tagPos),
373 RawBuffer symmetricEncrypt(const RawBuffer &key,
375 const CryptoAlgorithm &alg,
376 const RawBuffer &data)
378 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
382 case AlgoType::AES_CTR: {
383 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
384 // counter length is in bits
385 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
386 LogError("CTR length invalid: " << std::to_string(ctrLen));
387 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
389 // no break here, we still need to slide down to executeCrypt
391 case AlgoType::AES_CBC:
392 case AlgoType::AES_CFB: {
394 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
398 unpack<RawBuffer>(alg, ParamName::ED_IV),
403 case AlgoType::AES_GCM: {
404 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
405 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
407 alg.getParam(ParamName::ED_AAD, aad);
408 return encryptDataAesGcmPacked(key,
410 unpack<RawBuffer>(alg, ParamName::ED_IV),
419 ThrowErr(Exc::Crypto::OperationNotSupported,
420 "Incorrect algorithm provided for symmetric crypto operation");
423 RawBuffer symmetricDecrypt(const RawBuffer &key,
425 const CryptoAlgorithm &alg,
426 const RawBuffer &data)
428 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
432 case AlgoType::AES_CTR: {
433 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
434 // counter length is in bits
435 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
436 LogError("CTR length invalid: " << std::to_string(ctrLen));
437 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
439 // no break here, we still need to slide down to executeCrypt
441 case AlgoType::AES_CBC:
442 case AlgoType::AES_CFB: {
444 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
448 unpack<RawBuffer>(alg, ParamName::ED_IV),
453 case AlgoType::AES_GCM: {
454 int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
455 alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
457 alg.getParam(ParamName::ED_AAD, aad);
458 return decryptDataAesGcmPacked(key,
460 unpack<RawBuffer>(alg, ParamName::ED_IV),
469 ThrowErr(Exc::Crypto::OperationNotSupported,
470 "Incorrect algorithm provided for symmetric crypto operation");
473 RawBuffer asymmetricEncrypt(const RawBuffer &key,
475 const CryptoAlgorithm &alg,
476 const RawBuffer &data)
478 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
483 case AlgoType::RSA_OAEP: {
484 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
488 unpack<RawBuffer>(alg, ParamName::ED_IV),
497 ThrowErr(Exc::Crypto::OperationNotSupported,
498 "Incorrect algorithm provided for asymmetric crypto operation");
501 RawBuffer asymmetricDecrypt(const RawBuffer &key,
503 const CryptoAlgorithm &alg,
504 const RawBuffer &cipher)
506 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
511 case AlgoType::RSA_OAEP: {
512 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
516 unpack<RawBuffer>(alg, ParamName::ED_IV),
525 ThrowErr(Exc::Crypto::OperationNotSupported,
526 "Incorrect algorithm provided for asymmetric crypto operation");
529 RawBuffer sign(const RawBuffer &pkey,
531 const CryptoAlgorithm &alg,
532 const RawBuffer &message)
534 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
535 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
537 TrustZoneContext::Instance().executeSign(getAlgType(algo),
546 int verify(const RawBuffer &pkey,
548 const CryptoAlgorithm &alg,
549 const RawBuffer &message,
550 const RawBuffer &signature)
552 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
553 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
554 return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
562 } // namespace Internals
564 } // namespace Crypto