Code Monkey home page Code Monkey logo

tpm-js's Introduction

Interactive TPM simulator with codelabs

Overview

TPM-JS lets you experiment with a software TPM device in your browser. It's an educational tool that teaches you how to use a TPM device to secure your workflows. The codelab like sessions cover topics such as key generation, measured boot, remote attestation and sealing.

Screenshots

Welcome screen: Welcome Screen

Keys codelab: Keys codelab

PCRs codelab: PCRs codelab

Architecture

TPM-JS includes the following libraries:

The libraries are compiled to WebAssembly, and accessed via Javascript.

Dependencies

Build

Initialize git submodules:

git submodule update --init

Activate emsdk:

source {EMSDK PATH}/emsdk_env.sh

Build TPM-JS:

mkdir bulid-web
cd build-web
emcmake cmake ..
make -j4

Run unit-tests:

make check

Alternatively, you can build the project using the provided Docker file.

One time initialization:

./dcmake.sh

Then build using:

./dmake.sh -j4

Serve Files

Add the line application/wasm wasm to /etc/mime.types.

Serve files from the built web package:

cd build-web/web
python3 -m http.server --bind 127.0.0.1 8000

Disclaimer

This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google.

tpm-js's People

Contributors

cfircohen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tpm-js's Issues

Statement that endorsement seed never changes

In the first paragraph of https://google.github.io/tpm-js/#pg_keys, the statement, "The endorsement seed (eseed) is randomly generated at manufacturing time and never changes during the lifetime of the device." is made.

The spec seems to allow for the endorsement seed, epSeed, to change via the command TPM2_ChangeEPS as documented in table 34 of the architecture specification:
https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
In section 14.3.2 of that document, it elaborates the setup scheme.

While in practice folks may not be changing the epSeed, it is possible and thus no way to identify the device.

problem when compile

Sorry for bothering.When I tried to use the command "emconfigure cmake ..",it reports error: use 'emcmake' rather then 'emconfigure' for cmake projects. So I used ' emcmake cmake ..', it also report error,like the following:

configure: cmake .. -DCMAKE_TOOLCHAIN_FILE=/home/samfisher/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR="/home/samfisher/emsdk/node/12.9.1_64bit/bin/node"
CMake Warning at third_party/googletest/googlemock/CMakeLists.txt:43 (project):
VERSION keyword not followed by a value or was followed by a value that
expanded to nothing.

CMake Warning at third_party/googletest/googletest/CMakeLists.txt:54 (project):
VERSION keyword not followed by a value or was followed by a value that
expanded to nothing.

-- Checking for module 'libunwind-generic'
-- No package 'libunwind-generic' found
libunwind not found. Disabling unwind tests.
CMake Error at third_party/boringssl/CMakeLists.txt:51 (message):
Could not find Go

-- Configuring incomplete, errors occurred!
See also "/home/samfisher/test/tpm-js/bulid-web/CMakeFiles/CMakeOutput.log".
See also "/home/samfisher/test/tpm-js/bulid-web/CMakeFiles/CMakeError.log".

ReferenceError: vendor_root_cert is not defined at pg_certificates page

To reproduce: navigate to https://google.github.io/tpm-js/#pg_certificates and click the second Run button.

Output:

