parallaxsecond / rust-tss-esapi

TSS 2.0 Enhanced System API (ESAPI) Rust wrapper
https://docs.rs/tss-esapi/
Apache License 2.0
87 stars 51 forks source link

Windows TCTI/TBS support #421

Open onlythisnamewasfree opened 1 year ago

onlythisnamewasfree commented 1 year ago

I was wondering how this crate would also work on Windows platforms. I found:

The official tpm2-tss project https://github.com/tpm2-software/tpm2-tss contains a tcti-tbs.c driver and the included INSTALL mentions Windows in one paragraph (the description does not sound enthusiastic). The project indeed does compile to DLLs on Windows (the included VS solutions seems a bit outdated and needs some tweaks). I have no knowledge if it is feasible to compile it (easier?) without VS (e.g. under WSL with a Makefile?)

This crate generates the TSS bindings for 4 platforms: aarch64-unknown-linux-gnu, arm-unknown-linux-gnueabi, x86_64-unknown-darwin and x86_64-unknown-linux.gnu, so no Windows bindings, and does not implement Windows TBS as connection option.

Q: What is missing for this crate to work on Windows, too? 1) Generate the necessary bindings? 2) Implement the TBS connection/configuration option?

...or are there some fundamental issues/structures to implement/rework to make this work?

Superhepper commented 1 year ago

When I do development I use WSL on windows. So that works. Well I have never tried it with a real tpm in WSL don't know if the TPM seen in the WSL might just be a virtual one.

I think the points that you stated are correct those are the basic things needed in order to for this to work on windows. If I am not mistaken some of the APIs that might be blocked on windows that might cause some additional problems. https://github.com/parallaxsecond/rust-tss-esapi/issues/169

onlythisnamewasfree commented 1 year ago

Since Windows 7(?) a TPM is managed by TPM Base Services (TBS) https://learn.microsoft.com/en-us/windows/win32/tbs/tpm-base-services-portal - which coordinates applications' access to the TPM. One never gets direct TPM access?

On Linux one can access /dev/tpm0 directly, and with V2 now the /dev/tpmrm0 service multiplexes applications. I have not found a similar service for Windows, so I suspect the TBS does what tpmrm0 does on Linux? It would make sense that some commands don't work therefor on Windows.

Still, Rust is very portable, high-level TPM code should be portable, only the above mentioned low-level plumbing to attach to TBS is missing? Unfortunately, I don't run Windows and have no Win development experience - but it would be nice to just recompile and have a Windows binary for friends/colleagues that do. Hm.....

Superhepper commented 1 year ago

Yes, the TBS on windows is some kind of resource access manager. I think it serves the role that arbmd had before it was possible to multiplex access to the TPM device on linux. So if you could use some kind of TCTI based on TBS it should probably work.

onlythisnamewasfree commented 1 year ago

don't know if the TPM seen in the WSL might just be a virtual one

Would you mind to check whether WSDL uses the hardware tpm? For example run "tpm2_getcap properties-fixed" from the tpm tools and check manufacturer/vendor properties, and then compare to the TPM reported in Windows itself (Windows Security -> Device Security -> Security Processor)

Superhepper commented 1 year ago

Would you mind to check whether WSDL uses the hardware tpm? For example run "tpm2_getcap properties-fixed" from the tpm tools and check manufacturer/vendor properties, and then compare to the TPM reported in Windows itself (Windows Security -> Device Security -> Security Processor)

The computer I use is so old that it does not have a physical TPM. Not even a 1.2 one.

ionut-arm commented 1 year ago

I'd like to help and might try to tackle this in the future if no one's done it by then, but I have limited bandwidth for now. I'd be more than glad to accept a patch if someone can share a proof of concept, could try it out on my PC.

Will try out the TPM2 tools idea from WSL, I'll let you know how that goes when I get to it :)

onlythisnamewasfree commented 1 year ago

As Rust code is very portable, it would be nice to have Rust code that uses the TPM under Linux, and also work the same under Windows. By my first investigation this looks quite possible, if the missing bindings/config are filled-in. Although the official C-based TSS does seem to be less loved on Windows (see their README: "Windows dlls built [...] are currently prototypes").

Unfortunately, I don't have a Windows machine (borrowed one for testing) or Windows dev experience... (hmm... maybe use a Win VM?)

Superhepper commented 1 year ago

I tried to build the lib natively on a windows machine. It did not work I got the following error:

error: failed to run custom build command for `tss-esapi-sys v0.4.0 (C:\Users\jag_h\workspace\rust-tss-esapi\tss-esapi-sys)`

Caused by:
  process didn't exit successfully: `C:\Users\jag_h\workspace\rust-tss-esapi\target\debug\build\tss-esapi-sys-babf86740179bba7\build-script-build` (exit code: 101)
  --- stderr
  thread 'main' panicked at 'Compilation target (architecture, OS) tuple (x86_64, windows) is not part of the supported tuples. Please compile with the "generate-bindings" feature or add support for your platform :)', tss-esapi-sys\build.rs:35:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...

But it is interesting to see how much tinkering it will require to get it to build properly.

