Create Elliptical Curve Signing Key using TSS/C++ - c++

I need to create an elliptical signing key using the TSS/C++ library.
However when I create it I get a strange error from the TPM simulator:
TPM Error - TPM_RC::: The specified path is invalid.
Here is the method I use to create the signing key. Can someone show me what I am doing incorrectly
DWORD CreateKeyPair(Tpm2 tpm)
{
DWORD retCode = 0;
try
{
//Create a dummy PIN for now
ByteVec userAuth = ByteVec{ 1, 2, 3, 4 };
TPMS_SENSITIVE_CREATE sensCreate(userAuth, vector<BYTE>());
vector<TPMS_PCR_SELECTION> pcrSelectSigning{};
//signing key
TPMS_ECC_PARMS signingKeyParams(TPMT_SYM_DEF_OBJECT(),
TPMS_SCHEME_ECDSA(TPM_ALG_ID::SHA256),
TPM_ECC_CURVE::NIST_P256,
TPMS_NULL_KDF_SCHEME());
//Signing key public template
TPMT_PUBLIC signingKeyTemplate(TPM_ALG_ID::SHA256,
TPMA_OBJECT::sign | // Key attribues
// Not needed, TPMA_OBJECT::encrypt |
TPMA_OBJECT::fixedParent |
TPMA_OBJECT::fixedTPM |
TPMA_OBJECT::sensitiveDataOrigin |
TPMA_OBJECT::userWithAuth,
vector<BYTE>(),
signingKeyParams,
TPMS_ECC_POINT()
);
CreatePrimaryResponse singingPrimary = tpm.CreatePrimary(TPM_RH::OWNER,
sensCreate,
signingKeyTemplate,
vector<BYTE>(),
pcrSelectSigning);
}
catch (exception e)
{
cout << "Exception thrown: " << e.what() << endl;
}
return retCode;
}

Related

Handle PostgreSQL transaction errors in GDALVectorTranslate

In c++ I'm using the GDAL library for importing geo-spatial files into Postgres/PostGIS.
The GDAL library will create a table in the Postgres database and insert the data. But I can't figure out how to handle errors during the inserting of data.
I'm using GDALVectorTranslate https://gdal.org/api/gdal_utils.html#gdal__utils_8h_1aa176ae667bc857ab9c6016dbe62166eb
If an Postgres error occurs the error text will be outputted and the program continues to run. I would like to handle these Postgres errors.
An error could be:
ERROR 1: INSERT command for new feature failed.
ERROR: invalid byte sequence for encoding "UTF8": 0xe5 0x20 0x46
For now I let my program count the rows in the destination table and if zero then assume error. But that doesn't work if appending to an existing table.
auto *dst = (GDALDataset *) GDALVectorTranslate(nullptr, pgDs, 1, &sourceDs, opt, &bUsageError);
if (dst == nullptr) {
std::cout << "ERROR! Couldn't create table" << std::endl;
return FALSE;
} else {
OGRLayer *layer = dst->GetLayerByName(altName);
// Here the rows are counted
if (layer->GetFeatureCount() == 0) {
std::cout << "ERROR! Insert failed" << std::endl;
return FALSE;
}
std::cout << " Imported";
return TRUE;
}
You can register your own error handler to log and count the underlying errors:
struct {/*members for handling errors*/} ctx;
static void myErrorHandler(CPLErr e, CPLErrorNum n, const char* msg) {
ctx *myctx = (ctx*)CPLGetErrorHandlerUserData();
/* do something with ctx to log and increment error count */
}
int myTranslateFunc() {
ctx myctx; //+initialization
CPLPushErrorHandlerEx(&myErrorHandler,&myctx);
auto *dst = (GDALDataset *) GDALVectorTranslate(nullptr, pgDs, 1, &sourceDs, opt, &bUsageError);
CPLPopErrorHandler();
//inspect myctx for potential errors
}

Can't get a value from LMDB

