/*
- * Copyright (c) 2017 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2020 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 <utils.h>
#include <openssl/evp.h>
#include <openssl/dsa.h>
+#include <openssl/ec.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <tz-backend/tz-context.h>
#include <openssl-error-handler.h>
#include <km_ta_defines.h>
+#include <key-impl.h>
#include <functional>
-namespace {
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(_) 0
+#endif
+
+#if __has_cpp_attribute(fallthrough)
+#define fallthru [[fallthrough]]
+#else
+#define fallthru ((void)0)
+#endif
-using DSAPtr = std::unique_ptr<DSA, std::function<void(DSA*)>>;
+namespace {
-CKM::RawBuffer extractBignumData(BIGNUM* bn)
+CKM::RawBuffer extractBignumData(const BIGNUM* bn)
{
size_t size = static_cast<size_t>(BN_num_bytes(bn));
void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
CKM::RawBuffer &subprime, CKM::RawBuffer &base)
{
- DSAPtr dsa(DSA_new(), DSA_free);
+ auto dsa = uptr<DSA_free>(DSA_new());
if (!dsa) {
ThrowErr(CKM::Exc::Crypto::InternalError,
"Failed to create DSA context for parameter gen");
// at this stage dsa->p, dsa->q & dsa->r should contain our params
// extract them into buffers
- prime = extractBignumData(dsa->p);
- subprime = extractBignumData(dsa->q);
- base = extractBignumData(dsa->g);
+ const BIGNUM *p, *q, *g;
+ DSA_get0_pqg(dsa.get(), &p, &q, &g);
+ prime = extractBignumData(p);
+ subprime = extractBignumData(q);
+ base = extractBignumData(g);
+}
+
+tz_data_type toTzDataType(const CKM::DataType dataType) {
+ switch (dataType) {
+ case CKM::DataType::BINARY_DATA: return TYPE_GENERIC_SECRET;
+ case CKM::DataType::KEY_AES: return TYPE_SKEY;
+ case CKM::DataType::KEY_DSA_PRIVATE: return TYPE_AKEY_PRIVATE_DSA;
+ case CKM::DataType::KEY_RSA_PRIVATE: return TYPE_AKEY_PRIVATE_RSA;
+ case CKM::DataType::KEY_ECDSA_PRIVATE: return TYPE_AKEY_PRIVATE_EC;
+ case CKM::DataType::KEY_DSA_PUBLIC: return TYPE_AKEY_PUBLIC_DSA;
+ case CKM::DataType::KEY_RSA_PUBLIC: return TYPE_AKEY_PUBLIC_RSA;
+ case CKM::DataType::KEY_ECDSA_PUBLIC: return TYPE_AKEY_PUBLIC_EC;
+ default:
+ ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
+ "Data type could not be imported by tz-backend");
+ }
+}
+
+tz_ec toTzEc(CKM::ElipticCurve ec)
+{
+ switch(ec) {
+ case CKM::ElipticCurve::prime192v1: return EC_NIST_P192;
+ case CKM::ElipticCurve::prime256v1: return EC_NIST_P256;
+ case CKM::ElipticCurve::secp384r1: return EC_NIST_P384;
+ default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "EC not supported by tz-backend");
+ }
+}
+
+tz_prf toTzPrf(CKM::KdfPrf prf)
+{
+ switch(prf) {
+ case CKM::KdfPrf::HMAC_SHA256: return PRF_HMAC_SHA256;
+ case CKM::KdfPrf::HMAC_SHA384: return PRF_HMAC_SHA384;
+ case CKM::KdfPrf::HMAC_SHA512: return PRF_HMAC_SHA512;
+ default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "PRF not supported by tz-backend");
+ }
+}
+
+tz_kbkdf_mode toTzKbkdfMode(CKM::KbkdfMode mode)
+{
+ switch(mode) {
+ case CKM::KbkdfMode::COUNTER: return KBKDF_MODE_COUNTER;
+ default:
+ ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "KBKDF mode not supported by tz-backend");
+ }
+}
+
+tz_kbkdf_ctr_loc toTzCtrLoc(CKM::KbkdfCounterLocation loc)
+{
+ switch(loc) {
+ case CKM::KbkdfCounterLocation::BEFORE_FIXED: return KBKDF_LOC_BEFORE_FIXED;
+ case CKM::KbkdfCounterLocation::AFTER_FIXED: return KBKDF_LOC_AFTER_FIXED;
+ case CKM::KbkdfCounterLocation::MIDDLE_FIXED: return KBKDF_LOC_MIDDLE_FIXED;
+ default:
+ ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
+ "KBKDF counter location not supported by tz-backend");
+ }
}
} // namespace
namespace TZ {
namespace Internals {
+namespace {
+
tz_algo_type getGenSKeyType(AlgoType type)
{
switch (type)
};
}
-tz_algo_type getAlgType(KeyType keyType)
-{
- switch (keyType)
- {
- case KeyType::KEY_AES:
- return ALGO_AES_GEN;
- 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)
}
}
+void decompose(const CryptoAlgorithm &alg,
+ AlgoType &algo,
+ uint32_t &ctrLenOrTagSizeBits,
+ RawBuffer &iv,
+ RawBuffer &aad)
+{
+ algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ switch (algo) {
+ case AlgoType::AES_CTR:
+ iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+ ctrLenOrTagSizeBits = Params::DEFAULT_AES_IV_LEN * 8;
+ alg.getParam(ParamName::ED_CTR_LEN, ctrLenOrTagSizeBits);
+ // counter length is in bits
+ if (ctrLenOrTagSizeBits != Params::DEFAULT_AES_IV_LEN * 8) {
+ LogError("CTR length invalid: " << std::to_string(ctrLenOrTagSizeBits));
+ ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
+ }
+ break;
+ case AlgoType::AES_CBC:
+ iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+ break;
+ case AlgoType::AES_CFB:
+ iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+ break;
+ case AlgoType::AES_GCM:
+ iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+ ctrLenOrTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
+ alg.getParam(ParamName::ED_TAG_LEN, ctrLenOrTagSizeBits);
+ alg.getParam(ParamName::ED_AAD, aad);
+ break;
+ case AlgoType::RSA_OAEP:
+ break;
+ default:
+ ThrowErr(Exc::Crypto::InputParam, "Invalid decryption algorithm");
+ break;
+ }
+}
+
+} // namespace
+
RawBuffer generateIV()
{
RawBuffer result;
return result;
}
-Data generateSKey(const CryptoAlgorithm &alg,
+void generateSKey(const CryptoAlgorithm &alg,
const Password &pwd,
const RawBuffer &iv,
- RawBuffer &tag)
+ RawBuffer &tag,
+ const RawBuffer &hash)
{
AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
- Data keyData;
- keyData.type = DataType(KeyType::KEY_AES);
-
if (!pwd.empty()) {
if (iv.empty()) {
ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
RawBuffer pwdBuf(pwd.begin(), pwd.end());
TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
pwdBuf, iv, keyBits,
- keyData.data, tag);
+ tag, hash);
} else {
TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
- keyData.data);
+ hash);
}
- return keyData;
}
-DataPair generateAKey(const CryptoAlgorithm &alg,
+AlgoType generateAKey(const CryptoAlgorithm &alg,
const Password &pubPwd,
const Password &privPwd,
const RawBuffer &pubPwdIv,
const RawBuffer &privPwdIv,
RawBuffer &pubTag,
- RawBuffer &privTag)
+ RawBuffer &privTag,
+ const RawBuffer &hashPriv,
+ const RawBuffer &hashPub)
{
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())
switch (keyType) {
case AlgoType::RSA_GEN: {
- pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
- privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
-
+ int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
TrustZoneContext::Instance().generateRSAKey(keyBits,
pubPwdBuf,
pubPwdIv,
privPwdBuf,
privPwdIv,
- pubKeyData.data,
pubTag,
- privKeyData.data,
- privTag);
+ privTag,
+ hashPriv,
+ hashPub);
break;
}
case AlgoType::DSA_GEN: {
- pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
- privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
-
+ int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
RawBuffer prime;
RawBuffer subprime;
RawBuffer base;
pubPwdIv,
privPwdBuf,
privPwdIv,
- pubKeyData.data,
pubTag,
- privKeyData.data,
- privTag);
+ privTag,
+ hashPriv,
+ hashPub);
+ break;
+ }
+ case AlgoType::ECDSA_GEN: {
+ CKM::ElipticCurve ec = unpack<CKM::ElipticCurve>(alg, ParamName::GEN_EC);
+ TrustZoneContext::Instance().generateECKey(toTzEc(ec),
+ pubPwdBuf,
+ pubPwdIv,
+ privPwdBuf,
+ privPwdIv,
+ pubTag,
+ privTag,
+ hashPriv,
+ hashPub);
break;
}
default: {
}
}
- return DataPair(pubKeyData, privKeyData);
+ return keyType;
}
-void destroyKey(const RawBuffer &key)
+void destroyKey(const RawBuffer &keyId)
{
- TrustZoneContext::Instance().executeDestroy(key);
+ TrustZoneContext::Instance().executeDestroy(keyId);
}
-RawBuffer importData(const Data &data,
+void importData(const Data &data,
const EncryptionParams &encData,
const Password &pwd,
const RawBuffer &pwdIV,
- RawBuffer &tag)
+ RawBuffer &tag,
+ const RawBuffer &hash)
{
- 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;
+ const auto dataType = toTzDataType(data.type);
RawBuffer pwdBuf(pwd.begin(), pwd.end());
uint32_t keySizeBits = data.data.size() * 8;
pwdBuf,
pwdIV,
keySizeBits,
- Params::DERIVED_KEY_LENGTH_BITS,
- result,
- tag);
- return result;
+ tag,
+ hash);
+}
+
+void importWrappedKey(const RawBuffer &wrappingKeyId,
+ const Pwd &wrappingKeyPwd,
+ const CryptoAlgorithm &alg,
+ const Data &encryptedKey,
+ const Password &encryptedKeyPassword,
+ const RawBuffer &encryptedKeyIV,
+ RawBuffer &encryptedKeyTag,
+ const RawBuffer &encryptedKeyId)
+{
+ RawBuffer encryptedKeyPwdBuf(encryptedKeyPassword.begin(), encryptedKeyPassword.end());
+
+ AlgoType algo;
+ uint32_t ctrLenOrTagSizeBits = 0;
+ RawBuffer iv;
+ RawBuffer aad;
+ decompose(alg, algo, ctrLenOrTagSizeBits, iv, aad);
+
+ // TODO it is awful!
+ TrustZoneContext::Instance().importWrappedKey(wrappingKeyId,
+ wrappingKeyPwd,
+ getAlgType(algo),
+ iv,
+ ctrLenOrTagSizeBits,
+ aad,
+ toTzDataType(encryptedKey.type),
+ encryptedKey.data,
+ encryptedKeyPwdBuf,
+ encryptedKeyIV,
+ encryptedKeyTag,
+ encryptedKeyId);
+}
+
+RawBuffer exportWrappedKey(const RawBuffer &wrappingKeyId,
+ const Pwd &wrappingKeyPwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &keyToWrapId,
+ const Pwd &keyToWrapPwd,
+ const DataType &keyToWrapType)
+{
+ AlgoType algo;
+ uint32_t ctrLenOrTagSizeBits = 0;
+ RawBuffer iv;
+ RawBuffer aad;
+ decompose(alg, algo, ctrLenOrTagSizeBits, iv, aad);
+
+ // TODO it is awful!
+ return TrustZoneContext::Instance().exportWrappedKey(wrappingKeyId,
+ wrappingKeyPwd,
+ getAlgType(algo),
+ iv,
+ ctrLenOrTagSizeBits,
+ aad,
+ keyToWrapId,
+ keyToWrapPwd,
+ toTzDataType(keyToWrapType));
}
RawBuffer getData(const RawBuffer &dataId,
- const Pwd &pwd)
+ const Pwd &pwd,
+ const DataType &type)
{
RawBuffer result;
TrustZoneContext::Instance().getData(dataId,
pwd,
+ toTzDataType(type),
result);
return result;
}
TrustZoneContext::Instance().destroyData(dataId);
}
-BufferPair encryptDataAesGcm(const RawBuffer &key,
+BufferPair encryptDataAesGcm(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSize,
RawBuffer result;
RawBuffer tag;
- TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
+ TrustZoneContext::Instance().executeEncryptAE(keyId, pwd, iv, tagSize,
aad, data, result, tag);
return std::make_pair(result, tag);
}
-RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
+RawBuffer encryptDataAesGcmPacked(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSize,
const RawBuffer &data,
const RawBuffer &aad)
{
- auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
+ auto pair = encryptDataAesGcm(keyId, pwd, iv, tagSize, data, aad);
std::copy(pair.second.begin(), pair.second.end(),
std::back_inserter(pair.first));
return pair.first;
}
-RawBuffer decryptDataAesGcm(const RawBuffer &key,
+RawBuffer decryptDataAesGcm(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSizeBits,
{
RawBuffer result;
- TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
+ TrustZoneContext::Instance().executeDecryptAE(keyId, pwd, iv, tagSizeBits,
tag, aad, data, result);
return result;
}
-RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
+RawBuffer decryptDataAesGcmPacked(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSizeBits,
ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
auto tagPos = data.data() + data.size() - tagSizeBytes;
- return decryptDataAesGcm(key,
+ return decryptDataAesGcm(keyId,
pwd,
iv,
tagSizeBits,
}
-RawBuffer symmetricEncrypt(const RawBuffer &key,
+RawBuffer symmetricEncrypt(const RawBuffer &keyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &data)
{
AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
- uint64_t ctrLen = 0;
+ uint64_t ctrLen = Params::DEFAULT_AES_IV_LEN * 8;
switch (algo) {
case AlgoType::AES_CTR: {
- ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
+ alg.getParam(ParamName::ED_CTR_LEN, ctrLen);
// counter length is in bits
if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
LogError("CTR length invalid: " << std::to_string(ctrLen));
ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
}
// no break here, we still need to slide down to executeCrypt
+ fallthru;
}
case AlgoType::AES_CBC:
case AlgoType::AES_CFB: {
RawBuffer result;
TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
getAlgType(algo),
- key,
+ keyId,
pwd,
unpack<RawBuffer>(alg, ParamName::ED_IV),
data,
alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
RawBuffer aad;
alg.getParam(ParamName::ED_AAD, aad);
- return encryptDataAesGcmPacked(key,
+ return encryptDataAesGcmPacked(keyId,
pwd,
unpack<RawBuffer>(alg, ParamName::ED_IV),
tagLenBits,
"Incorrect algorithm provided for symmetric crypto operation");
}
-RawBuffer symmetricDecrypt(const RawBuffer &key,
+RawBuffer symmetricDecrypt(const RawBuffer &keyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &data)
{
AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
- uint64_t ctrLen = 0;
+ uint64_t ctrLen = Params::DEFAULT_AES_IV_LEN * 8;
switch (algo) {
case AlgoType::AES_CTR: {
- ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
+ alg.getParam(ParamName::ED_CTR_LEN, ctrLen);
// counter length is in bits
if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
LogError("CTR length invalid: " << std::to_string(ctrLen));
ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
}
// no break here, we still need to slide down to executeCrypt
+ fallthru;
}
case AlgoType::AES_CBC:
case AlgoType::AES_CFB: {
RawBuffer result;
TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
getAlgType(algo),
- key,
+ keyId,
pwd,
unpack<RawBuffer>(alg, ParamName::ED_IV),
data,
alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
RawBuffer aad;
alg.getParam(ParamName::ED_AAD, aad);
- return decryptDataAesGcmPacked(key,
+ return decryptDataAesGcmPacked(keyId,
pwd,
unpack<RawBuffer>(alg, ParamName::ED_IV),
tagSizeBits,
"Incorrect algorithm provided for symmetric crypto operation");
}
-RawBuffer asymmetricEncrypt(const RawBuffer &key,
+RawBuffer asymmetricEncrypt(const RawBuffer &keyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &data)
case AlgoType::RSA_OAEP: {
TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
getAlgType(algo),
- key,
+ keyId,
pwd,
- unpack<RawBuffer>(alg, ParamName::ED_IV),
+ result, // unused dummy
data,
result);
return result;
"Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer asymmetricDecrypt(const RawBuffer &key,
+RawBuffer asymmetricDecrypt(const RawBuffer &keyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &cipher)
case AlgoType::RSA_OAEP: {
TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
getAlgType(algo),
- key,
+ keyId,
pwd,
- unpack<RawBuffer>(alg, ParamName::ED_IV),
+ result, // unused dummy
cipher,
result);
return result;
"Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer sign(const RawBuffer &pkey,
+uint32_t initCipher(const RawBuffer &keyId,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ bool encrypt)
+{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+
+ switch (algo)
+ {
+ case AlgoType::AES_GCM: {
+ int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
+ alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
+ RawBuffer aad;
+ alg.getParam(ParamName::ED_AAD, aad);
+ return TrustZoneContext::Instance().initGcmCipher(encrypt ? CIPHER_ENCRYPT : CIPHER_DECRYPT,
+ keyId,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ tagSizeBits,
+ aad);
+ }
+ case AlgoType::AES_CBC:
+ case AlgoType::AES_CTR:
+ case AlgoType::AES_CFB:
+ // TODO optionally implement above modes as well
+ default:
+ break;
+ };
+
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Incorrect algorithm provided for symmetric crypto operation");
+}
+
+void addAAD(uint32_t opId,
+ const RawBuffer &aad)
+{
+ TrustZoneContext::Instance().addGcmAAD(opId, aad);
+}
+
+RawBuffer updateCipher(uint32_t opId,
+ const RawBuffer &data)
+{
+ return TrustZoneContext::Instance().updateGcmCipher(opId, data);
+}
+
+RawBuffer finalizeCipher(uint32_t opId,
+ const RawBuffer &data)
+{
+ return TrustZoneContext::Instance().finalizeGcmCipher(opId, data);
+}
+
+void cleanupCipher(uint32_t opId)
+{
+ return TrustZoneContext::Instance().cleanupCipher(opId);
+}
+
+RawBuffer sign(const RawBuffer &pkeyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &message)
{
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,
+ pkeyId,
pwd,
message,
signature);
return signature;
}
-int verify(const RawBuffer &pkey,
+int verify(const RawBuffer &pkeyId,
const Pwd &pwd,
const CryptoAlgorithm &alg,
const RawBuffer &message,
{
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,
+ pkeyId,
pwd,
message,
signature);
}
+void deriveECDH(const RawBuffer &prvKeyId,
+ const Pwd &prvKeyPwd,
+ const RawBuffer &pubKey,
+ const Password &secretPwd,
+ const RawBuffer &secretPwdIV,
+ RawBuffer &secretTag,
+ const RawBuffer &secretHash)
+{
+ auto peerKey = std::make_shared<KeyImpl>(pubKey);
+ if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
+ ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
+ auto peerEvp = peerKey->getEvpShPtr().get();
+ assert(peerEvp);
+
+ int subType = EVP_PKEY_type(EVP_PKEY_id(peerEvp));
+ if (subType != EVP_PKEY_EC)
+ ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
+
+ auto ecKey = EVP_PKEY_get0_EC_KEY(peerEvp);
+ if (!ecKey)
+ ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
+
+ auto ecPoint = EC_KEY_get0_public_key(ecKey);
+ if (!ecPoint)
+ ThrowErr(Exc::Crypto::InternalError, "Can't get EC public key");
+
+ auto ecGroup = EC_KEY_get0_group(ecKey);
+ if (!ecGroup)
+ ThrowErr(Exc::Crypto::InternalError, "Can't get EC group");
+
+ BIGNUM *x = BN_new();
+ BIGNUM *y = BN_new();
+ if (!EC_POINT_get_affine_coordinates(ecGroup, ecPoint, x, y, NULL))
+ ThrowErr(Exc::Crypto::InternalError, "Failed to get EC pub key coordinates");
+
+ auto xBuf = extractBignumData(x);
+ auto yBuf = extractBignumData(y);
+
+ RawBuffer secretPwdBuf(secretPwd.begin(), secretPwd.end());
+
+ int pubCurve = EC_GROUP_get_curve_name(ecGroup);
+ tz_ec tzCurve;
+ switch (pubCurve)
+ {
+ case NID_X9_62_prime192v1:
+ tzCurve = EC_NIST_P192;
+ break;
+
+ case NID_X9_62_prime256v1:
+ tzCurve = EC_NIST_P256;
+ break;
+
+ case NID_secp384r1:
+ tzCurve = EC_NIST_P384;
+ break;
+
+ default:
+ ThrowErr(Exc::Crypto::InputParam, "Unsupported public key EC");
+ }
+
+ TrustZoneContext::Instance().executeEcdh(prvKeyId,
+ prvKeyPwd,
+ tzCurve,
+ xBuf,
+ yBuf,
+ secretPwdBuf,
+ secretPwdIV,
+ secretTag,
+ secretHash);
+}
+
+void deriveKBKDF(const RawBuffer &secretId,
+ const Pwd &secretPwd,
+ const CryptoAlgorithm &alg,
+ const Password &keyPwd,
+ const RawBuffer &keyPwdIV,
+ RawBuffer &keyTag,
+ const RawBuffer &keyHash)
+{
+ RawBuffer label, context, fixed;
+ KbkdfCounterLocation counterLocation;
+ KdfPrf prf;
+ KbkdfMode mode;
+ size_t length, rlenBits = 32, llenBits = 32, tmp;
+ bool hasLabel = alg.getParam(ParamName::KBKDF_LABEL, label);
+ bool hasContext = alg.getParam(ParamName::KBKDF_CONTEXT, context);
+ bool hasFixed = alg.getParam(ParamName::KBKDF_FIXED_INPUT, fixed);
+ alg.getParam(ParamName::KBKDF_COUNTER_LOCATION, counterLocation);
+ alg.getParam(ParamName::KBKDF_MODE, mode);
+ alg.getParam(ParamName::KDF_PRF, prf);
+ alg.getParam(ParamName::KDF_LEN, length);
+ alg.getParam(ParamName::KBKDF_RLEN, rlenBits);
+ bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
+ bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
+
+ RawBuffer key;
+ if (hasFixed) {
+ if (hasLabel || hasContext || noSeparator || hasLLen ||
+ counterLocation == KbkdfCounterLocation::MIDDLE_FIXED)
+ ThrowErr(Exc::Crypto::InputParam, "Unexpected parameters for fixed input mode.");
+ } else {
+ if (!hasLabel || !hasContext)
+ ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
+
+ if (llenBits != 0 && llenBits != 8 && llenBits != 16 && llenBits != 24 && llenBits != 32)
+ ThrowErr(Exc::Crypto::InputParam, "Invalid llen value");
+ }
+ if (length != 16 && length != 24 && length != 32)
+ ThrowErr(Exc::Crypto::InputParam, "Invalid key length");
+
+ if (rlenBits != 8 && rlenBits != 16 && rlenBits != 24 && rlenBits != 32)
+ ThrowErr(Exc::Crypto::InputParam, "Invalid rlen value");
+
+ RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
+
+ TrustZoneContext::Instance().executeKbkdf(secretId,
+ secretPwd,
+ length,
+ label,
+ context,
+ fixed,
+ toTzPrf(prf),
+ toTzKbkdfMode(mode),
+ toTzCtrLoc(counterLocation),
+ rlenBits,
+ llenBits,
+ noSeparator,
+ keyPwdBuf,
+ keyPwdIV,
+ keyTag,
+ keyHash);
+}
+
+size_t maxChunkSize()
+{
+ return TrustZoneContext::Instance().getMaxChunkSize();
+}
+
} // namespace Internals
} // namespace TZ
} // namespace Crypto