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(const 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 #if OPENSSL_VERSION_NUMBER < 0x10100000L
75 prime = extractBignumData(dsa->p);
76 subprime = extractBignumData(dsa->q);
77 base = extractBignumData(dsa->g);
79 const BIGNUM *p, *q, *g;
80 DSA_get0_pqg(dsa.get(), &p, &q, &g);
81 prime = extractBignumData(p);
82 subprime = extractBignumData(q);
83 base = extractBignumData(g);
94 tz_algo_type getGenSKeyType(AlgoType type)
98 case AlgoType::AES_GEN: return ALGO_AES_GEN;
99 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
103 tz_algo_type getAlgType(AlgoType type)
107 case AlgoType::AES_CBC: return ALGO_AES_CBC;
108 case AlgoType::AES_CTR: return ALGO_AES_CTR;
109 case AlgoType::AES_CFB: return ALGO_AES_CFB;
110 case AlgoType::AES_GCM: return ALGO_AES_GCM;
111 case AlgoType::RSA_OAEP: return ALGO_RSA;
112 case AlgoType::RSA_SV: return ALGO_RSA_SV;
113 case AlgoType::DSA_SV: return ALGO_DSA_SV;
114 case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
115 default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
119 tz_algo_type getAlgType(KeyType keyType)
123 case KeyType::KEY_AES:
125 case KeyType::KEY_RSA_PUBLIC:
126 case KeyType::KEY_RSA_PRIVATE:
128 case KeyType::KEY_DSA_PUBLIC:
129 case KeyType::KEY_DSA_PRIVATE:
131 case KeyType::KEY_ECDSA_PUBLIC:
132 case KeyType::KEY_ECDSA_PRIVATE:
133 return ALGO_ECDSA_GEN;
135 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
139 tz_hash_type getHashType(HashAlgorithm hash)
143 case HashAlgorithm::SHA1: return HASH_SHA1;
144 case HashAlgorithm::SHA256: return HASH_SHA256;
145 case HashAlgorithm::SHA384: return HASH_SHA384;
146 case HashAlgorithm::SHA512: return HASH_SHA512;
148 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
152 RawBuffer generateIV()
155 TrustZoneContext::Instance().generateIV(result);
159 Data generateSKey(const CryptoAlgorithm &alg,
164 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
165 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
168 keyData.type = DataType(KeyType::KEY_AES);
172 ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
175 RawBuffer pwdBuf(pwd.begin(), pwd.end());
176 TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
180 TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
187 DataPair generateAKey(const CryptoAlgorithm &alg,
188 const Password &pubPwd,
189 const Password &privPwd,
190 const RawBuffer &pubPwdIv,
191 const RawBuffer &privPwdIv,
195 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
196 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
203 pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
205 RawBuffer privPwdBuf;
206 if (!privPwd.empty())
207 privPwdBuf.assign(privPwd.begin(), privPwd.end());
210 case AlgoType::RSA_GEN: {
211 pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
212 privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
214 TrustZoneContext::Instance().generateRSAKey(keyBits,
225 case AlgoType::DSA_GEN: {
226 pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
227 privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
232 generateDSAParams(keyBits, prime, subprime, base);
233 TrustZoneContext::Instance().generateDSAKey(keyBits,
248 ThrowErr(Exc::Crypto::InputParam,
249 "Invalid algo type provided for generateAKey function");
253 return DataPair(pubKeyData, privKeyData);
256 void destroyKey(const RawBuffer &key)
258 TrustZoneContext::Instance().executeDestroy(key);
261 RawBuffer importData(const Data &data,
262 const EncryptionParams &encData,
264 const RawBuffer &pwdIV,
270 if (data.type.isSKey()) {
271 dataType = TYPE_SKEY;
272 } else if (data.type.isBinaryData()) {
273 dataType = TYPE_GENERIC_SECRET;
274 } else if (data.type.isKeyPrivate()) {
275 dataType = TYPE_AKEY_PRIVATE;
276 } else if (data.type.isKeyPublic()) {
277 dataType = TYPE_AKEY_PUBLIC;
279 ThrowErr(Exc::Crypto::DataTypeNotSupported,
280 "Data type could not be impoted by tz-backend");
285 RawBuffer pwdBuf(pwd.begin(), pwd.end());
286 uint32_t keySizeBits = data.data.size() * 8;
287 TrustZoneContext::Instance().importData(dataType,
293 Params::DERIVED_KEY_LENGTH_BITS,
299 RawBuffer getData(const RawBuffer &dataId,
303 TrustZoneContext::Instance().getData(dataId,
309 void destroyData(const RawBuffer &dataId)
311 TrustZoneContext::Instance().destroyData(dataId);
314 BufferPair encryptDataAesGcm(const RawBuffer &key,
318 const RawBuffer &data,
319 const RawBuffer &aad)
324 TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
325 aad, data, result, tag);
327 return std::make_pair(result, tag);
330 RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
334 const RawBuffer &data,
335 const RawBuffer &aad)
337 auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
338 std::copy(pair.second.begin(), pair.second.end(),
339 std::back_inserter(pair.first));
343 RawBuffer decryptDataAesGcm(const RawBuffer &key,
347 const RawBuffer &tag,
348 const RawBuffer &data,
349 const RawBuffer &aad)
353 TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
354 tag, aad, data, result);
359 RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
363 const RawBuffer &data,
364 const RawBuffer &aad)
366 int tagSizeBytes = tagSizeBits / 8;
367 if (tagSizeBytes > static_cast<int>(data.size()))
368 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
370 auto tagPos = data.data() + data.size() - tagSizeBytes;
371 return decryptDataAesGcm(key,
375 RawBuffer(tagPos, data.data() + data.size()),
376 RawBuffer(data.data(), tagPos),
381 RawBuffer symmetricEncrypt(const RawBuffer &key,
383 const CryptoAlgorithm &alg,
384 const RawBuffer &data)
386 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
390 case AlgoType::AES_CTR: {
391 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
392 // counter length is in bits
393 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
394 LogError("CTR length invalid: " << std::to_string(ctrLen));
395 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
397 // no break here, we still need to slide down to executeCrypt
399 case AlgoType::AES_CBC:
400 case AlgoType::AES_CFB: {
402 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
406 unpack<RawBuffer>(alg, ParamName::ED_IV),
411 case AlgoType::AES_GCM: {
412 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
413 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
415 alg.getParam(ParamName::ED_AAD, aad);
416 return encryptDataAesGcmPacked(key,
418 unpack<RawBuffer>(alg, ParamName::ED_IV),
427 ThrowErr(Exc::Crypto::OperationNotSupported,
428 "Incorrect algorithm provided for symmetric crypto operation");
431 RawBuffer symmetricDecrypt(const RawBuffer &key,
433 const CryptoAlgorithm &alg,
434 const RawBuffer &data)
436 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
440 case AlgoType::AES_CTR: {
441 ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
442 // counter length is in bits
443 if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
444 LogError("CTR length invalid: " << std::to_string(ctrLen));
445 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
447 // no break here, we still need to slide down to executeCrypt
449 case AlgoType::AES_CBC:
450 case AlgoType::AES_CFB: {
452 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
456 unpack<RawBuffer>(alg, ParamName::ED_IV),
461 case AlgoType::AES_GCM: {
462 int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
463 alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
465 alg.getParam(ParamName::ED_AAD, aad);
466 return decryptDataAesGcmPacked(key,
468 unpack<RawBuffer>(alg, ParamName::ED_IV),
477 ThrowErr(Exc::Crypto::OperationNotSupported,
478 "Incorrect algorithm provided for symmetric crypto operation");
481 RawBuffer asymmetricEncrypt(const RawBuffer &key,
483 const CryptoAlgorithm &alg,
484 const RawBuffer &data)
486 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
491 case AlgoType::RSA_OAEP: {
492 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
496 unpack<RawBuffer>(alg, ParamName::ED_IV),
505 ThrowErr(Exc::Crypto::OperationNotSupported,
506 "Incorrect algorithm provided for asymmetric crypto operation");
509 RawBuffer asymmetricDecrypt(const RawBuffer &key,
511 const CryptoAlgorithm &alg,
512 const RawBuffer &cipher)
514 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
519 case AlgoType::RSA_OAEP: {
520 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
524 unpack<RawBuffer>(alg, ParamName::ED_IV),
533 ThrowErr(Exc::Crypto::OperationNotSupported,
534 "Incorrect algorithm provided for asymmetric crypto operation");
537 RawBuffer sign(const RawBuffer &pkey,
539 const CryptoAlgorithm &alg,
540 const RawBuffer &message)
542 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
543 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
544 if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
545 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
548 TrustZoneContext::Instance().executeSign(getAlgType(algo),
557 int verify(const RawBuffer &pkey,
559 const CryptoAlgorithm &alg,
560 const RawBuffer &message,
561 const RawBuffer &signature)
563 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
564 HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
565 if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
566 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
568 return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
576 } // namespace Internals
578 } // namespace Crypto