ReferenceError: vendor_root_cert is not defined
    at eval (eval at <anonymous> (https://google.github.io/tpm-js/js/main.js:291:44), <anonymous>:20:21)
    at https://google.github.io/tpm-js/js/main.js:291:44
    at l (https://code.jquery.com/jquery-3.3.1.min.js:2:29375)
    at c (https://code.jquery.com/jquery-3.3.1.min.js:2:29677)

Debian: Make fails

Everything works up to the step where i run "make -j4"
That's when i get the following error:

make[2]; ** No rule to make target 'html/images/*', needed by 'web/images'. Stop.
make[2]; ** No rule to make target 'html/templates/*', needed by 'web/index.html'. Stop.

Compilation on windows

Hi

I did all the steps but am stuck with make -j4 on windows. Can you tell me the how to execute this command on windows

Error in GetPublicRSA

Hi,

Looking through your code for creating TPM keys I found a slight error in a logic condition in GetPublicRSA. The restricted flag should be set if the key is to be restricted, but not when both sign and decrypt are set.
From the spec:

When both sign and decrypt are SET, restricted shall be CLEAR and scheme shall be TPM_ALG_NULL

make: *** No targets specified and no makefile found. Stop.

after building successfully with emcmake cmake .. I get the following output:

-- Could NOT find Threads (missing: Threads_FOUND)
-- Could NOT find Threads (missing: Threads_FOUND)
-- Patching BoringSSL CMakeLists.txt
-- Configuring done
-- Generating done
-- Build files have been written to: %userPath%/tpm-js

Then I try to run make -j4 but I get the following error message:

make: *** No targets specified and no makefile found. Stop.

I tryied running make -j4 on the build-web/ folder and also in tpm-js folder. In both cases I get the same error.

Am I missing something?

PS: after the building my build-web/ folder continues empty, Is this the expected behaviour?

Docker build fails

./dcmake.sh fails with:
cat: /emsdk/emsdk_set_env.sh: No such file or directory.

Could be linked to #551

cmake error

Hi,

I get the following errors when building:

root@ubuntu:/opt/tpm-js/build-web# emconfigure cmake ..
CMake Warning at third_party/googletest.cmake:22 (message):
Missing GOOGLEMOCK module
Call Stack (most recent call first):
CMakeLists.txt:81 (include)

CMake Warning at third_party/googletest.cmake:34 (message):
Missing GOOGLETEST module
Call Stack (most recent call first):
CMakeLists.txt:81 (include)

CMake Warning at third_party/ssl.cmake:39 (message):
Missing BoringSSL module
Call Stack (most recent call first):
CMakeLists.txt:82 (include)

-- Configuring done
CMake Error at third_party/tpm2tss.cmake:25 (add_library):
Cannot find source file:

/opt/tpm-js/third_party/tpm2-tss/src/util/log.c

Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
Call Stack (most recent call first):
CMakeLists.txt:84 (include)

CMake Error: Cannot determine link language for target "tpm2tss_lib".
CMake Error: CMake can not determine linker language for target: tpm2tss_lib
-- Generating done
-- Build files have been written to: /opt/tpm-js/build-web
ERROR:root:Configure step failed with non-zero return code: 1. Command line: cmake -DCMAKE_CROSSCOMPILING_EMULATOR="/opt/emsdk/node/8.9.1_64bit/bin/node" .. -DCMAKE_TOOLCHAIN_FILE=/opt/emsdk/emscripten/1.38.12/cmake/Modules/Platform/Emscripten.cmake at /opt/tpm-js/build-web

Loading Import Blob example fails

The last example "Loading Import Blob" from "Importing Keys" fails with Assertion failed: PolicySecret failed. The error code is 1251, which should be:

Format Error:
 Parameter: 0x4
 Error: TPM_RC_EXPIRED
  Description: the policy has expired

The reason I have Identified for this is the fixed 10s timeout/expiration in PolicySecret:

tpm-js/src/app.cc

Lines 1122 to 1134 in 616a166

int App::PolicySecret(uint32_t auth_handle, uint32_t session_handle) {
LOG1("PolicySecret %x\n", session_handle);
int32_t expiration = 10;
TPM2B_TIMEOUT timeout = {
.size = TPM2BStructSize<TPM2B_TIMEOUT>(),
};
TPMT_TK_AUTH ticket = {};
return Tss2_Sys_PolicySecret(tss_.GetSysContext(), auth_handle,
session_handle, &sessions_data_,
/*nonceTPM=*/nullptr, /*cpHashA=*/nullptr,
/*policyRef=*/nullptr, expiration, &timeout,
&ticket, &sessions_data_out_);
}

The problem with this is, that the timeout in this case is not relative, but absolute:

if((authTimeout < g_time)

So, after 10 seconds the exmple doesn't work anymore.

I tested this with the following code (copied from the examples). If I run this from the Javascript console in the first 10 seconds, it works and stops working afterwords:

  // Create primary key endorsement key from the default template.
  var ek = app.CreatePrimaryEndorsementKey();
  assert(ek.rc == TPM2_RC_SUCCESS, 'CreatePrimary failed');
  assert(app.FlushContext(ek.handle) == TPM2_RC_SUCCESS, 'FlushContext failed');

  // Build public key object from key material.
  var bn_n = new forge.jsbn.BigInteger(ek.rsa_public_n.substr(2), 16);
  var bn_e = new forge.jsbn.BigInteger('10001', 16);
  ek_pub = new forge.pki.setRsaPublicKey(bn_n, bn_e);
  console.log('EK: ', ek_pub);
  
  var sensitive = 'super secret stuff';
  carrier = new Module.KeyedHash(sensitive);
  console.log('OK');
  
  seed = forge.random.getBytesSync(16)
  aes_key = util.KDFa(TPM2_ALG_SHA256, seed, 'STORAGE', carrier.GetEncodedPublicName(), [], 128)
  mac_key = util.KDFa(TPM2_ALG_SHA256, seed, 'INTEGRITY', ByteArrayToStdVector([]), [], 256)
  console.log('OK');


  // Encrypt carrier keyed-hash object.
  var cipher = forge.cipher.createCipher('AES-CFB', aes_key)
  cipher.start({iv: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]})
  cipher.update(ByteArrayToForgeBuffer(StdVectorToByteArray(carrier.GetEncodedPrivate())))
  cipher.finish()
  enc_private = cipher.output.data

  // MAC encrypted blob.
  hmac = forge.hmac.create()
  hmac.start('sha256', mac_key)
  hmac.update(cipher.output.data)
  hmac.update(ByteArrayToForgeBuffer(StdVectorToByteArray(carrier.GetEncodedPublicName())).data)
  tag = hmac.digest().data

  // Encrypt seed by EK's public key.
  enc_seed = ek_pub.encrypt(seed, 'RSA-OAEP', {md: forge.md.sha256.create(), label: 'DUPLICATE\x00'})

  console.log('Import blob:');
  console.log('Encrypted seed: ', forge.util.bytesToHex(enc_seed));
  console.log('Encrypted private: ', forge.util.bytesToHex(enc_private))
  console.log('Encrypted private mac: ', forge.util.bytesToHex(tag))
  console.log('Carrier public: ', forge.util.bytesToHex(ByteArrayToForgeBuffer(StdVectorToByteArray(carrier.GetEncodedPublic())).data))
  
  // Create primary key endorsement key from the default template.
  var ek = app.CreatePrimaryEndorsementKey();
  assert(ek.rc == TPM2_RC_SUCCESS, 'CreatePrimary failed');

  // Authorization w/ EK has to use Policy Secret sessions.
  var session = app.StartAuthSession(/*trial=*/false);
  assert(session.rc == TPM2_RC_SUCCESS, 'StartAuthSession failed');

  // Refresh session.
  app.SetSessionHandle(TPM2_RS_PW);
  var rc = app.PolicySecret(TPM2_RH_ENDORSEMENT, session.handle);
  assert(rc == TPM2_RC_SUCCESS, 'PolicySecret failed');
  app.SetSessionHandle(session.handle);

  // Import blob.
  var import_result = app.Import(ek.handle, carrier.GetEncodedPublic(), tag, enc_private, enc_seed)
  assert(import_result.rc == TPM2_RC_SUCCESS, 'Import failed');
  console.log('Imported TPM2B_PRIVATE: ', StdVectorToByteArray(import_result.tpm2b_private));

  // Refresh session.
  app.SetSessionHandle(TPM2_RS_PW);
  var rc = app.PolicySecret(TPM2_RH_ENDORSEMENT, session.handle);
  assert(rc == TPM2_RC_SUCCESS, 'PolicySecret failed');
  app.SetSessionHandle(session.handle);

  // Load imported keyed-hash object.
  var loaded = app.Load(ek.handle, import_result.tpm2b_private, import_result.tpm2b_public)
  assert(loaded.rc == TPM2_RC_SUCCESS, 'Load failed');

  // Unseal sensitive data.
  app.SetSessionHandle(TPM2_RS_PW);
  var unsealed = app.Unseal(loaded.handle);
  assert(unsealed.rc == TPM2_RC_SUCCESS, 'Unseal failed');

  var unsealed_data = ByteArrayToForgeBuffer(unsealed.sensitive_data).data;
  console.log('Unsealed data: ', unsealed_data);
  assert(_.isEqual(unsealed_data, 'super secret stuff'), 'Sensitive data does not match');

  // Unload session and keys.
  assert(app.FlushContext(session.handle) == TPM2_RC_SUCCESS, 'FlushContext failed');
  assert(app.FlushContext(ek.handle) == TPM2_RC_SUCCESS, 'FlushContext failed');
  assert(app.FlushContext(loaded.handle) == TPM2_RC_SUCCESS, 'FlushContext failed');

  console.log('OK');

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.