Storing SRK on the TPM with Trousers - tpm

I am using Trousers to interact with TPM for a project. I have ran into an issue with the storage of SRK (Storage Root Key).
My understanding is that the SRK key pair is generated at the time of taking TPM ownership & is stored inside the TPM. But looks like some part of it is being stored in the system persistent storage (defined by system_ps_file config). And in case the system persistent storage gets deleted, it is not possible to load the SRK anymore.
Code to create the SRK
TSS_FLAG srk_flags = TSS_KEY_TSP_SRK|TSS_KEY_AUTHORIZATION;
int result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, srk_flags, srk_handle);
Code to load the SRK
TSS_UUID srk_uuid = TSS_UUID_SRK;
int result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, srk_uuid, srk_handle);
Above code works properly untill system persistent storage data file is present. But once it is deleted, I get:
ERROR: Tspi Context LoadKeyByUUID (SRK ) failed rc =0 x2020
Is there a way to recover the deleted storage file ? or to avoid using it for SRK ?

You are pretty much correct in your assessment of what's going on. The requirement to store the keys in persistent storage comes straight from the TSS spec:
All keys, which should be internally managed by the Key Management
Services of TSS must be registered in the persistent storage database
of TCS (System Persistent Storage) or TSP (User Persistent Storage).
Each key registered in one of these databases will be referenced by
its UUID and called a persistent key from this specification’s point
of view.
That being said, what's stored in place of the SRK is a zeroed-out "fake SRK", so theoretically you could run the same code to replace it:
BYTE *save;
/* Once the key file is created, it stays forever. There could be
* migratable keys in the hierarchy that are still useful to someone.
*/
result = ps_remove_key(&SRK_UUID);
if (result != TSS_SUCCESS && result != TCSERR(TSS_E_PS_KEY_NOTFOUND)) {
destroy_key_refs(&srkKeyContainer);
LogError("Error removing SRK from key file.");
*srkKeySize = 0;
free(*srkKey);
goto done;
}
/* Set the SRK pubkey to all 0's before writing the SRK to disk, this is for
* privacy reasons as outlined in the TSS spec */
save = srkKeyContainer.pubKey.key;
srkKeyContainer.pubKey.key = fake_pubkey;
offset = 0;
LoadBlob_TSS_KEY(&offset, fake_srk, &srkKeyContainer);
if ((result = ps_write_key(&SRK_UUID, &NULL_UUID, NULL, 0, fake_srk,
offset))) {
destroy_key_refs(&srkKeyContainer);
LogError("Error writing SRK to disk");
*srkKeySize = 0;
free(*srkKey);
goto done;
}
srkKeyContainer.pubKey.key = save;
But what you're supposed to do instead is back up your persistent storage. If you lose it you lose all the other keys (that are not the SRK) that you created.

Related

Delete element in the middle of mapping

I need to delete an item in the middle of the Everscale solidity mapping containing struct:
struct Example {
string data;
uint64 validFrom;
uint64 valiUntil;
}
mapping(uint64 => Example) example;
example[1668161798] = Example("Start", 1668161798, 1668162798);
...
example[1668163798] = Example("Middle", 1668163798, 1668164798); // <-- Need to delete this one
...
example[1668165798] = Example("End", 1668165798, 1668166798);
Question 1
What is the best way to do this in terms of:
Gas consumption?
Storage?
Is it using the delete instruction work from the Ethereum example, or is it better to rebuild and reassign the mapping?
delete example[1668163798];
Question 2
What happens to the data contained in the mapping's item after using delete? Is there any garbage collector that wipes them out to minimize the storage?
What will happen if I reassign new data on the same index after deletion?
delete example[1668163798];
is the right way to do it. "delete" assigns the default value of the type for the variable it is applied to. For the mapping key, it removes the pair from the dictionary, thus freeing the storage space.
assigning a new value to the previously deleted key is no different from adding any other (key, value) pair to the dictionary; it works just fine.

Is it possible to store Cytoscape.js layout data directly to a file format in app/web server and re-launch the same layout to minimize re-computation?

