2 * Copyright (c) 2017-2020 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>
28 #include <openssl/evp.h>
29 #include <openssl/dsa.h>
30 #include <openssl/ec.h>
31 #include <openssl/bio.h>
32 #include <openssl/bn.h>
34 #include <tz-backend/internals.h>
35 #include <tz-backend/tz-context.h>
36 #include <openssl-error-handler.h>
37 #include <km_ta_defines.h>
42 #ifndef __has_cpp_attribute
43 #define __has_cpp_attribute(_) 0
46 #if __has_cpp_attribute(fallthrough)
47 #define fallthru [[fallthrough]]
49 #define fallthru ((void)0)
54 CKM::RawBuffer extractBignumData(const BIGNUM* bn)
56 size_t size = static_cast<size_t>(BN_num_bytes(bn));
58 CKM::RawBuffer result(size);
59 int ret = BN_bn2bin(bn, result.data());
60 if (ret != static_cast<int>(size)) {
61 ThrowErr(CKM::Exc::Crypto::InternalError,
62 "Error while converting bignums - expected "
63 + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
69 void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
70 CKM::RawBuffer &subprime, CKM::RawBuffer &base)
72 auto dsa = uptr<DSA_free>(DSA_new());
74 ThrowErr(CKM::Exc::Crypto::InternalError,
75 "Failed to create DSA context for parameter gen");
78 if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
79 ThrowErr(CKM::Exc::Crypto::InternalError,
80 "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
83 // at this stage dsa->p, dsa->q & dsa->r should contain our params
84 // extract them into buffers
85 const BIGNUM *p, *q, *g;
86 DSA_get0_pqg(dsa.get(), &p, &q, &g);
87 prime = extractBignumData(p);
88 subprime = extractBignumData(q);
89 base = extractBignumData(g);
92 tz_data_type toTzDataType(const CKM::DataType dataType) {
94 case CKM::DataType::BINARY_DATA: return TYPE_GENERIC_SECRET;
95 case CKM::DataType::KEY_AES: return TYPE_SKEY;
96 case CKM::DataType::KEY_DSA_PRIVATE: return TYPE_AKEY_PRIVATE_DSA;
97 case CKM::DataType::KEY_RSA_PRIVATE: return TYPE_AKEY_PRIVATE_RSA;
98 case CKM::DataType::KEY_DSA_PUBLIC: return TYPE_AKEY_PUBLIC_DSA;
99 case CKM::DataType::KEY_RSA_PUBLIC: return TYPE_AKEY_PUBLIC_RSA;
101 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
102 "Data type could not be imported by tz-backend");
106 tz_ec toTzEc(CKM::ElipticCurve ec)
109 case CKM::ElipticCurve::prime192v1: return EC_NIST_P192;
110 case CKM::ElipticCurve::prime256v1: return EC_NIST_P256;
111 case CKM::ElipticCurve::secp384r1: return EC_NIST_P384;
112 default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "EC not supported by tz-backend");
121 namespace Internals {
123 tz_algo_type getGenSKeyType(AlgoType type)
127 case AlgoType::AES_GEN: return ALGO_AES_GEN;
128 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
132 tz_algo_type getAlgType(AlgoType type)
136 case AlgoType::AES_CBC: return ALGO_AES_CBC;
137 case AlgoType::AES_CTR: return ALGO_AES_CTR;
138 case AlgoType::AES_CFB: return ALGO_AES_CFB;
139 case AlgoType::AES_GCM: return ALGO_AES_GCM;
140 case AlgoType::RSA_OAEP: return ALGO_RSA;
141 case AlgoType::RSA_SV: return ALGO_RSA_SV;
142 case AlgoType::DSA_SV: return ALGO_DSA_SV;
143 case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
144 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
148 tz_hash_type getHashType(HashAlgorithm hash)
152 case HashAlgorithm::SHA1: return HASH_SHA1;
153 case HashAlgorithm::SHA256: return HASH_SHA256;
154 case HashAlgorithm::SHA384: return HASH_SHA384;
155 case HashAlgorithm::SHA512: return HASH_SHA512;
157 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
161 RawBuffer generateIV()
164 TrustZoneContext::Instance().generateIV(result);
168 void generateSKey(const CryptoAlgorithm &alg,
172 const RawBuffer &hash)
174 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
175 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
179 ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
182 RawBuffer pwdBuf(pwd.begin(), pwd.end());
183 TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
187 TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
193 AlgoType generateAKey(const CryptoAlgorithm &alg,
194 const Password &pubPwd,
195 const Password &privPwd,
196 const RawBuffer &pubPwdIv,
197 const RawBuffer &privPwdIv,
200 const RawBuffer &hashPriv,
201 const RawBuffer &hashPub)
203 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
207 pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
209 RawBuffer privPwdBuf;
210 if (!privPwd.empty())
211 privPwdBuf.assign(privPwd.begin(), privPwd.end());
214 case AlgoType::RSA_GEN: {
215 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
216 TrustZoneContext::Instance().generateRSAKey(keyBits,
227 case AlgoType::DSA_GEN: {
228 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
232 generateDSAParams(keyBits, prime, subprime, base);
233 TrustZoneContext::Instance().generateDSAKey(keyBits,
247 case AlgoType::ECDSA_GEN: {
248 CKM::ElipticCurve ec = unpack<CKM::ElipticCurve>(alg, ParamName::GEN_EC);
249 TrustZoneContext::Instance().generateECKey(toTzEc(ec),
261 ThrowErr(Exc::Crypto::InputParam,
262 "Invalid algo type provided for generateAKey function");
269 void destroyKey(const RawBuffer &key)
271 TrustZoneContext::Instance().executeDestroy(key);
274 void importData(const Data &data,
275 const EncryptionParams &encData,
277 const RawBuffer &pwdIV,
279 const RawBuffer &hash)
282 const auto dataType = toTzDataType(data.type);
284 RawBuffer pwdBuf(pwd.begin(), pwd.end());
285 uint32_t keySizeBits = data.data.size() * 8;
286 TrustZoneContext::Instance().importData(dataType,
296 RawBuffer getData(const RawBuffer &dataId,
300 TrustZoneContext::Instance().getData(dataId,
306 void destroyData(const RawBuffer &dataId)
308 TrustZoneContext::Instance().destroyData(dataId);
311 BufferPair encryptDataAesGcm(const RawBuffer &key,
315 const RawBuffer &data,
316 const RawBuffer &aad)
321 TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
322 aad, data, result, tag);
324 return std::make_pair(result, tag);
327 RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
331 const RawBuffer &data,
332 const RawBuffer &aad)
334 auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
335 std::copy(pair.second.begin(), pair.second.end(),
336 std::back_inserter(pair.first));
340 RawBuffer decryptDataAesGcm(const RawBuffer &key,
344 const RawBuffer &tag,
345 const RawBuffer &data,
346 const RawBuffer &aad)
350 TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
351 tag, aad, data, result);
356 RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
360 const RawBuffer &data,
361 const RawBuffer &aad)
363 int tagSizeBytes = tagSizeBits / 8;
364 if (tagSizeBytes > static_cast<int>(data.size()))
365 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
367 auto tagPos = data.data() + data.size() - tagSizeBytes;
368 return decryptDataAesGcm(key,
372 RawBuffer(tagPos, data.data() + data.size()),
373 RawBuffer(data.data(), tagPos),
378 RawBuffer symmetricEncrypt(const RawBuffer &key,
380 const CryptoAlgorithm &alg,
381 const RawBuffer &data)
383 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
387 case AlgoType::AES_CTR: {
388 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
389 // counter length is in bits
390 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
391 LogError("CTR length invalid: " << std::to_string(ctrLen));
392 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
394 // no break here, we still need to slide down to executeCrypt
397 case AlgoType::AES_CBC:
398 case AlgoType::AES_CFB: {
400 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
404 unpack<RawBuffer>(alg, ParamName::ED_IV),
409 case AlgoType::AES_GCM: {
410 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
411 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
413 alg.getParam(ParamName::ED_AAD, aad);
414 return encryptDataAesGcmPacked(key,
416 unpack<RawBuffer>(alg, ParamName::ED_IV),
425 ThrowErr(Exc::Crypto::OperationNotSupported,
426 "Incorrect algorithm provided for symmetric crypto operation");
429 RawBuffer symmetricDecrypt(const RawBuffer &key,
431 const CryptoAlgorithm &alg,
432 const RawBuffer &data)
434 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
438 case AlgoType::AES_CTR: {
439 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
440 // counter length is in bits
441 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
442 LogError("CTR length invalid: " << std::to_string(ctrLen));
443 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
445 // no break here, we still need to slide down to executeCrypt
448 case AlgoType::AES_CBC:
449 case AlgoType::AES_CFB: {
451 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
455 unpack<RawBuffer>(alg, ParamName::ED_IV),
460 case AlgoType::AES_GCM: {
461 int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
462 alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
464 alg.getParam(ParamName::ED_AAD, aad);
465 return decryptDataAesGcmPacked(key,
467 unpack<RawBuffer>(alg, ParamName::ED_IV),
476 ThrowErr(Exc::Crypto::OperationNotSupported,
477 "Incorrect algorithm provided for symmetric crypto operation");
480 RawBuffer asymmetricEncrypt(const RawBuffer &key,
482 const CryptoAlgorithm &alg,
483 const RawBuffer &data)
485 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
490 case AlgoType::RSA_OAEP: {
491 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
495 result, // unused dummy
504 ThrowErr(Exc::Crypto::OperationNotSupported,
505 "Incorrect algorithm provided for asymmetric crypto operation");
508 RawBuffer asymmetricDecrypt(const RawBuffer &key,
510 const CryptoAlgorithm &alg,
511 const RawBuffer &cipher)
513 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
518 case AlgoType::RSA_OAEP: {
519 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
523 result, // unused dummy
532 ThrowErr(Exc::Crypto::OperationNotSupported,
533 "Incorrect algorithm provided for asymmetric crypto operation");
536 RawBuffer sign(const RawBuffer &pkey,
538 const CryptoAlgorithm &alg,
539 const RawBuffer &message)
541 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
542 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
543 if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
544 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
547 TrustZoneContext::Instance().executeSign(getAlgType(algo),
556 int verify(const RawBuffer &pkey,
558 const CryptoAlgorithm &alg,
559 const RawBuffer &message,
560 const RawBuffer &signature)
562 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
563 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
564 if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
565 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
567 return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
575 void deriveECDH(const RawBuffer &prvKey,
576 const Pwd &prvKeyPwd,
577 const RawBuffer &pubKey,
578 const Password &secretPwd,
579 const RawBuffer &secretPwdIV,
580 RawBuffer &secretTag,
581 const RawBuffer &secretHash)
583 auto peerKey = std::make_shared<KeyImpl>(pubKey);
584 if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
585 ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
586 auto peerEvp = peerKey->getEvpShPtr().get();
589 int subType = EVP_PKEY_type(EVP_PKEY_id(peerEvp));
590 if (subType != EVP_PKEY_EC)
591 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
593 auto ecKey = EVP_PKEY_get0_EC_KEY(peerEvp);
595 ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
597 auto ecPoint = EC_KEY_get0_public_key(ecKey);
599 ThrowErr(Exc::Crypto::InternalError, "Can't get EC public key");
601 auto ecGroup = EC_KEY_get0_group(ecKey);
603 ThrowErr(Exc::Crypto::InternalError, "Can't get EC group");
605 BIGNUM *x = BN_new();
606 BIGNUM *y = BN_new();
607 if (!EC_POINT_get_affine_coordinates(ecGroup, ecPoint, x, y, NULL))
608 ThrowErr(Exc::Crypto::InternalError, "Failed to get EC pub key coordinates");
610 auto xBuf = extractBignumData(x);
611 auto yBuf = extractBignumData(y);
613 RawBuffer secretPwdBuf(secretPwd.begin(), secretPwd.end());
615 TrustZoneContext::Instance().executeEcdh(prvKey,
625 void deriveKBKDF(const RawBuffer &secret,
626 const CryptoAlgorithm &alg,
627 const Password &keyPwd,
628 const RawBuffer &keyPwdIV,
630 const RawBuffer &keyHash)
632 auto prf = unpack<KdfPrf>(alg, ParamName::KDF_PRF);
633 auto mode = unpack<KbkdfMode>(alg, ParamName::KBKDF_MODE);
634 auto location = unpack<KbkdfCounterLocation>(alg, ParamName::KBKDF_COUNTER_LOCATION);
636 size_t rlen = 32, llen = 32, dummy;
637 alg.getParam(ParamName::KBKDF_RLEN, rlen);
638 alg.getParam(ParamName::KBKDF_LLEN, llen);
639 bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, dummy);
641 RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
643 TrustZoneContext::Instance().executeKbkdf(secret,
657 } // namespace Internals
659 } // namespace Crypto