onlythisnamewasfree commented 1 year ago

I tried to build the lib natively on a windows machine. It did not work

That is expected, see my first post, the windows targets are not implemented.

However, the more interesting question is which route is easiest to get something running? x86_64-pc-windows-msvc is the target using the official TSS DLLs built with VS, using the included VS solution. But there is also x86_64-pc-windows-gnu, which should be closer to the Linux Way and maybe less work to get running, filling in the missing pieces?

Superhepper commented 1 year ago

Not sure. This was just me trying to get the build chain up on windows and see what would happen. I will have to look into how to generate bindings next when I have the time.

Superhepper commented 1 year ago

Right now I built the tpm2-tss(4.0.1) using Visual Studio 2022 on Windows 11. It required some minor modifications:

  1. Change the #include <unistd.h> to #include <stdint.h> (src/tss2-tcti/tcti-mssim.c)
  2. Cast tcti_mssim->tpm_sock to a proper pointer value, not sure if this will work though. (src/tss2-tcti/tcti-mssim.c)
  3. Make all projects target a the available windows SDK. ( I Used 10.0 latests)
  4. Change toolchain to LLVM (clang-cl).
  5. Download and install OpenSSL SDK. I chosed a packaged version from https://slproweb.com/products/Win32OpenSSL.html. The .sln file assumes this is installed to "C:\OpenSSL-v11-Win64\" if you do not have installed it there you need to modify the include dir paths and library paths in the tss2-esys.vcxproj.
onlythisnamewasfree commented 1 year ago

When I tried (see in my first post: "the included VS solutions seems a bit outdated and needs some tweaks"), I used current git snapshot and had to do 3-5, but I not 1-2 as far as I remember. Hm... probably current git already fixed this?

Superhepper commented 1 year ago

I am not sure why I had to do all that but it did not matter to because what I was more intressted in was to try to modify the build.rs in the sys crate in order to recognise the header files on windows. Without pkg I was struggling with how to pass version values. Because no version information is built into the lib or dll files.

yafetgetachew commented 11 months ago

Hey guys, are the windows targets implemented yet?

Superhepper commented 11 months ago

No, I have written a little bit of code to try to get it running. But it is experimental in tpm2-tss and my code is not really working yet.

Superhepper commented 11 months ago

So this is my progress so far:

  1. I used this PR to build tpm2-tss

  2. Download and install OpenSSL SDK. I chosed a packaged version from https://slproweb.com/products/Win32OpenSSL.html.

  3. I an installation directory that looked like this: | -> tpm2-tss-Win64 | -> include | -> tss2 | -> ...... | -> lib | -> ..... | ->VERSION The version file is not generated by the solution but if you read my comment in the CR you can see how you can fix that or just add the file manually to the folder.

  4. I used my very experimental win-build branch

  5. I ran the following command:

    • The lib clang path can either be the one in visual studio or you can download LLVM.
    • The tpm2 tss path needs to be set the install directory.

    LIBCLANG_PATH="<Path to the llvm bin folder> "TPM2_TSS_PATH="<Path to the install directory>" cargo build --features=generate-bindings

    So for me this looked something like:

    LIBCLANG_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin" TPM2_TSS_PATH="C:\Program Files\tpm2-tss-Win64" cargo build --features=generate-bindings

    Unfortunately this resulted in bindgen generating a lot of stuff that rust could not build. So that is something I will look into another time.

Superhepper commented 10 months ago

I need to get this in #471 then I might have something that actually builds. But I have no idea how to test it. Does any one know how to use the Microsoft simulator?

Superhepper commented 10 months ago

I have incorporated the latest changes so it now builds under windows. But I have no idea how to test it under windows so if any one have any ideas please provide them so I can see if I can setup some kind of CI for it.

Superhepper commented 5 months ago

477 has been merged.

and #523 is almost done I think which will make it a lot easier to build this crate under windows.

Unfortunately we still have #518 issue open. I would not claim that we would officially be supporting windows without it.

sathibault commented 4 months ago

I'm trying to build this on Windows following the comments above. I addition to LIBCLANG_PATH, I also had to define BINDGEN_EXTRA_CLANG_ARGS with additional -isystem paths for all the system header files. It didn't seem to find them on there own.

The clang call seems to pass now, but I'm getting a fatal error from bindgen:

  --- stdout
  cargo:rustc-link-search=native=D:/grokit/ext/tpm2-tss\lib
  cargo:rustc-link-lib=tss2-sys
  cargo:rustc-link-lib=tss2-esys
  cargo:version=4.1.0

  cargo:rustc-link-lib=tss2-tctildr
  cargo:rustc-link-lib=tss2-mu
  cargo:rustc-link-lib=tss2-tcti-tbs

  --- stderr
  thread 'main' panicked at C:\Users\thiba\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\codegen\mod.rs:717:71:
  called `Result::unwrap()` on an `Err` value: FromBytesWithNulError { kind: InteriorNul(1) }
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

