tpm2-software / tpm2-pytss Goto Github PK
View Code? Open in Web Editor NEWPython bindings for TSS
Home Page: https://tpm2-pytss.readthedocs.io/en/latest/
License: BSD 2-Clause "Simplified" License
Python bindings for TSS
Home Page: https://tpm2-pytss.readthedocs.io/en/latest/
License: BSD 2-Clause "Simplified" License
Looking through the CFFI documentation, it appears that all the pointers coming back are "owned" and are getting released via whatever ffi.new uses or are getting leaked. For example consider this:
def ECC_Parameters(
self,
curveID,
session1=ESYS_TR.NONE,
session2=ESYS_TR.NONE,
session3=ESYS_TR.NONE,
):
parameters = ffi.new("TPMS_ALGORITHM_DETAIL_ECC **")
_chkrc(
lib.Esys_ECC_Parameters(
self.ctx, session1, session2, session3, curveID, parameters
)
)
return TPMS_ALGORITHM_DETAIL_ECC(parameters[0])
parameters is "owned" by ffi.new and will call it's destructor. The question here is who owns the pointer that paramters[0] refers to? How do we ensure that is free'd? If so how do free it with Esys_Free?
I'm not sure so I posted this question to the CFFI group:
It would be useful to get access to the Marshal/Unmarshal API.
For example to generate a policy before signing it using only software.
tpm2-pytss is distributed under the BSD 2 Cluase License.
Fix spelling:
sed -i s/Cluase/Clause/ README.md
It would be useful to get the name NV areas and key objects without a ESAPI context when doing some types of attestation and audit sessions
memset()
sizeof()
for each typetest_auto_session_flags (tests.test_esys_auto_session_flags.TestAutoSessionFlags) ... WARNING:tcti:src/util/io.c:252:socket_connect() Failed to connect to host ::1, port 2322: errno 99: Cannot assign requested address
WARNING:tcti:src/tss2-tcti/tctildr.c:62:tcti_from_init() TCTI init for function 0x7f23d8f15230 failed with a000a
WARNING:tcti:src/tss2-tcti/tctildr.c:92:tcti_from_info() Could not initialize TCTI named: tcti-socket
ERROR:tcti:src/tss2-tcti/tctildr-dl.c:150:tcti_from_file() Could not initialize TCTI file: mssim
ERROR:tcti:src/tss2-tcti/tctildr.c:418:Tss2_TctiLdr_Initialize_Ex() Failed to instantiate TCTI
ERROR
Migrate from the gh-pages branch to readthedocs.org
Add support for tss2_fapi.h / libtss2_fapi.so
@pdxjohnny Do you have some resources for this ?
Make size a read only property. What about count? I could see folks wanted to set count on TPML objects if they go through setattr and modify things in a way the count tracker doesn't get it right.
It would be useful if the TPM2B structures that just has a size and a series of bytes would be bytes-like.
For example, the output from NV_Read is a TPM2B_MAX_NV_BUFFER should behave like a bytes object.
I have cloned the latest revision of tpm2-pytss and the built it using:
python3 setup.py build
I then used the following command to install it:
python3 setup.py install --verbose --prefix=/usr
When I do this I then get an install directory that looks like this:
binding.py
_esys_binding.cpython-36m-x86_64-linux-gnu.so
_esys_binding.py
esys_binding.py
esys.py
exceptions.py
__init__.py
__pycache__
tcti.py
util
version.py
Running the following code
from tpm2_pytss.binding import *
def main():
print("Hello world!")
if __name__ == "__main__":
main()
then results in the ollowing error:
Traceback (most recent call last):
File "main.py", line 2, in <module>
from tpm2_pytss.binding import *
File "/usr/lib64/python3.6/site-packages/tpm2_pytss-0.0.3-py3.6-linux-x86_64.egg/tpm2_pytss/binding.py", line 417, in <module>
TYPEDEFS = typedef_map()
File "/usr/lib64/python3.6/site-packages/tpm2_pytss-0.0.3-py3.6-linux-x86_64.egg/tpm2_pytss/binding.py", line 409, in typedef_map
for line in pkgutil.get_data(__name__.split(".")[0], "swig/tpm2_types.i")
File "/usr/lib64/python3.6/pkgutil.py", line 634, in get_data
return loader.get_data(resource_name)
File "<frozen importlib._bootstrap_external>", line 832, in get_data
FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib64/python3.6/site-packages/tpm2_pytss-0.0.3-py3.6-linux-x86_64.egg/tpm2_pytss/swig/tpm2_types.i'
In order to get things working I had to manually create the swig directory in the installation directory and copy the .i-files into it.
I wonder if this is bug or am I missing something?
Add the System API and test
Hi
I am new to tpm2, especially this python binding. I am stumbled with very limit documents, and then find out it is mission impossible to complete even a very simple task without help.
For example, the above command, how can I translate it to python?
My knowledge currently is:
tcti = TCTI.load('device')
tcti_config = '/dev/tpmrm0'
tcti_ctx = ctx_stack.enter_context(tcti(config=tcti_config, retry=1))
esys = ESYS()
esys_ctx = ctx_stack.enter_context(esys(tcti_ctx))
TR_SetAuth
, is it correct?authValue = TPM2B_AUTH(size=6, buffer=list(b'passwd'))
esys_ctx.TR_SetAuth(ESYS_TR_RH_OWNER, authValue)
esys_ctx.NV_Read(?, ?, ?, ?, ?)
Please shed me some light. Thank you very much!
tpm2-pytss/tests/test_esys_get_time.py
Line 12 in 6065a03
size parameter is unnessicary as it will be calculated from array length
@pdxjohnny I have another question about the FAPI bindings, this time with regard to the parameters. For FAPI calls with char const *
input parameters, a simple python str
can be passed. E.g.
with CHAR_PTR_PTR() as description:
description = self.fapi_ctx.GetDescription(path, description)
However, that does not work when the input parameter is a byte array
with UINT8_PTR_PTR() as keyPath:
with UINT8_PTR() as plaintext:
plaintext = ??? # <--- how to set the plaintext?
with SIZE_T_PTR() as plaintextSize:
with UINT8_PTR_PTR() as cipherText:
with SIZE_T_PTR() as cipherTextSize:
ret = self.fapi_ctx.Encrypt(path, plaintext, plaintextSize, cipherText, cipherTextSize)
This leaves me with two questions:
description
in the first example? Wouldn't it be better to handle these internally?plaintext
in the second example?Thanks in advance!
Unfortunately, there seems to be no mechanism to set the TSS log level at runtime besides via the env variable TSS2_LOG
, e.g. TSS2_LOG=all+ERROR,fapi+TRACE
, as documented here. What do you think of having a function setting this variable, maybe from a dict?
Example:
log_levels = { "all": "error", "tcti": "trace"}
log_levels_str = ",".join(f"{k}+{v}" for k, v in log_levels.items()) # 'all+error,tcti+trace'
os.environ["TSS2_LOG"] = log_levels_str
We might want to use enums instead of strings(?). In case you wonder, modules and log levels are parsed case insensitive.
Complete list of TSS log levels (as defined here):
Complete list of TSS log modules (grepped):
The documentation site doesn't seem to be able to automodule the docs anymore
Implement C->Python callbacks
When I am using tpm2_LoadExternal with a known key I get a name that is:
000b9adccfa3d608ee3601a2bcb2ee29bd45ae6f3de9aa8be44b6379c118c9692217
I then use the same key in the LoadExternal test. I use the following code to print the name of the key
key_name_ptr_ptr = stack.enter_context(TPM2B_NAME_PTR_PTR())
self.esys_ctx.TR_GetName(object_handle, key_name_ptr_ptr)
key_name_ptr = key_name_ptr_ptr.value
key_name = to_bytearray(key_name_ptr.size, key_name_ptr.name)
print(binascii.b2a_hex(key_name))
But I get the following result:
000b3268f9ca3e4af83e2547a933163a700f6580cf90d93abe8fb31afba129d2a682
I was not really sure how to extract the data from key_name_ptr_ptr variable so the error may be that I am doing it incorrectly.
The source tarballs from PyPI tpm2-pytss-0.0.6.tar.gz
and tpm2-pytss-0.1.0.tar.gz
are missing the tpm2_pytss/swig
subdirectory. For version 0.0.5 this has been fixed by 8da58b3 (see #20), and tpm2-pytss-0.0.5.tar.gz
is indeed fine, but apparently something changed again.
Ensure things like #20 don't happen again
Test the release process using https://packaging.python.org/guides/using-testpypi/
Hi,
I just installed the library and wanted to test it with a simple example:
from tpm2_pytss.fapi import FAPI, FAPIDefaultConfig
from tpm2_pytss.binding import *
fapi = FAPI()
fapi.get_random(10)
But I got this error:
Traceback (most recent call last):
File "tpm.py", line 6, in <module>
fapi.get_random(10)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/fapi.py", line 196, in get_random
self.GetRandom(length, datapp)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/context.py", line 78, in wrapper
return custom_wrap(func)(self.ctxp, *args, **kwds)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/context.py", line 112, in wrapper
result = func(self, *args, **kwds)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/util/swig.py", line 173, in wrapper
return func(*args, **kwargs)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/exceptions.py", line 48, in wrapper
rc = func(*args, **kwargs)
File "/home/pa/.local/lib/python3.8/site-packages/tpm2_pytss/fapi_binding.py", line 10790, in Fapi_GetRandom
return _fapi_binding.Fapi_GetRandom(context, numBytes, data)
TypeError: in method 'Fapi_GetRandom', argument 3 of type 'uint8_t **'
Any idea ?
tpm2-pytss/tpm2_pytss/exceptions.py
Line 11 in 6065a03
this will need to change (it's wrong, if r != 0 then this will never get called):
tpm2-pytss/tests/test_esys_get_time.py
Lines 110 to 126 in 6065a03
Exploring cython as an alternative to SWIG
create TPM2B_PUBLIC.fromPEM() and TPM2B_SENSITIVE.fromPEM routines to convert those data types for things like LoadExternal. Also support a fromAES? How do we want to handle symmetric keys? Should we just be able to pass a pem to the existing parse routines?
Apparently Keylime is written in Python and might want to use the bindings? Let's find out how we can help them if so.
https://keylime.dev/blog/2019/04/01/handy-docker-environment.html
Toggling physical presence is needed for testing PolicyPhysicalPresence and PP_Commands, I'm looking into a solution for the IBM simulator, but I'm unsure how to do it for swtpm.
Adding an EK certs with matching EK primary keys and keeping them in the standard NV indices would be useful for testing a standard MakeCredential and ActivateCredential setup as well as EK cert parsing.
Hi, this would be actually very simple. I have this function from fapi:
Sign(keyPath: char const *, padding: char const *, digest: uint8_t const *, digestSize: size_t, signature: uint8_t **, signatureSize: size_t *, publicKey: char **, certificate: char **) โ TSS2_RC
And I am trying to pass arguments to it, specifically the 3rd one (digest):
fapi_ctx.Sign(path_to_key, None, ???, digest_size, sig_holder, None, None, None)
After several hours of trial and error, trying everything from struct.pack(), through ctypes, to simply using several methods and fields in your class tpm2_pytss.binding (using dir()) I still receive this error:
Traceback (most recent call last):
File "lab5.py", line 84, in <module>
sign(ctx, stck, "HS/lab5_key", "qwe123", doc_txt)
File "lab5.py", line 77, in sign
fapi_ctx.Sign(path_to_key, None, digest_pointer, 32, sig_holder, None, None, None)
File "/media/sf_LNX_FILES/SEM2/ZIO/tpm2-pytss/tpm2_pytss/context.py", line 78, in wrapper
return custom_wrap(func)(self.ctxp, *args, **kwds)
File "/media/sf_LNX_FILES/SEM2/ZIO/tpm2-pytss/tpm2_pytss/context.py", line 112, in wrapper
result = func(self, *args, **kwds)
File "/media/sf_LNX_FILES/SEM2/ZIO/tpm2-pytss/tpm2_pytss/util/swig.py", line 173, in wrapper
return func(*args, **kwargs)
File "/media/sf_LNX_FILES/SEM2/ZIO/tpm2-pytss/tpm2_pytss/exceptions.py", line 48, in wrapper
rc = func(*args, **kwargs)
File "/media/sf_LNX_FILES/SEM2/ZIO/tpm2-pytss/tpm2_pytss/fapi_binding.py", line 14997, in Fapi_Sign
return _fapi_binding.Fapi_Sign(context, keyPath, padding, digest, digestSize, signature, signatureSize, publicKey, certificate)
TypeError: in method 'Fapi_Sign', argument 4 of type 'uint8_t const *'
I am not asking for help here, although it would be highly appreciated - instead I would just like to inform you that there is such a case, in which documentation to pytss doesn't help and hours of surfing web does no either. Perhaps there is a room for some improvement that would make passing parameters a little bit simpler for beginners?
Add the feature api and test
The TPM2B structs that are just size + fixed size byte array, such as TPM2B_DIGEST and TPM2B_PUBLIC_KEY_RSA should behave as the python bytes type.
A simple example is doing PCR_Read and then printing the value of each digest in TPML_DIGEST using base64.b16encode without having to convert each entry.
python3.8 -m pip install --user tpm2-pytss
Collecting tpm2-pytss
Using cached https://files.pythonhosted.org/packages/ff/e8/1f8e469ff55bec25b45b520a8155724c339c22d224331d15918f9cf87a0b/tpm2-pytss-0.1.0.tar.gz
Building wheels for collected packages: tpm2-pytss
Building wheel for tpm2-pytss (setup.py) ... error
ERROR: Command errored out with exit status 1:
command: /usr/local/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"'; __file__='"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-2mykngfn --python-tag cp38
cwd: /tmp/pip-install-apmpt5p0/tpm2-pytss/
Complete output (51 lines):
running bdist_wheel
running build
running build_py
file tpm2_pytss.py (for module tpm2_pytss) not found
creating build
creating build/lib.linux-x86_64-3.8
creating build/lib.linux-x86_64-3.8/tests
copying tests/test_tpm2_error.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_fapi_get_random.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_auto_session_flags.py -> build/lib.linux-x86_64-3.8/tests
copying tests/__init__.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_time.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_binding.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_base_test.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_capability.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_audit.py -> build/lib.linux-x86_64-3.8/tests
copying tests/base_esys.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_random.py -> build/lib.linux-x86_64-3.8/tests
creating build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/fapi.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/tcti.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/binding.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/context.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/__init__.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/exceptions.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/esys.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/config.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/version.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
creating build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/simulator.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/__init__.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/swig.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/calculate.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
running egg_info
writing tpm2_pytss.egg-info/PKG-INFO
writing dependency_links to tpm2_pytss.egg-info/dependency_links.txt
writing requirements to tpm2_pytss.egg-info/requires.txt
writing top-level names to tpm2_pytss.egg-info/top_level.txt
file tpm2_pytss.py (for module tpm2_pytss) not found
reading manifest file 'tpm2_pytss.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching 'tpm2_pytss/config.json'
warning: no files found matching '*' under directory 'tpm2_pytss/swig'
writing manifest file 'tpm2_pytss.egg-info/SOURCES.txt'
file tpm2_pytss.py (for module tpm2_pytss) not found
running build_ext
building 'tpm2_pytss._esys_binding' extension
swigging tpm2_pytss/swig/esys_binding.i to tpm2_pytss/swig/esys_binding_wrap.c
swig -python -I/usr/local/include -py3 -outdir tpm2_pytss -o tpm2_pytss/swig/esys_binding_wrap.c tpm2_pytss/swig/esys_binding.i
Unable to find file 'tpm2_pytss/swig/esys_binding.i'.
error: command 'swig' failed with exit status 1
----------------------------------------
ERROR: Failed building wheel for tpm2-pytss
Running setup.py clean for tpm2-pytss
Failed to build tpm2-pytss
Installing collected packages: tpm2-pytss
Running setup.py install for tpm2-pytss ... error
ERROR: Command errored out with exit status 1:
command: /usr/local/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"'; __file__='"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-dz7an7yw/install-record.txt --single-version-externally-managed --compile --user --prefix=
cwd: /tmp/pip-install-apmpt5p0/tpm2-pytss/
Complete output (51 lines):
running install
running build
running build_py
file tpm2_pytss.py (for module tpm2_pytss) not found
creating build
creating build/lib.linux-x86_64-3.8
creating build/lib.linux-x86_64-3.8/tests
copying tests/test_tpm2_error.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_fapi_get_random.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_auto_session_flags.py -> build/lib.linux-x86_64-3.8/tests
copying tests/__init__.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_time.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_binding.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_base_test.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_capability.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_audit.py -> build/lib.linux-x86_64-3.8/tests
copying tests/base_esys.py -> build/lib.linux-x86_64-3.8/tests
copying tests/test_esys_get_random.py -> build/lib.linux-x86_64-3.8/tests
creating build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/fapi.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/tcti.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/binding.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/context.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/__init__.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/exceptions.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/esys.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/config.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
copying tpm2_pytss/version.py -> build/lib.linux-x86_64-3.8/tpm2_pytss
creating build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/simulator.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/__init__.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/swig.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
copying tpm2_pytss/util/calculate.py -> build/lib.linux-x86_64-3.8/tpm2_pytss/util
running egg_info
writing tpm2_pytss.egg-info/PKG-INFO
writing dependency_links to tpm2_pytss.egg-info/dependency_links.txt
writing requirements to tpm2_pytss.egg-info/requires.txt
writing top-level names to tpm2_pytss.egg-info/top_level.txt
file tpm2_pytss.py (for module tpm2_pytss) not found
reading manifest file 'tpm2_pytss.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching 'tpm2_pytss/config.json'
warning: no files found matching '*' under directory 'tpm2_pytss/swig'
writing manifest file 'tpm2_pytss.egg-info/SOURCES.txt'
file tpm2_pytss.py (for module tpm2_pytss) not found
running build_ext
building 'tpm2_pytss._esys_binding' extension
swigging tpm2_pytss/swig/esys_binding.i to tpm2_pytss/swig/esys_binding_wrap.c
swig -python -I/usr/local/include -py3 -outdir tpm2_pytss -o tpm2_pytss/swig/esys_binding_wrap.c tpm2_pytss/swig/esys_binding.i
Unable to find file 'tpm2_pytss/swig/esys_binding.i'.
error: command 'swig' failed with exit status 1
----------------------------------------
ERROR: Command errored out with exit status 1: /usr/local/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"'; __file__='"'"'/tmp/pip-install-apmpt5p0/tpm2-pytss/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-dz7an7yw/install-record.txt --single-version-externally-managed --compile --user --prefix= Check the logs for full command output.
Send an email to [email protected]
You can subscribe to the users mailing list here https://lists.01.org/postorius/lists/tpm2.lists.01.org/
Why is it dffml users and not the tpm2 list?
Hi there, sorry if this is a dumb question, I am quite new to working with TPMs. I followed all of the setup instructions and I can run
python3 setup.py test
with no problems.
However, if I run
python3 fapi_get_random.py 8
I get the following error:
Traceback (most recent call last): File "examples/fapi_get_random.py", line 59, in <module> main() File "examples/fapi_get_random.py", line 48, in main x = fapi_ctx.GetRandom(length) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/context.py", line 78, in wrapper return custom_wrap(func)(self.ctxp, *args, **kwds) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/context.py", line 112, in wrapper result = func(self, *args, **kwds) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/util/swig.py", line 173, in wrapper return func(*args, **kwargs) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/exceptions.py", line 48, in wrapper rc = func(*args, **kwargs) TypeError: Fapi_GetRandom() missing 1 required positional argument: 'data'
I tried adding a "data=[]" and I get
Traceback (most recent call last): File "examples/fapi_get_random.py", line 59, in <module> main() File "examples/fapi_get_random.py", line 48, in main x = fapi_ctx.GetRandom(length, data) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/context.py", line 78, in wrapper return custom_wrap(func)(self.ctxp, *args, **kwds) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/context.py", line 112, in wrapper result = func(self, *args, **kwds) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/util/swig.py", line 173, in wrapper return func(*args, **kwargs) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/exceptions.py", line 48, in wrapper rc = func(*args, **kwargs) File "/home/pi/.local/lib/python3.7/site-packages/tpm2_pytss/fapi_binding.py", line 14865, in Fapi_GetRandom return _fapi_binding.Fapi_GetRandom(context, numBytes, data) TypeError: in method 'Fapi_GetRandom', argument 3 of type 'uint8_t **'
Is there something I'm missing when running the example vs running the tests?
Thanks
When trying to read PCR values I hit the problem that I can't set some arrays.
For example:
from tpm2_pytss.binding import TPML_PCR_SELECTION, TPMS_PCR_SELECTION, TPM2_ALG_SHA256
sel = TPMS_PCR_SELECTION(hash=TPM2_ALG_SHA256, sizeofSelect=3, pcrSelect=(0,0,255))
sels = TPML_PCR_SELECTION(count=1, pcrSelections=(sel,))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/.local/lib/python3.7/site-packages/tpm2_pytss/binding.py", line 126, in __init__
buffer_ptr = ByteArray.frompointer(getattr(self, buffer_prop))
TypeError: in method 'ByteArray_frompointer', argument 1 of type 'BYTE *'
The problem seems to exist for other similar types, such as TPML_DIGEST.
Hello guys,
I am new to using lib tpm2-pytss, and trying to run an example using the Esys_GetRandom function and received the following typeError with 'TPM2B_DIGEST **':
getRandom example code:
import sys
import random
import tempfile
import contextlib
import tpm2_pytss.binding
import tpm2_pytss.context
import tpm2_pytss.esys
import tpm2_pytss.tcti
from tpm2_pytss.binding import *
def main():
# Usage information
if len(sys.argv) != 2:
print("Ouput N random bytes to stdout")
print("Usage:length(between 8 and 32)")
sys.exit(1)
# Number of random bytes to get (between 8 and 32)
length = int(sys.argv[1])
# Input validation
if length < 8 or length > 32:
raise ValueError("length must be between 8 and 32")
ctxpp = tpm2_pytss.esys.ESYSContext.new_ctx_ptr()
print(type(ctxpp))
tcti_ctxpp = tpm2_pytss.binding.ESYSBinding.tcti_ctx_ptr_ptr()
tcti_ctxpp.__enter__()
tcti_ctxp = tcti_ctxpp.value
abi_version = tpm2_pytss.binding.TSS2_ABI_VERSION
ret = tpm2_pytss.binding.Esys_Initialize(ctxpp, tcti_ctxp, None)
ctxp = tpm2_pytss.esys.ESYSContext.ctx_ptr_value(ctxpp)
print(ret)
ans = TPM2B_DIGEST_PTR_PTR()
ret = Esys_GetRandom(ctxp,
tpm2_pytss.binding.ESYSBinding.ESYS_TR_NONE,
tpm2_pytss.binding.ESYSBinding.ESYS_TR_NONE,
tpm2_pytss.binding.ESYSBinding.ESYS_TR_NONE,
length,
ans)
if __name__ == "__main__":
main()
Can someone help me to run this code successfully and / or a way to run an example of getRandom using the functions with prefix "esys_"?
@pdxjohnny I find these bindings really cool! However I do not understand the logic behind what is returned by the FAPI commands.
Example A) Fapi_GetRandom returns a Swig Object of type 'TPMI_YES_NO *'
which can be casted into a ByteArray
which we can iterate over to get the bytes
length = 32
with UINT8_PTR_PTR() as random_uin8_ptr_ptr:
random_swig = fapi_ctx.GetRandom(length, random_uin8_ptr_ptr)
random_ByteArray = ByteArray.frompointer(random_swig)
random_bytearray = bytearray(length)
for i in range(0, length):
random_bytearray[i] = random_ByteArray[i]
print(random_bytearray)
Example B) Fapi_GetInfo returns a dict
with CHAR_PTR_PTR() as info:
cap = fapi_ctx.GetInfo(info)
print(cap['capabilities'][1])
Example C) Fapi_List returns an int
with CHAR_PTR_PTR() as info:
x = fapi_ctx.List("", info)
print(x)
How can I access the actual list? I tried print(CHAR_PTR.frompointer(x).value)
but gives me a segmentation fault. Is the int
returned the TPM return code or something else?
And more generally: Is the return code of Fapi commands documented somewhere?
Being able to create at least some type of objects (such as TPM2B_PUBLIC or TPM2B_NV_PUBLIC) from a dict could be an useful feature for users of the API.
By using dicts directly we can leave the (de)serialization part to the caller instead of enforcing a specific format such as JSON.
One use case that I have is that I want to create a NV counter on a remote system using ansible.
As ansible is a heavy user of YAML, so I want to define the NV area using an YAML hash, later on I want to do a audit session to attest the current counter value and therefor want to reuse the same YAML hash for generating the name locally to verify the audi session.
Hi, I am new with tpm2-pytss. I have a Raspberry pi with a TPM2.0 chip with it and I am able to run all the TPM2.0 commands by using the IBM library https://sourceforge.net/p/ibmtpm20tss/tss/ci/master/tree/demo/. But after I installed tpm2-pytss on it and tried running the GET_RANDOM test, it always give me the PERMISSION_ERROR like below:
Traceback (most recent call last):
File "test_py3.py", line 58, in <module>
main()
File "test_py3.py", line 26, in main
simulator = ctx_stack.enter_context(Simulator())
File "/usr/lib/python3.5/contextlib.py", line 307, in enter_context
result = _cm_type.__enter__(cm)
File "/home/pi/.local/lib/python3.5/site-packages/tpm2_pytss/util/simulator.py", line 128, in __enter__
self.start()
File "/home/pi/.local/lib/python3.5/site-packages/tpm2_pytss/util/simulator.py", line 101, in start
stderr=subprocess.PIPE,
File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1282, in _execute_child
raise child_exception_type(errno_num, err_msg)
PermissionError: [Errno 13] Permission denied
test_py3.py
import sys
import random
import tempfile
import contextlib
from tpm2_pytss.fapi import FAPI, FAPIDefaultConfig
from tpm2_pytss.binding import *
from tpm2_pytss.util.simulator import Simulator
def main():
# Usage information
if len(sys.argv) != 2:
print("Ouput N random bytes to stdout", file=sys.stderr)
print("", file=sys.stderr)
print("Usage: {sys.argv[0]} length(between 8 and 32)", file=sys.stderr)
sys.exit(1)
# Number of random bytes to get (between 8 and 32)
length = int(sys.argv[1])
# Input validation
if length < 8 or length > 32:
raise ValueError("length must be between 8 and 32")
# Create a context stack
with contextlib.ExitStack() as ctx_stack:
# Create a simulator
simulator = ctx_stack.enter_context(Simulator())
# Create temporary directories to separate this example's state
user_dir = ctx_stack.enter_context(tempfile.TemporaryDirectory())
log_dir = ctx_stack.enter_context(tempfile.TemporaryDirectory())
system_dir = ctx_stack.enter_context(tempfile.TemporaryDirectory())
# Create the FAPI object
fapi = FAPI(
FAPIDefaultConfig._replace(
user_dir=user_dir,
system_dir=system_dir,
log_dir=log_dir,
tcti="mssim:port=%d" % (simulator.port,),
tcti_retry=100,
ek_cert_less=1,
)
)
# Enter the context, create TCTI connection
fapi_ctx = ctx_stack.enter_context(fapi)
# Call Fapi_Provision
fapi_ctx.Provision(None, None, None)
# Create a pointer to the byte array we'll get back from GetRandom
array = ctx_stack.enter_context(UINT8_PTR_PTR())
# Call GetRandom and convert the resulting array to a Python bytearray
value = to_bytearray(length, fapi_ctx.GetRandom(length, array))
# Ensure we got the correct number of bytes
if length != len(value):
raise AssertionError("Requested %d bytes, got %d" % (length, len(value)))
# Print bytes to stdout
sys.stdout.buffer.write(value)
if __name__ == "__main__":
main()
I did copy the latest tmp_server to my $path, which is /usr/local/bin
Do you have any clues about it?
Thanks,
Iven
Make RC an object you can retrieve from the exception that allows you to access the various fields within the RC. Most people looking at an RC care about the actual error field, and don't really care if its parameter 1 or 2, they have to mask all that crap out to figure out what actually went wrong.
I have installed pytss using pip from the master branch. I'm trying to run a simple example. I'm getting a module import error like below.
>>> from tpm2_pytss.binding import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/pytss/tpm2-pytss/tpm2_pytss/binding.py", line 9, in <module>
from . import exceptions
File "/pytss/tpm2-pytss/tpm2_pytss/exceptions.py", line 7, in <module>
from .esys_binding import (
ModuleNotFoundError: No module named 'tpm2_pytss.esys_binding'
Check params before we call the esapi library so we can give better errors than something like: TypeError: expected integer.
I was trying to write a test for esys load external. But I could not even get the simplest test case to work.
import os
import secrets
from contextlib import ExitStack
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from tpm2_pytss.binding import *
from .base_esys import BaseTestESYS
class TestLoadExternal(BaseTestESYS):
def test_load_public_rsa_key(self):
# The tpm2-tools equivalent of what this tests is attempting to do is
# the following:
# tpm2_loadexternal
# --hierarchy=o
# --key-algorithm=rsa
# --public=public_rsa_key.pem
# --key-context=signing_key.ctx
# --name=signing_key.name
# Create the 2048 bit RSA key.
private_rsa_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_rsa_key = private_rsa_key.public_key()
with ExitStack() as stack:
# Create the public part.
in_public = TPM2B_PUBLIC(
size=0,
publicArea=TPMT_PUBLIC(
type=TPM2_ALG_RSA, # key-algorithm=rsa
nameAlg=TPM2_ALG_SHA256, # hash-algorithm = default = sha256
objectAttributes=(
TPMA_OBJECT_NODA
| TPMA_OBJECT_DECRYPT
| TPMA_OBJECT_SIGN_ENCRYPT
| TPMA_OBJECT_USERWITHAUTH
),
authPolicy=TPM2B_DIGEST(size=0),
parameters=TPMU_PUBLIC_PARMS(
rsaDetail=TPMS_RSA_PARMS(
scheme=TPMT_RSA_SCHEME(
scheme=TPM2_ALG_NULL,
details=TPMU_ASYM_SCHEME(
anySig=TPMS_SCHEME_HASH(
hashAlg=TPM2_ALG_NULL,
),
),
),
symmetric=TPMT_SYM_DEF_OBJECT(
algorithm=TPM2_ALG_NULL,
keyBits=TPMU_SYM_KEY_BITS(sym=0),
mode=TPMU_SYM_MODE(sym=TPM2_ALG_NULL),
),
keyBits=public_rsa_key.key_size, # Number of bits in the key 2048
exponent=public_rsa_key.public_numbers().e, # exponent of the key 65537
),
),
unique=TPM2B_PUBLIC_KEY_RSA(
# public part of rsa key.
buffer=public_rsa_key.public_numbers().n.to_bytes(public_rsa_key.key_size // 8, byteorder=sys.byteorder)
),
),
)
in_public_ptr = stack.enter_context(in_public.ptr())
object_handle = stack.enter_context(self.esys_ctx.flush_tr())
self.esys_ctx.LoadExternal(
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
None,
in_public_ptr,
ESYS_TR_RH_OWNER,
object_handle
)
# Get name from the object_handle and compare it to the public key.
# If there is a difference throw an exception.
When I run this test I get following error message. I run this directly at the device.I have tested this with a key that works for tpm2-tools by using a code that is slightly different and it does not matter the test still fails. So is pytss doing something wierd with my parameters?
"TPM2 Error tpm:parameter(2):key fields are not compatible with the selected use"
Add the TCTI API
Support a method on TPM2B_SENSITIVE to convert it to a TPM2B_PRIVATE capable for a call to Import ala what the tpm2-tools does:
Arguments present in _Finish
versions of functions are output arguments
When building this project with SWIG 4 (version 4.0.1-1 on Arch Linux), running the tests fails with
File "/home/jonas/tpm2-software/tpm2-pytss/tpm2_pytss/exceptions.py", line 8, in <module>
from . import esys_binding
File "/home/jonas/tpm2-software/tpm2-pytss/tpm2_pytss/esys_binding.py", line 413, in <module>
class TPMS_TAGGED_PROPERTY(object):
File "/home/jonas/tpm2-software/tpm2-pytss/tpm2_pytss/esys_binding.py", line 417, in TPMS_TAGGED_PROPERTY
value = property(_esys_binding.TPMS_TAGGED_PROPERTY_value_get, _esys_binding.TPMS_TAGGED_PROPERTY_value_set)
TypeError: 'property' object is not callable
This might actually be a bug in SWIG since it seems to overwrite its internal property()
function with the class attribute property
:
class TPMS_TAGGED_PROPERTY(object):
thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
__repr__ = _swig_repr
property = property(_esys_binding.TPMS_TAGGED_PROPERTY_property_get, _esys_binding.TPMS_TAGGED_PROPERTY_property_set)
value = property(_esys_binding.TPMS_TAGGED_PROPERTY_value_get, _esys_binding.TPMS_TAGGED_PROPERTY_value_set)
But even if the autogenerated esys_binding.py
file is fixed manually, there are lots of other errors, e.g.
======================================================================
ERROR: test_audit (tests.test_esys_audit.TestAudit)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jonas/tpm2-software/tpm2-pytss/tests/base_esys.py", line 28, in setUp
self.tcti_ctx = self.ctx_stack.enter_context(self.tcti(config=self.tcti_config))
File "/usr/lib/python3.7/contextlib.py", line 427, in enter_context
result = _cm_type.__enter__(cm)
File "/home/jonas/tpm2-software/tpm2-pytss/tpm2_pytss/tcti.py", line 34, in __enter__
ctxpp.__enter__()
File "/home/jonas/tpm2-software/tpm2-pytss/tpm2_pytss/util/swig.py", line 162, in __enter__
self.ptr = self._new()
TypeError: new_tcti_ctx_ptr_ptr() takes 0 positional arguments but 1 was given
The reason for this error seems to be that in SWIG 3, new_tcti_ctx_ptr_ptr
is defined as
def new_tcti_ctx_ptr_ptr() -> "struct TSS2_TCTI_CONTEXT **":
return _esys_binding.new_tcti_ctx_ptr_ptr()
new_tcti_ctx_ptr_ptr = _esys_binding.new_tcti_ctx_ptr_ptr
while in SWIG 4 the last line is missing. I guess tpm2_pytss/util/swig.py
needs to be adapted to work with SWIG 4.
Installing the legacy version swig3 and adding self.swig = "swig-3"
before super().run()
in setup.py
causes the test suite to run successfully on Arch Linux.
I was able to dump what its failing on (see below). It appears to be reading docutils.sty. I noticed sphinx is now version 3.5.3 which was updated on March 20. I wonder what happens if we specify an older version.
BILL: b'%% docutils.sty: macros for Docutils LaTeX output.\n%%\n%% Copyright \xc2\xa9 2020 G\xc3\xbcnter Milde\n%% Released under the terms of the `2-Clause BSD license`, in short:\n%%\n%% Copying and distribution of this file, with or without modification,\n%% are permitted in any medium without royalty provided the copyright\n%% notice and this notice are preserved.\n%% This file is offered as-is, without any warranty.\n\n% .. include:: README.md\n%\n% Implementation\n% ==============\n%\n% ::\n\n\\NeedsTeXFormat{LaTeX2e}\n\\ProvidesPackage{docutils}\n [2020/08/28 macros for Docutils LaTeX output]\n\n% Helpers\n% -------\n%\n% duclass::\n\n% class handling for environments (block-level elements)\n% \\begin{DUclass}{spam} tries \\DUCLASSspam and\n% \\end{DUclass}{spam} tries \\endDUCLASSspam\n\\ifx\\DUclass\\undefined % poor man\'s "provideenvironment"\n \\newenvironment{DUclass}[1]%\n {% "#1" does not work in end-part of environment.\n \\def\\DocutilsClassFunctionName{DUCLASS#1}\n \\csname \\DocutilsClassFunctionName \\endcsname}%\n {\\csname end\\DocutilsClassFunctionName \\endcsname}%\n\\fi\n\n% providelength::\n\n% Provide a length variable and set default, if it is new\n\\providecommand*{\\DUprovidelength}[2]{\n \\ifthenelse{\\isundefined{#1}}{\\newlength{#1}\\setlength{#1}{#2}}{}\n}\n\n\n% Configuration defaults\n% ----------------------\n%\n% See `Docutils LaTeX Writer`_ for details.\n%\n% abstract::\n\n\\providecommand*{\\DUCLASSabstract}{\n \\renewcommand{\\DUtitle}[1]{\\centerline{\\textbf{##1}}}\n}\n\n% dedication::\n\n% special topic for dedications\n\\providecommand*{\\DUCLASSdedication}{%\n \\renewenvironment{quote}{\\begin{center}}{\\end{center}}%\n}\n\n% TODO: add \\em to set dedication text in italics?\n%\n% docinfo::\n\n% width of docinfo table\n\\DUprovidelength{\\DUdocinfowidth}{0.9\\linewidth}\n\n% error::\n\n\\providecommand*{\\DUCLASSerror}{\\color{red}}\n\n% highlight_rules::\n\n% basic code highlight:\n\\providecommand*\\DUrolecomment[1]{\\textcolor[rgb]{0.40,0.40,0.40}{#1}}\n\\providecommand*\\DUroledeleted[1]{\\textcolor[rgb]{0.40,0.40,0.40}{#1}}\n\\providecommand*\\DUrolekeyword[1]{\\textbf{#1}}\n\\providecommand*\\DUrolestring[1]{\\textit{#1}}\n\n% Elements\n% --------\n%\n% Definitions for unknown or to-be-configured Docutils elements.\n%\n% admonition::\n\n% admonition environment (specially marked topic)\n\\ifx\\DUadmonition\\undefined % poor man\'s "provideenvironment"\n \\newbox{\\DUadmonitionbox}\n \\newenvironment{DUadmonition}%\n {\\begin{center}\n \\begin{lrbox}{\\DUadmonitionbox}\n \\begin{minipage}{0.9\\linewidth}\n }%\n { \\end{minipage}\n \\end{lrbox}\n \\fbox{\\usebox{\\DUadmonitionbox}}\n \\end{center}\n }\n\\fi\n\n% fieldlist::\n\n% field list environment (for separate configuration of `field lists`)\n\\ifthenelse{\\isundefined{\\DUfieldlist}}{\n \\newenvironment{DUfieldlist}%\n {\\quote\\description}\n {\\enddescription\\endquote}\n}{}\n\n% footnotes::\n\n% numerical or symbol footnotes with hyperlinks and backlinks\n\\providecommand*{\\DUfootnotemark}[3]{%\n \\raisebox{1em}{\\hypertarget{#1}{}}%\n \\hyperlink{#2}{\\textsuperscript{#3}}%\n}\n\\providecommand{\\DUfootnotetext}[4]{%\n \\begingroup%\n \\renewcommand{\\thefootnote}{%\n \\protect\\raisebox{1em}{\\protect\\hypertarget{#1}{}}%\n \\protect\\hyperlink{#2}{#3}}%\n \\footnotetext{#4}%\n \\endgroup%\n}\n\n% inline::\n\n% custom inline roles: \\DUrole{#1}{#2} tries \\DUrole#1{#2}\n\\providecommand*{\\DUrole}[2]{%\n \\ifcsname DUrole#1\\endcsname%\n \\csname DUrole#1\\endcsname{#2}%\n \\else%\n #2%\n \\fi%\n}\n\n% legend::\n\n% legend environment (in figures and formal tables)\n\\ifthenelse{\\isundefined{\\DUlegend}}{\n \\newenvironment{DUlegend}{\\small}{}\n}{}\n\n% lineblock::\n\n% line block environment\n\\DUprovidelength{\\DUlineblockindent}{2.5em}\n\\ifthenelse{\\isundefined{\\DUlineblock}}{\n \\newenvironment{DUlineblock}[1]{%\n \\list{}{\\setlength{\\partopsep}{\\parskip}\n \\addtolength{\\partopsep}{\\baselineskip}\n \\setlength{\\topsep}{0pt}\n \\setlength{\\itemsep}{0.15\\baselineskip}\n \\setlength{\\parsep}{0pt}\n \\setlength{\\leftmargin}{#1}}\n \\raggedright\n }\n {\\endlist}\n}{}\n\n% optionlist::\n\n% list of command line options\n\\providecommand*{\\DUoptionlistlabel}[1]{\\bfseries #1 \\hfill}\n\\DUprovidelength{\\DUoptionlistindent}{3cm}\n\\ifthenelse{\\isundefined{\\DUoptionlist}}{\n \\newenvironment{DUoptionlist}{%\n \\list{}{\\setlength{\\labelwidth}{\\DUoptionlistindent}\n \\setlength{\\rightmargin}{1cm}\n \\setlength{\\leftmargin}{\\rightmargin}\n \\addtolength{\\leftmargin}{\\labelwidth}\n \\addtolength{\\leftmargin}{\\labelsep}\n \\renewcommand{\\makelabel}{\\DUoptionlistlabel}}\n }\n {\\endlist}\n}{}\n\n% rubric::\n\n% informal heading\n\\providecommand*{\\DUrubric}[1]{\\subsubsection*{\\emph{#1}}}\n\n% sidebar::\n\n% text outside the main text flow\n\\providecommand{\\DUsidebar}[1]{%\n \\begin{center}\n \\colorbox[gray]{0.80}{\\parbox{0.9\\linewidth}{#1}}\n \\end{center}\n}\n\n% title::\n\n% title for topics, admonitions, unsupported section levels, and sidebar\n\\providecommand*{\\DUtitle}[1]{\\subsubsection*{#1}}\n\n% subtitle::\n\n% subtitle (for sidebar)\n\\providecommand*{\\DUsubtitle}[1]{\\par\\emph{#1}\\smallskip}\n\n% documentsubtitle::\n\n% subtitle (in document title)\n\\providecommand*{\\DUdocumentsubtitle}[1]{{\\large #1}}\n\n% titlereference::\n\n% titlereference standard role\n\\providecommand*{\\DUroletitlereference}[1]{\\textsl{#1}}\n\n% transition::\n\n% transition (break / fancybreak / anonymous section)\n\\providecommand*{\\DUtransition}{%\n \\hspace*{\\fill}\\hrulefill\\hspace*{\\fill}\n \\vskip 0.5\\baselineskip\n}\n'
It would be useful if all the TPML types could iterable and perhaps indexable.
A good example is getting all the digests from a call to PCR_Read.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.