I'm trying to store and fetch some data from LMDB. Data seems to be stored, I can see the keys in my database, but it gives me MDB_NOTFOUND when I try to fetch the value with the same ID I have just stored it under.
Database opening
MDB_env* environment;
MDB_dbi main;
MDB_dbi order;
mdb_env_create(&environment);
mdb_env_set_maxdbs(environment, 2);
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
int rc;
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
mdb_dbi_open(txn, "main", MDB_CREATE, &main);
mdb_dbi_open(txn, "order", MDB_CREATE | MDB_INTEGERKEY, &order);
mdb_txn_commit(txn);
Insertion
void Core::Archive::addElement(const Shared::Message& message) {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
message.serialize(ds);
uint64_t stamp = message.getTime().toMSecsSinceEpoch();
const std::string& id = message.getId().toStdString();
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size();
lmdbKey.mv_data = (uint8_t*)id.c_str();
lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data();
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
int rc;
rc = mdb_put(txn, main, &lmdbKey, &lmdbData, 0);
if (rc == 0) {
MDB_val orderKey;
orderKey.mv_size = 8;
orderKey.mv_data = (uint8_t*) &stamp;
rc = mdb_put(txn, order, &orderKey, &lmdbKey, 0);
if (rc) {
mdb_txn_abort(txn);
} else {
rc = mdb_txn_commit(txn);
if (rc) {
qDebug() << "A transaction error: " << mdb_strerror(rc);
}
}
} else {
qDebug() << "An element couldn't been added to the archive, skipping" << mdb_strerror(rc);
mdb_txn_abort(txn);
}
}
Fetching
Shared::Message Core::Archive::getElement(const QString& id) {
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.toStdString().size();
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
MDB_txn *txn;
int rc;
mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
rc = mdb_get(txn, main, &lmdbKey, &lmdbData);
if (rc) {
qDebug() <<"Get error: " << mdb_strerror(rc);
mdb_txn_abort(txn);
throw NotFound(id.toStdString(), jid.toStdString());
} else {
//it never comes here
}
}
Testing code
Core::Archive ar();
ar.open("Test");
Shared::Message msg1;
msg1.generateRandomId();
msg1.setBody("oldest");
msg1.setTime(QDateTime::currentDateTime().addDays(-7));
Shared::Message msg2;
msg2.generateRandomId();
msg2.setBody("Middle");
msg2.setTime(QDateTime::currentDateTime().addDays(-4));
Shared::Message msg3;
msg3.generateRandomId();
msg3.setBody("newest");
msg3.setTime(QDateTime::currentDateTime());
ar.addElement(msg2);
ar.addElement(msg3);
ar.addElement(msg1);
Shared::Message d0 = ar.getElement(msg1.getId());
My logs show stored keys. I can see the required key, I can even compare it with the requested key if I use cursors to scroll over the whole storage, it even shows they are equal, but mdb_cursor_get or mdb_get constantly give me MDB_NOTFOUND. What am I doing wrong?
I got it. No matter what I put into database, I have to read it as a char*
Had to modify fetching code
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
I had to change it to
lmdbKey.mv_data = (char*)id.toStdString().c_str();
and it worked

How to declare an empty rowset properly with SOCI?

Imagine that I have the following function. In case of invalid parameters or exception, the function has to exit with an empty rowset.
rowset<row> SelectAllFromTable(string tableName)
{
session sql(odbc, "...");
// if parameters are not valid -> return empty rowset<row>
if (tableName == "")
{
// query that returns 0 result
rowset<row> res = (sql.prepare << "SELECT ID FROM T1 WHERE ID = -9999");
return res;
}
string query = "SELECT * FROM " + tableName;
try
{
rowset<row> rs = sql.prepare << query;
return rs;
}
catch (exception const &e)
{
cerr << "Error: " << e.what() << endl;
// query that returns 0 result
rowset<row> res = (sql.prepare << "SELECT ID FROM T1 WHERE ID = -9999");
return res;
}
// query that returns 0 result
rowset<row> res = (sql.prepare << "SELECT ID FROM T1 WHERE ID = -9999");
return res;
}
The solution I wrote above works but my question is : Is there a better way to return an empty rowset with SOCI ?
Since the documentation hasn't much to offer to this I looked into the rowset Header: There is no default constructor for it and no public method to set the iterators, ergo you can't get an empty rowset by yourself.
Despite why don't you use exceptions which are just perfect for that case. Just don't catch the soci_error exception, then the caller SelectAllFromTable could catch it. This would have many advantages:
The caller would know if there is really no data in the table or there is no table
The caller could know why he can't use the table (misspelled or security reasons)
The caller could know if there are other troubles and take action or if not, rethrow it, so his caller might can.

Detect USB devices event

