!7 package init
From: @wujiangtao_cn Reviewed-by: @wangyoukang Signed-off-by: @wangyoukang
This commit is contained in:
commit
4da22d833c
57
CHANGELOG.md
57
CHANGELOG.md
@ -1,57 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [1.2.0] - 2023-01-09
|
|
||||||
### Fixed
|
|
||||||
- Updated minimal version of tpm2-tss to 2.4.x
|
|
||||||
- Fix encoding of emptyauth
|
|
||||||
- Fix some memory leaks
|
|
||||||
- Parent handle issues with signed representation by switching parent handle to BIGNUM.
|
|
||||||
- Fixed RSA_NO_PADDING modes with OpenSSL 1.1.1
|
|
||||||
- Fixed autogen (bootstrap) call from release package by embedding VERSION file.
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Use of restricted keys for signing
|
|
||||||
- StirRandom
|
|
||||||
- Run tests using swtpm
|
|
||||||
- The ability to import key blobs from things like the tpm2-tools project.
|
|
||||||
- Compatibility with openssl >=1.1.x
|
|
||||||
- Support for ECDH
|
|
||||||
- QNX support.
|
|
||||||
- Only set -Werror for non-release builds.
|
|
||||||
- Additional checks on TPM responses
|
|
||||||
- CODE_OF_CONDUCT
|
|
||||||
- SECURITY reporting instructions
|
|
||||||
|
|
||||||
## [1.1.0] - 2020-11-20
|
|
||||||
### Added
|
|
||||||
- Configure option for ptpm tests
|
|
||||||
- Configure script AX_CHECK_ENABLE_DEBUG
|
|
||||||
- Option for setting tcti on executable
|
|
||||||
- TCTI-env variable used by default
|
|
||||||
- Support for parent key passwords
|
|
||||||
- openssl.cnf sample file
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Fix several build system, autotools and testing related issues
|
|
||||||
Now adhere to CFLAGS conventions
|
|
||||||
- Include pkg-config dependecy on libtss2-mu in order to work with tpm2-tss 2.3
|
|
||||||
- Enables parallel testing of integration tests:
|
|
||||||
Make integration tests use TPM simulator; instead of first TPM it finds
|
|
||||||
Use of different port numbers for TCP based tests
|
|
||||||
- Fix EC param info (using named curve format)
|
|
||||||
- Use tpm2-tools 4.X stable branch for integration tests
|
|
||||||
- Use libtss2-tctildr.so instead of custom code for tcti setup
|
|
||||||
- Fix manpages for -P/--parent option and correct engine name
|
|
||||||
- Fix TCTI env variable handling
|
|
||||||
|
|
||||||
## [1.0.0] - 2019-04-04
|
|
||||||
### Added
|
|
||||||
- Initial release of the OpenSSL engine for TPM2.0 using the TCG's TPM
|
|
||||||
Software Stack compliant tpm2-tss libraries.
|
|
||||||
- tpm2tss (the engine) compatible against OpenSSL 1.0.2 and 1.1.0.
|
|
||||||
- tpm2tss-genkey (cli-tool) for creating keys for use with the engine.
|
|
||||||
- man-pages and bash-completion are included.
|
|
||||||
@ -1,133 +0,0 @@
|
|||||||
|
|
||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
|
||||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
||||||
identity and orientation.
|
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
|
||||||
community include:
|
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
|
||||||
* Giving and gracefully accepting constructive feedback
|
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
||||||
and learning from the experience
|
|
||||||
* Focusing on what is best not just for us as individuals, but for the overall
|
|
||||||
community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
|
||||||
any kind
|
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or email address,
|
|
||||||
without their explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
||||||
decisions when appropriate.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
|
||||||
an individual is officially representing the community in public spaces.
|
|
||||||
Examples of representing our community include using an official e-mail address,
|
|
||||||
posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported to the community leaders responsible for enforcement at
|
|
||||||
[MAINTAINERS](MAINTAINERS).
|
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
|
||||||
reporter of any incident.
|
|
||||||
|
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series of
|
|
||||||
actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or permanent
|
|
||||||
ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
|
||||||
community.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
||||||
version 2.1, available at
|
|
||||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by
|
|
||||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
|
||||||
[https://www.contributor-covenant.org/translations][translations].
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
||||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
||||||
[FAQ]: https://www.contributor-covenant.org/faq
|
|
||||||
[translations]: https://www.contributor-covenant.org/translations
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
# Guidelines for submitting bugs:
|
|
||||||
All non security bugs should be filed on the Issues tracker:
|
|
||||||
https://github.com/tpm2-software/tpm2-tss-engine/issues
|
|
||||||
|
|
||||||
Security sensitive bugs should follow the details in SECURITY.md.
|
|
||||||
|
|
||||||
# Guideline for submitting changes:
|
|
||||||
All changes to the source code must follow the coding standard used in the
|
|
||||||
tpm2-tss project [here](https://github.com/tpm2-software/tpm2-tss/blob/master/doc/coding_standard_c.md).
|
|
||||||
|
|
||||||
All changes should be introduced via github pull requests. This allows anyone to
|
|
||||||
comment and provide feedback in lieu of having a mailing list. For pull requests
|
|
||||||
opened by non-maintainers, any maintainer may review and merge that pull
|
|
||||||
request. For maintainers, they either must have their pull request reviewed by
|
|
||||||
another maintainer if possible, or leave the PR open for at least 24 hours, we
|
|
||||||
consider this the window for comments.
|
|
||||||
|
|
||||||
## Patch requirements
|
|
||||||
* All tests must pass on Travis CI for the merge to occur.
|
|
||||||
* All changes must not introduce superfluous changes or whitespace errors.
|
|
||||||
* All commits should adhere to the git commit message guidelines described
|
|
||||||
here: https://chris.beams.io/posts/git-commit/ with the following exceptions.
|
|
||||||
* We allow commit subject lines up to 80 characters.
|
|
||||||
* All contributions must adhere to the Developers Certificate of Origin. The
|
|
||||||
full text of the DCO is here: https://developercertificate.org/. Contributors
|
|
||||||
must add a 'Signed-off-by' line to their commits. This indicates the
|
|
||||||
submitters acceptance of the DCO.
|
|
||||||
|
|
||||||
## Guideline for merging changes
|
|
||||||
Pull Requests MUST be assigned to an upcoming release tag. If a release milestone does
|
|
||||||
not exist, the maintainer SHALL create it per the [RELEASE.md](RELEASE.md) instructions.
|
|
||||||
When accepting and merging a change, the maintainer MUST edit the description field for
|
|
||||||
the release milestone to add the CHANGELOG entry.
|
|
||||||
|
|
||||||
Changes must be merged with the "rebase" option on github to avoid merge commits.
|
|
||||||
This provides for a clear linear history.
|
|
||||||
24
LICENSE
24
LICENSE
@ -1,24 +0,0 @@
|
|||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
Andreas Fuchs <andreas.fuchs@sit.fraunhofer.de>
|
|
||||||
Juergen Repp <juergen.repp@sit.fraunhofer.de> (occasionally)
|
|
||||||
226
Makefile.am
226
Makefile.am
@ -1,226 +0,0 @@
|
|||||||
#;*****************************************************************************;
|
|
||||||
# Copyright (c) 2018 Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
# THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#;*****************************************************************************;
|
|
||||||
|
|
||||||
### Initialize global variables used throughout the file ###
|
|
||||||
INCLUDE_DIRS = -I$(srcdir)/include -I$(srcdir)/src
|
|
||||||
ACLOCAL_AMFLAGS = -I m4 --install
|
|
||||||
AM_CFLAGS = $(INCLUDE_DIRS) $(EXTRA_CFLAGS) $(TSS2_ESYS_CFLAGS) \
|
|
||||||
$(TSS2_MU_CFLAGS) $(TSS2_TCTILDR_CFLAGS) $(CRYPTO_CFLAGS) \
|
|
||||||
$(CODE_COVERAGE_CFLAGS)
|
|
||||||
AM_LDFLAGS = $(EXTRA_LDFLAGS) $(CODE_COVERAGE_LIBS)
|
|
||||||
AM_LDADD = $(TSS2_ESYS_LIBS) $(TSS2_MU_LIBS) $(TSS2_TCTILDR_LIBS) \
|
|
||||||
$(CRYPTO_LIBS)
|
|
||||||
|
|
||||||
AM_DISTCHECK_CONFIGURE_FLAGS = --with-enginesdir= --with-completionsdir= \
|
|
||||||
--enable-unit
|
|
||||||
|
|
||||||
# Initialize empty variables to be extended throughout
|
|
||||||
EXTRA_DIST =
|
|
||||||
CLEANFILES =
|
|
||||||
bin_PROGRAMS =
|
|
||||||
|
|
||||||
### Add ax_* rules ###
|
|
||||||
# ax_code_coverage
|
|
||||||
if AUTOCONF_CODE_COVERAGE_2019_01_06
|
|
||||||
include $(top_srcdir)/aminclude_static.am
|
|
||||||
clean-local: code-coverage-clean
|
|
||||||
distclean-local: code-coverage-dist-clean
|
|
||||||
else
|
|
||||||
@CODE_COVERAGE_RULES@
|
|
||||||
endif
|
|
||||||
|
|
||||||
# ax_valgrind_check
|
|
||||||
@VALGRIND_CHECK_RULES@
|
|
||||||
|
|
||||||
### OpenSSL Engine ###
|
|
||||||
openssl_enginedir = $(ENGINESDIR)
|
|
||||||
openssl_engine_LTLIBRARIES = libtpm2tss.la
|
|
||||||
|
|
||||||
include_HEADERS = include/tpm2-tss-engine.h
|
|
||||||
|
|
||||||
libtpm2tss_la_SOURCES = src/tpm2-tss-engine.c \
|
|
||||||
src/tpm2-tss-engine-common.c \
|
|
||||||
src/tpm2-tss-engine-common.h \
|
|
||||||
src/tpm2-tss-engine-digest-sign.c \
|
|
||||||
src/tpm2-tss-engine-err.c \
|
|
||||||
src/tpm2-tss-engine-err.h \
|
|
||||||
src/tpm2-tss-engine-ecc.c \
|
|
||||||
src/tpm2-tss-engine-rand.c \
|
|
||||||
src/tpm2-tss-engine-rsa.c
|
|
||||||
libtpm2tss_la_CFLAGS = $(AM_CFLAGS)
|
|
||||||
libtpm2tss_la_LIBADD = $(AM_LDADD)
|
|
||||||
libtpm2tss_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -avoid-version \
|
|
||||||
-export-symbols-regex '(tpm2tss*|bind_engine|v_check)'
|
|
||||||
|
|
||||||
install-exec-local:
|
|
||||||
([ -e $(DESTDIR)$(openssl_enginedir) ] || \
|
|
||||||
$(MKDIR_P) $(DESTDIR)$(openssl_enginedir))
|
|
||||||
|
|
||||||
# Due to confusions with OpenSSL Naming conventions for engines regarding the
|
|
||||||
# lib* prefix, we will create a symlink for the engine on install
|
|
||||||
# see https://github.com/tpm2-software/tpm2-tss-engine/issues/6#issuecomment-422489744
|
|
||||||
# see https://github.com/openssl/openssl/commit/9ee0ed3de66678a15db126d10b3e4226e835b8f5
|
|
||||||
install-exec-hook:
|
|
||||||
(cd $(DESTDIR)$(openssl_enginedir) && \
|
|
||||||
$(LN_S) -f libtpm2tss.so tpm2tss.so)
|
|
||||||
|
|
||||||
uninstall-hook:
|
|
||||||
(cd $(DESTDIR)$(openssl_enginedir) && \
|
|
||||||
[ -L tpm2tss.so ] && rm -f tpm2tss.so)
|
|
||||||
|
|
||||||
### KeyGenerator ###
|
|
||||||
bin_PROGRAMS += tpm2tss-genkey
|
|
||||||
|
|
||||||
tpm2tss_genkey_SOURCES = src/tpm2tss-genkey.c
|
|
||||||
tpm2tss_genkey_CFLAGS = $(AM_CFLAGS)
|
|
||||||
tpm2tss_genkey_LDADD = $(AM_LDADD) libtpm2tss.la
|
|
||||||
tpm2tss_genkey_LDFLAGS = $(AM_LDFLAGS)
|
|
||||||
|
|
||||||
### Tests ###
|
|
||||||
TESTS = $(TESTS_INTEGRATION) $(TESTS_UNIT)
|
|
||||||
|
|
||||||
check_PROGRAMS = $(TESTS_UNIT)
|
|
||||||
TESTS_UNIT =
|
|
||||||
TESTS_INTEGRATION =
|
|
||||||
|
|
||||||
if INTEGRATION
|
|
||||||
TESTS_INTEGRATION += $(TESTS_SHELL)
|
|
||||||
endif #INTEGRATION
|
|
||||||
TESTS_SHELL = test/ecdsa.sh \
|
|
||||||
test/ecdsa-emptyauth.sh \
|
|
||||||
test/ecdsa-handle-flush.sh \
|
|
||||||
test/rand.sh \
|
|
||||||
test/rsadecrypt.sh \
|
|
||||||
test/rsasign.sh \
|
|
||||||
test/failload.sh \
|
|
||||||
test/failwrite.sh \
|
|
||||||
test/rsasign_importtpm.sh \
|
|
||||||
test/rsasign_importtpmparent.sh \
|
|
||||||
test/rsasign_parent.sh \
|
|
||||||
test/rsasign_parent_pass.sh \
|
|
||||||
test/rsasign_persistent.sh \
|
|
||||||
test/rsasign_persistent_emptyauth.sh \
|
|
||||||
test/sserver.sh \
|
|
||||||
test/sclient.sh
|
|
||||||
if HAVE_OPENSSL_ECDH
|
|
||||||
TESTS_SHELL += test/ecdh.sh
|
|
||||||
endif
|
|
||||||
if HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
TESTS_SHELL += test/ecdsa-restricted.sh \
|
|
||||||
test/rsasign_restricted.sh
|
|
||||||
endif
|
|
||||||
EXTRA_DIST += $(TESTS_SHELL) test/neg-handle.pem
|
|
||||||
TEST_EXTENSIONS = .sh
|
|
||||||
SH_LOG_COMPILER = $(srcdir)/test/sh_log_compiler.sh
|
|
||||||
SH_LOG_FLAGS = $(INTEGRATION_ARGS)
|
|
||||||
EXTRA_DIST += $(SH_LOG_COMPILER)
|
|
||||||
|
|
||||||
if UNIT
|
|
||||||
TESTS_UNIT += test/error_tpm2-tss-engine-common test/tpm2-tss-engine-common
|
|
||||||
test_error_tpm2_tss_engine_common_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS)
|
|
||||||
test_error_tpm2_tss_engine_common_LDADD = $(AM_LDADD) $(CMOCKA_LIBS)
|
|
||||||
test_error_tpm2_tss_engine_common_LDFLAGS = $(AM_LDFLAGS) -Wl,--wrap=Esys_Initialize
|
|
||||||
test_error_tpm2_tss_engine_common_SOURCES = test/error_tpm2-tss-engine-common.c \
|
|
||||||
$(libtpm2tss_la_SOURCES)
|
|
||||||
test_tpm2_tss_engine_common_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) \
|
|
||||||
-DNEG_HANDLE_PEM=\"$(top_srcdir)/test/neg-handle.pem\"
|
|
||||||
test_tpm2_tss_engine_common_LDADD = $(AM_LDADD) $(CMOCKA_LIBS)
|
|
||||||
test_tpm2_tss_engine_common_LDFLAGS = $(AM_LDFLAGS)
|
|
||||||
test_tpm2_tss_engine_common_SOURCES = test/tpm2-tss-engine-common.c \
|
|
||||||
$(libtpm2tss_la_SOURCES)
|
|
||||||
endif #UNIT
|
|
||||||
|
|
||||||
# Adding user and developer information
|
|
||||||
EXTRA_DIST += \
|
|
||||||
CHANGELOG.md \
|
|
||||||
CONTRIBUTING.md \
|
|
||||||
INSTALL.md \
|
|
||||||
LICENSE \
|
|
||||||
README.md \
|
|
||||||
VERSION
|
|
||||||
|
|
||||||
# Generate the AUTHORS file from git log
|
|
||||||
AUTHORS:
|
|
||||||
$(AM_V_GEN)git log --format='%aN <%aE>' | \
|
|
||||||
grep -v 'users.noreply.github.com' | sort -u > $@
|
|
||||||
EXTRA_DIST += AUTHORS
|
|
||||||
CLEANFILES += AUTHORS
|
|
||||||
|
|
||||||
if HAVE_MAN_PAGES
|
|
||||||
### Man Pages
|
|
||||||
dist_man_MANS = \
|
|
||||||
man/man1/tpm2tss-genkey.1 \
|
|
||||||
man/man3/tpm2tss_tpm2data_write.3 \
|
|
||||||
man/man3/tpm2tss_rsa_makekey.3 \
|
|
||||||
man/man3/tpm2tss_rsa_genkey.3 \
|
|
||||||
man/man3/tpm2tss_ecc_makekey.3 \
|
|
||||||
man/man3/tpm2tss_ecc_genkey.3 \
|
|
||||||
man/man3/tpm2tss_ecc_getappdata.3 \
|
|
||||||
man/man3/tpm2tss_tpm2data_read.3 \
|
|
||||||
man/man3/tpm2tss_ecc_setappdata.3
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !HAVE_PANDOC
|
|
||||||
# If pandoc is not enabled, we want to complain that you need pandoc for make dist,
|
|
||||||
# so hook the target and complain.
|
|
||||||
dist-hook:
|
|
||||||
@(>&2 echo "You do not have pandoc, a requirement for the distribution of manpages")
|
|
||||||
@exit 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
man/man3/tpm2tss_tpm2data_read.3: man/man3/tpm2tss_tpm2data_write.3
|
|
||||||
$(AM_V_GEN)(rm $@ 2>/dev/null || true) && ln -s tpm2tss_tpm2data_write.3 $@
|
|
||||||
|
|
||||||
man/man3/tpm2tss_ecc_setappdata.3: man/man3/tpm2tss_ecc_getappdata.3
|
|
||||||
$(AM_V_GEN)(rm $@ 2>/dev/null || true) && ln -s tpm2tss_ecc_getappdata.3 $@
|
|
||||||
|
|
||||||
man/man1/%.1: man/%.1.md
|
|
||||||
$(AM_V_GEN)mkdir -p man/man1 && cat $< | $(PANDOC) -s -t man >$@
|
|
||||||
|
|
||||||
man/man3/%.3: man/%.3.md
|
|
||||||
$(AM_V_GEN)mkdir -p man/man3 && cat $< | $(PANDOC) -s -t man >$@
|
|
||||||
|
|
||||||
EXTRA_DIST += \
|
|
||||||
man/tpm2tss-genkey.1.md \
|
|
||||||
man/tpm2tss_tpm2data_write.3.md \
|
|
||||||
man/tpm2tss_rsa_makekey.3.md \
|
|
||||||
man/tpm2tss_rsa_genkey.3.md \
|
|
||||||
man/tpm2tss_ecc_makekey.3.md \
|
|
||||||
man/tpm2tss_ecc_genkey.3.md \
|
|
||||||
man/tpm2tss_ecc_getappdata.3.md
|
|
||||||
|
|
||||||
CLEANFILES += \
|
|
||||||
$(dist_man_MANS)
|
|
||||||
|
|
||||||
### Bash Completion
|
|
||||||
bash_completiondir = $(completionsdir)
|
|
||||||
bash_completion_DATA = bash-completion/tpm2tss-genkey
|
|
||||||
EXTRA_DIST += bash-completion/tpm2tss-genkey
|
|
||||||
101
RELEASE.md
101
RELEASE.md
@ -1,101 +0,0 @@
|
|||||||
# Release Process:
|
|
||||||
This document describes the general process that maintainers must follow when
|
|
||||||
making a release of the `tpm2-tss-engine` library and cli-tool.
|
|
||||||
|
|
||||||
# Milestones
|
|
||||||
All releases should have a milestone used to track the release. If the release version is not known, as covered in [Version Numbers](#Version Numbers),
|
|
||||||
then an "x" may be used for the unknown number, or the generic term "next" may be used. The description field of the milestone will be used to record
|
|
||||||
the CHANGELOG for that release. See [CHANGELOG Update](#CHANGELOG Update) for details.
|
|
||||||
|
|
||||||
# Version Numbers
|
|
||||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
In summary: Given a version number MAJOR.MINOR.PATCH, increment the:
|
|
||||||
1. MAJOR version when you make incompatible API changes,
|
|
||||||
2. MINOR version when you add functionality in a backwards-compatible manner, and
|
|
||||||
3. PATCH version when you make backwards-compatible bug fixes.
|
|
||||||
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
|
|
||||||
|
|
||||||
## Version String
|
|
||||||
The version string is set for the rest of the autotools bits by autoconf.
|
|
||||||
Autoconf gets this string from the `AC_INIT` macro in the configure.ac file.
|
|
||||||
Once you decide on the next version number (using the scheme above) you must set
|
|
||||||
it manually in configure.ac. The version string must be in the form `A.B.C`
|
|
||||||
where `A`, `B` and `C` are integers representing the major, minor and micro
|
|
||||||
components of the version number.
|
|
||||||
|
|
||||||
## Release Candidates
|
|
||||||
In the run up to a release the maintainers may create tags to identify progress
|
|
||||||
toward the release. In these cases we will append a string to the release number
|
|
||||||
to indicate progress using the abbreviation `rc` for 'release candidate'. This
|
|
||||||
string will take the form of `-rcX`. We append an incremental digit `X` in case
|
|
||||||
more than one release candidate is necessary to communicate progress as
|
|
||||||
development moves forward.
|
|
||||||
|
|
||||||
# CHANGELOG Update
|
|
||||||
Before tagging the repository with the release version, the maintainer MUST update the CHANGELOG file with the contents from the description field
|
|
||||||
from the corresponding release milestone and update any missing version string details in the CHANGELOG and milestone entry.
|
|
||||||
|
|
||||||
# Git Tags
|
|
||||||
When a release is made a tag is created in the git repo identifying the release
|
|
||||||
by the [version string](#Version String). The tag should be pushed to upstream
|
|
||||||
git repo as the last step in the release process.
|
|
||||||
**NOTE** tags for release candidates will be deleted from the git repository
|
|
||||||
after a release with the corresponding version number has been made.
|
|
||||||
**NOTE** release (not release candidate) tags should be considered immutable.
|
|
||||||
|
|
||||||
## Signed tags
|
|
||||||
Git supports GPG signed tags and releases will have tags signed by a maintainer.
|
|
||||||
For details on how to sign and verify git tags see:
|
|
||||||
https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work.
|
|
||||||
|
|
||||||
# Release tarballs
|
|
||||||
We use the git tag as a way to mark the point of the release in the projects
|
|
||||||
history. We do not however encourage users to build from git unless they intend
|
|
||||||
to modify the source code and contribute to the project. For the end user we
|
|
||||||
provide release tarballs following the GNU conventions as closely as possible.
|
|
||||||
|
|
||||||
To make a release tarball use the `distcheck` make target.
|
|
||||||
This target includes a number of sanity checks that are extremely helpful.
|
|
||||||
For more information on `automake` and release tarballs see:
|
|
||||||
https://www.gnu.org/software/automake/manual/html_node/Dist.html#Dist
|
|
||||||
|
|
||||||
## Hosting Releases on Github
|
|
||||||
Github automagically generates a page in their UI that maps git tags to
|
|
||||||
'releases' (even if the tag isn't for a release). Additionally they support
|
|
||||||
hosting release tarballs through this same interface. The release tarball
|
|
||||||
created in the previous step must be posted to github using the release
|
|
||||||
interface. Additionally, this tarball must be accompanied by a detached GPG
|
|
||||||
signature. The Debian wiki has an excellent description of how to post a signed
|
|
||||||
release to Github here:
|
|
||||||
https://wiki.debian.org/Creating%20signed%20GitHub%20releases
|
|
||||||
**NOTE** release candidates must be taken down after a release with the
|
|
||||||
corresponding version number is available.
|
|
||||||
|
|
||||||
## Signing Release Tarballs
|
|
||||||
Signatures must be generated using the `--detach-sign` and `--armor` options to
|
|
||||||
the `gpg` command.
|
|
||||||
|
|
||||||
## Verifying Signatures
|
|
||||||
Verifying the signature on a release tarball requires the project maintainers
|
|
||||||
public keys be installed in the GPG keyring of the verifier. With both the
|
|
||||||
release tarball and signature file in the same directory the following command
|
|
||||||
will verify the signature:
|
|
||||||
```
|
|
||||||
$ gpg --verify tpm2-tss-engine-X.Y.Z.tar.gz.asc
|
|
||||||
```
|
|
||||||
|
|
||||||
## Signing Keys
|
|
||||||
The GPG keys used to sign a release tag and the associated tarball must be the
|
|
||||||
same. Additionally they must:
|
|
||||||
* belong to a project maintainer
|
|
||||||
* be discoverable using a public GPG key server
|
|
||||||
* be associated with the maintainers github account
|
|
||||||
(https://help.github.com/articles/adding-a-new-gpg-key-to-your-github-account/)
|
|
||||||
|
|
||||||
# Announcements
|
|
||||||
Release candidates and proper releases should be announced on the mailing list:
|
|
||||||
- https://lists.linuxfoundation.org/mailman/listinfo/tpm2
|
|
||||||
|
|
||||||
This announcement should be accompanied by a link to the release page on Github
|
|
||||||
as well as a link to the CHANGELOG.md accompanying the release.
|
|
||||||
37
SECURITY.md
37
SECURITY.md
@ -1,37 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Currently supported versions:
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| any | :white_check_mark: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
### Reporting
|
|
||||||
|
|
||||||
Security vulnerabilities can be disclosed in one of two ways:
|
|
||||||
- GitHub: *preferred* By following [these](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability) instructions.
|
|
||||||
- Email: A descirption *should be emailed* to **all** members of the [MAINTAINERS](MAINTAINERS) file to coordinate the
|
|
||||||
disclosure of the vulnerability.
|
|
||||||
|
|
||||||
### Tracking
|
|
||||||
|
|
||||||
When a maintainer is notified of a security vulnerability, they *must* create a GitHub security advisory
|
|
||||||
per the instructions at:
|
|
||||||
|
|
||||||
- <https://docs.github.com/en/code-security/repository-security-advisories/about-github-security-advisories-for-repositories>
|
|
||||||
|
|
||||||
Maintainers *should* use the optional feature through GitHub to request a CVE be issued, alternatively RedHat has provided CVE's
|
|
||||||
in the past and *may* be used, but preference is on GitHub as the issuing CNA.
|
|
||||||
|
|
||||||
### Publishing
|
|
||||||
|
|
||||||
Once ready, maintainers should publish the security vulnerability as outlined in:
|
|
||||||
|
|
||||||
- <https://docs.github.com/en/code-security/repository-security-advisories/publishing-a-repository-security-advisory>
|
|
||||||
|
|
||||||
As well as ensuring the publishing of the CVE, maintainers *shal*l have new release versions ready to publish at the same time as
|
|
||||||
the CVE. Maintainers *should* should strive to adhere to a sub 60 say turn around from report to release.
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
_tpm2tss-genkey()
|
|
||||||
{
|
|
||||||
local cur prev opts
|
|
||||||
COMPREPLY=()
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
|
|
||||||
case "${prev}" in
|
|
||||||
-a | --alg)
|
|
||||||
COMPREPLY=( $(compgen -W "rsa ecdsa" -- ${cur}) );
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
-c | --curve)
|
|
||||||
COMPREPLY=( $(compgen -W "nist_p256" -- ${cur}) );
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
-e | --exponent)
|
|
||||||
COMPREPLY=( $(compgen -W "65537" -- ${cur}) );
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
-o | --ownerpw | \
|
|
||||||
-p | --password)
|
|
||||||
COMPREPLY=""
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
-s | --keysize)
|
|
||||||
COMPREPLY=( $(compgen -W "2048" -- ${cur}) );
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
-W | --parentpw)
|
|
||||||
COMPREPLY=""
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac;
|
|
||||||
|
|
||||||
opts="-a --alg -c --curve -e --exponent -h --help -o --ownerpw -p --password -s --keysize -v --verbose -W --parentpw"
|
|
||||||
if [[ ${cur} = -* ]] ; then
|
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
COMPREPLY=( $(compgen -f ${cur}) )
|
|
||||||
}
|
|
||||||
complete -F _tpm2tss-genkey tpm2tss-genkey
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
git describe --tags --always --dirty > VERSION
|
|
||||||
|
|
||||||
autoreconf --install --sym
|
|
||||||
256
configure.ac
256
configure.ac
@ -1,256 +0,0 @@
|
|||||||
#;*****************************************************************************;
|
|
||||||
# Copyright (c) 2018 Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
# THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#;*****************************************************************************;
|
|
||||||
AC_PREREQ([2.68])
|
|
||||||
|
|
||||||
AC_INIT([tpm2-tss-engine],
|
|
||||||
[m4_esyscmd_s([cat ./VERSION])],
|
|
||||||
[https://github.com/tpm2-software/tpm2-tss-engine/issues],
|
|
||||||
[],
|
|
||||||
[https://github.com/tpm2-software/tpm2-tss-engine])
|
|
||||||
|
|
||||||
dnl Let's be FHS-conform by default.
|
|
||||||
if test "$prefix" = '/usr'; then
|
|
||||||
test "$sysconfdir" = '${prefix}/etc' && sysconfdir="/etc"
|
|
||||||
test "$sharedstatedir" = '${prefix}/com' && sharedstatedir="/var"
|
|
||||||
test "$localstatedir" = '${prefix}/var' && localstatedir="/var"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
AC_CONFIG_SRCDIR([src/tpm2-tss-engine.c])
|
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
|
||||||
|
|
||||||
# propagate configure arguments to distcheck
|
|
||||||
AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],[$ac_configure_args])
|
|
||||||
|
|
||||||
AC_CANONICAL_SYSTEM
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Wno-portability])
|
|
||||||
#Backward compatible setting of "silent-rules"
|
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|
||||||
AM_MAINTAINER_MODE([enable])
|
|
||||||
|
|
||||||
AX_IS_RELEASE([dash-version])
|
|
||||||
AX_CHECK_ENABLE_DEBUG([info])
|
|
||||||
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_CC_C99
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
LT_INIT()
|
|
||||||
|
|
||||||
AC_PROG_MKDIR_P
|
|
||||||
AC_PROG_LN_S
|
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([src/config.h])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([tctienvvar],
|
|
||||||
[AS_HELP_STRING([--disable-tctienvvar],
|
|
||||||
[Disable setting the TCTI option from an environment variable])],,
|
|
||||||
[enable_tctienvvar=yes])
|
|
||||||
AS_IF([test "x$enable_tctienvvar" = xyes], [AC_DEFINE([ENABLE_TCTIENVVAR], [1],
|
|
||||||
'Enable getting TCTI from env variable')])
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([defaultflags],
|
|
||||||
[AS_HELP_STRING([--disable-defaultflags],
|
|
||||||
[Disable default preprocessor, compiler, and linker flags.])],,
|
|
||||||
[enable_defaultflags=yes])
|
|
||||||
AS_IF([test "x$enable_defaultflags" = "xyes"],
|
|
||||||
[
|
|
||||||
AX_ADD_COMPILER_FLAG([-std=gnu99])
|
|
||||||
AX_ADD_COMPILER_FLAG([-Wall])
|
|
||||||
AX_ADD_COMPILER_FLAG([-Wextra])
|
|
||||||
AX_ADD_COMPILER_FLAG([-Wformat-security])
|
|
||||||
AS_IF([test "x$ax_is_release" = "xno"], [AX_ADD_COMPILER_FLAG([-Werror])])
|
|
||||||
AX_ADD_COMPILER_FLAG([-fstack-protector-all])
|
|
||||||
AX_ADD_COMPILER_FLAG([-fpic])
|
|
||||||
AX_ADD_COMPILER_FLAG([-fPIC])
|
|
||||||
|
|
||||||
# work around GCC bug #53119
|
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
|
|
||||||
AX_ADD_COMPILER_FLAG([-Wno-missing-braces])
|
|
||||||
|
|
||||||
AX_ADD_LINK_FLAG([-Wl,--no-undefined])
|
|
||||||
AX_ADD_LINK_FLAG([-Wl,-z,noexecstack])
|
|
||||||
AX_ADD_LINK_FLAG([-Wl,-z,now])
|
|
||||||
AX_ADD_LINK_FLAG([-Wl,-z,relro])
|
|
||||||
])
|
|
||||||
|
|
||||||
AX_CODE_COVERAGE
|
|
||||||
m4_ifdef([_AX_CODE_COVERAGE_RULES],
|
|
||||||
[AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [true])],
|
|
||||||
[AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [false])])
|
|
||||||
AX_ADD_AM_MACRO_STATIC([])
|
|
||||||
|
|
||||||
PKG_PROG_PKG_CONFIG([0.25])
|
|
||||||
PKG_CHECK_MODULES([CRYPTO], [libcrypto >= 1.0.2g],
|
|
||||||
[ac_enginesdir=`$PKG_CONFIG --variable=enginesdir libcrypto`])
|
|
||||||
PKG_CHECK_MODULES([TSS2_ESYS], [tss2-esys >= 2.3])
|
|
||||||
PKG_CHECK_MODULES([TSS2_MU], [tss2-mu])
|
|
||||||
PKG_CHECK_MODULES([TSS2_TCTILDR], [tss2-tctildr])
|
|
||||||
AC_CHECK_LIB([crypto], EC_KEY_METHOD_set_compute_key,
|
|
||||||
[AM_CONDITIONAL([HAVE_OPENSSL_ECDH], true)],
|
|
||||||
[AM_CONDITIONAL([HAVE_OPENSSL_ECDH], false)])
|
|
||||||
AC_CHECK_LIB([crypto], EVP_PKEY_meth_set_digest_custom,
|
|
||||||
[AM_CONDITIONAL([HAVE_OPENSSL_DIGEST_SIGN], true)],
|
|
||||||
[AM_CONDITIONAL([HAVE_OPENSSL_DIGEST_SIGN], false)])
|
|
||||||
AS_IF([test "x$ac_cv_lib_crypto_EVP_PKEY_meth_set_digest_custom" = xyes],
|
|
||||||
[AC_DEFINE([HAVE_OPENSSL_DIGEST_SIGN], [1],
|
|
||||||
Have required functionality from OpenSSL to support digest and sign)])
|
|
||||||
|
|
||||||
AC_PATH_PROG([PANDOC], [pandoc])
|
|
||||||
AS_IF([test -z "$PANDOC"],
|
|
||||||
[AC_MSG_WARN([Required executable pandoc not found, man pages will not be built])])
|
|
||||||
AM_CONDITIONAL([HAVE_PANDOC],[test -n "$PANDOC"])
|
|
||||||
AM_CONDITIONAL([HAVE_MAN_PAGES],[test -d "${srcdir}/man/man1" -o -n "$PANDOC"])
|
|
||||||
|
|
||||||
AC_PATH_PROG([EXPECT], [expect])
|
|
||||||
AS_IF([test -z "$EXPECT"],
|
|
||||||
[AC_MSG_WARN([Required executable expect not found, some tests might fail])])
|
|
||||||
|
|
||||||
AC_ARG_WITH([enginesdir],
|
|
||||||
[AS_HELP_STRING([--with-enginesdir],
|
|
||||||
[Set the OpenSSL engine directory (default: use pkg-config)])],
|
|
||||||
[],
|
|
||||||
[with_enginesdir=$ac_enginesdir])
|
|
||||||
AS_IF([test -z "$with_enginesdir"],
|
|
||||||
[AC_MSG_WARN([Empty enginesdir, using $libdir/engines instead.])])
|
|
||||||
# This weirdness is necessary to enable distcheck via DISTCHECK_CONFIGURE_FLAGS
|
|
||||||
AS_IF([test -z "$with_enginesdir"],
|
|
||||||
[with_enginesdir=$libdir/engines])
|
|
||||||
AC_SUBST(ENGINESDIR, "$with_enginesdir")
|
|
||||||
|
|
||||||
AC_ARG_WITH([completionsdir],
|
|
||||||
[AS_HELP_STRING([--with-completionsdir],
|
|
||||||
[Set the bash completions directory (default: use pkg-config)])],
|
|
||||||
[],
|
|
||||||
[with_completionsdir=`$PKG_CONFIG --variable=completionsdir bash-completion`])
|
|
||||||
AS_IF([test -z "$with_completionsdir"],
|
|
||||||
[AC_MSG_WARN([Empty completionsdir, using $datarootdir/bash-completion/completions instead.])])
|
|
||||||
AS_IF([test -z "$with_completionsdir"],
|
|
||||||
[with_completionsdir=$datarootdir/bash-completion/completions])
|
|
||||||
AC_SUBST(completionsdir, "$with_completionsdir")
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([unit],
|
|
||||||
[AS_HELP_STRING([--enable-unit],
|
|
||||||
[build cmocka unit tests])],,
|
|
||||||
[enable_unit=no])
|
|
||||||
AS_IF([test "x$enable_unit" != "xno" ],
|
|
||||||
[PKG_CHECK_MODULES([CMOCKA], [cmocka >= 1.0])])
|
|
||||||
AM_CONDITIONAL([UNIT], [test "x$enable_unit" != xno])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([integration],
|
|
||||||
[AS_HELP_STRING([--enable-integration],
|
|
||||||
[build integration tests against TPM])],,
|
|
||||||
[enable_integration=no])
|
|
||||||
AM_CONDITIONAL([INTEGRATION], [test "x$enable_integration" != xno])
|
|
||||||
|
|
||||||
# Use physical TPM device for testing
|
|
||||||
AC_ARG_WITH([device],
|
|
||||||
[AS_HELP_STRING([--with-device=<device>],[TPM device for testing])],
|
|
||||||
[AS_IF([test \( -w "$with_device" \) -a \( -r "$with_device" \)],
|
|
||||||
[AC_MSG_RESULT([success])
|
|
||||||
AX_NORMALIZE_PATH([with_device])
|
|
||||||
with_device_set=yes],
|
|
||||||
[AC_MSG_ERROR([TPM device provided does not exist or is not writable])])],
|
|
||||||
[with_device_set=no])
|
|
||||||
AM_CONDITIONAL([TESTDEVICE],[test "x$with_device_set" = xyes])
|
|
||||||
|
|
||||||
AC_CHECK_FUNC([backtrace_symbols_fd],[AC_DEFINE([HAVE_EXECINFO],[1], ['Define to 1 if you have the <execinfo.h> header file.'])])
|
|
||||||
|
|
||||||
# Integration test with simulator
|
|
||||||
AS_IF([test "x$enable_integration" = xyes && test "x$with_device_set" = xno],
|
|
||||||
[integration_args=""
|
|
||||||
AC_CHECK_PROG([tpm2_startup], [tpm2_startup], [yes])
|
|
||||||
AS_IF([test "x$tpm2_startup" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require the tpm2_startup executable])])
|
|
||||||
AC_CHECK_PROG([swtpm], [swtpm], [yes])
|
|
||||||
AC_CHECK_PROG([tpm_server], [tpm_server], [yes])
|
|
||||||
AS_IF([test "x$swtpm" != xyes && test "x$tpm_server" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require either the swtpm or the tpm_server executable])])
|
|
||||||
AC_CHECK_PROG([realpath], [realpath], [yes])
|
|
||||||
AS_IF([test "x$realpath" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require the realpath executable])])
|
|
||||||
AC_CHECK_PROG([ss], [ss], [yes])
|
|
||||||
AS_IF([test "x$ss" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require the ss executable])])
|
|
||||||
AS_IF([test "x$enable_tctienvvar" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require building with TCTI environment variable support])])
|
|
||||||
AC_SUBST([INTEGRATION_ARGS], [$integration_args])
|
|
||||||
])
|
|
||||||
|
|
||||||
# Integration test with physical device
|
|
||||||
AS_IF([test "x$enable_integration" = xyes && test "x$with_device_set" = xyes ],
|
|
||||||
[integration_args="$with_device"
|
|
||||||
AC_CHECK_PROG([realpath], [realpath], [yes])
|
|
||||||
AS_IF([test "x$realpath" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require the realpath executable])])
|
|
||||||
AS_IF([test "x$enable_tctienvvar" != xyes],
|
|
||||||
[AC_MSG_ERROR([Integration tests require building with TCTI environment variable support])])
|
|
||||||
AC_SUBST([INTEGRATION_ARGS], [$integration_args])
|
|
||||||
])
|
|
||||||
|
|
||||||
AX_VALGRIND_CHECK
|
|
||||||
|
|
||||||
#
|
|
||||||
# sanitizer compiler flags
|
|
||||||
#
|
|
||||||
AC_ARG_WITH([sanitizer],
|
|
||||||
[AS_HELP_STRING([--with-sanitizer={none,address,undefined}],
|
|
||||||
[build with the given sanitizer])],,
|
|
||||||
[with_sanitizer=none])
|
|
||||||
AS_CASE(["x$with_sanitizer"],
|
|
||||||
["xnone"],
|
|
||||||
[],
|
|
||||||
["xaddress"],
|
|
||||||
[
|
|
||||||
SANITIZER_CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
|
|
||||||
SANITIZER_LDFLAGS="-lasan"
|
|
||||||
],
|
|
||||||
["xundefined"],
|
|
||||||
[
|
|
||||||
SANITIZER_CFLAGS="-fsanitize=undefined"
|
|
||||||
SANITIZER_LDFLAGS="-lubsan"
|
|
||||||
],
|
|
||||||
[AC_MSG_ERROR([Bad value for --with-sanitizer])])
|
|
||||||
AC_SUBST([SANITIZER_CFLAGS])
|
|
||||||
AC_SUBST([SANITIZER_LDFLAGS])
|
|
||||||
|
|
||||||
AC_OUTPUT
|
|
||||||
|
|
||||||
AC_MSG_RESULT([
|
|
||||||
$PACKAGE_NAME $VERSION
|
|
||||||
man-pages: $PANDOC
|
|
||||||
enginesdir: $with_enginesdir
|
|
||||||
completionsdir: $with_completionsdir
|
|
||||||
device: $with_device
|
|
||||||
])
|
|
||||||
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef TPM2_TSS_ENGINE_H
|
|
||||||
#define TPM2_TSS_ENGINE_H
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <tss2/tss2_tpm2_types.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KEY_TYPE_BLOB,
|
|
||||||
KEY_TYPE_HANDLE
|
|
||||||
} KEY_TYPE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int emptyAuth;
|
|
||||||
TPM2B_DIGEST userauth;
|
|
||||||
TPM2B_PUBLIC pub;
|
|
||||||
TPM2_HANDLE parent;
|
|
||||||
KEY_TYPE privatetype;
|
|
||||||
union {
|
|
||||||
TPM2B_PRIVATE priv;
|
|
||||||
TPM2_HANDLE handle;
|
|
||||||
};
|
|
||||||
} TPM2_DATA;
|
|
||||||
|
|
||||||
#define TPM2TSS_SET_OWNERAUTH ENGINE_CMD_BASE
|
|
||||||
#define TPM2TSS_SET_TCTI (ENGINE_CMD_BASE + 1)
|
|
||||||
#define TPM2TSS_SET_PARENTAUTH (ENGINE_CMD_BASE + 2)
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_write(const TPM2_DATA *tpm2data, const char *filename);
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_read(const char *filename, TPM2_DATA **tpm2Datap);
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap);
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_importtpm(const char *filenamepub, const char *filenametpm,
|
|
||||||
TPM2_HANDLE parent, int emptyAuth,
|
|
||||||
TPM2_DATA **tpm2Datap);
|
|
||||||
|
|
||||||
EVP_PKEY *
|
|
||||||
tpm2tss_rsa_makekey(TPM2_DATA *tpm2Data);
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_rsa_genkey(RSA *rsa, int bits, BIGNUM *e, char *password,
|
|
||||||
TPM2_HANDLE parentHandle);
|
|
||||||
|
|
||||||
EVP_PKEY *
|
|
||||||
tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data);
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
|
|
||||||
TPM2_HANDLE parentHandle);
|
|
||||||
|
|
||||||
TPM2_DATA *
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
tpm2tss_ecc_getappdata(EC_KEY *key);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
tpm2tss_ecc_getappdata(const EC_KEY *key);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
int
|
|
||||||
tpm2tss_ecc_setappdata(EC_KEY *key, TPM2_DATA *data);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* TPM2_TSS_ENGINE_H */
|
|
||||||
52
m4/flags.m4
52
m4/flags.m4
@ -1,52 +0,0 @@
|
|||||||
dnl AX_ADD_COMPILER_FLAG:
|
|
||||||
dnl A macro to add a CFLAG to the EXTRA_CFLAGS variable. This macro will
|
|
||||||
dnl check to be sure the compiler supports the flag. Flags can be made
|
|
||||||
dnl mandatory (configure will fail).
|
|
||||||
dnl $1: C compiler flag to add to EXTRA_CFLAGS.
|
|
||||||
dnl $2: Set to "required" to cause configure failure if flag not supported.
|
|
||||||
AC_DEFUN([AX_ADD_COMPILER_FLAG],[
|
|
||||||
AX_CHECK_COMPILE_FLAG([$1],[
|
|
||||||
EXTRA_CFLAGS="$EXTRA_CFLAGS $1"
|
|
||||||
AC_SUBST([EXTRA_CFLAGS])],[
|
|
||||||
AS_IF([test x$2 != xrequired],[
|
|
||||||
AC_MSG_WARN([Optional CFLAG "$1" not supported by your compiler, continuing.])],[
|
|
||||||
AC_MSG_ERROR([Required CFLAG "$1" not supported by your compiler, aborting.])]
|
|
||||||
)],[
|
|
||||||
-Wall -Werror]
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
dnl AX_ADD_PREPROC_FLAG:
|
|
||||||
dnl Add the provided preprocessor flag to the EXTRA_CFLAGS variable. This
|
|
||||||
dnl macro will check to be sure the preprocessor supports the flag.
|
|
||||||
dnl The flag can be made mandatory by providing the string 'required' as
|
|
||||||
dnl the second parameter.
|
|
||||||
dnl $1: Preprocessor flag to add to EXTRA_CFLAGS.
|
|
||||||
dnl $2: Set to "required" t ocause configure failure if preprocesor flag
|
|
||||||
dnl is not supported.
|
|
||||||
AC_DEFUN([AX_ADD_PREPROC_FLAG],[
|
|
||||||
AX_CHECK_PREPROC_FLAG([$1],[
|
|
||||||
EXTRA_CFLAGS="$EXTRA_CFLAGS $1"
|
|
||||||
AC_SUBST([EXTRA_CFLAGS])],[
|
|
||||||
AS_IF([test x$2 != xrequired],[
|
|
||||||
AC_MSG_WARN([Optional preprocessor flag "$1" not supported by your compiler, continuing.])],[
|
|
||||||
AC_MSG_ERROR([Required preprocessor flag "$1" not supported by your compiler, aborting.])]
|
|
||||||
)],[
|
|
||||||
-Wall -Werror]
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
dnl AX_ADD_LINK_FLAG:
|
|
||||||
dnl A macro to add a LDLAG to the EXTRA_LDFLAGS variable. This macro will
|
|
||||||
dnl check to be sure the linker supports the flag. Flags can be made
|
|
||||||
dnl mandatory (configure will fail).
|
|
||||||
dnl $1: linker flag to add to EXTRA_LDFLAGS.
|
|
||||||
dnl $2: Set to "required" to cause configure failure if flag not supported.
|
|
||||||
AC_DEFUN([AX_ADD_LINK_FLAG],[
|
|
||||||
AX_CHECK_LINK_FLAG([$1],[
|
|
||||||
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $1"
|
|
||||||
AC_SUBST([EXTRA_LDFLAGS])],[
|
|
||||||
AS_IF([test x$2 != xrequired],[
|
|
||||||
AC_MSG_WARN([Optional LDFLAG "$1" not supported by your linker, continuing.])],[
|
|
||||||
AC_MSG_ERROR([Required LDFLAG "$1" not supported by your linker, aborting.])]
|
|
||||||
)]
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
% tpm2tss-genkey(1) tpm2-tss-engine | General Commands Manual
|
|
||||||
%
|
|
||||||
% OCTOBER 2020
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss-genkey**(1) -- generate TPM keys for tpm2-tss-engine
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**tpm2tss-genkey** [*options*] <*filename*>
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss-genkey** creates a key inside a TPM 2.0 connected via the
|
|
||||||
tpm2tss software stack. Those keys may be an RSA key for decryption or signing
|
|
||||||
or an ECC key for ECDSA signatures.
|
|
||||||
|
|
||||||
The tool respects the OPENSSL_CONF option for specifying engine specific control
|
|
||||||
parameters. See `man(5) config` for details on openssl config files.
|
|
||||||
|
|
||||||
# ARGUMENTS
|
|
||||||
|
|
||||||
The `tpm2tss-genkey` command expects a filename for storing the resulting TPM
|
|
||||||
key information. This file can then be loaded with OpenSSL using
|
|
||||||
`openssl pkeyutl -engine tpm2tss -keyform engine -inkey <filename>`.
|
|
||||||
|
|
||||||
# OPTIONS
|
|
||||||
|
|
||||||
* `-a <algorithm>`, `--alg <algorithm>`:
|
|
||||||
The public key algorithm (rsa, ecdsa) (default: rsa)
|
|
||||||
|
|
||||||
* `-c <curve>`, `--curve <curve>`:
|
|
||||||
If alg ecdsa is chosen, the curve for ecc (default: nist_p256)
|
|
||||||
|
|
||||||
* `-u <file>`, `--public <file>`:
|
|
||||||
Public key (TPM2B_PUBLIC) to be imported. Requires `-r`.
|
|
||||||
|
|
||||||
* `-r <file>`, `--private <file>`:
|
|
||||||
The (encrypted) private key (TPM2B_PRIVATE) to be imported.
|
|
||||||
Requires `-u`.
|
|
||||||
|
|
||||||
* `-e <exponent>`, `--exponent <exponent>`:
|
|
||||||
If alg rsa is chosen, the exponent for rsa (default: 65537)
|
|
||||||
|
|
||||||
* `-h`, `--help`:
|
|
||||||
Print help
|
|
||||||
|
|
||||||
* `-o <password>`, `--ownerpw <password>`:
|
|
||||||
Password for the owner hierarchy (default: none)
|
|
||||||
Openssl Config control command: `SET_OWNERAUTH`
|
|
||||||
|
|
||||||
* `-p <password>`, `--password <password>`:
|
|
||||||
Password for the created key (default: none)
|
|
||||||
|
|
||||||
* `-P <handle>`, `--parent <handle>`:
|
|
||||||
Specific handle for the parent key (default: none)
|
|
||||||
|
|
||||||
* `-s <keysize>`, `--keysize <keysize>`:
|
|
||||||
If alg rsa is chosen, the key size in bits (default: 2048)
|
|
||||||
|
|
||||||
* `-v`, `--verbose`:
|
|
||||||
Print verbose messages
|
|
||||||
|
|
||||||
* `-W <password>`, `--parentpw <password>`:
|
|
||||||
Password for the parent key (default: none)
|
|
||||||
Openssl Config control command: `SET_PARENTAUTH`
|
|
||||||
|
|
||||||
* `-t <tcti-conf>`, `--tcti <tcti-conf>`:
|
|
||||||
TCTI Configuration string (default: none)
|
|
||||||
Openssl Config control command: `SET_TCTI`
|
|
||||||
|
|
||||||
# EXAMPLES
|
|
||||||
|
|
||||||
Engine information can be retrieved using:
|
|
||||||
```
|
|
||||||
$ openssl engine -t -c tpm2tss
|
|
||||||
```
|
|
||||||
The following sequence of commands creates an RSA key using the TPM, exports the
|
|
||||||
public key, encrypts a data file and decrypts it using the TPM:
|
|
||||||
```
|
|
||||||
$ tpm2tss-genkey -a rsa -s 2048 mykey
|
|
||||||
$ openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub
|
|
||||||
$ openssl pkeyutl -pubin -inkey mykey.pub -in mydata -encrypt -out mycipher
|
|
||||||
$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -decrypt -in mycipher -out mydata
|
|
||||||
```
|
|
||||||
The following sequence of commands creates an RSA key using the TPM, exports the
|
|
||||||
public key, signs a data file using the TPM and validates the signature:
|
|
||||||
```
|
|
||||||
$ tpm2tss-genkey -a rsa -s 2048 mykey
|
|
||||||
$ openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub
|
|
||||||
$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -sign -in mydata -out mysig
|
|
||||||
$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -verify -in mydata -sigfile mysig
|
|
||||||
```
|
|
||||||
The following sequence of commands creates an ECDSA key using the TPM, exports
|
|
||||||
the public key, signs a data file using the TPM and validates the signature:
|
|
||||||
```
|
|
||||||
$ tpm2tss-genkey -a ecdsa -c nist_p256 mykey
|
|
||||||
$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -sign -in mydata -out mysig
|
|
||||||
$ openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -verify -in mydata -sigfile mysig
|
|
||||||
```
|
|
||||||
|
|
||||||
# RETURNS
|
|
||||||
|
|
||||||
0 on success or 1 on failure.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2017-2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1)
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_ecc_genkey** -- Make an ECC key object
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**int tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_ECC_genkey** issues the generation of an ECC key `key` using the TPM.
|
|
||||||
The ECC curve is determined by `curve`. The new key will be protected by
|
|
||||||
`password`.
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_ecc_genkey**() returns 1. Otherwise 0.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1), tpm2tss_genkey(1)
|
|
||||||
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_ecc_getappdata**, **tpm2tss_ecc_setappdata** -- Make an ECC key object
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**TPM2_DATA * tpm2tss_ecc_getappdata(const EC_KEY *key);**
|
|
||||||
|
|
||||||
**int tpm2tss_ecc_setappdata(EC_KEY *key, TPM2_DATA *data);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_ecc_getappdata**
|
|
||||||
|
|
||||||
**tpm2tss_ecc_setappdata**
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_ecc_getappdata**() and
|
|
||||||
**tpm2tss_ecc_setappdata**() return 1. Otherwise 0.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1), tpm2tss_genkey(1)
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_ecc_makekey** -- Make an ECC key object
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**EVP_PKEY * tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_ecc_makekey** takes a TPM2_DATA object as `tpm2Data` and creates a
|
|
||||||
corresponding OpenSSL EVP_PKEY object.
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_ecc_makekey**() returns the created
|
|
||||||
EVP_PKEY object's pointer. Otherwise NULL.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1)
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_rsa_genkey** -- Make an RSA key object
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**int tpm2tss_rsa_genkey(RSA *rsa, int bits, BIGNUM *e, char *password);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_rsa_genkey** issues the generation of an RSA key `rsa` using the TPM.
|
|
||||||
The keylength is determined by `bits`. The exponent is determined by `e`.
|
|
||||||
The new key will be protected by `password`.
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_rsa_genkey**() returns 1. Otherwise 0.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1), tpm2tss_genkey(1)
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_rsa_makekey** -- Make an RSA key object
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**EVP_PKEY * tpm2tss_rsa_makekey(TPM2_DATA *tpm2Data);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_rsa_makekey** takes a TPM2_DATA object as `tpm2Data` and creates a
|
|
||||||
corresponding OpenSSL EVP_PKEY object.
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_rsa_makekey**() returns the created
|
|
||||||
EVP_PKEY object's pointer. Otherwise NULL.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1)
|
|
||||||
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
% tpm2tss-tpm2data_write(3) tpm2-tss-engine | Library calls
|
|
||||||
%
|
|
||||||
% JUNE 2018
|
|
||||||
|
|
||||||
# NAME
|
|
||||||
**tpm2tss_tpm2data_write**, **tpm2tss_tpm2data_read** -- read/write TPM2_DATA
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
|
|
||||||
**#include <tpm2tss.h>**
|
|
||||||
|
|
||||||
**int tpm2tss_tpm2data_read(const char *filename, TPM2_DATA **tpm2Datap);**
|
|
||||||
|
|
||||||
**int tpm2tss_tpm2data_write(const TPM2_DATA *tpm2Data, const char *filename);**
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
|
|
||||||
**tpm2tss_tpm2data_read** reads the TPM2_DATA object from a file called
|
|
||||||
`filename`, allocates memory and stores it under the parameter `tpm2Datap`.
|
|
||||||
Must be freed using the `free()` function.
|
|
||||||
|
|
||||||
**tpm2tss_tpm2data_write** writes the TPM2_DATA object from the parameter
|
|
||||||
`tpm2Data` to a newly created file called `filename`.
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
|
|
||||||
Upon successful completion **tpm2tss_tpm2data_write**() and
|
|
||||||
**tpm2tss_tpm2data_read**() return 1. Otherwise 0.
|
|
||||||
|
|
||||||
## AUTHOR
|
|
||||||
|
|
||||||
Written by Andreas Fuchs.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
tpm2tss is Copyright (C) 2018 Fraunhofer SIT sponsored by Infineon
|
|
||||||
Technologies AG. License BSD 3-clause.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
openssl(1)
|
|
||||||
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
openssl_conf = openssl_init
|
|
||||||
|
|
||||||
[openssl_init]
|
|
||||||
engines = engine_section
|
|
||||||
|
|
||||||
[engine_section]
|
|
||||||
tpm2tss = tpm2tss_section
|
|
||||||
|
|
||||||
[tpm2tss_section]
|
|
||||||
engine_id = tpm2tss
|
|
||||||
dynamic_path = /usr/lib/engines-1.1/libtpm2tss.so
|
|
||||||
default_algorithms = RSA,ECDSA
|
|
||||||
init = 1
|
|
||||||
#SET_TCTI = <TCTI_options>
|
|
||||||
#SET_OWNERAUTH = <could_set_password_here, but then it's readable>
|
|
||||||
#SET_PARENTAUTH = <password_of_parent_key>
|
|
||||||
|
|
||||||
[req]
|
|
||||||
distinguished_name = subject
|
|
||||||
|
|
||||||
[subject]
|
|
||||||
# prompts and defaults here
|
|
||||||
@ -1,698 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
* Copyright (c) 2019, Wind River Systems.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <tss2/tss2_tctildr.h>
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
ASN1_SEQUENCE(TSSPRIVKEY) = {
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, type, ASN1_OBJECT),
|
|
||||||
ASN1_EXP_OPT(TSSPRIVKEY, emptyAuth, ASN1_BOOLEAN, 0),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, parent, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, pubkey, ASN1_OCTET_STRING),
|
|
||||||
ASN1_SIMPLE(TSSPRIVKEY, privkey, ASN1_OCTET_STRING)
|
|
||||||
} ASN1_SEQUENCE_END(TSSPRIVKEY)
|
|
||||||
|
|
||||||
#define TSSPRIVKEY_PEM_STRING "TSS2 PRIVATE KEY"
|
|
||||||
|
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(TSSPRIVKEY);
|
|
||||||
IMPLEMENT_PEM_write_bio(TSSPRIVKEY, TSSPRIVKEY, TSSPRIVKEY_PEM_STRING, TSSPRIVKEY);
|
|
||||||
IMPLEMENT_PEM_read_bio(TSSPRIVKEY, TSSPRIVKEY, TSSPRIVKEY_PEM_STRING, TSSPRIVKEY);
|
|
||||||
|
|
||||||
/** Initialize the Esys context
|
|
||||||
*
|
|
||||||
* Initialize an Esys context.
|
|
||||||
* @param esys_ctx The context to initialize.
|
|
||||||
* @retval TSS2_RC_SUCCESS on success
|
|
||||||
* @retval TSS2_BASE_RC_BAD_REFERENCE if no pointer was provided
|
|
||||||
* @retval Errors from Tcti initialization or Esys_Initialize()
|
|
||||||
*/
|
|
||||||
TSS2_RC
|
|
||||||
esys_ctx_init(ESYS_CONTEXT **esys_ctx)
|
|
||||||
{
|
|
||||||
|
|
||||||
TSS2_RC r;
|
|
||||||
if (!esys_ctx) {
|
|
||||||
ERR(esys_ctx_init, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
r = TSS2_BASE_RC_BAD_REFERENCE;
|
|
||||||
} else {
|
|
||||||
TSS2_TCTI_CONTEXT *tcti_ctx = NULL;
|
|
||||||
|
|
||||||
r = Tss2_TctiLdr_Initialize(tcti_nameconf, &tcti_ctx);
|
|
||||||
if (TSS2_RC_SUCCESS != r) {
|
|
||||||
ERR(esys_ctx_init, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
} else {
|
|
||||||
r = Esys_Initialize(esys_ctx, tcti_ctx, NULL);
|
|
||||||
if (TSS2_RC_SUCCESS != r) {
|
|
||||||
ERR(esys_ctx_init, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
Tss2_TctiLdr_Finalize(&tcti_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Finalize the Esys context
|
|
||||||
*
|
|
||||||
* Get the TCTI context and finalize this alongside the Esys context.
|
|
||||||
* @param esys_ctx The Esys context
|
|
||||||
* @retval TSS2_RC_SUCCESS on success
|
|
||||||
* @retval TSS2_BASE_RC_BAD_REFERENCE if no pointer was provided
|
|
||||||
* @retval Errors from Esys_GetTcti()
|
|
||||||
*/
|
|
||||||
TSS2_RC
|
|
||||||
esys_ctx_free(ESYS_CONTEXT **esys_ctx)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
if ((!esys_ctx) || (!*esys_ctx)) {
|
|
||||||
ERR(esys_ctx_free, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
r = TSS2_BASE_RC_BAD_REFERENCE;
|
|
||||||
} else {
|
|
||||||
TSS2_TCTI_CONTEXT *tcti_ctx;
|
|
||||||
r = Esys_GetTcti(*esys_ctx, &tcti_ctx);
|
|
||||||
Esys_Finalize(esys_ctx);
|
|
||||||
if (TSS2_RC_SUCCESS != r) {
|
|
||||||
ERR(esys_ctx_free, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
} else {
|
|
||||||
Tss2_TctiLdr_Finalize(&tcti_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Serialize tpm2data onto disk
|
|
||||||
*
|
|
||||||
* Write the tpm2tss key data into a file using PEM encoding.
|
|
||||||
* @param tpm2Data The data to be written to disk.
|
|
||||||
* @param filename The filename to write the data to.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_write(const TPM2_DATA *tpm2Data, const char *filename)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
BIO *bio = NULL;
|
|
||||||
TSSPRIVKEY *tpk = NULL;
|
|
||||||
BIGNUM *bn_parent = NULL;
|
|
||||||
|
|
||||||
uint8_t privbuf[sizeof(tpm2Data->priv)];
|
|
||||||
uint8_t pubbuf[sizeof(tpm2Data->pub)];
|
|
||||||
size_t privbuf_len = 0, pubbuf_len = 0;
|
|
||||||
|
|
||||||
if ((bio = BIO_new_file(filename, "w")) == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_write, TPM2TSS_R_FILE_WRITE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
tpk = TSSPRIVKEY_new();
|
|
||||||
if (!tpk) {
|
|
||||||
ERR(tpm2tss_tpm2data_write, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Tss2_MU_TPM2B_PRIVATE_Marshal(&tpm2Data->priv, &privbuf[0],
|
|
||||||
sizeof(privbuf), &privbuf_len);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_write, TPM2TSS_R_DATA_CORRUPTED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Tss2_MU_TPM2B_PUBLIC_Marshal(&tpm2Data->pub, &pubbuf[0],
|
|
||||||
sizeof(pubbuf), &pubbuf_len);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_write, TPM2TSS_R_DATA_CORRUPTED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
tpk->type = OBJ_txt2obj(OID_loadableKey, 1);
|
|
||||||
tpk->parent = ASN1_INTEGER_new();
|
|
||||||
tpk->privkey = ASN1_OCTET_STRING_new();
|
|
||||||
tpk->pubkey = ASN1_OCTET_STRING_new();
|
|
||||||
if (!tpk->type || !tpk->privkey || !tpk->pubkey || !tpk->parent) {
|
|
||||||
ERR(tpm2tss_tpm2data_write, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
tpk->emptyAuth = tpm2Data->emptyAuth ? 0xFF : 0;
|
|
||||||
bn_parent = BN_new();
|
|
||||||
if (!bn_parent) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (tpm2Data->parent != 0) {
|
|
||||||
BN_set_word(bn_parent, tpm2Data->parent);
|
|
||||||
} else {
|
|
||||||
BN_set_word(bn_parent, TPM2_RH_OWNER);
|
|
||||||
}
|
|
||||||
BN_to_ASN1_INTEGER(bn_parent, tpk->parent);
|
|
||||||
ASN1_STRING_set(tpk->privkey, &privbuf[0], privbuf_len);
|
|
||||||
ASN1_STRING_set(tpk->pubkey, &pubbuf[0], pubbuf_len);
|
|
||||||
|
|
||||||
PEM_write_bio_TSSPRIVKEY(bio, tpk);
|
|
||||||
TSSPRIVKEY_free(tpk);
|
|
||||||
BIO_free(bio);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
if (bio)
|
|
||||||
BIO_free(bio);
|
|
||||||
if (tpk)
|
|
||||||
TSSPRIVKEY_free(tpk);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create tpm2data from a TPM key
|
|
||||||
*
|
|
||||||
* Retrieve the public key of tpm2data from the TPM for a given handle.
|
|
||||||
* @param handle The TPM's key handle.
|
|
||||||
* @param tpm2Datap The data after read.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
ESYS_TR keyHandle = ESYS_TR_NONE;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
TPM2B_PUBLIC *outPublic;
|
|
||||||
|
|
||||||
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(tpm2Data, 0, sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
tpm2Data->privatetype = KEY_TYPE_HANDLE;
|
|
||||||
tpm2Data->handle = handle;
|
|
||||||
|
|
||||||
r = esys_ctx_init(&esys_ctx);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Esys_TR_FromTPMPublic(esys_ctx, tpm2Data->handle,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&keyHandle);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Esys_ReadPublic(esys_ctx, keyHandle,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&outPublic, NULL, NULL);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the persistent key has the NODA flag set, we check whether it does
|
|
||||||
have an empty authValue. If NODA is not set, then we don't check because
|
|
||||||
that would increment the DA lockout counter */
|
|
||||||
if ((outPublic->publicArea.objectAttributes & TPMA_OBJECT_NODA) != 0) {
|
|
||||||
ESYS_TR session;
|
|
||||||
TPMT_SYM_DEF sym = {.algorithm = TPM2_ALG_AES,
|
|
||||||
.keyBits = {.aes = 128},
|
|
||||||
.mode = {.aes = TPM2_ALG_CFB}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Esys_StartAuthSession() and session handling use OpenSSL for random
|
|
||||||
bytes and thus might end up inside this engine again. This becomes
|
|
||||||
a problem if we have no resource manager, i.e. the tpm simulator. */
|
|
||||||
const RAND_METHOD *rand_save = RAND_get_rand_method();
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
RAND_set_rand_method(RAND_SSLeay());
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
RAND_set_rand_method(RAND_OpenSSL());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We do the check by starting a bound audit session and executing a
|
|
||||||
very cheap command. */
|
|
||||||
r = Esys_StartAuthSession(esys_ctx, ESYS_TR_NONE, keyHandle,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
NULL, TPM2_SE_HMAC, &sym, TPM2_ALG_SHA256,
|
|
||||||
&session);
|
|
||||||
/* Though this response code is sub-optimal, it's the only way to
|
|
||||||
detect the bug in ESYS. */
|
|
||||||
if (r == TSS2_ESYS_RC_GENERAL_FAILURE) {
|
|
||||||
DBG("Running tpm2-tss < 2.2 which has a bug here. Requiring auth.");
|
|
||||||
tpm2Data->emptyAuth = 0;
|
|
||||||
goto session_error;
|
|
||||||
} else if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Esys_TRSess_SetAttributes(esys_ctx, session,
|
|
||||||
TPMA_SESSION_ENCRYPT, TPMA_SESSION_ENCRYPT);
|
|
||||||
Esys_TRSess_SetAttributes(esys_ctx, session,
|
|
||||||
TPMA_SESSION_CONTINUESESSION,
|
|
||||||
TPMA_SESSION_CONTINUESESSION);
|
|
||||||
|
|
||||||
r = Esys_ReadPublic(esys_ctx, keyHandle,
|
|
||||||
session, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
|
|
||||||
RAND_set_rand_method(rand_save);
|
|
||||||
|
|
||||||
/* tpm2-tss < 2.2 has some bugs. (1) it may miscalculate the auth from
|
|
||||||
above leading to a password query in case of empty auth and (2) it
|
|
||||||
may return an error because the object's auth value is "\0". */
|
|
||||||
if (r == TSS2_RC_SUCCESS) {
|
|
||||||
DBG("Object does not require auth");
|
|
||||||
tpm2Data->emptyAuth = 1;
|
|
||||||
} else if (r == (TPM2_RC_BAD_AUTH | TPM2_RC_S | TPM2_RC_1)) {
|
|
||||||
DBG("Object does require auth");
|
|
||||||
tpm2Data->emptyAuth = 0;
|
|
||||||
} else {
|
|
||||||
ERR(tpm2tss_tpm2data_readtpm, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
Esys_FlushContext (esys_ctx, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
session_error:
|
|
||||||
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
tpm2Data->pub = *outPublic;
|
|
||||||
Esys_Free(outPublic);
|
|
||||||
|
|
||||||
*tpm2Datap = tpm2Data;
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
if (keyHandle != ESYS_TR_NONE)
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
if (tpm2Data)
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Deserialize tpm2data from disk
|
|
||||||
*
|
|
||||||
* Read the tpm2tss key data from a file using PEM encoding.
|
|
||||||
* @param filename The filename to read the data from.
|
|
||||||
* @param tpm2Datap The data after read.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_read(const char *filename, TPM2_DATA **tpm2Datap)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
BIO *bio = NULL;
|
|
||||||
TSSPRIVKEY *tpk = NULL;
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
char type_oid[64];
|
|
||||||
BIGNUM *bn_parent;
|
|
||||||
|
|
||||||
if ((bio = BIO_new_file(filename, "r")) == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
tpk = PEM_read_bio_TSSPRIVKEY(bio, NULL, NULL, NULL);
|
|
||||||
if (!tpk) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_DATA_CORRUPTED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BIO_free(bio);
|
|
||||||
bio = NULL;
|
|
||||||
|
|
||||||
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(tpm2Data, 0, sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
tpm2Data->privatetype = KEY_TYPE_BLOB;
|
|
||||||
|
|
||||||
tpm2Data->emptyAuth = !!tpk->emptyAuth;
|
|
||||||
|
|
||||||
bn_parent = ASN1_INTEGER_to_BN(tpk->parent, NULL);
|
|
||||||
if (!bn_parent) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (BN_is_negative(bn_parent)) {
|
|
||||||
tpm2Data->parent = ASN1_INTEGER_get(tpk->parent);
|
|
||||||
} else {
|
|
||||||
tpm2Data->parent = BN_get_word(bn_parent);
|
|
||||||
}
|
|
||||||
if (tpm2Data->parent == 0)
|
|
||||||
tpm2Data->parent = TPM2_RH_OWNER;
|
|
||||||
|
|
||||||
if (!OBJ_obj2txt(type_oid, sizeof(type_oid), tpk->type, 1) ||
|
|
||||||
strcmp(type_oid, OID_loadableKey)) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_CANNOT_MAKE_KEY);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
r = Tss2_MU_TPM2B_PRIVATE_Unmarshal(tpk->privkey->data,
|
|
||||||
tpk->privkey->length, NULL,
|
|
||||||
&tpm2Data->priv);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_DATA_CORRUPTED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
r = Tss2_MU_TPM2B_PUBLIC_Unmarshal(tpk->pubkey->data, tpk->pubkey->length,
|
|
||||||
NULL, &tpm2Data->pub);
|
|
||||||
if (r) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_DATA_CORRUPTED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSSPRIVKEY_free(tpk);
|
|
||||||
|
|
||||||
*tpm2Datap = tpm2Data;
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
if (tpm2Data)
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
if (bio)
|
|
||||||
BIO_free(bio);
|
|
||||||
if (tpk)
|
|
||||||
TSSPRIVKEY_free(tpk);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TPM2B_PUBLIC primaryEccTemplate = TPM2B_PUBLIC_PRIMARY_ECC_TEMPLATE;
|
|
||||||
static TPM2B_PUBLIC primaryRsaTemplate = TPM2B_PUBLIC_PRIMARY_RSA_TEMPLATE;
|
|
||||||
|
|
||||||
static TPM2B_SENSITIVE_CREATE primarySensitive = {
|
|
||||||
.sensitive = {
|
|
||||||
.userAuth = {
|
|
||||||
.size = 0,
|
|
||||||
},
|
|
||||||
.data = {
|
|
||||||
.size = 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPM2B_DATA allOutsideInfo = {
|
|
||||||
.size = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPML_PCR_SELECTION allCreationPCR = {
|
|
||||||
.count = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Initialize the ESYS TPM connection and primary/persistent key
|
|
||||||
*
|
|
||||||
* Establish a connection with the TPM using ESYS libraries and create a primary
|
|
||||||
* key under the owner hierarchy or to initialize the ESYS object for a
|
|
||||||
* persistent if provided.
|
|
||||||
* @param esys_ctx The resulting ESYS context.
|
|
||||||
* @param parentHandle The TPM handle of a persistent key or TPM2_RH_OWNER or 0
|
|
||||||
* @param parent The resulting ESYS_TR handle for the parent key.
|
|
||||||
* @retval TSS2_RC_SUCCESS on success
|
|
||||||
* @retval TSS2_RCs according to the error
|
|
||||||
*/
|
|
||||||
TSS2_RC
|
|
||||||
init_tpm_parent(ESYS_CONTEXT **esys_ctx,
|
|
||||||
TPM2_HANDLE parentHandle, ESYS_TR *parent)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
TPM2B_PUBLIC *primaryTemplate = NULL;
|
|
||||||
TPMS_CAPABILITY_DATA *capabilityData = NULL;
|
|
||||||
UINT32 index;
|
|
||||||
*parent = ESYS_TR_NONE;
|
|
||||||
*esys_ctx = NULL;
|
|
||||||
|
|
||||||
DBG("Establishing connection with TPM.\n");
|
|
||||||
r = esys_ctx_init(esys_ctx);
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
if (parentHandle && parentHandle != TPM2_RH_OWNER) {
|
|
||||||
DBG("Connecting to a persistent parent key.\n");
|
|
||||||
r = Esys_TR_FromTPMPublic(*esys_ctx, parentHandle,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
parent);
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
r = Esys_TR_SetAuth(*esys_ctx, *parent, &parentauth);
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
return TSS2_RC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Creating primary key under owner.\n");
|
|
||||||
r = Esys_TR_SetAuth(*esys_ctx, ESYS_TR_RH_OWNER, &ownerauth);
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
r = Esys_GetCapability (*esys_ctx,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
TPM2_CAP_ALGS, 0, TPM2_MAX_CAP_ALGS,
|
|
||||||
NULL, &capabilityData);
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
for (index = 0; index < capabilityData->data.algorithms.count; index++) {
|
|
||||||
if (capabilityData->data.algorithms.algProperties[index].alg == TPM2_ALG_ECC) {
|
|
||||||
primaryTemplate = &primaryEccTemplate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TPM2_ALG_ECC is *mandatory* for TPM2.0; the above should never
|
|
||||||
* fail. However, *if* such a broken TPM is used then ephemeral
|
|
||||||
* primaries according to the TSS2 PEM file standard can *never*
|
|
||||||
* have worked on that hardware, so it isn't *breaking* anything
|
|
||||||
* for us to unilaterally use an ephemeral RSA parent in this case
|
|
||||||
* instead.
|
|
||||||
*
|
|
||||||
* However, it may not be interoperable to do so, and it isn't a
|
|
||||||
* good idea anyway since RSA keys are *slow* to generate, so
|
|
||||||
* users with a broken TPM like this really *should* have followed
|
|
||||||
* the recommendation to create the RSA primary and store it in
|
|
||||||
* the NVRAM at 0x81000001. And then the TSS2 PEM keys should use
|
|
||||||
* *that* as the parent, not the ephemeral version. In fact, there
|
|
||||||
* is a strong case to be made for defaulting to 0x81000001 if it
|
|
||||||
* exists, *before* (or never) falling back to generating an RSA
|
|
||||||
* key here.
|
|
||||||
*/
|
|
||||||
if (primaryTemplate == NULL) {
|
|
||||||
for (index = 0; index < capabilityData->data.algorithms.count; index++) {
|
|
||||||
if (capabilityData->data.algorithms.algProperties[index].alg == TPM2_ALG_RSA) {
|
|
||||||
primaryTemplate = &primaryRsaTemplate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Esys_Free (capabilityData);
|
|
||||||
|
|
||||||
if (primaryTemplate == NULL) {
|
|
||||||
ERR(init_tpm_parent, TPM2TSS_R_UNKNOWN_ALG);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Esys_CreatePrimary(*esys_ctx, ESYS_TR_RH_OWNER,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&primarySensitive, primaryTemplate, &allOutsideInfo,
|
|
||||||
&allCreationPCR,
|
|
||||||
parent, NULL, NULL, NULL, NULL);
|
|
||||||
if (r == 0x000009a2) {
|
|
||||||
ERR(init_tpm_parent, TPM2TSS_R_OWNER_AUTH_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ERRchktss(init_tpm_parent, r, goto error);
|
|
||||||
|
|
||||||
return TSS2_RC_SUCCESS;
|
|
||||||
error:
|
|
||||||
if (*parent != ESYS_TR_NONE)
|
|
||||||
Esys_FlushContext(*esys_ctx, *parent);
|
|
||||||
*parent = ESYS_TR_NONE;
|
|
||||||
|
|
||||||
esys_ctx_free(esys_ctx);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initialize the ESYS TPM connection and load the key
|
|
||||||
*
|
|
||||||
* Establish a connection with the TPM using ESYS libraries, create a primary
|
|
||||||
* key under the owner hierarchy and then load the TPM key and set its auth
|
|
||||||
* value.
|
|
||||||
* @param esys_ctx The ESYS_CONTEXT to be populated.
|
|
||||||
* @param keyHandle The resulting handle for the key key.
|
|
||||||
* @param tpm2Data The key data, owner auth and key auth to be used
|
|
||||||
* @retval TSS2_RC_SUCCESS on success
|
|
||||||
* @retval TSS2_RCs according to the error
|
|
||||||
*/
|
|
||||||
TSS2_RC
|
|
||||||
init_tpm_key (ESYS_CONTEXT **esys_ctx, ESYS_TR *keyHandle, TPM2_DATA *tpm2Data)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
ESYS_TR parent = ESYS_TR_NONE;
|
|
||||||
*keyHandle = ESYS_TR_NONE;
|
|
||||||
*esys_ctx = NULL;
|
|
||||||
|
|
||||||
if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
DBG("Establishing connection with TPM.\n");
|
|
||||||
r = esys_ctx_init(esys_ctx);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
|
|
||||||
r = Esys_TR_FromTPMPublic(*esys_ctx, tpm2Data->handle,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
keyHandle);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
} else if (tpm2Data->privatetype == KEY_TYPE_BLOB
|
|
||||||
&& tpm2Data->parent != TPM2_RH_OWNER) {
|
|
||||||
r = init_tpm_parent(esys_ctx, tpm2Data->parent, &parent);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
|
|
||||||
DBG("Loading key blob.\n");
|
|
||||||
r = Esys_Load(*esys_ctx, parent,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&tpm2Data->priv, &tpm2Data->pub, keyHandle);
|
|
||||||
Esys_TR_Close(*esys_ctx, &parent);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
} else if (tpm2Data->privatetype == KEY_TYPE_BLOB) {
|
|
||||||
r = init_tpm_parent(esys_ctx, 0, &parent);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
|
|
||||||
DBG("Loading key blob.\n");
|
|
||||||
r = Esys_Load(*esys_ctx, parent,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&tpm2Data->priv, &tpm2Data->pub, keyHandle);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
|
|
||||||
r = Esys_FlushContext(*esys_ctx, parent);
|
|
||||||
ERRchktss(rsa_priv_enc, r, goto error);
|
|
||||||
parent = ESYS_TR_NONE;
|
|
||||||
} else {
|
|
||||||
r = -1;
|
|
||||||
ERR(init_tpm_key, TPM2TSS_R_TPM2DATA_READ_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Esys_TR_SetAuth(*esys_ctx, *keyHandle, &tpm2Data->userauth);
|
|
||||||
ERRchktss(init_tpm_key, r, goto error);
|
|
||||||
|
|
||||||
return TSS2_RC_SUCCESS;
|
|
||||||
error:
|
|
||||||
if (parent != ESYS_TR_NONE)
|
|
||||||
Esys_FlushContext(*esys_ctx, parent);
|
|
||||||
if (*keyHandle != ESYS_TR_NONE)
|
|
||||||
Esys_FlushContext(*esys_ctx, *keyHandle);
|
|
||||||
*keyHandle = ESYS_TR_NONE;
|
|
||||||
|
|
||||||
esys_ctx_free(esys_ctx);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Deserialize a tpm key from disk
|
|
||||||
*
|
|
||||||
* Read a tpm key as marshaled TPM2B_PUBLIC and (encrypted) TPM2B_PRIVATE from
|
|
||||||
* disk and convert them into a TPM2_DATA representation
|
|
||||||
* @param filenamepub The filename to read the public portion from.
|
|
||||||
* @param filenametpm The filename to read the private portion from.
|
|
||||||
* @param parent Handle of the parent key.
|
|
||||||
* @param emptyAuth Whether the object does not require authentication.
|
|
||||||
* @param tpm2Datap The data after read.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_tpm2data_importtpm(const char *filenamepub, const char *filenametpm,
|
|
||||||
TPM2_HANDLE parent, int emptyAuth,
|
|
||||||
TPM2_DATA **tpm2Datap)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
BIO *bio;
|
|
||||||
TPM2_DATA *tpm2data;
|
|
||||||
int filepub_size, filepriv_size;
|
|
||||||
|
|
||||||
uint8_t filepub[sizeof(TPM2B_PUBLIC)];
|
|
||||||
uint8_t filepriv[sizeof(TPM2B_PRIVATE)];
|
|
||||||
|
|
||||||
if ((bio = BIO_new_file(filenamepub, "r")) == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
filepub_size = BIO_read(bio, &filepub[0], sizeof(filepub));
|
|
||||||
BIO_free(bio);
|
|
||||||
if (filepub_size < 0) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((bio = BIO_new_file(filenametpm, "r")) == NULL) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
filepriv_size = BIO_read(bio, &filepriv[0], sizeof(filepriv));
|
|
||||||
BIO_free(bio);
|
|
||||||
if (filepriv_size < 0) {
|
|
||||||
ERR(tpm2tss_tpm2data_read, TPM2TSS_R_FILE_READ);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tpm2data = OPENSSL_malloc(sizeof(TPM2_DATA));
|
|
||||||
if (!tpm2data)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memset(tpm2data, 0, sizeof(*tpm2data));
|
|
||||||
tpm2data->privatetype = KEY_TYPE_BLOB;
|
|
||||||
tpm2data->parent = parent;
|
|
||||||
tpm2data->emptyAuth = emptyAuth;
|
|
||||||
|
|
||||||
r = Tss2_MU_TPM2B_PUBLIC_Unmarshal(&filepub[0], filepub_size, NULL,
|
|
||||||
&tpm2data->pub);
|
|
||||||
ERRchktss(tpm2tss_tpm2data_read, r, goto error);
|
|
||||||
|
|
||||||
r = Tss2_MU_TPM2B_PRIVATE_Unmarshal(&filepriv[0], filepriv_size, NULL,
|
|
||||||
&tpm2data->priv);
|
|
||||||
ERRchktss(tpm2tss_tpm2data_read, r, goto error);
|
|
||||||
|
|
||||||
*tpm2Datap = tpm2data;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
error:
|
|
||||||
OPENSSL_free(tpm2data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,199 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
* Copyright (c) 2019, Wind River Systems.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef TPM2_TSS_ENGINE_COMMON_H
|
|
||||||
#define TPM2_TSS_ENGINE_COMMON_H
|
|
||||||
|
|
||||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
|
|
||||||
&& !defined(__STDC_NO_ATOMICS__)
|
|
||||||
# include <stdatomic.h>
|
|
||||||
# define TPM2_TSS_ENGINE_HAVE_C11_ATOMICS
|
|
||||||
typedef _Atomic int T2TE_ATOMIC_INT;
|
|
||||||
#else
|
|
||||||
typedef int T2TE_ATOMIC_INT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <tpm2-tss-engine.h>
|
|
||||||
#include <tss2/tss2_mu.h>
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine-err.h"
|
|
||||||
|
|
||||||
#include <openssl/asn1t.h>
|
|
||||||
#include <openssl/asn1.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
|
|
||||||
extern TPM2B_DIGEST ownerauth;
|
|
||||||
extern TPM2B_DIGEST parentauth;
|
|
||||||
|
|
||||||
extern char *tcti_nameconf;
|
|
||||||
|
|
||||||
int init_ecc(ENGINE *e);
|
|
||||||
int init_rand(ENGINE *e);
|
|
||||||
int init_rsa(ENGINE *e);
|
|
||||||
|
|
||||||
TSS2_RC esys_ctx_init (ESYS_CONTEXT **esys_ctx);
|
|
||||||
|
|
||||||
TSS2_RC esys_ctx_free (ESYS_CONTEXT **esys_ctx);
|
|
||||||
|
|
||||||
TSS2_RC init_tpm_parent ( ESYS_CONTEXT **esys_ctx,
|
|
||||||
TPM2_HANDLE parentHandle,
|
|
||||||
ESYS_TR *parent);
|
|
||||||
|
|
||||||
TSS2_RC init_tpm_key ( ESYS_CONTEXT **esys_ctx,
|
|
||||||
ESYS_TR *keyHandle,
|
|
||||||
TPM2_DATA *tpm2Data);
|
|
||||||
|
|
||||||
#define ENGINE_HASH_ALG TPM2_ALG_SHA256
|
|
||||||
|
|
||||||
#define TPM2B_PUBLIC_PRIMARY_RSA_TEMPLATE { \
|
|
||||||
.publicArea = { \
|
|
||||||
.type = TPM2_ALG_RSA, \
|
|
||||||
.nameAlg = ENGINE_HASH_ALG, \
|
|
||||||
.objectAttributes = (TPMA_OBJECT_USERWITHAUTH | \
|
|
||||||
TPMA_OBJECT_RESTRICTED | \
|
|
||||||
TPMA_OBJECT_DECRYPT | \
|
|
||||||
TPMA_OBJECT_NODA | \
|
|
||||||
TPMA_OBJECT_FIXEDTPM | \
|
|
||||||
TPMA_OBJECT_FIXEDPARENT | \
|
|
||||||
TPMA_OBJECT_SENSITIVEDATAORIGIN), \
|
|
||||||
.authPolicy = { \
|
|
||||||
.size = 0, \
|
|
||||||
}, \
|
|
||||||
.parameters.rsaDetail = { \
|
|
||||||
.symmetric = { \
|
|
||||||
.algorithm = TPM2_ALG_AES, \
|
|
||||||
.keyBits.aes = 128, \
|
|
||||||
.mode.aes = TPM2_ALG_CFB, \
|
|
||||||
}, \
|
|
||||||
.scheme = { \
|
|
||||||
.scheme = TPM2_ALG_NULL, \
|
|
||||||
.details = {} \
|
|
||||||
}, \
|
|
||||||
.keyBits = 2048, \
|
|
||||||
.exponent = 0,\
|
|
||||||
}, \
|
|
||||||
.unique.rsa = { \
|
|
||||||
.size = 0, \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The parameters of this key can never be changed because they are
|
|
||||||
* part of the interoperable 'standard' form for TSS2 PEM keys.
|
|
||||||
* Where the parent key is ephemeral and generated on demand, it
|
|
||||||
* has to be generated precisely the *same* every time or it cannot
|
|
||||||
* work. The ECC primary is used for *all* keys regardless of their
|
|
||||||
* type.
|
|
||||||
*/
|
|
||||||
#define TPM2B_PUBLIC_PRIMARY_ECC_TEMPLATE { \
|
|
||||||
.publicArea = { \
|
|
||||||
.type = TPM2_ALG_ECC, \
|
|
||||||
.nameAlg = ENGINE_HASH_ALG, \
|
|
||||||
.objectAttributes = (TPMA_OBJECT_USERWITHAUTH | \
|
|
||||||
TPMA_OBJECT_RESTRICTED | \
|
|
||||||
TPMA_OBJECT_DECRYPT | \
|
|
||||||
TPMA_OBJECT_NODA | \
|
|
||||||
TPMA_OBJECT_FIXEDTPM | \
|
|
||||||
TPMA_OBJECT_FIXEDPARENT | \
|
|
||||||
TPMA_OBJECT_SENSITIVEDATAORIGIN), \
|
|
||||||
.authPolicy = { \
|
|
||||||
.size = 0, \
|
|
||||||
}, \
|
|
||||||
.parameters.eccDetail = { \
|
|
||||||
.symmetric = { \
|
|
||||||
.algorithm = TPM2_ALG_AES, \
|
|
||||||
.keyBits.aes = 128, \
|
|
||||||
.mode.aes = TPM2_ALG_CFB, \
|
|
||||||
}, \
|
|
||||||
.scheme = { \
|
|
||||||
.scheme = TPM2_ALG_NULL, \
|
|
||||||
.details = {} \
|
|
||||||
}, \
|
|
||||||
.curveID = TPM2_ECC_NIST_P256, \
|
|
||||||
.kdf = { \
|
|
||||||
.scheme = TPM2_ALG_NULL, \
|
|
||||||
.details = {} \
|
|
||||||
}, \
|
|
||||||
}, \
|
|
||||||
.unique.ecc = { \
|
|
||||||
.x.size = 0, \
|
|
||||||
.y.size = 0 \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ASN1_OBJECT *type;
|
|
||||||
ASN1_BOOLEAN emptyAuth;
|
|
||||||
ASN1_INTEGER *parent;
|
|
||||||
ASN1_OCTET_STRING *pubkey;
|
|
||||||
ASN1_OCTET_STRING *privkey;
|
|
||||||
} TSSPRIVKEY;
|
|
||||||
|
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(TSSPRIVKEY);
|
|
||||||
|
|
||||||
DECLARE_PEM_write_bio(TSSPRIVKEY, TSSPRIVKEY);
|
|
||||||
DECLARE_PEM_read_bio(TSSPRIVKEY, TSSPRIVKEY);
|
|
||||||
|
|
||||||
#define OID_loadableKey "2.23.133.10.1.3"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
T2TE_ATOMIC_INT refcount;
|
|
||||||
ESYS_CONTEXT *esys_ctx;
|
|
||||||
ESYS_TR key_handle;
|
|
||||||
int privatetype;
|
|
||||||
} TPM2_SIG_KEY_CTX;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TPM2_SIG_KEY_CTX *key;
|
|
||||||
TPM2_ALG_ID hash_alg;
|
|
||||||
ESYS_TR seq_handle;
|
|
||||||
size_t sig_size;
|
|
||||||
} TPM2_SIG_DATA;
|
|
||||||
|
|
||||||
int
|
|
||||||
digest_update(EVP_MD_CTX *ctx, const void *data, size_t count);
|
|
||||||
int
|
|
||||||
digest_finish(TPM2_SIG_DATA *data, TPM2B_DIGEST **digest,
|
|
||||||
TPMT_TK_HASHCHECK **validation);
|
|
||||||
int
|
|
||||||
digest_sign_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx, TPM2_DATA *tpm2data,
|
|
||||||
size_t sig_size);
|
|
||||||
int
|
|
||||||
digest_sign_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
|
|
||||||
void
|
|
||||||
digest_sign_cleanup(EVP_PKEY_CTX *ctx);
|
|
||||||
|
|
||||||
#endif /* TPM2_TSS_ENGINE_COMMON_H */
|
|
||||||
@ -1,315 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2021, Graphiant, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
#ifndef TPM2_TSS_ENGINE_HAVE_C11_ATOMICS
|
|
||||||
/* fall back to using GCC/clang atomic builtins */
|
|
||||||
# define atomic_fetch_add(PTR, VAL) \
|
|
||||||
__atomic_fetch_add((PTR), (VAL), __ATOMIC_SEQ_CST)
|
|
||||||
#define atomic_fetch_sub(PTR, VAL) \
|
|
||||||
__atomic_fetch_sub ((PTR), (VAL), __ATOMIC_SEQ_CST)
|
|
||||||
#endif /* TPM2_TSS_ENGINE_HAVE_C11_ATOMICS */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise a digest operation for digest and sign.
|
|
||||||
*
|
|
||||||
* @param ctx OpenSSL message digest context
|
|
||||||
* @param data Digest and sign data
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
digest_init(EVP_MD_CTX *ctx, TPM2_SIG_DATA *data)
|
|
||||||
{
|
|
||||||
TPM2B_AUTH null_auth = { .size = 0 };
|
|
||||||
const EVP_MD *md;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
md = EVP_MD_CTX_md(ctx);
|
|
||||||
if (!md) {
|
|
||||||
ERR(digest_init, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (EVP_MD_type(md)) {
|
|
||||||
case NID_sha1:
|
|
||||||
data->hash_alg = TPM2_ALG_SHA1;
|
|
||||||
break;
|
|
||||||
case NID_sha256:
|
|
||||||
data->hash_alg = TPM2_ALG_SHA256;
|
|
||||||
break;
|
|
||||||
case NID_sha384:
|
|
||||||
data->hash_alg = TPM2_ALG_SHA384;
|
|
||||||
break;
|
|
||||||
case NID_sha512:
|
|
||||||
data->hash_alg = TPM2_ALG_SHA512;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR(digest_init, TPM2TSS_R_UNKNOWN_ALG);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = Esys_HashSequenceStart(data->key->esys_ctx, ESYS_TR_NONE,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, &null_auth,
|
|
||||||
data->hash_alg, &data->seq_handle);
|
|
||||||
ERRchktss(digest_init, r, return 0);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a digest with more data
|
|
||||||
*
|
|
||||||
* @param ctx OpenSSL message digest context
|
|
||||||
* @param data Data to add to digest
|
|
||||||
* @param count Length of data to add
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
|
||||||
{
|
|
||||||
EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(ctx);
|
|
||||||
TPM2_SIG_DATA *sig_data = EVP_PKEY_CTX_get_app_data(pctx);
|
|
||||||
const uint8_t *current_data = data;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
DBG("digest_update %p %p\n", pctx, ctx);
|
|
||||||
|
|
||||||
while (count > 0) {
|
|
||||||
TPM2B_MAX_BUFFER digest_data = { .size = count };
|
|
||||||
if (digest_data.size > sizeof(digest_data.buffer))
|
|
||||||
digest_data.size = sizeof(digest_data.buffer);
|
|
||||||
memcpy(&digest_data.buffer[0], current_data, digest_data.size);
|
|
||||||
current_data += digest_data.size;
|
|
||||||
count -= digest_data.size;
|
|
||||||
|
|
||||||
r = Esys_SequenceUpdate(sig_data->key->esys_ctx, sig_data->seq_handle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE,
|
|
||||||
ESYS_TR_NONE, &digest_data);
|
|
||||||
ERRchktss(digest_update, r, return 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish a digest operation for digest and sign
|
|
||||||
*
|
|
||||||
* @param data Digest and sign data
|
|
||||||
* @param digest Digest calculated by TPM
|
|
||||||
* @param validation Validation ticket for the digest calculated by TPM
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
digest_finish(TPM2_SIG_DATA *data, TPM2B_DIGEST **digest,
|
|
||||||
TPMT_TK_HASHCHECK **validation)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
r = Esys_SequenceComplete(data->key->esys_ctx, data->seq_handle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE,
|
|
||||||
ESYS_TR_NONE, NULL, ESYS_TR_RH_OWNER,
|
|
||||||
digest, validation);
|
|
||||||
ERRchktss(digest_finish, r, return 0);
|
|
||||||
|
|
||||||
/* Esys_SequenceComplete consumes the handle */
|
|
||||||
data->seq_handle = ESYS_TR_NONE;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise a digest and sign operation
|
|
||||||
*
|
|
||||||
* @param ctx OpenSSL pkey context
|
|
||||||
* @param mctx OpenSSL message digest context
|
|
||||||
* @param tpm2data TPM data for the key to use
|
|
||||||
* @param sig_size Size of the signature data
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
digest_sign_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx, TPM2_DATA *tpm2data,
|
|
||||||
size_t sig_size)
|
|
||||||
{
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
if (!tpm2data)
|
|
||||||
/* non-TPM key - nothing to do */
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
TPM2_SIG_DATA *data = OPENSSL_malloc(sizeof(*data));
|
|
||||||
if (!data) {
|
|
||||||
ERR(digest_sign_init, ERR_R_MALLOC_FAILURE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->seq_handle = ESYS_TR_NONE;
|
|
||||||
data->sig_size = sig_size;
|
|
||||||
|
|
||||||
data->key = OPENSSL_malloc(sizeof(*data->key));
|
|
||||||
if (!data->key) {
|
|
||||||
ERR(digest_sign_init, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->key->refcount = 1;
|
|
||||||
|
|
||||||
r = init_tpm_key(&data->key->esys_ctx, &data->key->key_handle, tpm2data);
|
|
||||||
ERRchktss(digest_sign_init, r, goto error);
|
|
||||||
data->key->privatetype = tpm2data->privatetype;
|
|
||||||
|
|
||||||
EVP_PKEY_CTX_set_app_data(ctx, data);
|
|
||||||
/*
|
|
||||||
* Override the update function so that the TPM performs the
|
|
||||||
* digest, which is required for restricted keys - the TPM will
|
|
||||||
* reject a null validation ticket in this case for the signing
|
|
||||||
* operation.
|
|
||||||
*/
|
|
||||||
EVP_MD_CTX_set_update_fn(mctx, digest_update);
|
|
||||||
|
|
||||||
if (!digest_init(mctx, data))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (data->key) {
|
|
||||||
if (data->key->key_handle != ESYS_TR_NONE) {
|
|
||||||
if (data->key->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(data->key->esys_ctx, &data->key->key_handle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(data->key->esys_ctx, data->key->key_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data->key->esys_ctx)
|
|
||||||
esys_ctx_free(&data->key->esys_ctx);
|
|
||||||
OPENSSL_free(data->key);
|
|
||||||
}
|
|
||||||
OPENSSL_free(data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy digest and sign context
|
|
||||||
*
|
|
||||||
* @param dst Destination OpenSSL pkey context
|
|
||||||
* @param src Source OpenSSL pkey context
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
digest_sign_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
|
||||||
{
|
|
||||||
TPM2_SIG_DATA *src_sig_data = EVP_PKEY_CTX_get_app_data(src);
|
|
||||||
TPMS_CONTEXT *context = NULL;
|
|
||||||
TPM2_SIG_DATA *dst_sig_data = NULL;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
if (src_sig_data) {
|
|
||||||
dst_sig_data = OPENSSL_malloc(sizeof(*dst_sig_data));
|
|
||||||
if (!dst_sig_data) {
|
|
||||||
ERR(digest_sign_copy, ERR_R_MALLOC_FAILURE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_sig_data->hash_alg = src_sig_data->hash_alg;
|
|
||||||
dst_sig_data->sig_size = src_sig_data->sig_size;
|
|
||||||
|
|
||||||
if (src_sig_data->seq_handle != ESYS_TR_NONE) {
|
|
||||||
/* duplicate sequence handle */
|
|
||||||
|
|
||||||
r = Esys_ContextSave(src_sig_data->key->esys_ctx,
|
|
||||||
src_sig_data->seq_handle, &context);
|
|
||||||
ERRchktss(digest_sign_copy, r, goto error);
|
|
||||||
dst_sig_data->seq_handle = ESYS_TR_NONE;
|
|
||||||
r = Esys_ContextLoad(src_sig_data->key->esys_ctx, context,
|
|
||||||
&dst_sig_data->seq_handle);
|
|
||||||
ERRchktss(digest_sign_copy, r, goto error);
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_sig_data->key = src_sig_data->key;
|
|
||||||
atomic_fetch_add(&dst_sig_data->key->refcount, 1);
|
|
||||||
|
|
||||||
EVP_PKEY_CTX_set_app_data(dst, dst_sig_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Esys_Free(context);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
error:
|
|
||||||
Esys_Free(context);
|
|
||||||
OPENSSL_free(dst_sig_data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up digest and sign context
|
|
||||||
*
|
|
||||||
* @param ctx OpenSSL pkey context
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
digest_sign_cleanup(EVP_PKEY_CTX *ctx)
|
|
||||||
{
|
|
||||||
TPM2_SIG_DATA *sig_data = EVP_PKEY_CTX_get_app_data(ctx);
|
|
||||||
|
|
||||||
if (sig_data) {
|
|
||||||
if (sig_data->seq_handle != ESYS_TR_NONE)
|
|
||||||
Esys_FlushContext(sig_data->key->esys_ctx, sig_data->seq_handle);
|
|
||||||
|
|
||||||
if (atomic_fetch_sub(&sig_data->key->refcount, 1) == 1) {
|
|
||||||
if (sig_data->key->key_handle != ESYS_TR_NONE) {
|
|
||||||
if (sig_data->key->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(sig_data->key->esys_ctx,
|
|
||||||
&sig_data->key->key_handle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(sig_data->key->esys_ctx,
|
|
||||||
sig_data->key->key_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
esys_ctx_free(&sig_data->key->esys_ctx);
|
|
||||||
OPENSSL_free(sig_data->key);
|
|
||||||
}
|
|
||||||
OPENSSL_free(sig_data);
|
|
||||||
EVP_PKEY_CTX_set_app_data(ctx, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,875 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
#include <openssl/ecdsa.h>
|
|
||||||
|
|
||||||
#include <tss2/tss2_mu.h>
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
static int ec_key_app_data = -1;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
const ECDSA_METHOD *ecc_method_default = NULL;
|
|
||||||
ECDSA_METHOD *ecc_methods = NULL;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
const EC_KEY_METHOD *ecc_method_default = NULL;
|
|
||||||
EC_KEY_METHOD *ecc_methods = NULL;
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
static int (*ecdsa_pkey_orig_copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
|
|
||||||
static void (*ecdsa_pkey_orig_cleanup)(EVP_PKEY_CTX *ctx);
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
static TPM2B_DATA allOutsideInfo = {
|
|
||||||
.size = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPML_PCR_SELECTION allCreationPCR = {
|
|
||||||
.count = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPM2B_PUBLIC keyEcTemplate = {
|
|
||||||
.publicArea = {
|
|
||||||
.type = TPM2_ALG_ECC,
|
|
||||||
.nameAlg = ENGINE_HASH_ALG,
|
|
||||||
.objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
|
|
||||||
TPMA_OBJECT_SIGN_ENCRYPT |
|
|
||||||
TPMA_OBJECT_FIXEDTPM |
|
|
||||||
TPMA_OBJECT_FIXEDPARENT |
|
|
||||||
TPMA_OBJECT_SENSITIVEDATAORIGIN |
|
|
||||||
TPMA_OBJECT_NODA),
|
|
||||||
.parameters.eccDetail = {
|
|
||||||
.curveID = 0, /* To be filled out later */
|
|
||||||
.symmetric = {
|
|
||||||
.algorithm = TPM2_ALG_NULL,
|
|
||||||
.keyBits.aes = 0,
|
|
||||||
.mode.aes = 0,
|
|
||||||
},
|
|
||||||
.scheme = {
|
|
||||||
.scheme = TPM2_ALG_NULL,
|
|
||||||
.details = {}
|
|
||||||
},
|
|
||||||
.kdf = {
|
|
||||||
.scheme = TPM2_ALG_NULL,
|
|
||||||
.details = {}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.unique.ecc = {
|
|
||||||
.x.size = 0,
|
|
||||||
.y.size = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
static int EC_GROUP_order_bits(const EC_GROUP *group)
|
|
||||||
{
|
|
||||||
if (!group)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
BIGNUM *order = BN_new();
|
|
||||||
|
|
||||||
if (order == NULL) {
|
|
||||||
ERR_clear_error();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!EC_GROUP_get_order(group, order, NULL)) {
|
|
||||||
ERR_clear_error();
|
|
||||||
BN_free(order);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = BN_num_bits(order);
|
|
||||||
BN_free(order);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
/**
|
|
||||||
* Initialize a TPM2B_ECC_POINT from an OpenSSL EC_POINT.
|
|
||||||
*
|
|
||||||
* @param point Pointer to output tpm point
|
|
||||||
* @param pub_key OpenSSL public key to convert
|
|
||||||
* @param group Curve group
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
init_tpm_public_point(TPM2B_ECC_POINT *point, const EC_POINT *ec_point,
|
|
||||||
const EC_GROUP *ec_group)
|
|
||||||
{
|
|
||||||
unsigned char buffer[1 + sizeof(point->point.x.buffer)
|
|
||||||
+ sizeof(point->point.y.buffer)] = {0};
|
|
||||||
|
|
||||||
BN_CTX *ctx = BN_CTX_new();
|
|
||||||
if (!ctx)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
BN_CTX_start(ctx);
|
|
||||||
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
// first, check for actual buffer size required
|
|
||||||
if ((len = EC_POINT_point2oct(ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx)) <= sizeof(buffer)) {
|
|
||||||
len = EC_POINT_point2oct(ec_group, ec_point,
|
|
||||||
POINT_CONVERSION_UNCOMPRESSED, buffer, sizeof(buffer), ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
BN_CTX_free(ctx);
|
|
||||||
|
|
||||||
if (len == 0 || len > sizeof(buffer))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
len = (len - 1) / 2;
|
|
||||||
|
|
||||||
point->point.x.size = len;
|
|
||||||
point->point.y.size = len;
|
|
||||||
memcpy(point->point.x.buffer, &buffer[1], len);
|
|
||||||
memcpy(point->point.y.buffer, &buffer[1 + len], len);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a shared secret using a TPM key
|
|
||||||
*
|
|
||||||
* @param psec Pointer to output buffer holding shared secret
|
|
||||||
* @param pseclen Size of the psec buffer
|
|
||||||
* @param pub_key The peer's public key
|
|
||||||
* @param ecdh The ECC key object for the host private key
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
ecdh_compute_key(unsigned char **psec, size_t *pseclen,
|
|
||||||
const EC_POINT *pub_key, const EC_KEY *eckey)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If this is not a TPM2 key, bail out since fall through to software
|
|
||||||
* functions requires a non-const EC_KEY, yet the ECDH prototype only
|
|
||||||
* provides it as const.
|
|
||||||
*/
|
|
||||||
TPM2_DATA *tpm2Data = tpm2tss_ecc_getappdata(eckey);
|
|
||||||
if (tpm2Data == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
TPM2B_ECC_POINT inPoint;
|
|
||||||
TPM2B_ECC_POINT *outPoint = NULL;
|
|
||||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
|
||||||
|
|
||||||
int ret = init_tpm_public_point(&inPoint, pub_key, group);
|
|
||||||
if (!ret)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR keyHandle = ESYS_TR_NONE;
|
|
||||||
TSS2_RC r = init_tpm_key(&esys_ctx, &keyHandle, tpm2Data);
|
|
||||||
ERRchktss(ecdh_compute_key, r, goto error);
|
|
||||||
|
|
||||||
r = Esys_ECDH_ZGen(esys_ctx, keyHandle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&inPoint, &outPoint);
|
|
||||||
ERRchktss(ecdh_compute_key, r, goto error);
|
|
||||||
|
|
||||||
*pseclen = outPoint->point.x.size;
|
|
||||||
*psec = OPENSSL_malloc(*pseclen);
|
|
||||||
if (!*psec)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
memcpy(*psec, outPoint->point.x.buffer, *pseclen);
|
|
||||||
ret = 1;
|
|
||||||
goto out;
|
|
||||||
error:
|
|
||||||
ret = 0;
|
|
||||||
out:
|
|
||||||
if (keyHandle != ESYS_TR_NONE) {
|
|
||||||
if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(esys_ctx, keyHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Esys_Free(outPoint);
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
static ECDSA_SIG *
|
|
||||||
ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle,
|
|
||||||
TPM2B_DIGEST *digest, TPMT_TK_HASHCHECK *validation,
|
|
||||||
TPM2_ALG_ID hash_alg)
|
|
||||||
{
|
|
||||||
TPMT_SIG_SCHEME inScheme = {
|
|
||||||
.scheme = TPM2_ALG_ECDSA,
|
|
||||||
.details.ecdsa.hashAlg = hash_alg,
|
|
||||||
};
|
|
||||||
BIGNUM *bns = NULL, *bnr = NULL;
|
|
||||||
ECDSA_SIG *ret = NULL;
|
|
||||||
TPMT_SIGNATURE *sig = NULL;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
r = Esys_Sign(esys_ctx, key_handle, ESYS_TR_PASSWORD,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, digest, &inScheme,
|
|
||||||
validation, &sig);
|
|
||||||
ERRchktss(ecdsa_sign, r, goto error);
|
|
||||||
|
|
||||||
ret = ECDSA_SIG_new();
|
|
||||||
if (ret == NULL) {
|
|
||||||
ERR(ecdsa_sign, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
bns = BN_bin2bn(&sig->signature.ecdsa.signatureS.buffer[0],
|
|
||||||
sig->signature.ecdsa.signatureS.size, NULL);
|
|
||||||
bnr = BN_bin2bn(&sig->signature.ecdsa.signatureR.buffer[0],
|
|
||||||
sig->signature.ecdsa.signatureR.size, NULL);
|
|
||||||
if (!bns || !bnr) {
|
|
||||||
ERR(ecdsa_sign, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
ret->s = bns;
|
|
||||||
ret->r = bnr;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
ECDSA_SIG_set0(ret, bnr, bns);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (bns)
|
|
||||||
BN_free(bns);
|
|
||||||
if (bnr)
|
|
||||||
BN_free(bnr);
|
|
||||||
if (ret)
|
|
||||||
ECDSA_SIG_free(ret);
|
|
||||||
ret = NULL;
|
|
||||||
out:
|
|
||||||
Esys_Free(sig);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sign data using a TPM key
|
|
||||||
*
|
|
||||||
* This function performs the sign function using the private key in ECDSA.
|
|
||||||
* This operation is usually used to perform signature and authentication
|
|
||||||
* operations.
|
|
||||||
* @param dgst The data to be signed.
|
|
||||||
* @param dgst_len Length of the from buffer.
|
|
||||||
* @param inv Ignored
|
|
||||||
* @param rp Ignored
|
|
||||||
* @param eckey The ECC key object.
|
|
||||||
* @retval 0 on failure
|
|
||||||
* @retval size Size of the returned signature
|
|
||||||
*/
|
|
||||||
static ECDSA_SIG *
|
|
||||||
ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
|
||||||
const BIGNUM *rp, EC_KEY *eckey)
|
|
||||||
{
|
|
||||||
ECDSA_SIG *ret = NULL;
|
|
||||||
TPM2_DATA *tpm2Data = tpm2tss_ecc_getappdata(eckey);
|
|
||||||
TPM2_ALG_ID hash_alg;
|
|
||||||
|
|
||||||
/* If this is not a TPM2 key, fall through to software functions */
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
ECDSA_set_method(eckey, ecc_method_default);
|
|
||||||
ret = ECDSA_do_sign_ex(dgst, dgst_len, inv, rp, eckey);
|
|
||||||
ECDSA_set_method(eckey, ecc_methods);
|
|
||||||
return ret;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
EC_KEY_set_method(eckey, ecc_method_default);
|
|
||||||
ret = ECDSA_do_sign_ex(dgst, dgst_len, inv, rp, eckey);
|
|
||||||
EC_KEY_set_method(eckey, ecc_methods);
|
|
||||||
return ret;
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("ecdsa_sign called for input data(size=%i):\n", dgst_len);
|
|
||||||
DBGBUF(dgst, dgst_len);
|
|
||||||
|
|
||||||
TSS2_RC r;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR keyHandle = ESYS_TR_NONE;
|
|
||||||
|
|
||||||
TPMT_TK_HASHCHECK validation = { .tag = TPM2_ST_HASHCHECK,
|
|
||||||
.hierarchy = TPM2_RH_NULL,
|
|
||||||
.digest.size = 0 };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ECDSA signatures truncate the incoming hash to fit the curve,
|
|
||||||
* and the signature mechanism is the same regardless of the
|
|
||||||
* hash being used.
|
|
||||||
*
|
|
||||||
* The TPM bizarrely wants to be told the hash algorithm, and
|
|
||||||
* either it or the TSS will validate that the digest length
|
|
||||||
* matches the hash that it's told, despite it having no business
|
|
||||||
* caring about such things.
|
|
||||||
*
|
|
||||||
* So, we can truncate the digest any pretend it's any smaller
|
|
||||||
* digest that the TPM actually does support, as long as that
|
|
||||||
* digest is larger than the size of the curve.
|
|
||||||
*/
|
|
||||||
int curve_len = (EC_GROUP_order_bits(EC_KEY_get0_group(eckey)) + 7) / 8;
|
|
||||||
/* If we couldn't work it out, don't truncate */
|
|
||||||
if (!curve_len)
|
|
||||||
curve_len = dgst_len;
|
|
||||||
|
|
||||||
if (dgst_len == SHA_DIGEST_LENGTH ||
|
|
||||||
(curve_len <= SHA_DIGEST_LENGTH && dgst_len > SHA_DIGEST_LENGTH)) {
|
|
||||||
hash_alg = TPM2_ALG_SHA1;
|
|
||||||
dgst_len = SHA_DIGEST_LENGTH;
|
|
||||||
} else if (dgst_len == SHA256_DIGEST_LENGTH ||
|
|
||||||
(curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) {
|
|
||||||
hash_alg = TPM2_ALG_SHA256;
|
|
||||||
dgst_len = SHA256_DIGEST_LENGTH;
|
|
||||||
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
|
|
||||||
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
|
|
||||||
hash_alg = TPM2_ALG_SHA384;
|
|
||||||
dgst_len = SHA384_DIGEST_LENGTH;
|
|
||||||
} else if (dgst_len == SHA512_DIGEST_LENGTH ||
|
|
||||||
(curve_len <= SHA512_DIGEST_LENGTH && dgst_len > SHA512_DIGEST_LENGTH)) {
|
|
||||||
hash_alg = TPM2_ALG_SHA512;
|
|
||||||
dgst_len = SHA512_DIGEST_LENGTH;
|
|
||||||
} else {
|
|
||||||
ERR(ecdsa_sign, TPM2TSS_R_PADDING_UNKNOWN);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
TPM2B_DIGEST digest = { .size = dgst_len };
|
|
||||||
if (digest.size > sizeof(digest.buffer)) {
|
|
||||||
ERR(ecdsa_sign, TPM2TSS_R_DIGEST_TOO_LARGE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memcpy(&digest.buffer[0], dgst, digest.size);
|
|
||||||
|
|
||||||
r = init_tpm_key(&esys_ctx, &keyHandle, tpm2Data);
|
|
||||||
ERRchktss(ecdsa_sign, r, goto error);
|
|
||||||
|
|
||||||
ret = ecdsa_sign(esys_ctx, keyHandle, &digest, &validation, hash_alg);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
error:
|
|
||||||
r = -1;
|
|
||||||
out:
|
|
||||||
if (keyHandle != ESYS_TR_NONE) {
|
|
||||||
if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(esys_ctx, keyHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
return (r == TSS2_RC_SUCCESS) ? ret : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
static int
|
|
||||||
ecdsa_pkey_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
|
||||||
{
|
|
||||||
if (ecdsa_pkey_orig_copy && !ecdsa_pkey_orig_copy(dst, src))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return digest_sign_copy(dst, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ecdsa_pkey_cleanup(EVP_PKEY_CTX *ctx)
|
|
||||||
{
|
|
||||||
digest_sign_cleanup(ctx);
|
|
||||||
|
|
||||||
if (ecdsa_pkey_orig_cleanup)
|
|
||||||
ecdsa_pkey_orig_cleanup(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called for digest & sign init, after message digest algorithm set */
|
|
||||||
static int
|
|
||||||
ecdsa_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
|
||||||
{
|
|
||||||
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
|
|
||||||
EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
|
|
||||||
TPM2_DATA *tpm2data = tpm2tss_ecc_getappdata(eckey);
|
|
||||||
|
|
||||||
DBG("ecdsa_digest_custom %p %p\n", ctx, mctx);
|
|
||||||
|
|
||||||
return digest_sign_init(ctx, mctx, tpm2data, ECDSA_size(eckey));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ecdsa_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
|
||||||
EVP_MD_CTX *mctx)
|
|
||||||
{
|
|
||||||
TPM2_SIG_DATA *sig_data = EVP_PKEY_CTX_get_app_data(ctx);
|
|
||||||
TSS2_RC r = TSS2_RC_SUCCESS;
|
|
||||||
TPMT_TK_HASHCHECK *validation_ptr = NULL;
|
|
||||||
TPM2B_DIGEST *digest_ptr = NULL;
|
|
||||||
ECDSA_SIG *ecdsa_s = NULL;
|
|
||||||
|
|
||||||
DBG("ecdsa_signctx %p %p sig_data %p\n", ctx, mctx, sig_data);
|
|
||||||
|
|
||||||
if (!sig) {
|
|
||||||
/* caller just wants to know the size */
|
|
||||||
*siglen = sig_data->sig_size;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sig_data) {
|
|
||||||
/* handle non-TPM key */
|
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
|
||||||
unsigned int md_len = 0;
|
|
||||||
|
|
||||||
if (!EVP_DigestFinal_ex(mctx, md, &md_len))
|
|
||||||
return 0;
|
|
||||||
if (EVP_PKEY_sign(ctx, sig, siglen, md, md_len) <= 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!digest_finish(sig_data, &digest_ptr, &validation_ptr))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ecdsa_s = ecdsa_sign(sig_data->key->esys_ctx, sig_data->key->key_handle,
|
|
||||||
digest_ptr, validation_ptr,
|
|
||||||
sig_data->hash_alg);
|
|
||||||
if (!ecdsa_s)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
*siglen = i2d_ECDSA_SIG(ecdsa_s, &sig);
|
|
||||||
|
|
||||||
r = 1;
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error:
|
|
||||||
r = 0;
|
|
||||||
out:
|
|
||||||
ECDSA_SIG_free(ecdsa_s);
|
|
||||||
Esys_Free(digest_ptr);
|
|
||||||
Esys_Free(validation_ptr);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
/** Helper to populate the ECC key object.
|
|
||||||
*
|
|
||||||
* In order to use an ECC key object in a typical manner, all fields of the
|
|
||||||
* OpenSSL's corresponding object bust be filled. This function fills the public
|
|
||||||
* values correctly.
|
|
||||||
* @param key The key object to fill.
|
|
||||||
* @retval 0 on failure
|
|
||||||
* @retval 1 on success
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
populate_ecc(EC_KEY *key)
|
|
||||||
{
|
|
||||||
EC_GROUP *ecgroup = NULL;
|
|
||||||
int nid;
|
|
||||||
BIGNUM *x = NULL, *y = NULL;
|
|
||||||
TPM2_DATA *tpm2Data = tpm2tss_ecc_getappdata(key);
|
|
||||||
if (tpm2Data == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (tpm2Data->pub.publicArea.parameters.eccDetail.curveID) {
|
|
||||||
case TPM2_ECC_NIST_P256:
|
|
||||||
nid = EC_curve_nist2nid("P-256");
|
|
||||||
break;
|
|
||||||
case TPM2_ECC_NIST_P384:
|
|
||||||
nid = EC_curve_nist2nid("P-384");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
nid = -1;
|
|
||||||
}
|
|
||||||
if (nid < 0) {
|
|
||||||
ERR(populate_ecc, TPM2TSS_R_UNKNOWN_CURVE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ecgroup = EC_GROUP_new_by_curve_name(nid);
|
|
||||||
if (ecgroup == NULL) {
|
|
||||||
ERR(populate_ecc, TPM2TSS_R_UNKNOWN_CURVE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!EC_KEY_set_group(key, ecgroup)) {
|
|
||||||
ERR(populate_ecc, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
EC_GROUP_free(ecgroup);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);
|
|
||||||
EC_GROUP_free(ecgroup);
|
|
||||||
|
|
||||||
x = BN_bin2bn(tpm2Data->pub.publicArea.unique.ecc.x.buffer,
|
|
||||||
tpm2Data->pub.publicArea.unique.ecc.x.size, NULL);
|
|
||||||
|
|
||||||
y = BN_bin2bn(tpm2Data->pub.publicArea.unique.ecc.y.buffer,
|
|
||||||
tpm2Data->pub.publicArea.unique.ecc.y.size, NULL);
|
|
||||||
|
|
||||||
if (!x || !y) {
|
|
||||||
ERR(populate_ecc, ERR_R_MALLOC_FAILURE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EC_KEY_set_public_key_affine_coordinates(key, x, y)) {
|
|
||||||
ERR(populate_ecc, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
BN_free(y);
|
|
||||||
BN_free(x);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_free(y);
|
|
||||||
BN_free(x);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to load an ECC key from a tpm2Data
|
|
||||||
*
|
|
||||||
* This function creates a key object given a TPM2_DATA object. The resulting
|
|
||||||
* key object can then be used for signing with the tpm2tss engine. Ownership
|
|
||||||
* of the TPM2_DATA object is taken on success.
|
|
||||||
* @param tpm2Data The key data to use. Must have been allocated using
|
|
||||||
* OPENSSL_malloc.
|
|
||||||
* @retval key The key object
|
|
||||||
* @retval NULL on failure.
|
|
||||||
*/
|
|
||||||
EVP_PKEY *
|
|
||||||
tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data)
|
|
||||||
{
|
|
||||||
DBG("Creating ECC key object.\n");
|
|
||||||
|
|
||||||
EVP_PKEY *pkey;
|
|
||||||
EC_KEY *eckey;
|
|
||||||
|
|
||||||
/* create the new objects to return */
|
|
||||||
if ((pkey = EVP_PKEY_new()) == NULL) {
|
|
||||||
ERR(tpm2tss_ecc_makekey, ERR_R_MALLOC_FAILURE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((eckey = EC_KEY_new()) == NULL) {
|
|
||||||
ERR(tpm2tss_ecc_makekey, ERR_R_MALLOC_FAILURE);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
if (!ECDSA_set_method(eckey, ecc_methods)) {
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
if (!EC_KEY_set_method(eckey, ecc_methods)) {
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
EC_KEY_free(eckey);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
|
|
||||||
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
EC_KEY_free(eckey);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tpm2tss_ecc_setappdata(eckey, tpm2Data)) {
|
|
||||||
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!populate_ecc(eckey))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
DBG("Created ECC key object.\n");
|
|
||||||
|
|
||||||
return pkey;
|
|
||||||
error:
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve app data
|
|
||||||
*
|
|
||||||
* Since the ECC api (opposed to the RSA api) does not provide a standardized
|
|
||||||
* way to retrieve app data between the library and an application, this helper
|
|
||||||
* is defined
|
|
||||||
* @param key The key object
|
|
||||||
* @retval tpm2Data The corresponding TPM data
|
|
||||||
* @retval NULL on failure.
|
|
||||||
*/
|
|
||||||
TPM2_DATA *
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
tpm2tss_ecc_getappdata(EC_KEY *key)
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
tpm2tss_ecc_getappdata(const EC_KEY *key)
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
{
|
|
||||||
if (ec_key_app_data == -1) {
|
|
||||||
DBG("Module uninitialized\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
return ECDSA_get_ex_data(key, ec_key_app_data);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
return EC_KEY_get_ex_data(key, ec_key_app_data);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set app data
|
|
||||||
*
|
|
||||||
* Since the ECC api (opposed to the RSA api) does not provide a standardized
|
|
||||||
* way to set app data between the library and an application, this helper
|
|
||||||
* is defined
|
|
||||||
* @param key The key object
|
|
||||||
* @param tpm2Data The corresponding TPM data
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_ecc_setappdata(EC_KEY *key, TPM2_DATA *tpm2Data)
|
|
||||||
{
|
|
||||||
if (ec_key_app_data == -1) {
|
|
||||||
DBG("Module uninitialized\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
return ECDSA_set_ex_data(key, ec_key_app_data, tpm2Data);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
return EC_KEY_set_ex_data(key, ec_key_app_data, tpm2Data);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_ecc_appdata(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
|
|
||||||
long argl, void *argp)
|
|
||||||
{
|
|
||||||
TPM2_DATA *tpm2Data = ptr;
|
|
||||||
|
|
||||||
(void)parent;
|
|
||||||
(void)ad;
|
|
||||||
(void)idx;
|
|
||||||
(void)argl;
|
|
||||||
(void)argp;
|
|
||||||
|
|
||||||
if (!ptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generate a tpm2tss ecc key object.
|
|
||||||
*
|
|
||||||
* This function creates a new TPM ECC key. The TPM data is stored inside the
|
|
||||||
* object*s app data and can be retrieved using tpm2tss_ecc_getappdata().
|
|
||||||
* @param key The key object for the TPM ECC key to be created
|
|
||||||
* @param curve The curve to be used for the key
|
|
||||||
* @param password The Password to be set for the new key
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
|
|
||||||
TPM2_HANDLE parentHandle)
|
|
||||||
{
|
|
||||||
DBG("GenKey for ecdsa.\n");
|
|
||||||
|
|
||||||
TSS2_RC r;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR parent = ESYS_TR_NONE;
|
|
||||||
TPM2B_PUBLIC *keyPublic = NULL;
|
|
||||||
TPM2B_PRIVATE *keyPrivate = NULL;
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
TPM2B_PUBLIC inPublic = keyEcTemplate;
|
|
||||||
TPM2B_SENSITIVE_CREATE inSensitive = {
|
|
||||||
.sensitive = {
|
|
||||||
.userAuth = {
|
|
||||||
.size = 0,
|
|
||||||
},
|
|
||||||
.data = {
|
|
||||||
.size = 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR(tpm2tss_ecc_genkey, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(tpm2Data, 0, sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
inPublic.publicArea.parameters.eccDetail.curveID = curve;
|
|
||||||
|
|
||||||
if (password) {
|
|
||||||
DBG("Setting a password for the created key.\n");
|
|
||||||
if (strlen(password) > sizeof(tpm2Data->userauth.buffer) - 1 || strlen(password) > sizeof(inSensitive.sensitive.userAuth.buffer) - 1) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
tpm2Data->userauth.size = strlen(password);
|
|
||||||
memcpy(&tpm2Data->userauth.buffer[0], password,
|
|
||||||
tpm2Data->userauth.size);
|
|
||||||
|
|
||||||
inSensitive.sensitive.userAuth.size = strlen(password);
|
|
||||||
memcpy(&inSensitive.sensitive.userAuth.buffer[0], password,
|
|
||||||
strlen(password));
|
|
||||||
} else
|
|
||||||
tpm2Data->emptyAuth = 1;
|
|
||||||
|
|
||||||
r = init_tpm_parent(&esys_ctx, parentHandle, &parent);
|
|
||||||
ERRchktss(tpm2tss_ecc_genkey, r, goto error);
|
|
||||||
|
|
||||||
tpm2Data->parent = parentHandle;
|
|
||||||
|
|
||||||
DBG("Generating the ECC key inside the TPM.\n");
|
|
||||||
|
|
||||||
r = Esys_Create(esys_ctx, parent,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&inSensitive, &inPublic, &allOutsideInfo, &allCreationPCR,
|
|
||||||
&keyPrivate, &keyPublic, NULL, NULL, NULL);
|
|
||||||
ERRchktss(tpm2tss_ecc_genkey, r, goto error);
|
|
||||||
|
|
||||||
DBG("Generated the ECC key inside the TPM.\n");
|
|
||||||
|
|
||||||
tpm2Data->pub = *keyPublic;
|
|
||||||
tpm2Data->priv = *keyPrivate;
|
|
||||||
|
|
||||||
if (!tpm2tss_ecc_setappdata(key, tpm2Data)) {
|
|
||||||
ERR(tpm2tss_ecc_genkey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!populate_ecc(key)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
error:
|
|
||||||
r = -1;
|
|
||||||
tpm2tss_ecc_setappdata(key, NULL);
|
|
||||||
if (tpm2Data)
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
|
|
||||||
end:
|
|
||||||
Esys_Free(keyPrivate);
|
|
||||||
Esys_Free(keyPublic);
|
|
||||||
|
|
||||||
if (parent != ESYS_TR_NONE && !parentHandle)
|
|
||||||
Esys_FlushContext(esys_ctx, parent);
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
|
|
||||||
return (r == TSS2_RC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initialize the tpm2tss engine's ecc submodule
|
|
||||||
*
|
|
||||||
* Initialize the tpm2tss engine's submodule by setting function pointer.
|
|
||||||
* @param e The engine context.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
init_ecc(ENGINE *e)
|
|
||||||
{
|
|
||||||
(void)(e);
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
ecc_method_default = ECDSA_OpenSSL();
|
|
||||||
if (ecc_method_default == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ecc_methods = ECDSA_METHOD_new(ecc_method_default);
|
|
||||||
if (ecc_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ECDSA_METHOD_set_sign(ecc_methods, ecdsa_ec_key_sign);
|
|
||||||
|
|
||||||
if (ec_key_app_data == -1)
|
|
||||||
ec_key_app_data = ECDSA_get_ex_new_index(0, NULL, NULL, NULL,
|
|
||||||
free_ecc_appdata);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
ecc_method_default = EC_KEY_OpenSSL();
|
|
||||||
if (ecc_method_default == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ecc_methods = EC_KEY_METHOD_new(ecc_method_default);
|
|
||||||
if (ecc_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int (*orig_sign) (int, const unsigned char *, int, unsigned char *,
|
|
||||||
unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *)
|
|
||||||
= NULL;
|
|
||||||
EC_KEY_METHOD_get_sign(ecc_methods, &orig_sign, NULL, NULL);
|
|
||||||
EC_KEY_METHOD_set_sign(ecc_methods, orig_sign, NULL, ecdsa_ec_key_sign);
|
|
||||||
EC_KEY_METHOD_set_compute_key(ecc_methods, ecdh_compute_key);
|
|
||||||
|
|
||||||
if (ec_key_app_data == -1)
|
|
||||||
ec_key_app_data = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL,
|
|
||||||
free_ecc_appdata);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
#if HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
/* digest and sign support */
|
|
||||||
|
|
||||||
EVP_PKEY_METHOD *pkey_ecc_methods;
|
|
||||||
|
|
||||||
pkey_ecc_methods = EVP_PKEY_meth_new(EVP_PKEY_EC, 0);
|
|
||||||
if (pkey_ecc_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const EVP_PKEY_METHOD *pkey_orig_ecc_methods =
|
|
||||||
EVP_PKEY_meth_find(EVP_PKEY_EC);
|
|
||||||
if (pkey_orig_ecc_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
EVP_PKEY_meth_copy(pkey_ecc_methods, pkey_orig_ecc_methods);
|
|
||||||
/*
|
|
||||||
* save originals since we only override some of the pkey
|
|
||||||
* functionality, rather than reimplementing all of it
|
|
||||||
*/
|
|
||||||
EVP_PKEY_meth_get_copy(pkey_ecc_methods, &ecdsa_pkey_orig_copy);
|
|
||||||
EVP_PKEY_meth_get_cleanup(pkey_ecc_methods, &ecdsa_pkey_orig_cleanup);
|
|
||||||
|
|
||||||
EVP_PKEY_meth_set_copy(pkey_ecc_methods, ecdsa_pkey_copy);
|
|
||||||
EVP_PKEY_meth_set_cleanup(pkey_ecc_methods, ecdsa_pkey_cleanup);
|
|
||||||
EVP_PKEY_meth_set_signctx(pkey_ecc_methods, NULL, ecdsa_signctx);
|
|
||||||
EVP_PKEY_meth_set_digest_custom(pkey_ecc_methods, ecdsa_digest_custom);
|
|
||||||
EVP_PKEY_meth_add0(pkey_ecc_methods);
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <openssl/err.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine-err.h"
|
|
||||||
|
|
||||||
#define TPM2TSS_LIB_NAME "tpm2-tss-engine"
|
|
||||||
|
|
||||||
#define xstr(s) str(s)
|
|
||||||
#define str(s) #s
|
|
||||||
|
|
||||||
#define ERR_F(f) { ERR_PACK(0, TPM2TSS_F_ ## f, 0), xstr(f) }
|
|
||||||
#define ERR_R(r, s) { ERR_PACK(0, 0, r), xstr(s) }
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ERR
|
|
||||||
static ERR_STRING_DATA TPM2TSS_f[] = {
|
|
||||||
/* tpm2-tss-engine.c */
|
|
||||||
ERR_F(loadkey),
|
|
||||||
ERR_F(init_engine),
|
|
||||||
ERR_F(get_auth),
|
|
||||||
ERR_F(engine_ctrl),
|
|
||||||
/* tpm2-tss-engine-common.c */
|
|
||||||
ERR_F(tpm2tss_tpm2data_write),
|
|
||||||
ERR_F(tpm2tss_tpm2data_read),
|
|
||||||
ERR_F(tpm2tss_tpm2data_readtpm),
|
|
||||||
ERR_F(init_tpm_parent),
|
|
||||||
ERR_F(init_tpm_key),
|
|
||||||
ERR_F(esys_ctx_init),
|
|
||||||
ERR_F(esys_ctx_free),
|
|
||||||
/* tpm2-tss-engine-ecc.c */
|
|
||||||
ERR_F(ecdsa_sign),
|
|
||||||
ERR_F(populate_ecc),
|
|
||||||
ERR_F(tpm2tss_ecc_genkey),
|
|
||||||
ERR_F(tpm2tss_ecc_makekey),
|
|
||||||
/* tpm2-tss-engine-rand.c */
|
|
||||||
ERR_F(rand_bytes),
|
|
||||||
ERR_F(rand_seed),
|
|
||||||
/* tpm2-tss-engine-rsa.c */
|
|
||||||
ERR_F(rsa_priv_enc),
|
|
||||||
ERR_F(rsa_priv_dec),
|
|
||||||
ERR_F(tpm2tss_rsa_genkey),
|
|
||||||
ERR_F(populate_rsa),
|
|
||||||
{0, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static ERR_STRING_DATA TPM2TSS_r[] = {
|
|
||||||
ERR_R(TPM2TSS_R_TPM2DATA_READ_FAILED, Failed to read TPM2 data),
|
|
||||||
ERR_R(TPM2TSS_R_UNKNOWN_ALG, The algorithm is unknown (neither RSA, ECDSA)),
|
|
||||||
ERR_R(TPM2TSS_R_CANNOT_MAKE_KEY, Cannot create OpenSSL key object),
|
|
||||||
ERR_R(TPM2TSS_R_SUBINIT_FAILED, Could not initialize submodule),
|
|
||||||
ERR_R(TPM2TSS_R_FILE_WRITE, Could not create file for writing),
|
|
||||||
ERR_R(TPM2TSS_R_DATA_CORRUPTED, Data is corrupted and could not be parsed),
|
|
||||||
ERR_R(TPM2TSS_R_FILE_READ, Could not open file for reading),
|
|
||||||
ERR_R(TPM2TSS_R_PADDING_UNKNOWN, Unknown padding scheme requested),
|
|
||||||
ERR_R(TPM2TSS_R_PADDING_FAILED, Padding operation failed),
|
|
||||||
ERR_R(TPM2TSS_R_UNKNOWN_TPM_ERROR, Unknown TPM error occurred. Please check tpm2tss logs),
|
|
||||||
ERR_R(TPM2TSS_R_DIGEST_TOO_LARGE, The provided digest value is too large),
|
|
||||||
ERR_R(TPM2TSS_R_GENERAL_FAILURE, Some unknown error occurred),
|
|
||||||
ERR_R(TPM2TSS_R_UNKNOWN_CURVE, Unknown ECC curve),
|
|
||||||
ERR_R(TPM2TSS_R_UI_ERROR, User interaction),
|
|
||||||
ERR_R(TPM2TSS_R_UNKNOWN_CTRL, Unknown engine ctrl),
|
|
||||||
ERR_R(TPM2TSS_R_DL_OPEN_FAILED, Failed to open TCTI library),
|
|
||||||
ERR_R(TPM2TSS_R_DL_INVALID, The TCTI library is invalid),
|
|
||||||
/* TPM/TSS Reasons that are useful to the user */
|
|
||||||
ERR_R(TPM2TSS_R_AUTH_FAILURE, Authorization failed),
|
|
||||||
ERR_R(TPM2TSS_R_OWNER_AUTH_FAILED, Owner authorization failed),
|
|
||||||
ERR_R(TPM2TSS_R_OLD_TSS, An old TSS (<2.2) was detected and a TPM session may have leaked),
|
|
||||||
{0, NULL}
|
|
||||||
};
|
|
||||||
#endif /* OPENSSL_NO_ERR */
|
|
||||||
|
|
||||||
static int TPM2TSS_lib_error_code = 0;
|
|
||||||
static int TPM2TSS_error_init = 0;
|
|
||||||
|
|
||||||
static ERR_STRING_DATA TPM2TSS_lib_name[] = {
|
|
||||||
{0, TPM2TSS_LIB_NAME},
|
|
||||||
{0, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Load TPM2TSS error string
|
|
||||||
*
|
|
||||||
* Load the errorstring from TPM2TSS_f and TPM2TSS_r into OpenSSL's error
|
|
||||||
* handling stack.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ERR_load_TPM2TSS_strings(void)
|
|
||||||
{
|
|
||||||
if (TPM2TSS_lib_error_code == 0)
|
|
||||||
TPM2TSS_lib_error_code = ERR_get_next_error_library();
|
|
||||||
|
|
||||||
if (!TPM2TSS_error_init) {
|
|
||||||
TPM2TSS_error_init = 1;
|
|
||||||
#ifndef OPENSSL_NO_ERR
|
|
||||||
ERR_load_strings(TPM2TSS_lib_error_code, TPM2TSS_f);
|
|
||||||
ERR_load_strings(TPM2TSS_lib_error_code, TPM2TSS_r);
|
|
||||||
#endif /* OPENSSL_NO_ERR */
|
|
||||||
|
|
||||||
TPM2TSS_lib_name->error = ERR_PACK(TPM2TSS_lib_error_code, 0, 0);
|
|
||||||
ERR_load_strings(0, TPM2TSS_lib_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unload TPM2TSS error string
|
|
||||||
*
|
|
||||||
* Unload the errorstring from TPM2TSS_f and TPM2TSS_r into OpenSSL's error
|
|
||||||
* handling stack.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ERR_unload_TPM2TSS_strings(void)
|
|
||||||
{
|
|
||||||
if (TPM2TSS_error_init) {
|
|
||||||
#ifndef OPENSSL_NO_ERR
|
|
||||||
ERR_unload_strings(TPM2TSS_lib_error_code, TPM2TSS_f);
|
|
||||||
ERR_unload_strings(TPM2TSS_lib_error_code, TPM2TSS_r);
|
|
||||||
#endif /* OPENSSL_NO_ERR */
|
|
||||||
|
|
||||||
ERR_unload_strings(0, TPM2TSS_lib_name);
|
|
||||||
TPM2TSS_error_init = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add error to error stack
|
|
||||||
*
|
|
||||||
* Add the error to the error stack of OpenSSL.
|
|
||||||
* This function is usually not called directly but using the macros ERR(f,r)
|
|
||||||
* or ERRchktss(f, r, s) from source code.
|
|
||||||
* @param function Identifier of the function invocing the error.
|
|
||||||
* @param reason Identifier of the reason for the error.
|
|
||||||
* @param file File from which the error originates.
|
|
||||||
* @param line Line inside the file from which the error originates.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ERR_error(int function, int reason, const char *file, int line)
|
|
||||||
{
|
|
||||||
(void)(function);
|
|
||||||
(void)(file);
|
|
||||||
(void)(line);
|
|
||||||
if (TPM2TSS_lib_error_code == 0)
|
|
||||||
TPM2TSS_lib_error_code = ERR_get_next_error_library();
|
|
||||||
ERR_PUT_error(TPM2TSS_lib_error_code, function, reason, file, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Print a buffer to stderr
|
|
||||||
*
|
|
||||||
* A helper function to print data buffers to stderr. This function is usually
|
|
||||||
* not called directly, but the macro DBGBUF() is used instead.
|
|
||||||
* @param b The buffer
|
|
||||||
* @param s The buffer's size
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
printbuf(const uint8_t *b, size_t s)
|
|
||||||
{
|
|
||||||
if (s > 1000)
|
|
||||||
return;
|
|
||||||
for (size_t i = 0; i < s; i++)
|
|
||||||
fprintf(stderr, "%02x", b[i]);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
@ -1,133 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef TPM2_TSS_ENGINE_ERR_H
|
|
||||||
#define TPM2_TSS_ENGINE_ERR_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define DBG(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
#define DBGBUF(...) printbuf(__VA_ARGS__)
|
|
||||||
void printbuf(const uint8_t *b, size_t s);
|
|
||||||
|
|
||||||
#else /* DEBUG */
|
|
||||||
#define DBG(...)
|
|
||||||
#define DBGBUF(...)
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
#define ERR(f,r) ERR_error(TPM2TSS_F_ ## f, r, __FILE__, __LINE__)
|
|
||||||
|
|
||||||
/* This macro checks for common TPM error codes which are meaningful to the
|
|
||||||
user */
|
|
||||||
#define ERRchktss(f, r, s) do { \
|
|
||||||
if (r) { \
|
|
||||||
switch(r) { \
|
|
||||||
case TSS2_ESYS_RC_MEMORY: \
|
|
||||||
ERR(f, ERR_R_MALLOC_FAILURE); \
|
|
||||||
break; \
|
|
||||||
case 0x000009a2: \
|
|
||||||
ERR(f, TPM2TSS_R_AUTH_FAILURE); \
|
|
||||||
break; \
|
|
||||||
default: \
|
|
||||||
ERR(f, TPM2TSS_R_UNKNOWN_TPM_ERROR); \
|
|
||||||
} \
|
|
||||||
s; \
|
|
||||||
} \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
void ERR_load_TPM2TSS_strings(void);
|
|
||||||
void ERR_unload_TPM2TSS_strings(void);
|
|
||||||
void ERR_error(int function, int reason, const char *file, int line);
|
|
||||||
|
|
||||||
/* Function codes */
|
|
||||||
/* tpm2-tss-engine.c */
|
|
||||||
#define TPM2TSS_F_loadkey 100
|
|
||||||
#define TPM2TSS_F_init_engine 101
|
|
||||||
#define TPM2TSS_F_get_auth 102
|
|
||||||
#define TPM2TSS_F_engine_ctrl 103
|
|
||||||
/* tpm2-tss-engine-common.c */
|
|
||||||
#define TPM2TSS_F_tpm2tss_tpm2data_write 110
|
|
||||||
#define TPM2TSS_F_tpm2tss_tpm2data_read 111
|
|
||||||
#define TPM2TSS_F_tpm2tss_tpm2data_readtpm 112
|
|
||||||
#define TPM2TSS_F_init_tpm_parent 113
|
|
||||||
#define TPM2TSS_F_init_tpm_key 114
|
|
||||||
#define TPM2TSS_F_esys_ctx_init 115
|
|
||||||
#define TPM2TSS_F_esys_ctx_free 116
|
|
||||||
/* tpm2-tss-engine-ecc.c */
|
|
||||||
#define TPM2TSS_F_ecdsa_sign 120
|
|
||||||
#define TPM2TSS_F_populate_ecc 121
|
|
||||||
#define TPM2TSS_F_tpm2tss_ecc_genkey 122
|
|
||||||
#define TPM2TSS_F_tpm2tss_ecc_makekey 123
|
|
||||||
#define TPM2TSS_F_ecdh_compute_key 124
|
|
||||||
|
|
||||||
/* tpm2-tss-engine-digest-sign.c */
|
|
||||||
#define TPM2TSS_F_digest_init 150
|
|
||||||
#define TPM2TSS_F_digest_update 151
|
|
||||||
#define TPM2TSS_F_digest_finish 152
|
|
||||||
#define TPM2TSS_F_digest_sign_init 153
|
|
||||||
#define TPM2TSS_F_digest_sign_copy 154
|
|
||||||
|
|
||||||
/* tpm2-tss-engine-rand.c */
|
|
||||||
#define TPM2TSS_F_rand_bytes 130
|
|
||||||
#define TPM2TSS_F_rand_seed 131
|
|
||||||
/* tpm2-tss-engine-rsa.c */
|
|
||||||
#define TPM2TSS_F_rsa_priv_enc 140
|
|
||||||
#define TPM2TSS_F_rsa_priv_dec 141
|
|
||||||
#define TPM2TSS_F_tpm2tss_rsa_genkey 142
|
|
||||||
#define TPM2TSS_F_populate_rsa 143
|
|
||||||
#define TPM2TSS_F_rsa_signctx 144
|
|
||||||
|
|
||||||
/* Reason codes */
|
|
||||||
#define TPM2TSS_R_TPM2DATA_READ_FAILED 100
|
|
||||||
#define TPM2TSS_R_UNKNOWN_ALG 101
|
|
||||||
#define TPM2TSS_R_CANNOT_MAKE_KEY 102
|
|
||||||
#define TPM2TSS_R_SUBINIT_FAILED 103
|
|
||||||
#define TPM2TSS_R_FILE_WRITE 104
|
|
||||||
#define TPM2TSS_R_DATA_CORRUPTED 105
|
|
||||||
#define TPM2TSS_R_FILE_READ 106
|
|
||||||
#define TPM2TSS_R_PADDING_UNKNOWN 107
|
|
||||||
#define TPM2TSS_R_PADDING_FAILED 108
|
|
||||||
#define TPM2TSS_R_UNKNOWN_TPM_ERROR 109
|
|
||||||
#define TPM2TSS_R_DIGEST_TOO_LARGE 110
|
|
||||||
#define TPM2TSS_R_GENERAL_FAILURE 111
|
|
||||||
#define TPM2TSS_R_UNKNOWN_CURVE 112
|
|
||||||
#define TPM2TSS_R_UI_ERROR 113
|
|
||||||
#define TPM2TSS_R_UNKNOWN_CTRL 114
|
|
||||||
#define TPM2TSS_R_DL_OPEN_FAILED 115
|
|
||||||
#define TPM2TSS_R_DL_INVALID 116
|
|
||||||
/* TPM/TSS Reasons that are useful to the user */
|
|
||||||
#define TPM2TSS_R_AUTH_FAILURE 150
|
|
||||||
#define TPM2TSS_R_OWNER_AUTH_FAILED 151
|
|
||||||
#define TPM2TSS_R_OLD_TSS 152
|
|
||||||
|
|
||||||
#endif /* TPM2_TSS_ENGINE_ERR_H */
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
#include <tss2/tss2_mu.h>
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
/** rand seed
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rand_seed(const void *seed, int seed_len)
|
|
||||||
{
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
r = esys_ctx_init(&esys_ctx);
|
|
||||||
ERRchktss(rand_seed, r, goto end);
|
|
||||||
|
|
||||||
TPM2B_SENSITIVE_DATA stir;
|
|
||||||
size_t offset = 0;
|
|
||||||
char *cur_data = (char*)seed;
|
|
||||||
|
|
||||||
static const size_t tpm_random_stir_max_size = 128;
|
|
||||||
while(offset < (size_t)seed_len) {
|
|
||||||
size_t left = seed_len - offset;
|
|
||||||
size_t chunk = left > tpm_random_stir_max_size ? tpm_random_stir_max_size : left;
|
|
||||||
|
|
||||||
stir.size = chunk;
|
|
||||||
memcpy(stir.buffer, cur_data + offset, chunk);
|
|
||||||
|
|
||||||
r = Esys_StirRandom(
|
|
||||||
esys_ctx,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&stir);
|
|
||||||
ERRchktss(rand_seed, r, goto end);
|
|
||||||
|
|
||||||
offset += chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
if(esys_ctx)
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
return (r == TSS2_RC_SUCCESS)? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Genereate random values
|
|
||||||
*
|
|
||||||
* Use the TPM to generate a number of random values.
|
|
||||||
* @param buf The buffer to write the random values to
|
|
||||||
* @param num The amound of random bytes to generate
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rand_bytes(unsigned char *buf, int num)
|
|
||||||
{
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
TSS2_RC r;
|
|
||||||
|
|
||||||
r = esys_ctx_init(&esys_ctx);
|
|
||||||
ERRchktss(rand_bytes, r, goto end);
|
|
||||||
|
|
||||||
TPM2B_DIGEST *b;
|
|
||||||
while (num > 0) {
|
|
||||||
r = Esys_GetRandom(esys_ctx,
|
|
||||||
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
num, &b);
|
|
||||||
ERRchktss(rand_bytes, r, goto end);
|
|
||||||
|
|
||||||
memcpy(buf, &b->buffer, b->size);
|
|
||||||
num -= b->size;
|
|
||||||
buf += b->size;
|
|
||||||
Esys_Free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
|
|
||||||
end:
|
|
||||||
return (r == TSS2_RC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the entropy status of the prng
|
|
||||||
*
|
|
||||||
* Since we provide real (TPM-based) randomness even for the pseudorand
|
|
||||||
* function, our status is allways good.
|
|
||||||
* @retval 1 allways good status
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rand_status()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static RAND_METHOD rand_methods = {
|
|
||||||
rand_seed,
|
|
||||||
rand_bytes,
|
|
||||||
NULL, /* cleanup() */
|
|
||||||
NULL, /* add() */
|
|
||||||
rand_bytes, /* pseudorand() */
|
|
||||||
rand_status /* status() */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Initialize the tpm2tss engine's rand submodule
|
|
||||||
*
|
|
||||||
* Initialize the tpm2tss engine's submodule by setting function pointer.
|
|
||||||
* @param e The engine context.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
init_rand(ENGINE *e)
|
|
||||||
{
|
|
||||||
return ENGINE_set_RAND(e, &rand_methods);
|
|
||||||
}
|
|
||||||
@ -1,813 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
#define chkerr_goto(x) if (x) { DBG("%s:%i:%s: Error 0x%04x\n", __FILE__, \
|
|
||||||
__LINE__, __func__, x); goto error; }
|
|
||||||
|
|
||||||
const RSA_METHOD *default_rsa = NULL;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
RSA_METHOD rsa_methods;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
RSA_METHOD *rsa_methods = NULL;
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
static int (*rsa_pkey_orig_copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
|
|
||||||
static void (*rsa_pkey_orig_cleanup)(EVP_PKEY_CTX *ctx);
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
static int (*rsa_orig_finish)(RSA *rsa);
|
|
||||||
|
|
||||||
static TPM2B_DATA allOutsideInfo = {
|
|
||||||
.size = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPML_PCR_SELECTION allCreationPCR = {
|
|
||||||
.count = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static TPM2B_PUBLIC keyTemplate = {
|
|
||||||
.publicArea = {
|
|
||||||
.type = TPM2_ALG_RSA,
|
|
||||||
.nameAlg = ENGINE_HASH_ALG,
|
|
||||||
.objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
|
|
||||||
TPMA_OBJECT_SIGN_ENCRYPT |
|
|
||||||
TPMA_OBJECT_DECRYPT |
|
|
||||||
TPMA_OBJECT_FIXEDTPM |
|
|
||||||
TPMA_OBJECT_FIXEDPARENT |
|
|
||||||
TPMA_OBJECT_SENSITIVEDATAORIGIN |
|
|
||||||
TPMA_OBJECT_NODA),
|
|
||||||
.authPolicy.size = 0,
|
|
||||||
.parameters.rsaDetail = {
|
|
||||||
.symmetric = {
|
|
||||||
.algorithm = TPM2_ALG_NULL,
|
|
||||||
.keyBits.aes = 0,
|
|
||||||
.mode.aes = 0,
|
|
||||||
},
|
|
||||||
.scheme = {
|
|
||||||
.scheme = TPM2_ALG_NULL,
|
|
||||||
.details = {}
|
|
||||||
},
|
|
||||||
.keyBits = 0, /* to be set by the genkey function */
|
|
||||||
.exponent = 0, /* to be set by the genkey function */
|
|
||||||
},
|
|
||||||
.unique.rsa.size = 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Sign data using a TPM key
|
|
||||||
*
|
|
||||||
* This function performs the encrypt function using the private key in RSA.
|
|
||||||
* This operation is usually used to perform signature and authentication
|
|
||||||
* operations.
|
|
||||||
* @param flen Length of the from buffer.
|
|
||||||
* @param from The data to be signed.
|
|
||||||
* @param to The buffer to write the signature to.
|
|
||||||
* @param rsa The rsa key object.
|
|
||||||
* @param padding The padding scheme to be used.
|
|
||||||
* @retval 0 on failure
|
|
||||||
* @retval size Size of the returned signature
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
TPM2_DATA *tpm2Data = RSA_get_app_data(rsa);
|
|
||||||
|
|
||||||
/* If this is not a TPM2 key, fall through to software functions */
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
DBG("Non-TPM key passed. Calling standard function.\n");
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
return default_rsa->rsa_priv_enc(flen, from, to, rsa, padding);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
return RSA_meth_get_priv_enc(default_rsa)(flen, from, to, rsa, padding);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("rsa_priv_enc called for scheme %i and input data(size=%i):\n",
|
|
||||||
padding, flen);
|
|
||||||
DBGBUF(from, flen);
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
TSS2_RC r = TSS2_RC_SUCCESS;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR keyHandle = ESYS_TR_NONE;
|
|
||||||
TPM2B_DATA label = { .size = 0 };
|
|
||||||
TPM2B_PUBLIC_KEY_RSA *sig = NULL;
|
|
||||||
TPMT_RSA_DECRYPT inScheme = { .scheme = TPM2_ALG_NULL };
|
|
||||||
|
|
||||||
TPM2B_PUBLIC_KEY_RSA digest;
|
|
||||||
digest.size = RSA_size(rsa);
|
|
||||||
if (digest.size > sizeof(digest.buffer)) {
|
|
||||||
ERR(rsa_priv_enc, TPM2TSS_R_DIGEST_TOO_LARGE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (padding) {
|
|
||||||
case RSA_PKCS1_PADDING:
|
|
||||||
ret = RSA_padding_add_PKCS1_type_1(&digest.buffer[0], digest.size,
|
|
||||||
from, flen);
|
|
||||||
break;
|
|
||||||
case RSA_X931_PADDING:
|
|
||||||
ret = RSA_padding_add_X931(&digest.buffer[0], digest.size, from, flen);
|
|
||||||
break;
|
|
||||||
case RSA_NO_PADDING:
|
|
||||||
ret = RSA_padding_add_none(&digest.buffer[0], digest.size, from, flen);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR(rsa_priv_enc, TPM2TSS_R_PADDING_UNKNOWN);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (ret <= 0) {
|
|
||||||
ERR(rsa_priv_enc, TPM2TSS_R_PADDING_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Padded digest data (size=%i):\n", digest.size);
|
|
||||||
DBGBUF(&digest.buffer[0], digest.size);
|
|
||||||
|
|
||||||
r = init_tpm_key(&esys_ctx, &keyHandle, tpm2Data);
|
|
||||||
ERRchktss(rsa_priv_enc, r, goto error);
|
|
||||||
|
|
||||||
DBG("Signing (via decrypt operation).\n");
|
|
||||||
r = Esys_RSA_Decrypt(esys_ctx, keyHandle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&digest, &inScheme, &label, &sig);
|
|
||||||
ERRchktss(rsa_priv_enc, r, goto error);
|
|
||||||
|
|
||||||
DBG("Signature done (size=%i):\n", sig->size);
|
|
||||||
DBGBUF(&sig->buffer[0], sig->size);
|
|
||||||
|
|
||||||
ret = sig->size;
|
|
||||||
if (ret > RSA_size(rsa) || ret <= 0) {
|
|
||||||
ERR(rsa_priv_enc, TPM2TSS_R_DIGEST_TOO_LARGE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memcpy(to, &sig->buffer[0], ret);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error:
|
|
||||||
r = -1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
Esys_Free(sig);
|
|
||||||
if (keyHandle != ESYS_TR_NONE) {
|
|
||||||
if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(esys_ctx, keyHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
return (r == TSS2_RC_SUCCESS) ? ret : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Decrypt data using a TPM key
|
|
||||||
*
|
|
||||||
* This function performs the decrypt function using the private key in RSA.
|
|
||||||
* @param flen Length of the from buffer.
|
|
||||||
* @param from The data to be decrypted.
|
|
||||||
* @param to The buffer to write the plaintext to.
|
|
||||||
* @param rsa The rsa key object.
|
|
||||||
* @param padding The padding scheme to be used.
|
|
||||||
* @retval 0 on failure
|
|
||||||
* @retval size Size of the returned plaintext
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA * rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
TPM2_DATA *tpm2Data = RSA_get_app_data(rsa);
|
|
||||||
|
|
||||||
/* If this is not a TPM2 key, fall through to software functions */
|
|
||||||
if (tpm2Data == NULL)
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
return default_rsa->rsa_priv_dec(flen, from, to, rsa, padding);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
return RSA_meth_get_priv_dec(default_rsa)(flen, from, to, rsa, padding);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
DBG("rsa_priv_dec called for scheme %i and input data(size=%i):\n",
|
|
||||||
padding, flen);
|
|
||||||
DBGBUF(from, flen);
|
|
||||||
|
|
||||||
TSS2_RC r;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR keyHandle = ESYS_TR_NONE;
|
|
||||||
TPM2B_DATA label = { .size = 0 };
|
|
||||||
TPM2B_PUBLIC_KEY_RSA *message = NULL;
|
|
||||||
TPMT_RSA_DECRYPT inScheme;
|
|
||||||
|
|
||||||
TPM2B_PUBLIC_KEY_RSA cipher = { .size = flen };
|
|
||||||
if (flen > (int)sizeof(cipher.buffer) || flen < 0) {
|
|
||||||
ERR(rsa_priv_dec, TPM2TSS_R_DIGEST_TOO_LARGE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memcpy(&cipher.buffer[0], from, flen);
|
|
||||||
|
|
||||||
switch (padding) {
|
|
||||||
case RSA_PKCS1_PADDING:
|
|
||||||
inScheme.scheme = TPM2_ALG_RSAES;
|
|
||||||
break;
|
|
||||||
case RSA_PKCS1_OAEP_PADDING:
|
|
||||||
inScheme.scheme = TPM2_ALG_OAEP;
|
|
||||||
inScheme.details.oaep.hashAlg = TPM2_ALG_SHA1;
|
|
||||||
break;
|
|
||||||
case RSA_NO_PADDING:
|
|
||||||
inScheme.scheme = TPM2_ALG_NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR(rsa_priv_dec, TPM2TSS_R_PADDING_UNKNOWN);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = init_tpm_key(&esys_ctx, &keyHandle, tpm2Data);
|
|
||||||
ERRchktss(rsa_priv_dec, r, goto out);
|
|
||||||
|
|
||||||
r = Esys_RSA_Decrypt(esys_ctx, keyHandle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&cipher, &inScheme, &label, &message);
|
|
||||||
ERRchktss(rsa_priv_dec, r, goto out);
|
|
||||||
|
|
||||||
DBG("Decrypted message (size=%i):\n", message->size);
|
|
||||||
DBGBUF(&message->buffer[0], message->size);
|
|
||||||
|
|
||||||
flen = message->size;
|
|
||||||
if (flen > RSA_size(rsa) || flen <= 0) {
|
|
||||||
ERR(rsa_priv_dec, TPM2TSS_R_DIGEST_TOO_LARGE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memcpy(to, &message->buffer[0], flen);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error:
|
|
||||||
r = -1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
Esys_Free(message);
|
|
||||||
if (keyHandle != ESYS_TR_NONE) {
|
|
||||||
if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
|
||||||
Esys_TR_Close(esys_ctx, &keyHandle);
|
|
||||||
} else {
|
|
||||||
Esys_FlushContext(esys_ctx, keyHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
return (r == TSS2_RC_SUCCESS) ? flen : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clean up the RSA key
|
|
||||||
*
|
|
||||||
* @param rsa The rsa key object.
|
|
||||||
* @retval 1 on success, or 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
rsa_finish(RSA *rsa)
|
|
||||||
{
|
|
||||||
TPM2_DATA *tpm2Data = RSA_get_app_data(rsa);
|
|
||||||
|
|
||||||
if (tpm2Data != NULL) {
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
RSA_set_app_data(rsa, NULL);
|
|
||||||
}
|
|
||||||
if (rsa_orig_finish) {
|
|
||||||
rsa_orig_finish(rsa);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to populate the RSA key object.
|
|
||||||
*
|
|
||||||
* In order to use an RSA key object in a typical manner, all fields of the
|
|
||||||
* OpenSSL's corresponding object bust be filled. This function fills the public
|
|
||||||
* values correctly and fill the private values with 0.
|
|
||||||
* @param rsa The key object to fill.
|
|
||||||
* @retval 0 on failure
|
|
||||||
* @retval 1 on success
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
populate_rsa(RSA *rsa)
|
|
||||||
{
|
|
||||||
TPM2_DATA *tpm2Data = RSA_get_app_data(rsa);
|
|
||||||
UINT32 exponent;
|
|
||||||
|
|
||||||
if (tpm2Data == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
exponent = tpm2Data->pub.publicArea.parameters.rsaDetail.exponent;
|
|
||||||
if (!exponent)
|
|
||||||
exponent = 0x10001;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
/* Setting the public portion of the key */
|
|
||||||
rsa->n = BN_bin2bn(tpm2Data->pub.publicArea.unique.rsa.buffer,
|
|
||||||
tpm2Data->pub.publicArea.unique.rsa.size, rsa->n);
|
|
||||||
if (rsa->n == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (rsa->e == NULL)
|
|
||||||
rsa->e = BN_new();
|
|
||||||
if (rsa->e == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->e, exponent);
|
|
||||||
|
|
||||||
/* Setting private portions to 0 values so the public key can be extracted
|
|
||||||
from the keyfile if this is desired. */
|
|
||||||
if (rsa->d == NULL)
|
|
||||||
rsa->d = BN_new();
|
|
||||||
if (rsa->d == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->d, 0);
|
|
||||||
if (rsa->p == NULL)
|
|
||||||
rsa->p = BN_new();
|
|
||||||
if (rsa->p == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->p, 0);
|
|
||||||
if (rsa->q == NULL)
|
|
||||||
rsa->q = BN_new();
|
|
||||||
if (rsa->q == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->q, 0);
|
|
||||||
if (rsa->dmp1 == NULL)
|
|
||||||
rsa->dmp1 = BN_new();
|
|
||||||
if (rsa->dmp1 == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->dmp1, 0);
|
|
||||||
if (rsa->dmq1 == NULL)
|
|
||||||
rsa->dmq1 = BN_new();
|
|
||||||
if (rsa->dmq1 == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->dmq1, 0);
|
|
||||||
if (rsa->iqmp == NULL)
|
|
||||||
rsa->iqmp = BN_new();
|
|
||||||
if (rsa->iqmp == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
BN_set_word(rsa->iqmp, 0);
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
BIGNUM *n = BN_bin2bn(tpm2Data->pub.publicArea.unique.rsa.buffer,
|
|
||||||
tpm2Data->pub.publicArea.unique.rsa.size, NULL);
|
|
||||||
BIGNUM *e = BN_new();
|
|
||||||
BIGNUM *d = BN_new();
|
|
||||||
BIGNUM *p = BN_new();
|
|
||||||
BIGNUM *q = BN_new();
|
|
||||||
BIGNUM *dmp1 = BN_new();
|
|
||||||
BIGNUM *dmq1 = BN_new();
|
|
||||||
BIGNUM *iqmp = BN_new();
|
|
||||||
|
|
||||||
if (!n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp) {
|
|
||||||
if (n)
|
|
||||||
BN_free(n);
|
|
||||||
if (e)
|
|
||||||
BN_free(e);
|
|
||||||
if (d)
|
|
||||||
BN_free(d);
|
|
||||||
if (p)
|
|
||||||
BN_free(p);
|
|
||||||
if (q)
|
|
||||||
BN_free(q);
|
|
||||||
if (dmp1)
|
|
||||||
BN_free(dmp1);
|
|
||||||
if (dmq1)
|
|
||||||
BN_free(dmq1);
|
|
||||||
if (iqmp)
|
|
||||||
BN_free(iqmp);
|
|
||||||
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_set_word(e, exponent);
|
|
||||||
BN_set_word(d, 0);
|
|
||||||
BN_set_word(p, 0);
|
|
||||||
BN_set_word(q, 0);
|
|
||||||
BN_set_word(dmp1, 0);
|
|
||||||
BN_set_word(dmq1, 0);
|
|
||||||
BN_set_word(iqmp, 0);
|
|
||||||
|
|
||||||
RSA_set0_key(rsa, n, e, d);
|
|
||||||
RSA_set0_factors(rsa, p, q);
|
|
||||||
RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to load an RSA key from a tpm2Data
|
|
||||||
*
|
|
||||||
* This function creates a key object given a TPM2_DATA object. The resulting
|
|
||||||
* key object can then be used for signing and decrypting with the tpm2tss
|
|
||||||
* engine. Ownership of the TPM2_DATA object is taken on success.
|
|
||||||
* @param tpm2Data The key data to use. Must have been allocated using
|
|
||||||
* OPENSSL_malloc.
|
|
||||||
* @retval key The key object
|
|
||||||
* @retval NULL on failure.
|
|
||||||
*/
|
|
||||||
EVP_PKEY *
|
|
||||||
tpm2tss_rsa_makekey(TPM2_DATA *tpm2Data)
|
|
||||||
{
|
|
||||||
EVP_PKEY *pkey;
|
|
||||||
RSA *rsa;
|
|
||||||
|
|
||||||
DBG("Creating RSA key object.\n");
|
|
||||||
|
|
||||||
/* create the new objects to return */
|
|
||||||
if ((pkey = EVP_PKEY_new()) == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rsa = RSA_new()) == NULL) {
|
|
||||||
ERR(populate_rsa, ERR_R_MALLOC_FAILURE);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
rsa->meth = &rsa_methods;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
RSA_set_method(rsa, rsa_methods);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
|
||||||
ERR(populate_rsa, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
RSA_free(rsa);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RSA_set_app_data(rsa, tpm2Data)) {
|
|
||||||
ERR(populate_rsa, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!populate_rsa(rsa)) {
|
|
||||||
RSA_set_app_data(rsa, NULL);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Created RSA key object.\n");
|
|
||||||
|
|
||||||
return pkey;
|
|
||||||
error:
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generate a tpm2tss rsa key object.
|
|
||||||
*
|
|
||||||
* This function creates a new TPM RSA key. The TPM data is stored inside the
|
|
||||||
* object*s app data and can be retrieved using RSA_get_app_data().
|
|
||||||
* @param rsa The key object for the TPM RSA key to be created.
|
|
||||||
* @param bits The key size
|
|
||||||
* @param e The key's exponent
|
|
||||||
* @param password The Password to be set for the new key
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tpm2tss_rsa_genkey(RSA *rsa, int bits, BIGNUM *e, char *password,
|
|
||||||
TPM2_HANDLE parentHandle)
|
|
||||||
{
|
|
||||||
DBG("Generating RSA key for %i bits keysize.\n", bits);
|
|
||||||
|
|
||||||
TSS2_RC r = TSS2_RC_SUCCESS;
|
|
||||||
ESYS_CONTEXT *esys_ctx = NULL;
|
|
||||||
ESYS_TR parent = ESYS_TR_NONE;
|
|
||||||
TPM2B_PUBLIC *keyPublic = NULL;
|
|
||||||
TPM2B_PRIVATE *keyPrivate = NULL;
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
TPM2B_PUBLIC inPublic = keyTemplate;
|
|
||||||
TPM2B_SENSITIVE_CREATE inSensitive = {
|
|
||||||
.sensitive = {
|
|
||||||
.userAuth = {
|
|
||||||
.size = 0,
|
|
||||||
},
|
|
||||||
.data = {
|
|
||||||
.size = 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR(tpm2tss_rsa_genkey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(tpm2Data, 0, sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
inPublic.publicArea.parameters.rsaDetail.keyBits = bits;
|
|
||||||
if (e)
|
|
||||||
inPublic.publicArea.parameters.rsaDetail.exponent = BN_get_word(e);
|
|
||||||
|
|
||||||
if (password) {
|
|
||||||
DBG("Setting a password for the created key.\n");
|
|
||||||
if (strlen(password) > sizeof(tpm2Data->userauth.buffer) - 1) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
tpm2Data->userauth.size = strlen(password);
|
|
||||||
memcpy(&tpm2Data->userauth.buffer[0], password,
|
|
||||||
tpm2Data->userauth.size);
|
|
||||||
|
|
||||||
inSensitive.sensitive.userAuth.size = strlen(password);
|
|
||||||
memcpy(&inSensitive.sensitive.userAuth.buffer[0], password,
|
|
||||||
strlen(password));
|
|
||||||
} else
|
|
||||||
tpm2Data->emptyAuth = 1;
|
|
||||||
|
|
||||||
r = init_tpm_parent(&esys_ctx, parentHandle, &parent);
|
|
||||||
ERRchktss(tpm2tss_rsa_genkey, r, goto error);
|
|
||||||
|
|
||||||
tpm2Data->parent = parentHandle;
|
|
||||||
|
|
||||||
DBG("Generating the RSA key inside the TPM.\n");
|
|
||||||
|
|
||||||
r = Esys_Create(esys_ctx, parent,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
&inSensitive, &inPublic, &allOutsideInfo, &allCreationPCR,
|
|
||||||
&keyPrivate, &keyPublic, NULL, NULL, NULL);
|
|
||||||
ERRchktss(tpm2tss_rsa_genkey, r, goto error);
|
|
||||||
|
|
||||||
DBG("Generated the RSA key inside the TPM.\n");
|
|
||||||
|
|
||||||
tpm2Data->pub = *keyPublic;
|
|
||||||
tpm2Data->priv = *keyPrivate;
|
|
||||||
|
|
||||||
if (!RSA_set_app_data(rsa, tpm2Data)) {
|
|
||||||
ERR(tpm2tss_rsa_genkey, TPM2TSS_R_GENERAL_FAILURE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!populate_rsa(rsa)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
error:
|
|
||||||
r = -1;
|
|
||||||
if (rsa)
|
|
||||||
RSA_set_app_data(rsa, NULL);
|
|
||||||
if (tpm2Data)
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
|
|
||||||
end:
|
|
||||||
Esys_Free(keyPrivate);
|
|
||||||
Esys_Free(keyPublic);
|
|
||||||
|
|
||||||
if (parent != ESYS_TR_NONE && !parentHandle)
|
|
||||||
Esys_FlushContext(esys_ctx, parent);
|
|
||||||
|
|
||||||
esys_ctx_free(&esys_ctx);
|
|
||||||
|
|
||||||
return (r == TSS2_RC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
RSA_METHOD rsa_methods = {
|
|
||||||
"TPM2TSS RSA methods",
|
|
||||||
NULL, /* tpm_rsa_pub_enc */
|
|
||||||
NULL, /* tpm_rsa_pub_dec */
|
|
||||||
rsa_priv_enc, /* act sign */
|
|
||||||
rsa_priv_dec, /* act decrypt */
|
|
||||||
NULL, /* rsa_mod_exp */
|
|
||||||
NULL, /* bn_mod_exp */
|
|
||||||
NULL, /* init */
|
|
||||||
NULL, /* finish */
|
|
||||||
0,
|
|
||||||
NULL, /* app_data */
|
|
||||||
NULL, /* sign */
|
|
||||||
NULL, /* verify */
|
|
||||||
NULL /* genkey */
|
|
||||||
};
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
static int
|
|
||||||
rsa_pkey_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
|
||||||
{
|
|
||||||
if (rsa_pkey_orig_copy && !rsa_pkey_orig_copy(dst, src))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return digest_sign_copy(dst, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rsa_pkey_cleanup(EVP_PKEY_CTX *ctx)
|
|
||||||
{
|
|
||||||
digest_sign_cleanup(ctx);
|
|
||||||
|
|
||||||
if (rsa_pkey_orig_cleanup)
|
|
||||||
rsa_pkey_orig_cleanup(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called for digest & sign init, after message digest algorithm set */
|
|
||||||
static int
|
|
||||||
rsa_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
|
||||||
{
|
|
||||||
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
|
|
||||||
RSA *rsa = EVP_PKEY_get0_RSA(pkey);
|
|
||||||
TPM2_DATA *tpm2data = RSA_get_app_data(rsa);
|
|
||||||
|
|
||||||
DBG("rsa_digest_custom %p %p\n", ctx, mctx);
|
|
||||||
|
|
||||||
return digest_sign_init(ctx, mctx, tpm2data, RSA_size(rsa));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rsa_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
|
||||||
EVP_MD_CTX *mctx)
|
|
||||||
{
|
|
||||||
TPM2_SIG_DATA *sig_data = EVP_PKEY_CTX_get_app_data(ctx);
|
|
||||||
TSS2_RC r = TSS2_RC_SUCCESS;
|
|
||||||
TPMT_TK_HASHCHECK *validation_ptr = NULL;
|
|
||||||
TPM2B_DIGEST *digest_ptr = NULL;
|
|
||||||
TPMT_SIGNATURE *tpm_sig = NULL;
|
|
||||||
int pad_mode;
|
|
||||||
|
|
||||||
DBG("rsa_signctx %p %p sig_data %p\n", ctx, mctx, sig_data);
|
|
||||||
|
|
||||||
if (!sig) {
|
|
||||||
/* caller just wants to know the size */
|
|
||||||
*siglen = sig_data->sig_size;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sig_data) {
|
|
||||||
/* handle non-TPM key */
|
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
|
||||||
unsigned int md_len = 0;
|
|
||||||
|
|
||||||
if (!EVP_DigestFinal_ex(mctx, md, &md_len))
|
|
||||||
return 0;
|
|
||||||
if (EVP_PKEY_sign(ctx, sig, siglen, md, md_len) <= 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EVP_PKEY_CTX_get_rsa_padding(ctx, &pad_mode) <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
TPMT_SIG_SCHEME in_scheme = {
|
|
||||||
.scheme = TPM2_ALG_NULL,
|
|
||||||
.details.rsassa.hashAlg = sig_data->hash_alg,
|
|
||||||
};
|
|
||||||
switch (pad_mode) {
|
|
||||||
case RSA_PKCS1_PADDING:
|
|
||||||
in_scheme.scheme = TPM2_ALG_RSASSA;
|
|
||||||
break;
|
|
||||||
case RSA_PKCS1_PSS_PADDING:
|
|
||||||
in_scheme.scheme = TPM2_ALG_RSAPSS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR(rsa_signctx, TPM2TSS_R_PADDING_UNKNOWN);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!digest_finish(sig_data, &digest_ptr, &validation_ptr))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = Esys_Sign(sig_data->key->esys_ctx, sig_data->key->key_handle,
|
|
||||||
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
|
||||||
digest_ptr, &in_scheme, validation_ptr, &tpm_sig);
|
|
||||||
ERRchktss(rsa_signctx, r, goto error);
|
|
||||||
|
|
||||||
memcpy(sig, tpm_sig->signature.rsassa.sig.buffer, sig_data->sig_size);
|
|
||||||
*siglen = sig_data->sig_size;
|
|
||||||
|
|
||||||
r = 1;
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error:
|
|
||||||
r = 0;
|
|
||||||
out:
|
|
||||||
Esys_Free(tpm_sig);
|
|
||||||
Esys_Free(digest_ptr);
|
|
||||||
Esys_Free(validation_ptr);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
/** Initialize the tpm2tss engine's rsa submodule
|
|
||||||
*
|
|
||||||
* Initialize the tpm2tss engine's submodule by setting function pointer.
|
|
||||||
* @param e The engine context.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
init_rsa(ENGINE *e)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000
|
|
||||||
default_rsa = RSA_PKCS1_SSLeay();
|
|
||||||
if (default_rsa == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rsa_methods.rsa_pub_enc = default_rsa->rsa_pub_enc;
|
|
||||||
rsa_methods.rsa_pub_dec = default_rsa->rsa_pub_dec;
|
|
||||||
rsa_methods.rsa_mod_exp = default_rsa->rsa_mod_exp;
|
|
||||||
rsa_methods.bn_mod_exp = default_rsa->bn_mod_exp;
|
|
||||||
|
|
||||||
if (!ENGINE_set_RSA(e, &rsa_methods))
|
|
||||||
return 0;
|
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
default_rsa = RSA_PKCS1_OpenSSL();
|
|
||||||
if (default_rsa == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rsa_methods = RSA_meth_dup(default_rsa);
|
|
||||||
RSA_meth_set1_name(rsa_methods, "TPM2TSS RSA methods");
|
|
||||||
RSA_meth_set_priv_enc(rsa_methods, rsa_priv_enc);
|
|
||||||
RSA_meth_set_priv_dec(rsa_methods, rsa_priv_dec);
|
|
||||||
rsa_orig_finish = RSA_meth_get_finish(rsa_methods);
|
|
||||||
RSA_meth_set_finish(rsa_methods, rsa_finish);
|
|
||||||
|
|
||||||
if (!ENGINE_set_RSA(e, rsa_methods))
|
|
||||||
return 0;
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
|
||||||
|
|
||||||
#if HAVE_OPENSSL_DIGEST_SIGN
|
|
||||||
/* digest and sign support */
|
|
||||||
|
|
||||||
EVP_PKEY_METHOD *pkey_rsa_methods;
|
|
||||||
|
|
||||||
pkey_rsa_methods = EVP_PKEY_meth_new(EVP_PKEY_RSA,
|
|
||||||
EVP_PKEY_FLAG_AUTOARGLEN);
|
|
||||||
if (pkey_rsa_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const EVP_PKEY_METHOD *pkey_orig_rsa_methods =
|
|
||||||
EVP_PKEY_meth_find(EVP_PKEY_RSA);
|
|
||||||
if (pkey_orig_rsa_methods == NULL)
|
|
||||||
return 0;
|
|
||||||
EVP_PKEY_meth_copy(pkey_rsa_methods, pkey_orig_rsa_methods);
|
|
||||||
/*
|
|
||||||
* save originals since we only override some of the pkey
|
|
||||||
* functionality, rather than reimplementing all of it
|
|
||||||
*/
|
|
||||||
EVP_PKEY_meth_get_copy(pkey_rsa_methods, &rsa_pkey_orig_copy);
|
|
||||||
EVP_PKEY_meth_get_cleanup(pkey_rsa_methods, &rsa_pkey_orig_cleanup);
|
|
||||||
|
|
||||||
EVP_PKEY_meth_set_copy(pkey_rsa_methods, rsa_pkey_copy);
|
|
||||||
EVP_PKEY_meth_set_cleanup(pkey_rsa_methods, rsa_pkey_cleanup);
|
|
||||||
EVP_PKEY_meth_set_signctx(pkey_rsa_methods, NULL, rsa_signctx);
|
|
||||||
EVP_PKEY_meth_set_digest_custom(pkey_rsa_methods, rsa_digest_custom);
|
|
||||||
EVP_PKEY_meth_add0(pkey_rsa_methods);
|
|
||||||
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,372 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
#include <openssl/ecdsa.h>
|
|
||||||
|
|
||||||
#include <tss2/tss2_mu.h>
|
|
||||||
#include <tss2/tss2_esys.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The identifier of the engine
|
|
||||||
*/
|
|
||||||
static const char *engine_id = "tpm2tss";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The full name of the engine
|
|
||||||
*/
|
|
||||||
static const char *engine_name = "TPM2-TSS engine for OpenSSL";
|
|
||||||
|
|
||||||
TPM2B_DIGEST ownerauth = { .size = 0 };
|
|
||||||
TPM2B_DIGEST parentauth = { .size = 0 };
|
|
||||||
|
|
||||||
char *tcti_nameconf = NULL;
|
|
||||||
|
|
||||||
/** Retrieve password
|
|
||||||
*
|
|
||||||
* Helper function to retreive a password from the user.
|
|
||||||
* @param prompt_info [in] The object name to ask the user for
|
|
||||||
* @param ui_method [in] The ui method callbacks to be used
|
|
||||||
* @param cb_data [in] The callback data for the ui
|
|
||||||
* @param auth [out] The user provided password
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
get_auth(const char *prompt_info, UI_METHOD *ui_method, void *cb_data,
|
|
||||||
TPM2B_AUTH *auth)
|
|
||||||
{
|
|
||||||
DBG("get_auth called for object %s with ui_method %p\n", prompt_info,
|
|
||||||
ui_method);
|
|
||||||
char *ui_prompt = NULL;
|
|
||||||
UI *ui = NULL;
|
|
||||||
if (!ui_method) {
|
|
||||||
ERR(get_auth, TPM2TSS_R_UI_ERROR);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ui = UI_new_method(ui_method);
|
|
||||||
if (!ui) {
|
|
||||||
ERR(get_auth, TPM2TSS_R_UI_ERROR);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ui_prompt = UI_construct_prompt(ui, "password", prompt_info);
|
|
||||||
if (!ui_prompt) {
|
|
||||||
ERR(get_auth, TPM2TSS_R_UI_ERROR);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (0 > UI_add_input_string(ui, ui_prompt, UI_INPUT_FLAG_DEFAULT_PWD,
|
|
||||||
(char *)&auth->buffer[0], 0,
|
|
||||||
sizeof(auth->buffer) - 1)) {
|
|
||||||
ERR(get_auth, TPM2TSS_R_UI_ERROR);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
UI_add_user_data(ui, cb_data);
|
|
||||||
if (0 > UI_process(ui)) {
|
|
||||||
ERR(get_auth, TPM2TSS_R_UI_ERROR);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
auth->size = strlen((char *)&auth->buffer[0]);
|
|
||||||
OPENSSL_free(ui_prompt);
|
|
||||||
UI_free(ui);
|
|
||||||
|
|
||||||
DBG("password is %s\n", (char *)&auth->buffer[0]);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
if (ui_prompt)
|
|
||||||
OPENSSL_free(ui_prompt);
|
|
||||||
if (ui)
|
|
||||||
UI_free(ui);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const ENGINE_CMD_DEFN cmd_defns[] = {
|
|
||||||
{ TPM2TSS_SET_OWNERAUTH, "SET_OWNERAUTH",
|
|
||||||
"Set the password for the owner hierarchy (default none)",
|
|
||||||
ENGINE_CMD_FLAG_STRING },
|
|
||||||
{ TPM2TSS_SET_TCTI, "SET_TCTI",
|
|
||||||
"Set the TCTI module and options (default none)",
|
|
||||||
ENGINE_CMD_FLAG_STRING },
|
|
||||||
{ TPM2TSS_SET_PARENTAUTH, "SET_PARENTAUTH",
|
|
||||||
"Set the password for the parent key (default none)",
|
|
||||||
ENGINE_CMD_FLAG_STRING },
|
|
||||||
{0, NULL, NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) ())
|
|
||||||
{
|
|
||||||
(void)(e);
|
|
||||||
(void)(i);
|
|
||||||
(void)(f);
|
|
||||||
switch (cmd) {
|
|
||||||
case TPM2TSS_SET_OWNERAUTH:
|
|
||||||
if (!p) {
|
|
||||||
DBG("Setting owner auth to empty auth.\n");
|
|
||||||
ownerauth.size = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
DBG("Setting owner auth to password.\n");
|
|
||||||
if (strlen((char *)p) > sizeof(ownerauth.buffer) - 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ownerauth.size = strlen((char *)p);
|
|
||||||
memcpy(&ownerauth.buffer[0], p, ownerauth.size);
|
|
||||||
return 1;
|
|
||||||
case TPM2TSS_SET_TCTI:
|
|
||||||
OPENSSL_free(tcti_nameconf);
|
|
||||||
if (!p) {
|
|
||||||
DBG("Setting TCTI to the ESAPI default\n");
|
|
||||||
} else {
|
|
||||||
tcti_nameconf = OPENSSL_strdup(p);
|
|
||||||
DBG("Setting TCTI option to \"%s\"\n", tcti_nameconf);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
case TPM2TSS_SET_PARENTAUTH:
|
|
||||||
if (!p) {
|
|
||||||
DBG("Setting parent auth to empty auth.\n");
|
|
||||||
parentauth.size = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
DBG("Setting parent auth to password.\n");
|
|
||||||
if (strlen((char *)p) > sizeof(parentauth.buffer) - 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
parentauth.size = strlen((char *)p);
|
|
||||||
memcpy(&parentauth.buffer[0], p, parentauth.size);
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ERR(engine_ctrl, TPM2TSS_R_UNKNOWN_CTRL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Load a TPM2TSS key
|
|
||||||
*
|
|
||||||
* This function implements the prototype for loading a key from a file.
|
|
||||||
* @param e The engine for this callback (unused).
|
|
||||||
* @param key_id The name of the file with the TPM key data.
|
|
||||||
* @param ui The ui functions for querying the user.
|
|
||||||
* @param cb_data Callback data.
|
|
||||||
*/
|
|
||||||
static EVP_PKEY *
|
|
||||||
loadkey(ENGINE *e, const char *key_id, UI_METHOD *ui, void *cb_data)
|
|
||||||
{
|
|
||||||
(void)(e);
|
|
||||||
(void)(ui);
|
|
||||||
(void)(cb_data);
|
|
||||||
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
EVP_PKEY *pkey = NULL;
|
|
||||||
|
|
||||||
DBG("Loading private key %s\n", key_id);
|
|
||||||
if (strncmp(key_id, "0x81", 4) == 0) {
|
|
||||||
uint32_t handle;
|
|
||||||
sscanf(key_id, "0x%x", &handle);
|
|
||||||
if (!tpm2tss_tpm2data_readtpm(handle, &tpm2Data)) {
|
|
||||||
ERR(loadkey, TPM2TSS_R_TPM2DATA_READ_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!tpm2tss_tpm2data_read(key_id, &tpm2Data)) {
|
|
||||||
ERR(loadkey, TPM2TSS_R_TPM2DATA_READ_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tpm2Data->emptyAuth) {
|
|
||||||
tpm2Data->userauth.size = 0;
|
|
||||||
} else {
|
|
||||||
if (!get_auth("user key", ui, cb_data, &tpm2Data->userauth)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Loaded key uses alg-id %x\n", tpm2Data->pub.publicArea.type);
|
|
||||||
|
|
||||||
switch (tpm2Data->pub.publicArea.type) {
|
|
||||||
case TPM2_ALG_RSA:
|
|
||||||
pkey = tpm2tss_rsa_makekey(tpm2Data);
|
|
||||||
break;
|
|
||||||
case TPM2_ALG_ECC:
|
|
||||||
pkey = tpm2tss_ecc_makekey(tpm2Data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR(loadkey, TPM2TSS_R_UNKNOWN_ALG);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (!pkey) {
|
|
||||||
ERR(loadkey, TPM2TSS_R_CANNOT_MAKE_KEY);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("TPM2 Key loaded\n");
|
|
||||||
|
|
||||||
return pkey;
|
|
||||||
error:
|
|
||||||
if (tpm2Data)
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initialize the tpm2tss engine
|
|
||||||
*
|
|
||||||
* Initialize the tpm2tss engine by calling each of the submodules' init
|
|
||||||
* functions for setting function pointer.
|
|
||||||
* @param e The engine context.
|
|
||||||
* @retval 1 on success
|
|
||||||
* @retval 0 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
init_engine(ENGINE *e) {
|
|
||||||
static int initialized = 0;
|
|
||||||
|
|
||||||
DBG("Initializing\n");
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
DBG("Already initialized\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
#ifdef ENABLE_TCTIENVVAR
|
|
||||||
/* Set the default TCTI option from the environment */
|
|
||||||
OPENSSL_free(tcti_nameconf);
|
|
||||||
if (getenv("TPM2TSSENGINE_TCTI")) {
|
|
||||||
tcti_nameconf = OPENSSL_strdup(getenv("TPM2TSSENGINE_TCTI"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rc = init_rand(e);
|
|
||||||
if (rc != 1) {
|
|
||||||
ERR(init_engine, TPM2TSS_R_SUBINIT_FAILED);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = init_rsa(e);
|
|
||||||
if (rc != 1) {
|
|
||||||
ERR(init_engine, TPM2TSS_R_SUBINIT_FAILED);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = init_ecc(e);
|
|
||||||
if (rc != 1) {
|
|
||||||
ERR(init_engine, TPM2TSS_R_SUBINIT_FAILED);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
initialized = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Destroys the engine context
|
|
||||||
*
|
|
||||||
* Unloads the strings of the tpm2tss engine.
|
|
||||||
* @param e The engine context (unused).
|
|
||||||
* @retval 1 for success
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
destroy_engine(ENGINE *e)
|
|
||||||
{
|
|
||||||
(void)(e);
|
|
||||||
OPENSSL_free(tcti_nameconf);
|
|
||||||
ERR_unload_TPM2TSS_strings();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** OpenSSL's method to bind an engine.
|
|
||||||
*
|
|
||||||
* This initializes the name, id and function pointers of the engine.
|
|
||||||
* @param e The TPM engine to initialize
|
|
||||||
* @param id The identifier of the engine
|
|
||||||
* @retval 0 if binding failed
|
|
||||||
* @retval 1 on success
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
bind(ENGINE *e, const char *id)
|
|
||||||
{
|
|
||||||
(void)(id);
|
|
||||||
|
|
||||||
if (!ENGINE_set_id(e, engine_id)) {
|
|
||||||
DBG("ENGINE_set_id failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
if (!ENGINE_set_name(e, engine_name)) {
|
|
||||||
DBG("ENGINE_set_name failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The init function is not allways called so we initialize crypto methods
|
|
||||||
directly from bind. */
|
|
||||||
if (!init_engine(e)) {
|
|
||||||
DBG("tpm2tss enigne initialization failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ENGINE_set_load_privkey_function(e, loadkey)) {
|
|
||||||
DBG("ENGINE_set_load_privkey_function failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ENGINE_set_destroy_function(e, destroy_engine)) {
|
|
||||||
DBG("ENGINE_set_destroy_function failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ENGINE_set_ctrl_function(e, engine_ctrl)) {
|
|
||||||
DBG("ENGINE_set_ctrl_function failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ENGINE_set_cmd_defns(e, cmd_defns)) {
|
|
||||||
DBG("ENGINE_set_cmd_defns failed\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_load_TPM2TSS_strings();
|
|
||||||
return 1;
|
|
||||||
end:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC_BIND_FN(bind)
|
|
||||||
IMPLEMENT_DYNAMIC_CHECK_FN()
|
|
||||||
@ -1,415 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. Neither the name of tpm2-tss-engine nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
/* This tool uses a different error reporting scheme than the lib. */
|
|
||||||
#undef ERR
|
|
||||||
#define VERB(...) if (opt.verbose) fprintf(stderr, __VA_ARGS__)
|
|
||||||
#define ERR(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
|
|
||||||
char *help =
|
|
||||||
"Usage: [options] <filename>\n"
|
|
||||||
"Arguments:\n"
|
|
||||||
" <filename> storage for the encrypted private key\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -a, --alg public key algorithm (rsa, ecdsa) (default: rsa)\n"
|
|
||||||
" -c, --curve curve for ecc (default: nist_p256)\n"
|
|
||||||
" -e, --exponent exponent for rsa (default: 65537)\n"
|
|
||||||
" -h, --help print help\n"
|
|
||||||
" -u, --public import a key and read its public portion from this file\n"
|
|
||||||
" -r, --private import the sensitive key portion from this file\n"
|
|
||||||
" -o, --ownerpw password for the owner hierarchy (default: none)\n"
|
|
||||||
" -p, --password password for the created key (default: none)\n"
|
|
||||||
" -P, --parent specific handle for the parent key (default: none)\n"
|
|
||||||
" -s, --keysize key size in bits for rsa (default: 2048)\n"
|
|
||||||
" -v, --verbose print verbose messages\n"
|
|
||||||
" -W, --parentpw password for the parent key (default: none)\n"
|
|
||||||
" -t, --tcti tcti configuration string (default: none)\n"
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
static const char *optstr = "a:c:e:hu:r:o:p:P:s:vW:t:";
|
|
||||||
|
|
||||||
static const struct option long_options[] = {
|
|
||||||
{"alg", required_argument, 0, 'a'},
|
|
||||||
{"curve", required_argument, 0, 'c'},
|
|
||||||
{"exponent", required_argument, 0, 'e'},
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"public", required_argument, 0, 'u'},
|
|
||||||
{"private", required_argument, 0, 'r'},
|
|
||||||
{"ownerpw", required_argument, 0, 'o'},
|
|
||||||
{"password", required_argument, 0, 'p'},
|
|
||||||
{"parent", required_argument, 0, 'P'},
|
|
||||||
{"keysize", required_argument, 0, 's'},
|
|
||||||
{"verbose", no_argument, 0, 'v'},
|
|
||||||
{"parentpw", required_argument, 0, 'W'},
|
|
||||||
{"tcti", required_argument, 0, 't'},
|
|
||||||
{0, 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct opt {
|
|
||||||
char *filename;
|
|
||||||
TPMI_ALG_PUBLIC alg;
|
|
||||||
TPMI_ECC_CURVE curve;
|
|
||||||
int exponent;
|
|
||||||
char *importpub;
|
|
||||||
char *importtpm;
|
|
||||||
char *ownerpw;
|
|
||||||
char *password;
|
|
||||||
TPM2_HANDLE parent;
|
|
||||||
char *parentpw;
|
|
||||||
int keysize;
|
|
||||||
int verbose;
|
|
||||||
char *tcti_conf;
|
|
||||||
} opt;
|
|
||||||
|
|
||||||
/** Parse and set command line options.
|
|
||||||
*
|
|
||||||
* This function parses the command line options and sets the appropriate values
|
|
||||||
* in the opt struct.
|
|
||||||
* @param argc The argument count.
|
|
||||||
* @param argv The arguments.
|
|
||||||
* @retval 0 on success
|
|
||||||
* @retval 1 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
parse_opts(int argc, char **argv)
|
|
||||||
{
|
|
||||||
/* set the default values */
|
|
||||||
opt.filename = NULL;
|
|
||||||
opt.alg = TPM2_ALG_RSA;
|
|
||||||
opt.curve = TPM2_ECC_NIST_P256;
|
|
||||||
opt.exponent = 65537;
|
|
||||||
opt.importpub = NULL;
|
|
||||||
opt.importtpm = NULL;
|
|
||||||
opt.ownerpw = NULL;
|
|
||||||
opt.password = NULL;
|
|
||||||
opt.parent = 0;
|
|
||||||
opt.parentpw = NULL;
|
|
||||||
opt.keysize = 2048;
|
|
||||||
opt.verbose = 0;
|
|
||||||
opt.tcti_conf = NULL;
|
|
||||||
|
|
||||||
/* parse the options */
|
|
||||||
int c;
|
|
||||||
int opt_idx = 0;
|
|
||||||
while (-1 != (c = getopt_long(argc, argv, optstr,
|
|
||||||
long_options, &opt_idx))) {
|
|
||||||
switch(c) {
|
|
||||||
case 'h':
|
|
||||||
printf("%s", help);
|
|
||||||
exit(0);
|
|
||||||
case 'v':
|
|
||||||
opt.verbose = 1;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
if (strcasecmp(optarg, "rsa") == 0) {
|
|
||||||
opt.alg = TPM2_ALG_RSA;
|
|
||||||
break;
|
|
||||||
} else if (strcasecmp(optarg, "ecdsa") == 0) {
|
|
||||||
opt.alg = TPM2_ALG_ECDSA;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ERR("Unknown algorithm.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
case 'c':
|
|
||||||
if (strcasecmp(optarg, "nist_p256") == 0) {
|
|
||||||
opt.curve = TPM2_ECC_NIST_P256;
|
|
||||||
break;
|
|
||||||
} else if (strcasecmp(optarg, "nist_p384") == 0) {
|
|
||||||
opt.curve = TPM2_ECC_NIST_P384;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ERR("Unknown curve.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
case 'e':
|
|
||||||
if (sscanf(optarg, "%i", &opt.exponent) != 1) {
|
|
||||||
ERR("Error parsing keysize.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
opt.importpub = optarg;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
opt.importtpm = optarg;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
opt.ownerpw = optarg;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
opt.password = optarg;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
if (sscanf(optarg, "%x", &opt.parent) != 1 &&
|
|
||||||
sscanf(optarg, "0x%x", &opt.parent) != 1 &&
|
|
||||||
sscanf(optarg, "%i", &opt.parent) != 1) {
|
|
||||||
ERR("Error parsing parent handle");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
opt.parentpw = optarg;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (sscanf(optarg, "%i", &opt.keysize) != 1) {
|
|
||||||
ERR("Error parsing keysize.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
opt.tcti_conf = optarg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR("Unknown option at index %i.\n\n", opt_idx);
|
|
||||||
ERR("%s", help);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse the non-option arguments */
|
|
||||||
if (optind >= argc) {
|
|
||||||
ERR("Missing argument <filename>.\n\n");
|
|
||||||
ERR("%s", help);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
opt.filename = argv[optind];
|
|
||||||
optind++;
|
|
||||||
|
|
||||||
if (optind < argc) {
|
|
||||||
ERR("Unknown argument provided.\n\n");
|
|
||||||
ERR("%s", help);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!opt.importpub != !!opt.importtpm) {
|
|
||||||
ERR("Import requires both --public and --private\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generate an RSA key
|
|
||||||
*
|
|
||||||
* This function calls out to generate an RSA key using the TPM.
|
|
||||||
* @retval TPM2_DATA data to be written to disk
|
|
||||||
* @retval NULL on failure
|
|
||||||
*/
|
|
||||||
static TPM2_DATA *
|
|
||||||
genkey_rsa()
|
|
||||||
{
|
|
||||||
VERB("Generating RSA key using TPM\n");
|
|
||||||
|
|
||||||
RSA *rsa = NULL;
|
|
||||||
BIGNUM *e = BN_new();
|
|
||||||
if (!e) {
|
|
||||||
ERR("out of memory\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
BN_set_word(e, opt.exponent);
|
|
||||||
|
|
||||||
rsa = RSA_new();
|
|
||||||
if (!rsa) {
|
|
||||||
ERR("out of memory\n");
|
|
||||||
BN_free(e);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!tpm2tss_rsa_genkey(rsa, opt.keysize, e, opt.password, opt.parent)) {
|
|
||||||
BN_free(e);
|
|
||||||
RSA_free(rsa);
|
|
||||||
ERR("Error: Generating key failed\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERB("Key generated\n");
|
|
||||||
|
|
||||||
TPM2_DATA *tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR("out of memory\n");
|
|
||||||
BN_free(e);
|
|
||||||
RSA_free(rsa);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(tpm2Data, RSA_get_app_data(rsa), sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
BN_free(e);
|
|
||||||
RSA_free(rsa);
|
|
||||||
|
|
||||||
return tpm2Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generate an ECDSA key
|
|
||||||
*
|
|
||||||
* This function calls out to generate an ECDSA key using the TPM.
|
|
||||||
* @retval TPM2_DATA data to be written to disk
|
|
||||||
* @retval NULL on failure
|
|
||||||
*/
|
|
||||||
static TPM2_DATA *
|
|
||||||
genkey_ecdsa()
|
|
||||||
{
|
|
||||||
EC_KEY *eckey = NULL;
|
|
||||||
|
|
||||||
eckey = EC_KEY_new();
|
|
||||||
if (!eckey) {
|
|
||||||
ERR("out of memory\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!tpm2tss_ecc_genkey(eckey, opt.curve, opt.password, opt.parent)) {
|
|
||||||
EC_KEY_free(eckey);
|
|
||||||
ERR("Error: Generating key failed\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TPM2_DATA *tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR("out of memory\n");
|
|
||||||
EC_KEY_free(eckey);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(tpm2Data, tpm2tss_ecc_getappdata(eckey), sizeof(*tpm2Data));
|
|
||||||
|
|
||||||
EC_KEY_free(eckey);
|
|
||||||
|
|
||||||
return tpm2Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Main function
|
|
||||||
*
|
|
||||||
* This function initializes OpenSSL and then calls the key generation
|
|
||||||
* functions.
|
|
||||||
* @param argc The argument count.
|
|
||||||
* @param argv The arguments.
|
|
||||||
* @retval 0 on success
|
|
||||||
* @retval 1 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (parse_opts(argc, argv) != 0)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
int r;
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
|
|
||||||
OPENSSL_config(NULL);
|
|
||||||
#else
|
|
||||||
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize the tpm2-tss engine */
|
|
||||||
ENGINE_load_dynamic();
|
|
||||||
|
|
||||||
/* Openssl 1.1.0 requires the lib-prefix for the engine_id */
|
|
||||||
ENGINE *tpm_engine = ENGINE_by_id("tpm2tss");
|
|
||||||
if (!tpm_engine)
|
|
||||||
tpm_engine = ENGINE_by_id("libtpm2tss");
|
|
||||||
if (tpm_engine == NULL) {
|
|
||||||
ERR("Could not load tpm2tss engine\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_res = ENGINE_init(tpm_engine);
|
|
||||||
VERB("Engine name: %s\nInit result: %d \n", ENGINE_get_name(tpm_engine),
|
|
||||||
init_res);
|
|
||||||
if (!init_res)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (opt.ownerpw &&
|
|
||||||
!ENGINE_ctrl(tpm_engine, TPM2TSS_SET_OWNERAUTH, 0, opt.ownerpw, NULL)) {
|
|
||||||
ERR("Could not set ownerauth\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.parentpw &&
|
|
||||||
!ENGINE_ctrl(tpm_engine, TPM2TSS_SET_PARENTAUTH, 0, opt.parentpw, NULL)) {
|
|
||||||
ERR("Could not set parentauth\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.tcti_conf &&
|
|
||||||
!ENGINE_ctrl(tpm_engine, TPM2TSS_SET_TCTI, 0, opt.tcti_conf, NULL)) {
|
|
||||||
ERR("Could not set parentauth\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.importpub && opt.importtpm) {
|
|
||||||
VERB("Importing the TPM key\n");
|
|
||||||
r = tpm2tss_tpm2data_importtpm(opt.importpub, opt.importtpm, opt.parent,
|
|
||||||
opt.password == NULL, &tpm2Data);
|
|
||||||
if (r != 1)
|
|
||||||
return 1;
|
|
||||||
} else switch (opt.alg) {
|
|
||||||
case TPM2_ALG_RSA:
|
|
||||||
VERB("Generating the rsa key\n");
|
|
||||||
tpm2Data = genkey_rsa();
|
|
||||||
break;
|
|
||||||
case TPM2_ALG_ECDSA:
|
|
||||||
VERB("Generating the ecdsa key\n");
|
|
||||||
tpm2Data = genkey_ecdsa();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tpm2Data == NULL) {
|
|
||||||
ERR("Key could not be generated.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the key to disk */
|
|
||||||
VERB("Writing key to disk\n");
|
|
||||||
|
|
||||||
if (!tpm2tss_tpm2data_write(tpm2Data, opt.filename)) {
|
|
||||||
ERR("Error writing file\n");
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
OPENSSL_free(tpm2Data);
|
|
||||||
|
|
||||||
VERB("*** SUCCESS ***\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
62
test/ecdh.sh
62
test/ecdh.sh
@ -1,62 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euf
|
|
||||||
|
|
||||||
# Create a primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
tpm2_createprimary --hierarchy=o \
|
|
||||||
--key-algorithm=ecc \
|
|
||||||
--hash-algorithm=sha256 \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
|
|
||||||
# Create an ECDH key pair
|
|
||||||
echo "Generating ECDH key pair"
|
|
||||||
ECDH_TPM_PUBKEY=ecdhtpm.pub
|
|
||||||
ECDH_TPM_KEY=ecdhtpm
|
|
||||||
tpm2_create --key-auth=abc \
|
|
||||||
--parent-context=${PARENT_CTX} \
|
|
||||||
--key-algorithm=ecc256:ecdh-sha256 \
|
|
||||||
--public=${ECDH_TPM_PUBKEY} \
|
|
||||||
--private=${ECDH_TPM_KEY} \
|
|
||||||
--attributes fixedparent\|fixedtpm\|decrypt\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load key to persistent handle
|
|
||||||
ECDH_CTX=ecdhkey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${ECDH_TPM_PUBKEY} \
|
|
||||||
--private=${ECDH_TPM_KEY} \
|
|
||||||
--key-context=${ECDH_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${ECDH_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Get public key of handle
|
|
||||||
ECDH_TPM_PUBKEY_PEM=ecdhtpm.pem
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=${ECDH_TPM_PUBKEY_PEM} --format=pem
|
|
||||||
|
|
||||||
# Generate peer key pair
|
|
||||||
ECDH_PEER_PUBKEY=echdpeer.pub
|
|
||||||
ECDH_PEER_KEY=ecdhpeer
|
|
||||||
openssl ecparam -name prime256v1 -genkey -noout -out ${ECDH_PEER_KEY}
|
|
||||||
openssl ec -in ${ECDH_PEER_KEY} -pubout -out ${ECDH_PEER_PUBKEY}
|
|
||||||
|
|
||||||
# Perform ECDH using the TPM key pair as the private key and the peer key pair as the public key
|
|
||||||
SECRET0=$(echo "abc" | openssl pkeyutl -derive -engine tpm2tss -keyform engine -inkey ${HANDLE} -peerkey ${ECDH_PEER_PUBKEY} -peerform pem -passin stdin | base64)
|
|
||||||
echo -e "TPM(prv) <-> PEER(pub): ${SECRET0}"
|
|
||||||
|
|
||||||
# Perform ECDH with the peer key pair as the private key and the TPM key pair as the public key
|
|
||||||
SECRET1=$(openssl pkeyutl -derive -inkey ${ECDH_PEER_KEY} -peerkey ${ECDH_TPM_PUBKEY_PEM} -peerform pem | base64)
|
|
||||||
echo -e "TPM(pub) <-> PEER(prv): ${SECRET1}"
|
|
||||||
|
|
||||||
# Release persistent HANDLE and remove files
|
|
||||||
tpm2_evictcontrol --object-context=${HANDLE}
|
|
||||||
rm ${ECDH_PEER_KEY} ${ECDH_PEER_PUBKEY} ${ECDH_TPM_PUBKEY} ${ECDH_TPM_KEY} ${ECDH_TPM_PUBKEY_PEM} ${ECDH_CTX}
|
|
||||||
|
|
||||||
# Ensure tpm and peer generated secrets are the same
|
|
||||||
if [ "${SECRET0}" != "${SECRET1}" ]; then
|
|
||||||
echo "secrets don't match"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata
|
|
||||||
|
|
||||||
tpm2tss-genkey -a ecdsa -c nist_p256 mykey
|
|
||||||
|
|
||||||
openssl pkeyutl -keyform engine -engine tpm2tss -inkey mykey -sign -in mydata -out mysig
|
|
||||||
|
|
||||||
R="$(openssl pkeyutl -keyform engine -engine tpm2tss -inkey mykey -verify -in mydata -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata.txt
|
|
||||||
|
|
||||||
# Create a Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=ecc \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an ECDSA key pair
|
|
||||||
echo "Generating ECDSA key pair"
|
|
||||||
TPM_ECDSA_PUBKEY=ecdsakey.pub
|
|
||||||
TPM_ECDSA_KEY=ecdsakey
|
|
||||||
tpm2_create --key-auth=abc \
|
|
||||||
--parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=ecc \
|
|
||||||
--public=${TPM_ECDSA_PUBKEY} --private=${TPM_ECDSA_KEY} \
|
|
||||||
--attributes=sign\|decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load Key to persistent handle
|
|
||||||
ECDSA_CTX=ecdsakey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${TPM_ECDSA_PUBKEY} --private=${TPM_ECDSA_KEY} \
|
|
||||||
--key-context=${ECDSA_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${ECDSA_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Signing Data
|
|
||||||
R="$(echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -sign -in mydata.txt -out mysig -passin stdin 2>&1 || true)"
|
|
||||||
if echo $R | grep "ErrorCode (0x000001c4)" > /dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Get public key of handle
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=mykey.pem --format=pem
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pem -verify -in mydata.txt -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
# Generate 2k + a bit of data
|
|
||||||
dd if=/dev/zero of=mydata.txt count=4 bs=512 status=none
|
|
||||||
echo -n "abcde12345abcde12345">>mydata.txt
|
|
||||||
|
|
||||||
# Create a Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=ecc \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an ECDSA key pair
|
|
||||||
echo "Generating ECDSA key pair"
|
|
||||||
TPM_ECDSA_PUBKEY=ecdsakey.pub
|
|
||||||
TPM_ECDSA_KEY=ecdsakey
|
|
||||||
tpm2_create --parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=ecc256:ecdsa-sha256:null \
|
|
||||||
--public=${TPM_ECDSA_PUBKEY} --private=${TPM_ECDSA_KEY} \
|
|
||||||
--attributes=sign\|restricted\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load Key to persistent handle
|
|
||||||
ECDSA_CTX=ecdsakey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${TPM_ECDSA_PUBKEY} --private=${TPM_ECDSA_KEY} \
|
|
||||||
--key-context=${ECDSA_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${ECDSA_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
tpm2_readpublic --object-context=${HANDLE}
|
|
||||||
|
|
||||||
# Digest & sign Data
|
|
||||||
openssl dgst -engine tpm2tss -keyform engine -sha256 -sign ${HANDLE} -out mysig mydata.txt
|
|
||||||
|
|
||||||
# Get public key of handle
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=mykey.pem --format=pem
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
R="$(openssl dgst -verify mykey.pem -sha256 -signature mysig mydata.txt || true)"
|
|
||||||
if ! echo $R | grep "Verified OK" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata
|
|
||||||
|
|
||||||
tpm2tss-genkey -a ecdsa -c nist_p256 -p abc mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -keyform engine -engine tpm2tss -inkey mykey -sign -in mydata -out mysig -passin stdin
|
|
||||||
|
|
||||||
R="$(echo "abc" | openssl pkeyutl -keyform engine -engine tpm2tss -inkey mykey -verify -in mydata -sigfile mysig -passin stdin || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: BSD-2 */
|
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright 2019, Fraunhofer SIT sponsored by Infineon Technologies AG
|
|
||||||
* All rights reserved.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
#include "tpm2-tss-engine-common.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_EXECINFO
|
|
||||||
#include <execinfo.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include <cmocka.h>
|
|
||||||
|
|
||||||
TSS2_RC
|
|
||||||
__wrap_Esys_Initialize()
|
|
||||||
{
|
|
||||||
printf("Esys_Initialize called\n");
|
|
||||||
#ifdef HAVE_EXECINFO
|
|
||||||
void* b[128];
|
|
||||||
backtrace_symbols_fd(b, backtrace(b, sizeof(b)/sizeof(b[0])), STDOUT_FILENO);
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_tpm2tss_tpm2data_readtpm(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
int i;
|
|
||||||
i = tpm2tss_tpm2data_readtpm(0, NULL);
|
|
||||||
assert_int_equal(i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_tpm2tss_tpm2data_read(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
int i;
|
|
||||||
i = tpm2tss_tpm2data_read("", NULL);
|
|
||||||
assert_int_equal(i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_init_tpm_parent_via_api(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
int i;
|
|
||||||
i = tpm2tss_rsa_genkey(NULL, 0, NULL, NULL, 0);
|
|
||||||
assert_int_equal(i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_init_tpm_parent(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
TSS2_RC r;
|
|
||||||
ESYS_CONTEXT *e;
|
|
||||||
ESYS_TR t;
|
|
||||||
r = init_tpm_parent(&e, -1, &t);
|
|
||||||
assert_int_not_equal(r, TSS2_RC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_init_tpm_key(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
int i;
|
|
||||||
TSS2_RC r;
|
|
||||||
i = tpm2tss_rsa_genkey(NULL, 0, NULL, NULL, 0);
|
|
||||||
assert_int_equal(i, 0);
|
|
||||||
|
|
||||||
ESYS_CONTEXT *e;
|
|
||||||
ESYS_TR t;
|
|
||||||
TPM2_DATA td = { .privatetype = KEY_TYPE_HANDLE };
|
|
||||||
r = init_tpm_key(&e, &t, &td);
|
|
||||||
assert_int_not_equal(r, TSS2_RC_SUCCESS);
|
|
||||||
//assert_int_equal(1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
const struct CMUnitTest tests[] = {
|
|
||||||
cmocka_unit_test(check_tpm2tss_tpm2data_readtpm),
|
|
||||||
cmocka_unit_test(check_tpm2tss_tpm2data_read),
|
|
||||||
cmocka_unit_test(check_init_tpm_parent_via_api),
|
|
||||||
cmocka_unit_test(check_init_tpm_parent),
|
|
||||||
cmocka_unit_test(check_init_tpm_key),
|
|
||||||
};
|
|
||||||
|
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mykey
|
|
||||||
chmod ugo-rwx mykey
|
|
||||||
|
|
||||||
R="$(openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub 2>&1 || true)"
|
|
||||||
echo $R
|
|
||||||
if ! echo $R | grep "unable to load Private Key" >/dev/null; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
R="$(tpm2tss-genkey -a ecdsa -c nist_p256 -p abc /no/such/file/path 2>&1 || true)"
|
|
||||||
echo $R
|
|
||||||
if ! echo $R | grep "Error writing file" >/dev/null; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
-----BEGIN TSS2 PRIVATE KEY-----
|
|
||||||
MIIB8gYGZ4EFCgEDoAMBAQECBIEAAAEEggEYARYAAQALAAYEcgAAABAAEAgAAAEA
|
|
||||||
AQEAyJBHMXSEunTQBWTX2uot2qnvMBEJbhuM4+/bv7Ltaz2zjFdxdSB5tLp4fJZQ
|
|
||||||
AoUggU3HmF8sOGYfHTFJeNZJRFqXdB9sotNWLrWUeMXrAxdDJitGli5n87YrCTDu
|
|
||||||
6/DbJYbw1sd4/QL0sqXgzLogU7VPJhc+el5DjjimEeN6oU99zfN1HZacPTs74h0Q
|
|
||||||
LPrL3BACc/lkg1q6ePREulRI/Atcy5g5hgApfjSB6kMrbOwzzkGiZVZpZBqfPaik
|
|
||||||
k0SjQqNZFYejfDt99PgKQHyPHfuEVrjS788jQKvRWoPTYUQCI6iJDcp5JLk0RbqV
|
|
||||||
gD68RWwhQVDCmUpq5ebP/f/47wSBwAC+ACDN2bcOjh1KxxE8YlJXVdmuwBiUL3mF
|
|
||||||
hLLNWV3HWHnoAAAQ3OnaC4u9p1bOSyUPcw7fUR4UTNbqD2cSwPPMNRslR5RhoNBP
|
|
||||||
+j6M2vlKP7UeSxZ/at8CZHtKWV+VS+Osy9Dn+wHdqa1YSvRCBgP1a75OI9jjQ+li
|
|
||||||
I64327Vq1ZEl0LIyWdCCWrISRMcVT7JPmGhtuAS4KdHztl58JV9mntQPclW3Rp4o
|
|
||||||
5M/74zf2eaTxZOBV+OxhPR77SSQQ+w==
|
|
||||||
-----END TSS2 PRIVATE KEY-----
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
openssl rand -engine tpm2tss -hex 10 >/dev/null
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata
|
|
||||||
|
|
||||||
tpm2tss-genkey -a rsa -s 2048 -p abc mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub -passin stdin
|
|
||||||
|
|
||||||
openssl pkeyutl -pubin -inkey mykey.pub -encrypt -in mydata -out mycipher
|
|
||||||
rm mydata
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -decrypt -in mycipher -out mydata -passin stdin
|
|
||||||
#this is a workaround because -decrypt sometimes exits 0 falsely
|
|
||||||
test "x$(cat mydata)" = "xabcde12345abcde12345"
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata
|
|
||||||
|
|
||||||
tpm2tss-genkey -a rsa -s 2048 -p abc mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub -passin stdin
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -sign -in mydata -out mysig -passin stdin
|
|
||||||
|
|
||||||
#this is a workaround because -verify allways exits 1
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pub -verify -in mydata -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
DIR=$(mktemp -d)
|
|
||||||
TPM_RSA_PUBKEY=${DIR}/rsakey.pub
|
|
||||||
TPM_RSA_KEY=${DIR}/rsakey
|
|
||||||
PARENT_CTX=${DIR}/primary_owner_key.ctx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">${DIR}/mydata
|
|
||||||
|
|
||||||
tpm2_startup -c || true
|
|
||||||
|
|
||||||
# Create primary key as persistent handle
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=ecc \
|
|
||||||
--key-context=${PARENT_CTX} \
|
|
||||||
--attributes="decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted"
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an RSA key pair
|
|
||||||
echo "Generating RSA key pair"
|
|
||||||
tpm2_create --key-auth=abc --parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--attributes="sign|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda"
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
tpm2tss-genkey --public ${TPM_RSA_PUBKEY} --private ${TPM_RSA_KEY} --password abc ${DIR}/mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in ${DIR}/mykey -pubout -outform pem -out ${DIR}/mykey.pub -passin stdin
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -sign -in ${DIR}/mydata -out ${DIR}/mysig -passin stdin
|
|
||||||
|
|
||||||
#this is a workaround because -verify allways exits 1
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey ${DIR}/mykey.pub -verify -in ${DIR}/mydata -sigfile ${DIR}/mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
DIR=$(mktemp -d)
|
|
||||||
TPM_RSA_PUBKEY=${DIR}/rsakey.pub
|
|
||||||
TPM_RSA_KEY=${DIR}/rsakey
|
|
||||||
PARENT_CTX=${DIR}/primary_owner_key.ctx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">${DIR}/mydata
|
|
||||||
|
|
||||||
tpm2_startup -c || true
|
|
||||||
|
|
||||||
# Create primary key as persistent handle
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${PARENT_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an RSA key pair
|
|
||||||
echo "Generating RSA key pair"
|
|
||||||
tpm2_create --key-auth=abc --parent-context=${HANDLE} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--attributes="sign|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda"
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
tpm2tss-genkey --public ${TPM_RSA_PUBKEY} --private ${TPM_RSA_KEY} --password abc --parent ${HANDLE} ${DIR}/mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in ${DIR}/mykey -pubout -outform pem -out ${DIR}/mykey.pub -passin stdin
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -sign -in ${DIR}/mydata -out ${DIR}/mysig -passin stdin
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
#this is a workaround because -verify allways exits 1
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey ${DIR}/mykey.pub -verify -in ${DIR}/mydata -sigfile ${DIR}/mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata.txt
|
|
||||||
|
|
||||||
# Create an Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load primary key to persistent handle
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${PARENT_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Generating a key underneath the persistent parent
|
|
||||||
tpm2tss-genkey -a rsa -s 2048 -p abc -P ${HANDLE} mykey
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub -passin stdin
|
|
||||||
cat mykey.pub
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -sign -in mydata.txt -out mysig -passin stdin
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
#this is a workaround because -verify allways exits 1
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pub -verify -in mydata.txt -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata.txt
|
|
||||||
|
|
||||||
# Create an Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX} --key-auth=abc
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load primary key to persistent handle
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${PARENT_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Generating a key underneath the persistent, password protected, parent
|
|
||||||
tpm2tss-genkey -a rsa -s 2048 -p abc -P ${HANDLE} -W abc mykey
|
|
||||||
|
|
||||||
cat > engine.conf <<EOF
|
|
||||||
openssl_conf = openssl_init
|
|
||||||
|
|
||||||
[openssl_init]
|
|
||||||
engines = engine_section
|
|
||||||
|
|
||||||
[engine_section]
|
|
||||||
tpm2tss = tpm2tss_section
|
|
||||||
|
|
||||||
[tpm2tss_section]
|
|
||||||
SET_PARENTAUTH = abc
|
|
||||||
EOF
|
|
||||||
|
|
||||||
export OPENSSL_CONF=engine.conf
|
|
||||||
|
|
||||||
echo "abc" | openssl rsa -engine tpm2tss -inform engine -in mykey -pubout -outform pem -out mykey.pub -passin stdin
|
|
||||||
cat mykey.pub
|
|
||||||
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey mykey -sign -in mydata.txt -out mysig -passin stdin
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
#this is a workaround because -verify allways exits 1
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pub -verify -in mydata.txt -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata.txt
|
|
||||||
|
|
||||||
# Create an Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an RSA key pair
|
|
||||||
echo "Generating RSA key pair"
|
|
||||||
TPM_RSA_PUBKEY=rsakey.pub
|
|
||||||
TPM_RSA_KEY=rsakey
|
|
||||||
tpm2_create --key-auth=abc \
|
|
||||||
--parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--attributes=sign\|decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load Key to persistent handle
|
|
||||||
RSA_CTX=rsakey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--key-context=${RSA_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${RSA_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Signing Data
|
|
||||||
echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -sign -in mydata.txt -out mysig -passin stdin
|
|
||||||
# Get public key of handle
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=mykey.pem --format=pem
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pem -verify -in mydata.txt -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
echo -n "abcde12345abcde12345">mydata.txt
|
|
||||||
|
|
||||||
# Create an Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an RSA key pair
|
|
||||||
echo "Generating RSA key pair"
|
|
||||||
TPM_RSA_PUBKEY=rsakey.pub
|
|
||||||
TPM_RSA_KEY=rsakey
|
|
||||||
tpm2_create --parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--attributes=sign\|decrypt\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load Key to persistent handle
|
|
||||||
RSA_CTX=rsakey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--key-context=${RSA_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${RSA_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Signing Data
|
|
||||||
#Actually signing should not require an auth value
|
|
||||||
if ! openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -sign -in mydata.txt -out mysig -passin file:notexists; then
|
|
||||||
#The expect script is only here, because tpm2-tss <2.2 had some bug, and thus us asking for passwords when none were required.
|
|
||||||
expect <<EOF
|
|
||||||
spawn openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -sign -in mydata.txt -out mysig -passin stdin
|
|
||||||
expect "Enter password for user key:"
|
|
||||||
send "\r\n"
|
|
||||||
expect eof
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get public key of handle
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=mykey.pem --format=pem
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
R="$(openssl pkeyutl -pubin -inkey mykey.pem -verify -in mydata.txt -sigfile mysig || true)"
|
|
||||||
if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
# Generate 2k + a bit of data
|
|
||||||
dd if=/dev/zero of=mydata.txt count=4 bs=512 status=none
|
|
||||||
echo -n "abcde12345abcde12345">>mydata.txt
|
|
||||||
|
|
||||||
# Create a Primary key pair
|
|
||||||
echo "Generating primary key"
|
|
||||||
PARENT_CTX=primary_owner_key.ctx
|
|
||||||
|
|
||||||
tpm2_createprimary --hierarchy=o --hash-algorithm=sha256 --key-algorithm=rsa \
|
|
||||||
--key-context=${PARENT_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Create an RSA key pair
|
|
||||||
echo "Generating RSA key pair"
|
|
||||||
TPM_RSA_PUBKEY=rsakey.pub
|
|
||||||
TPM_RSA_KEY=rsakey
|
|
||||||
tpm2_create --parent-context=${PARENT_CTX} \
|
|
||||||
--hash-algorithm=sha256 --key-algorithm=rsa:rsassa-sha256:null \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--attributes=sign\|restricted\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
# Load Key to persistent handle
|
|
||||||
RSA_CTX=rsakey.ctx
|
|
||||||
tpm2_load --parent-context=${PARENT_CTX} \
|
|
||||||
--public=${TPM_RSA_PUBKEY} --private=${TPM_RSA_KEY} \
|
|
||||||
--key-context=${RSA_CTX}
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${RSA_CTX} | cut -d ' ' -f 2 | head -n 1)
|
|
||||||
tpm2_flushcontext --transient-object
|
|
||||||
|
|
||||||
tpm2_readpublic --object-context=${HANDLE}
|
|
||||||
|
|
||||||
# Digest & sign Data
|
|
||||||
openssl dgst -engine tpm2tss -keyform engine -sha256 -sign ${HANDLE} -out mysig mydata.txt
|
|
||||||
|
|
||||||
# Get public key of handle
|
|
||||||
tpm2_readpublic --object-context=${HANDLE} --output=mykey.pem --format=pem
|
|
||||||
|
|
||||||
# Release persistent HANDLE
|
|
||||||
tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}
|
|
||||||
|
|
||||||
R="$(openssl dgst -verify mykey.pem -sha256 -signature mysig mydata.txt || true)"
|
|
||||||
if ! echo $R | grep "Verified OK" >/dev/null; then
|
|
||||||
echo $R
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
if openssl version | grep "OpenSSL 1.0.2" >/dev/null; then
|
|
||||||
echo "OpenSSL 1.0.2 does not load the certificate; private key mismatch ???"
|
|
||||||
exit 77
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -en "SSL CONNECTION WORKING\n">test.html
|
|
||||||
|
|
||||||
function cleanup()
|
|
||||||
{
|
|
||||||
kill -term $SERVER || true
|
|
||||||
}
|
|
||||||
|
|
||||||
openssl ecparam -genkey -name prime256v1 -noout -out ca.key
|
|
||||||
|
|
||||||
echo -e "\n\n\n\n\n\n\n" | openssl req -new -x509 -batch -extensions v3_ca -key ca.key -out ca.crt
|
|
||||||
|
|
||||||
echo -e "\n\n\n\n\n\n\n\n\n" | openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr
|
|
||||||
|
|
||||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
|
|
||||||
|
|
||||||
tpm2tss-genkey -a rsa client.tpm.key
|
|
||||||
|
|
||||||
echo -e "\n\n\n\n\n\n\n\n\n" | openssl req -new -key client.tpm.key -keyform engine -engine tpm2tss -out client.csr
|
|
||||||
|
|
||||||
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
|
|
||||||
|
|
||||||
openssl s_server -cert server.crt -key server.key -accept 8443 -verify 1 -CAfile ca.crt -WWW &
|
|
||||||
SERVER=$!
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
kill -0 $!
|
|
||||||
|
|
||||||
trap "cleanup" EXIT
|
|
||||||
|
|
||||||
# We have to sleep, such that the pipe stays open until the command is finished.
|
|
||||||
(echo -e "GET /test.html HTTP/1.1\r\n\r\n" && sleep 1) | openssl s_client -connect 127.0.0.1:8443 -cert client.crt -key client.tpm.key -engine tpm2tss -keyform engine -CAfile ca.crt
|
|
||||||
|
|
||||||
echo "SUCCESS"
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export LANG=C
|
|
||||||
export OPENSSL_ENGINES="${OPENSSL_ENGINES:=$PWD/.libs}"
|
|
||||||
export LD_LIBRARY_PATH="$OPENSSL_ENGINES:${LD_LIBRARY_PATH-}"
|
|
||||||
export PATH="$PWD:$PATH"
|
|
||||||
|
|
||||||
if [ -z "$2" ]; then
|
|
||||||
# no device passed
|
|
||||||
test_script="$(realpath "$1")"
|
|
||||||
else
|
|
||||||
test_script="$(realpath "$2")"
|
|
||||||
INTEGRATION_DEVICE=$1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating tpm2tss symlink"
|
|
||||||
ln -fs libtpm2tss.so .libs/tpm2tss.so
|
|
||||||
|
|
||||||
tmp_dir="$(mktemp --directory)"
|
|
||||||
echo "Switching to temporary directory $tmp_dir"
|
|
||||||
cd "$tmp_dir"
|
|
||||||
|
|
||||||
if [ -z "$INTEGRATION_DEVICE" ]; then
|
|
||||||
# No device is passed so the TPM simulator will be used.
|
|
||||||
for simulator in 'swtpm' 'tpm_server'; do
|
|
||||||
simulator_binary="$(command -v "$simulator")" && break
|
|
||||||
done
|
|
||||||
if [ -z "$simulator_binary" ]; then
|
|
||||||
echo 'ERROR: No TPM simulator was found on PATH'
|
|
||||||
exit 99
|
|
||||||
fi
|
|
||||||
|
|
||||||
for attempt in $(seq 9 -1 0); do
|
|
||||||
simulator_port="$(shuf --input-range 1024-65534 --head-count 1)"
|
|
||||||
echo "Starting simulator on port $simulator_port"
|
|
||||||
case "$simulator_binary" in
|
|
||||||
*swtpm) "$simulator_binary" socket --tpm2 --server port="$simulator_port" \
|
|
||||||
--ctrl type=tcp,port="$(( simulator_port + 1 ))" \
|
|
||||||
--flags not-need-init --tpmstate dir="$tmp_dir" \
|
|
||||||
--seccomp "action=none" &;;
|
|
||||||
*tpm_server) "$simulator_binary" -port "$simulator_port" &;;
|
|
||||||
esac
|
|
||||||
simulator_pid="$!"
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
if ( ss --listening --tcp --ipv4 --processes | grep "$simulator_pid" | grep --quiet "$simulator_port" &&
|
|
||||||
ss --listening --tcp --ipv4 --processes | grep "$simulator_pid" | grep --quiet "$(( simulator_port + 1 ))" )
|
|
||||||
then
|
|
||||||
echo "Simulator with PID $simulator_pid started successfully"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
echo "Failed to start simulator, the port might be in use"
|
|
||||||
kill "$simulator_pid"
|
|
||||||
|
|
||||||
if [ "$attempt" -eq 0 ]; then
|
|
||||||
echo 'ERROR: Reached maximum number of tries to start simulator, giving up'
|
|
||||||
exit 99
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
case "$simulator_binary" in
|
|
||||||
*swtpm) export TPM2TSSENGINE_TCTI="swtpm:port=$simulator_port";;
|
|
||||||
*tpm_server) export TPM2TSSENGINE_TCTI="mssim:port=$simulator_port";;
|
|
||||||
esac
|
|
||||||
export TPM2TOOLS_TCTI="$TPM2TSSENGINE_TCTI"
|
|
||||||
|
|
||||||
tpm2_startup --clear
|
|
||||||
else
|
|
||||||
# A physical TPM will be used for the integration test.
|
|
||||||
echo "Running the test with $INTEGRATION_DEVICE"
|
|
||||||
export TPM2TSSENGINE_TCTI="libtss2-tcti-device.so:$INTEGRATION_DEVICE"
|
|
||||||
export TPM2TOOLS_TCTI="$TPM2TSSENGINE_TCTI"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Starting $test_script"
|
|
||||||
"$test_script"
|
|
||||||
test_status="$?"
|
|
||||||
|
|
||||||
kill "$simulator_pid"
|
|
||||||
rm -rf "$tmp_dir"
|
|
||||||
|
|
||||||
exit "$test_status"
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -eufx
|
|
||||||
|
|
||||||
if openssl version | grep "OpenSSL 1.0.2" >/dev/null; then
|
|
||||||
echo "OpenSSL 1.0.2 does not load the certificate; private key mismatch ???"
|
|
||||||
exit 77
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -n "WORKING !!!">index.html
|
|
||||||
|
|
||||||
function cleanup()
|
|
||||||
{
|
|
||||||
kill -term $SERVER
|
|
||||||
}
|
|
||||||
|
|
||||||
tpm2tss-genkey -a ecdsa mykey
|
|
||||||
|
|
||||||
echo -e "\n\n\n\n\n\n\n" | openssl req -new -x509 -engine tpm2tss -key mykey -keyform engine -out mykey.crt
|
|
||||||
|
|
||||||
openssl s_server -www -cert mykey.crt -key mykey -keyform engine -engine tpm2tss -accept 127.0.0.1:8444 &
|
|
||||||
SERVER=$!
|
|
||||||
trap "cleanup" EXIT
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
echo "GET index.html" | openssl s_client -connect localhost:8444
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: BSD-2 */
|
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright 2021, Erik Larsson
|
|
||||||
* All rights reserved.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "tpm2-tss-engine.h"
|
|
||||||
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include <cmocka.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
check_tpm2tss_tpm2data_read(void **state)
|
|
||||||
{
|
|
||||||
(void)(state);
|
|
||||||
TPM2_DATA *tpm2Data = NULL;
|
|
||||||
int rc;
|
|
||||||
rc = tpm2tss_tpm2data_read(NEG_HANDLE_PEM, &tpm2Data);
|
|
||||||
assert_int_equal(rc, 1);
|
|
||||||
assert_int_equal(tpm2Data->parent, 0x81000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
const struct CMUnitTest tests[] = {
|
|
||||||
cmocka_unit_test(check_tpm2tss_tpm2data_read),
|
|
||||||
};
|
|
||||||
|
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
||||||
}
|
|
||||||
BIN
tpm2-tss-engine-1.1.0.tar.gz
Normal file
BIN
tpm2-tss-engine-1.1.0.tar.gz
Normal file
Binary file not shown.
88
tpm2-tss-engine.spec
Normal file
88
tpm2-tss-engine.spec
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
Name: tpm2-tss-engine
|
||||||
|
Version: 1.1.0
|
||||||
|
Release: 1
|
||||||
|
Summary: OpenSSL Engine for TPM2 devices using the tpm2-tss software stack
|
||||||
|
|
||||||
|
License: BSD
|
||||||
|
URL: https://github.com/tpm2-software/tpm2-tss-engine
|
||||||
|
Source0: https://github.com/tpm2-software/tpm2-tss-engine/releases/download/v%{version}/%{name}-%{version}.tar.gz
|
||||||
|
|
||||||
|
BuildRequires: make
|
||||||
|
BuildRequires: autoconf
|
||||||
|
BuildRequires: autoconf-archive
|
||||||
|
BuildRequires: automake
|
||||||
|
BuildRequires: libtool
|
||||||
|
BuildRequires: gcc
|
||||||
|
BuildRequires: gcc-c++
|
||||||
|
BuildRequires: pkgconfig
|
||||||
|
#BuildRequires: pandoc
|
||||||
|
BuildRequires: tpm2-tss-devel
|
||||||
|
BuildRequires: openssl-devel
|
||||||
|
|
||||||
|
Requires: openssl
|
||||||
|
Requires: tpm2-tss
|
||||||
|
|
||||||
|
%description
|
||||||
|
tpm2-tss-engine is an engine implementation for OpenSSL that uses tpm2-tss
|
||||||
|
software stack. It uses the Enhanced System API (ESAPI) interface of the
|
||||||
|
TSS 2.0 for downwards communication. It supports RSA decryption and signatures
|
||||||
|
as well as ECDSA signatures.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%autosetup -n %{name}-%{version} -p1
|
||||||
|
|
||||||
|
|
||||||
|
%build
|
||||||
|
%configure
|
||||||
|
%make_build
|
||||||
|
|
||||||
|
|
||||||
|
%install
|
||||||
|
%make_install
|
||||||
|
find %{buildroot}%{_libdir}/engines-1.1 -type f -name \*.la -exec rm {} +
|
||||||
|
find %{buildroot}%{_libdir}/engines-1.1 -type f -name \*.a -exec rm {} +
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%license LICENSE
|
||||||
|
%doc README.md CHANGELOG.md
|
||||||
|
%{_libdir}/engines-1.1/libtpm2tss.so
|
||||||
|
%{_libdir}/engines-1.1/tpm2tss.so
|
||||||
|
|
||||||
|
|
||||||
|
%package devel
|
||||||
|
Summary: Headers and libraries for building applications against tpm2-tss-engine
|
||||||
|
Requires: %{name}%{_isa} = %{version}-%{release}
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
This package contains headers and libraries for building apps applications
|
||||||
|
against tpm2-tss-engine
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%{_includedir}/tpm2-tss-engine.h
|
||||||
|
%{_mandir}/man3/tpm2tss_*.3.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%package utilities
|
||||||
|
Summary: Utility binary for openssl using tpm2-tss software stack
|
||||||
|
Requires: %{name}%{_isa} = %{version}-%{release}
|
||||||
|
|
||||||
|
%description utilities
|
||||||
|
This package contains the binary of the engine implementation for openssl that
|
||||||
|
uses the tpm2-tss software stack
|
||||||
|
|
||||||
|
%files utilities
|
||||||
|
%{_bindir}/tpm2tss-genkey
|
||||||
|
%{_datadir}/bash-completion/completions/tpm2tss-genkey
|
||||||
|
%{_mandir}/man1/tpm2tss-*.1.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Wed May 17 2023 wujiangtao<wujiangtao@xfusion.com> - 1.1.0-1
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC: Package init
|
||||||
Loading…
x
Reference in New Issue
Block a user