Some of the cytoscape layout is randomize where the position is not fix every time we launch it. I understand from multiple stack overflow questions where we can save the layout data (i.e. including its position x and y) into browser local storage or session storage so that we can display the same layout using the same data.
However, the problem with local storage or session storage is good for one users. But, imagine if there are thousands of users using the same app, the server will undergo mass computation for each user to store respective data to individual browsers. Can we save the data into a file format directly into app/web server so that 1000 users will see the same layout and this reduces the computation of different data set as well.
Thank you. Would like to know the possibility to convert data into a file and store in the web/app server.
Yes, you can store position data. Actually, there are 2 options in my mind.
Use cy.json(). You can store the elements as JSON like JSON.stringify(cy.json().elements) and then save this JSON string.
cy.json().elements is something like the below image
You can restore this data easily like cy.json({elements: JSON.parse(jsonStr));
As you could see cy.json().elements is a bit big thing. Position data is just a small object like {x: 0, y: 0}. Additional to position it contains many other data. So if you only need to restore the positions, you could store them manually easily with a code like below. You can use ele.id and node.position() functions.
function storePositions() {
const nodes = cy.nodes();
const nodePositions = {};
for (let i = 0; i < nodes.length; i++) {
nodePositions[nodes[i].id()] = nodes[i].position();
}
return nodePositions;
}
You can also restore node positions easily. You can use getElementById and node.position() functions.
function restorePositions(nodePositions) {
const nodes = cy.nodes();
const nodePositions = {};
for (let k in nodePositions) {
const node = cy.getElementById(k);
if (node && node.length > 0) {
node.position(nodePositions[k]);
}
}
return nodePositions;
}

setStoreByValueJCache + Hazelcast interface does not work

I have done some test using setStoreByValue(true/false) and I do not appreciate the difference.
I expect to store in the cache a lot of more that 30 objects when I use store by reference.
CacheManager manager = Caching.getCachingProvider().getCacheManager();
MutableConfiguration<String, CaLpgDataCollectionDto<CaBigNumber>> configuration = new MutableConfiguration<String, CaLpgDataCollectionDto<CaBigNumber>>();
configuration.setStoreByValue(false);
Cache<String, CaLpgDataCollectionDto<CaBigNumber>> testCache = manager.createCache("testCache", configuration);
//ICache is a Hazelcast interface that extends JCache, provides more functionality
ICache<String, CaLpgDataCollectionDto<CaBigNumber>> icache = testCache.unwrap(ICache.class);
List<CaLpgDataRowDto<CaBigNumber>> bigList = lpgDatasource.getDataRows();
while (bigList.size() <= 5000000)
{
bigList.addAll(bigList);
}
lpgDatasource.setDataRows(bigList);
System.out.println("Free memory before (bytes): " + Runtime.getRuntime().freeMemory());
for (int i = 0; i < 30 ; i++)
{
icache.put("objectTest"+i, lpgDatasource);
}
Am I using properly this propertie?
Kind regards.
JSR107 standard specifies that store-by-reference is an optional feature (see page 9 of JSR107 1.1.1 specification here. You can query a CachingProvider to test whether an optional feature is supported via CachingProvider#isSupported(OptionalFeature).
Hazelcast, being primarily used as a distributed cache, does not support store by reference. Keys and values have to be serializable in order to be transferred across the network among Hazelcast members and clients. Also, depending on the chosen in-memory storage format, values can be stored as serialized blobs (the default option with BINARY in-memory format) or as deserialized objects, however even in the latter case the value is serialized/deserialized first so it is a clone of the original.

Searching the Registry for a key - JScript

Is there a way to search the Registry for a specific key using Windows Scripting Host?
I'm using JavaScript (Jscript/VBScript?) to do so, and the msdn Library doesn't mention any such method: http://msdn.microsoft.com/en-us/library/2x3w20xf(v=VS.85).aspx
Thanks,
So here's an update to the problem:
The problem is a bit more complicated than a direct registry search. I have to look through the installed products on a windows box, to find a specific product entry that i want to delete. The registry path is defined as:
HKEY_LOCAL_MACHINE\Software\Microsoft...\Products.
Within the Products key, the installed products are listed, but their keys are defined as hash codes. Within the product keys are other keys with defined names and defined values. I want to be able to search on the latter keys and values. How can I do that, by-passing the unknown hash codes?
For example, I need to find a product with DisplayVersion key = 1.0.0. The path to that key is:
HKLM\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\Products\A949EBE4EED5FD113A0CB40EED7D0258\InstallProperties\DisplayVersion.
How can I either pick up, or avoid writing, the product key: A949EBE4EED5FD113A0CB40EED7D0258 ??
Assuming you're using JScript via the Windows Scripting Host (and not JavaScript from a browser) you can get the value of a specific key using the WScript.RegRead method:
// MyScript.js
var key = 'HKEY_CURRENT_USER\\SessionInformation\\ProgramCount'
, wsh = WScript.CreateObject('WScript.Shell')
, val = wsh.RegRead(key);
WScript.Echo('You are currently running ' + val + ' programs.');
If you actually need to search for a key or value based on some conditions rather than a known registry key then you can to implement your own recursive search algorithm where registry values of type "REG_SZ" are leaf nodes.
As an exercise to get more familiar with JScript on the Windows Scripting Host, I've made a small interface to the registry that does exactly this. The example included in the project shows how to perform such a registry search in a WSF script:
<job id="FindDisplayVersions">
<script language="jscript" src="../registry.js"/>
<script language="jscript">
// Search the registry and gather 20 DisplayVersion values.
var reg = new Registry()
, rootKey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products'
, keyRegex = /Products\\(.*?)\\InstallProperties\\DisplayVersion$/
, valRegex = /^1\./
, maxResults = 20
, uids = [];
reg.find(rootKey, function(path, value) {
var keyMatch = keyRegex.exec(path);
if (keyMatch) {
if (valRegex.exec(value)) {
uids.push(keyMatch[1] + '\t=\t' + value);
if (uids.length >= maxResults) { return false; } // Stop searching
}
}
return true; // Keep searching.
});
WScript.Echo(uids.join("\n"));
</script>
</job>
Note that, as #Robert Harvey points out, this could take a really long time if the root key is too deeply connected. Simple testing takes only a few seconds on the key I chose but your mileage may vary; of course, no warranty or fitness for a purpose, don't blame me if your computer blows up.
http://code.google.com/p/jslibs/
if you don't find it there, you have to implement it yourself

question on Implementing IQueryCancelAutoPlay in a windows service

I am implementing IQueryCancelAutoPlay COM interface and registering it with the Running Objects Table from a Windows Service*.
My problem is that it never gets called when I insert a mass storage device (or any device really). Here's some more information:
My code for registering with the ROT:
Text::string clsIdString = Text::to_string(Com::CLSID_QCAListener);
// remove curly braces
clsIdString = clsIdString.substr(1, clsIdString.length() - 2);
// set registry key to make sure we get notifications from windows
Reg::SetValue(HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\CancelAutoplay\\CLSID"),
clsIdString, _T(""));
HRESULT result = S_OK;
// create class moniker ...
CComPtr<IMoniker> moniker;
result = CreateClassMoniker(Com::CLSID_QCAListener, &moniker);
if( !ValidateResult(result, "Error creating class moniker") )
return;
DBG << _T("Getting IRunningObjectTable pointer ...") << std::endl;
// get running oject table ...
CComPtr<IRunningObjectTable> runningObjectTable;
result = GetRunningObjectTable(0, &runningObjectTable);
if( !ValidateResult(result, "Error getting running object table") )
return;
// create an instance of the QCAListener class ...
Com::QCAListener * listenerInstance = new Com::QCAListener();
if(!ValidateResult( listenerInstance != 0,
"Error creating QueryCancelAutoplayListener"))
return;
// ... and set the pointer in the _qcaListener variable
CComPtr<IQueryCancelAutoPlay> qcaListener;
listenerInstance->QueryInterface(IID_IQueryCancelAutoPlay, reinterpret_cast<void**>(&qcaListener));
DBG << _T("Registering IQueryCancelAutoPlay with ROT ...") << std::endl;
result = runningObjectTable->Register(
ROTFLAGS_REGISTRATIONKEEPSALIVE,
listenerInstance,
moniker,
&_qcaRegistration);
ValidateResult(result, "Error registering QueryCancelAutoplayListener with the ROT");
runningObjectTable->Register returns S_OK, and at the end of the code block's execution the ref-count for listenerInstance is 1 (if I remove the call to runningObjectTable->Register completely, the ref-count remains 0 when qcaListener goes out of scope so this means an instance of my class remains active in the ROT).
More details: In development, my service runs with my account credentials (local administrator). Although this will probably change, it should work as it is with the current configuration.
Can anyone shed any light on this?
*- I know the documentation says I shouldn't implement IQueryCancelAutoPlay in a service but I need to do this for various reasons (business requirement, etc).
I figured it out (for those who stumble upon this answer when having a similar problem):
The service runs under a different window station and a different desktop. When the IQueryCalcelAutoPlay implementation is registered in the ROT this is done for a different desktop.
The current user's desktop shell (explorer) will not find this registration when a new USB device is inserted (as it is not registered with the current desktop).

Resources