(I'm building with main branch of this repo)

Any thoughts about this error?

Superhepper commented 4 months ago

What feature flags are you using when building?

sathibault commented 4 months ago

What feature flags are you using when building?

tss-esapi = {git = "https://github.com/parallaxsecond/rust-tss-esapi.git", features=["generate-bindings"] }

Superhepper commented 4 months ago

Did you build it using powershell or what shell did you use? And how did your build command look like?

Superhepper commented 4 months ago

With powershell I did like this:

PS C:\workspace\rust-tss-esapi> $Env:LIBCLANG_PATH = "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin"
PS C:\workspace\rust-tss-esapi> $Env:TPM2_TSS_PATH = "C:\Program Files\tpm2-tss-Win64"
PS C:\workspace\rust-tss-esapi> cargo build --features=generate-bindings

<C:\Program Files\tpm2-tss-Win64> = The directory where I manually setup the tpm2-tss installation.

And the latest from master builds fine for me. Windows 11 rustc 1.73.0 cargo 1.73.0

sathibault commented 4 months ago

With powershell I did like this:

PS C:\workspace\rust-tss-esapi> $Env:LIBCLANG_PATH = "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin"
PS C:\workspace\rust-tss-esapi> $Env:TPM2_TSS_PATH = "C:\Program Files\tpm2-tss-Win64"
PS C:\workspace\rust-tss-esapi> cargo build --features=generate-bindings

<C:\Program Files\tpm2-tss-Win64> = The directory where I manually setup the tpm2-tss installation.

And the latest from master builds fine for me. Windows 11 rustc 1.73.0 cargo 1.73.0

This is not working for me. How did you install tpm2-tss? Is it a binary install? What version? (I built tpm2-tss from master since the PR you mentioned above was merged).

Superhepper commented 4 months ago

So the tpm2-tss-Win64 (can be named anything) needs to be setup in a very specific way. You need to build all the binaries locally. And then manually move them into this directory.

I realize that my first description might not have been so easy to understand.

This is how the directory should look like.

├── tpm2-tss-Win64
│   ├── include
│   │   ├── tss2
│   │       ├── tss2_*.h
│   ├── lib
│   │   ├── tss2-*.lib
│   │   ├── tss2-*.dll
│   │   ├── tss2-*.pdb
│   └── VERSION
sathibault commented 4 months ago
│   │   ├── tss2

Yes, I had done that properly. I've tried to match your setup. So I have: Visual Studio 2022 with Clang tools tpm2-tss/master rust-tss-esapi/main Developer PowerShell for Visual Studio 2022

Without adding any extra include path, my result was:

  Unable to generate bindings to TSS2 ESYS APIs.: ClangDiagnostic("C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.19041.0\\\\um/windows.h:167:10: fatal error: 'excpt.h' file not found\n")

I then added an extra include path:

$Env:BINDGEN_EXTRA_CLANG_ARGS = '"-isystemC:/Program Files/Microsoft Visual Studio/2022/Professional/SDK/ScopeCppSDK/vc15/VC/include"'

With that my result is:

  thread 'main' panicked at C:\Users\thiba\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\codegen\mod.rs:717:71:
  called `Result::unwrap()` on an `Err` value: FromBytesWithNulError { kind: InteriorNul(1) }
Superhepper commented 4 months ago

When I am trying to use tpm2-tss master I get the same error.

I updated bindgen to 0.69.4. And now it builds fine.

sathibault commented 4 months ago

When I am trying to use tpm2-tss master I get the same error.

I updated bindgen to 0.69.4. And now it builds fine.

Confirmed, it is working for me as well with that change. Thank you!

onlythisnamewasfree commented 1 month ago

Reading through this bug (and related bugs) some seem to have succeeded, however I havn't figured it out myself yet. I have C:\OpenSSL-v11-Win64, with VS2022Community and a git checkout of tpm2-tss I successfully generated tpm2-tss/x64/Debug, which contains the 7 tss2-*.dll/.lib./pdb files. I also have a Rust project open in VSCodium, it uses tss-esapi 7.5.1 and the hardware TPM under Linux just fine.

Now... how do I build this project under native Windows, generate the tss-esapi-sys bindings and use the HW TPM? In a current git checkout of tss-esapi-sys I see no signs of Windows support - yet?

Thank you!

Superhepper commented 1 month ago

Currently there is no released version tss-esapi that can build natively on Windows. So you will have to use master if you want to try it out.

nicolaspernoud commented 3 weeks ago

Hello, I managed to build on windows, but as I understand, there is now way for now to bind to the physical TPM ? Or what would be the windows equivalent of :

    let context = Context::new(
        TctiNameConf::from_environment_variable()
            .expect("Failed to get TCTI / TPM2TOOLS_TCTI from environment. Try `export TCTI=device:/dev/tpmrm0`"),
    )
    .expect("Failed to create Context");
Superhepper commented 3 weeks ago

On windows you have to use the TBS TCTI. And you are right it seems as it has not been added. And that is being added https://github.com/parallaxsecond/rust-tss-esapi/pull/523.

nicolaspernoud commented 3 weeks ago

Good new, I hope that #523 will be merged soon !