I made a console application which detects plugin and plugout events for all type of usb devices. but I wanted some filteration in it like I wanted to detect only webcams . This was done by using GUID class. The class for webcam is 'Image' class with GUID "{6bdd1fc5-810f-11d0-bec7-08002be2092f}" .The problem is that this 'Image' class is also used for scanners and I dont want to detect scanners.The code is given below:
static void Main(string[] args)
{
WqlEventQuery weqQuery = new WqlEventQuery();
weqQuery.EventClassName = "__InstanceOperationEvent";
weqQuery.WithinInterval = new TimeSpan(0, 0, 3);
weqQuery.Condition = #"TargetInstance ISA 'Win32_PnPEntity'";
ManagementEventWatcher m_mewWatcher = new ManagementEventWatcher(weqQuery);
m_mewWatcher.EventArrived += new EventArrivedEventHandler(m_mewWatcher_EventArrived);
m_mewWatcher.Start();
Console.ReadLine();
}
static void m_mewWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
bool bUSBEvent = false;
string deviceCaption = "";
string deviceType = "";
foreach (PropertyData pdData in e.NewEvent.Properties)
{
try
{
ManagementBaseObject mbo = (ManagementBaseObject)pdData.Value;
if (mbo != null)
{
foreach (PropertyData pdDataSub in mbo.Properties)
{
Console.WriteLine(pdDataSub.Name + " = " + pdDataSub.Value);
if (pdDataSub.Name == "Caption")
{
deviceCaption = pdDataSub.Value.ToString();
}
if (pdDataSub.Name == "ClassGuid" && pdDataSub.Value.ToString() == "{6bdd1fc5-810f-11d0-bec7-08002be2092f}")
{
bUSBEvent = true;
deviceType = "Image";
}
}
if (bUSBEvent)
{
if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent")
{
Console.WriteLine("A " + deviceType + " device " + deviceCaption + " was plugged in at " + DateTime.Now.ToString());
}
else if (e.NewEvent.ClassPath.ClassName == "__InstanceDeletionEvent")
{
Console.WriteLine("A " + deviceType + " device " + deviceCaption + " was plugged out at " + DateTime.Now.ToString());
}
}
}
}
catch (Exception ex)
{
}
}
}
for references check this link
I waited but no body answered this question so, after seeing all properties of ManagementBaseObject I found that there is a property named Service which is different for scanners. In scanners the value of Service property is usbscan while in cameras it is usbvideo.
eg.
you can do something like this
if (mbo.Properties["Service"].Value.ToString() == "usbscan")
{
//then it means it is a scanner
}
else
{
//then it means it is a camera
}
note: The main question was that how can we differentiate between a scanner and a webcam because they both use same GUID.

C++ cassandra client select int value

I'm trying to select an integer value but I can't
This is my code:
cassandra_socket = boost::shared_ptr<TSocket>(new TSocket(host, port));
cassandra_transport = boost::shared_ptr<TFramedTransport>(new TFramedTransport(cassandra_socket));
protocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(cassandra_transport));
cassandra_client = new CassandraClient(protocol);
try {
cassandra_transport->open();
cassandra_client->set_keyspace("MPS");
ColumnOrSuperColumn csc;
ColumnPath cpath;
cpath.column_family.assign("SubmitResposes_count");
/* This is required - thrift 'feature' */
cpath.__isset.column = true;
cpath.column = "Counter";
cassandra_client->get(csc, "1", cpath,org::apache::cassandra::ConsistencyLevel::ONE);
cout << "Value read is '" << csc.column.value << "'..." << endl;
}
catch (NotFoundException &nf) {
FORCE_TRACE(0, "NOT FOUND EXCEPTION ERROR: %s", nf.what());
} catch (InvalidRequestException &re) {
FORCE_TRACE(0, "INVALID REQUEST ERROR: %s", re.why);
} catch (TException &tx) {
FORCE_TRACE(0, "TEEXCEPTION ERROR: %s", tx.what());
}
it gives me this exception:
InvalidRequest ERROR: Expected 4 or 0 byte int (1)
& this is the table I've created:
create table SubmitResposes_count(
ID int primary key,
Counter bigint);
Your key is an int:
ID int primary key,
but you are querying using a string key:
cassandra_client->get(csc, "1", cpath,org::apache::cassandra::ConsistencyLevel::ONE);
^^^
Cassandra is trying to validate your string as an int, which is causing this exception.