/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2019 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <generic-backend/algo-validation.h>
#include <generic-backend/crypto-params.h>
#include <dpl/log/log.h>
+#include <openssl/evp.h>
+#include <openssl/dsa.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
#include <tz-backend/internals.h>
#include <tz-backend/tz-context.h>
+#include <openssl-error-handler.h>
#include <km_ta_defines.h>
+#include <functional>
+
+namespace {
+
+using DSAPtr = std::unique_ptr<DSA, std::function<void(DSA*)>>;
+
+CKM::RawBuffer extractBignumData(const BIGNUM* bn)
+{
+ size_t size = static_cast<size_t>(BN_num_bytes(bn));
+
+ CKM::RawBuffer result(size);
+ int ret = BN_bn2bin(bn, result.data());
+ if (ret != static_cast<int>(size)) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Error while converting bignums - expected "
+ + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
+ }
+
+ return result;
+}
+
+void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
+ CKM::RawBuffer &subprime, CKM::RawBuffer &base)
+{
+ DSAPtr dsa(DSA_new(), DSA_free);
+ if (!dsa) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Failed to create DSA context for parameter gen");
+ }
+
+ if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
+ }
+
+ // at this stage dsa->p, dsa->q & dsa->r should contain our params
+ // extract them into buffers
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ prime = extractBignumData(dsa->p);
+ subprime = extractBignumData(dsa->q);
+ base = extractBignumData(dsa->g);
+#else
+ const BIGNUM *p, *q, *g;
+ DSA_get0_pqg(dsa.get(), &p, &q, &g);
+ prime = extractBignumData(p);
+ subprime = extractBignumData(q);
+ base = extractBignumData(g);
+#endif
+}
+
+} // namespace
namespace CKM {
namespace Crypto {
namespace TZ {
namespace Internals {
-tz_algo_type getGenKeyType(AlgoType type)
+tz_algo_type getGenSKeyType(AlgoType type)
{
switch (type)
{
case AlgoType::AES_CTR: return ALGO_AES_CTR;
case AlgoType::AES_CFB: return ALGO_AES_CFB;
case AlgoType::AES_GCM: return ALGO_AES_GCM;
+ case AlgoType::RSA_OAEP: return ALGO_RSA;
+ case AlgoType::RSA_SV: return ALGO_RSA_SV;
+ case AlgoType::DSA_SV: return ALGO_DSA_SV;
+ case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
};
}
case KeyType::KEY_RSA_PUBLIC:
case KeyType::KEY_RSA_PRIVATE:
return ALGO_RSA_GEN;
+ case KeyType::KEY_DSA_PUBLIC:
+ case KeyType::KEY_DSA_PRIVATE:
+ return ALGO_DSA_GEN;
+ case KeyType::KEY_ECDSA_PUBLIC:
+ case KeyType::KEY_ECDSA_PRIVATE:
+ return ALGO_ECDSA_GEN;
default:
ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
};
}
+tz_hash_type getHashType(HashAlgorithm hash)
+{
+ switch (hash)
+ {
+ case HashAlgorithm::SHA1: return HASH_SHA1;
+ case HashAlgorithm::SHA256: return HASH_SHA256;
+ case HashAlgorithm::SHA384: return HASH_SHA384;
+ case HashAlgorithm::SHA512: return HASH_SHA512;
+ default:
+ ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+ }
+}
+
RawBuffer generateIV()
{
RawBuffer result;
int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
Data keyData;
- keyData.type = DataType(keyType);
+ keyData.type = DataType(KeyType::KEY_AES);
if (!pwd.empty()) {
if (iv.empty()) {
}
RawBuffer pwdBuf(pwd.begin(), pwd.end());
- TrustZoneContext::Instance().generateSKeyPwd(getGenKeyType(keyType),
+ TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
pwdBuf, iv, keyBits,
keyData.data, tag);
} else {
- TrustZoneContext::Instance().generateSKey(getGenKeyType(keyType), keyBits,
+ TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
keyData.data);
}
return keyData;
}
-DataPair generateAKey(const CryptoAlgorithm &,
- const Password &,
- const RawBuffer &)
+DataPair generateAKey(const CryptoAlgorithm &alg,
+ const Password &pubPwd,
+ const Password &privPwd,
+ const RawBuffer &pubPwdIv,
+ const RawBuffer &privPwdIv,
+ RawBuffer &pubTag,
+ RawBuffer &privTag)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "AKeys are not yet implemented in TrustZone backend");
+ AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
+
+ Data pubKeyData;
+ Data privKeyData;
+
+ RawBuffer pubPwdBuf;
+ if (!pubPwd.empty())
+ pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
+
+ RawBuffer privPwdBuf;
+ if (!privPwd.empty())
+ privPwdBuf.assign(privPwd.begin(), privPwd.end());
+
+ switch (keyType) {
+ case AlgoType::RSA_GEN: {
+ pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
+ privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
+
+ TrustZoneContext::Instance().generateRSAKey(keyBits,
+ pubPwdBuf,
+ pubPwdIv,
+ privPwdBuf,
+ privPwdIv,
+ pubKeyData.data,
+ pubTag,
+ privKeyData.data,
+ privTag);
+ break;
+ }
+ case AlgoType::DSA_GEN: {
+ pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
+ privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
+
+ RawBuffer prime;
+ RawBuffer subprime;
+ RawBuffer base;
+ generateDSAParams(keyBits, prime, subprime, base);
+ TrustZoneContext::Instance().generateDSAKey(keyBits,
+ prime,
+ subprime,
+ base,
+ pubPwdBuf,
+ pubPwdIv,
+ privPwdBuf,
+ privPwdIv,
+ pubKeyData.data,
+ pubTag,
+ privKeyData.data,
+ privTag);
+ break;
+ }
+ default: {
+ ThrowErr(Exc::Crypto::InputParam,
+ "Invalid algo type provided for generateAKey function");
+ }
+ }
+
+ return DataPair(pubKeyData, privKeyData);
}
void destroyKey(const RawBuffer &key)
TrustZoneContext::Instance().executeDestroy(key);
}
-RawBuffer importKey(const Data &data,
- const Password &pwd,
- const RawBuffer &iv,
- RawBuffer &tag)
+RawBuffer importData(const Data &data,
+ const EncryptionParams &encData,
+ const Password &pwd,
+ const RawBuffer &pwdIV,
+ RawBuffer &tag)
{
- tz_algo_type algo = getAlgType(data.type);
+
+ uint32_t dataType;
+
+ if (data.type.isSKey()) {
+ dataType = TYPE_SKEY;
+ } else if (data.type.isBinaryData()) {
+ dataType = TYPE_GENERIC_SECRET;
+ } else if (data.type.isKeyPrivate()) {
+ dataType = TYPE_AKEY_PRIVATE;
+ } else if (data.type.isKeyPublic()) {
+ dataType = TYPE_AKEY_PUBLIC;
+ } else {
+ ThrowErr(Exc::Crypto::DataTypeNotSupported,
+ "Data type could not be impoted by tz-backend");
+ }
+
RawBuffer result;
RawBuffer pwdBuf(pwd.begin(), pwd.end());
- TrustZoneContext::Instance().importKey(algo,
+ uint32_t keySizeBits = data.data.size() * 8;
+ TrustZoneContext::Instance().importData(dataType,
data.data,
+ encData,
pwdBuf,
- iv,
+ pwdIV,
+ keySizeBits,
+ Params::DERIVED_KEY_LENGTH_BITS,
result,
tag);
return result;
}
+RawBuffer getData(const RawBuffer &dataId,
+ const Pwd &pwd)
+{
+ RawBuffer result;
+ TrustZoneContext::Instance().getData(dataId,
+ pwd,
+ result);
+ return result;
+}
+
+void destroyData(const RawBuffer &dataId)
+{
+ TrustZoneContext::Instance().destroyData(dataId);
+}
+
BufferPair encryptDataAesGcm(const RawBuffer &key,
const Pwd &pwd,
const RawBuffer &iv,
"Incorrect algorithm provided for symmetric crypto operation");
}
-RawBuffer asymmetricEncrypt(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer asymmetricEncrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ RawBuffer result;
+
+ switch (algo)
+ {
+ case AlgoType::RSA_OAEP: {
+ TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ data,
+ result);
+ return result;
+ }
+ default:
+ break;
+ }
+
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Asymmetric encryption is not yet supported on TrustZone backend");
+ "Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer asymmetricDecrypt(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer asymmetricDecrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &cipher)
{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ RawBuffer result;
+
+ switch (algo)
+ {
+ case AlgoType::RSA_OAEP: {
+ TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ cipher,
+ result);
+ return result;
+ }
+ default:
+ break;
+ }
+
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Asymmetric encryption is not yet supported on TrustZone backend");
+ "Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer sign(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer sign(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Certificate signing is not yet supported on TrustZone backend");
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+ if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
+ ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
+
+ RawBuffer signature;
+ TrustZoneContext::Instance().executeSign(getAlgType(algo),
+ getHashType(hash),
+ pkey,
+ pwd,
+ message,
+ signature);
+ return signature;
}
-int verify(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &,
- const RawBuffer &)
+int verify(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message,
+ const RawBuffer &signature)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Certificate signing is not yet supported on TrustZone backend");
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+ if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
+ ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
+
+ return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
+ getHashType(hash),
+ pkey,
+ pwd,
+ message,
+ signature);
}
} // namespace Internals