diff --git a/security/stx-ssl/LICENSE b/security/stx-ssl/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/security/stx-ssl/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/security/stx-ssl/centos/build_srpm.data b/security/stx-ssl/centos/build_srpm.data new file mode 100644 index 00000000..b2285b4c --- /dev/null +++ b/security/stx-ssl/centos/build_srpm.data @@ -0,0 +1,2 @@ +COPY_LIST="$PKG_BASE/files/* $PKG_BASE/LICENSE $PKG_BASE/server-csr.conf" +TIS_PATCH_VER=13 diff --git a/security/stx-ssl/centos/wrs-ssl.spec b/security/stx-ssl/centos/wrs-ssl.spec new file mode 100644 index 00000000..57cb0718 --- /dev/null +++ b/security/stx-ssl/centos/wrs-ssl.spec @@ -0,0 +1,41 @@ +Summary: wrs-ssl version 1.0.0-r2 +Name: wrs-ssl +Version: 1.0.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +BuildRequires: openssl + +Source0: LICENSE +Source1: server-csr.conf +Source2: tpmdevice-setup + +%description +Wind River Security + +%install +rm -rf $RPM_BUILD_ROOT + +RPM_BUILD_DIR_PKG="%{name}-%{version}" +mkdir -p $RPM_BUILD_DIR_PKG +CSRCONF="$RPM_BUILD_DIR_PKG/server-csr.conf" +PEMFILE="$RPM_BUILD_DIR_PKG/server-cert.pem" +cp %{SOURCE1} $CSRCONF +# generate a self signed default certificate +/usr/bin/openssl req -new -x509 -sha256 -keyout $PEMFILE -out $PEMFILE -days 365 -nodes -config $CSRCONF +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/ssl/private +install -m 400 $PEMFILE $RPM_BUILD_ROOT/%{_sysconfdir}/ssl/private/server-cert.pem + +mkdir -p $RPM_BUILD_ROOT/%{_sbindir} +install -m 700 %{SOURCE2} $RPM_BUILD_ROOT/%{_sbindir}/tpmdevice-setup + +mkdir -p $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name}-%{version} +install -m 644 %{SOURCE0} $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name}-%{version} + +%files +%defattr(-,root,root,-) +%{_sysconfdir}/* +%{_sbindir}/* +%{_defaultdocdir}/%{name}-%{version} diff --git a/security/stx-ssl/files/tpmdevice-setup b/security/stx-ssl/files/tpmdevice-setup new file mode 100644 index 00000000..5fa10772 --- /dev/null +++ b/security/stx-ssl/files/tpmdevice-setup @@ -0,0 +1,160 @@ +#!/bin/bash +# +# Copyright (c) 2013-2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# TPM setup (both active controller and remote) + +CERTIFICATE_FILE="server-cert.pem" +LOGFILE="/etc/ssl/private/.install.log" +ORIGINAL_KEY=$1 +TPM_OBJECT_CONTEXT=$2 +PUBLIC_KEY=$3 +TPM_KEY_HIERARCHY_HANDLE=0x81010002 + +if [ -z "$ORIGINAL_KEY" ] || [ -z "$TPM_OBJECT_CONTEXT" ] || [ -z "$PUBLIC_KEY" ]; then + echo "ERROR: Missing required parameters" + echo "USAGE: $0 " + exit 1 +fi + +CERTIFICATE_DIR=$(dirname "${ORIGINAL_KEY}") +export TPM_DATA_DIR=$CERTIFICATE_DIR + +# TPM specific environment +TPM_OBJECT_NAME="$CERTIFICATE_DIR/key.blob.name" +RESOURCEMGR_DEFAULT_PORT="2323" + +### Helper functions ### + +# Echo's an error and exits with provided error code +# Input : error message ($1), ret code ($2) +# Output : None +# Note : If no retcode is provided, exits with 1 +error_exit () { + echo "$1" + # remove previous object context + rm -f $TPM_OBJECT_CONTEXT &> /dev/null + exit "${2:-1}" +} + +# func: checkTPMTools +# check if the appropriate TPM2.0-tools are installed +# +# Input : None +# Output : None +checkTPMTools () { +declare -a helper_scripts=("tss2_createprimary" + "tss2_importpem" + "tss2_getcapability" + "tss2_load" + "tss2_contextsave" + "tss2_evictcontrol" + "tss2_flushcontext" + "create_tpm2_key" + "resourcemgr") +for src in "${helper_scripts[@]}"; do + if ! type "$src" &>/dev/null; then + error_exit "ERROR: Cannot find $src. Needed for TPM configuration" + fi +done +} + +startResourceMgr () { +resourcemgr &>> $LOGFILE 2>&1 & + +# ensure the resourcemgr is started +for i in {1..5} +do + sleep 0.5 + MGR_RUNNING=`pidof resourcemgr` + if [ ! -z $MGR_RUNNING ]; then + break + fi +done +[ ! -z $MGR_RUNNING ] || error_exit "Unable to start TPM resourcemgr" + +# check to see if the resourcemgr port is open +IS_OPEN=0 +for i in {1..5} +do + sleep 0.5 + _test=`netstat -an | grep $RESOURCEMGR_DEFAULT_PORT | grep -i listen` + if [ ! -z "$_test" ]; then + IS_OPEN=1 + break + fi +done +[ $IS_OPEN -ne 0 ] || error_exit "Unable to initialize resourcemgr" +} + +stopResourceMgr () { +# Kill any previous instances of resourcemgr +pkill -c -TERM resourcemgr &> /dev/null 2>&1 +} + + + +### Main ### +# remove previous object context +rm -f $TPM_OBJECT_CONTEXT &> /dev/null +rm -f $CERTIFICATE_DIR/*.bin &> /dev/null + +tpmCheck=`lsmod | grep "tpm" -c` +[ "$tpmCheck" -ne 0 ] || error_exit "TPM Kernel Module not found. Check BIOS/Kernel configuration" + +# Ensure that the appropriate TPM tool utilities are +# installed on the system +checkTPMTools + +# Confirm that this is a TPM 2.0 device +TPM_VERSION=`tss2_getcapability -cap 6 | grep TPM_PT_FAMILY_INDICATOR | awk '{print $4}' | xxd -r -p` +if [ "$TPM_VERSION" != "2.0" ]; then + error_exit "ERROR: TPM Device is not version 2.0 compatible" +fi + +# Start the Intel ResourceMgr to clear the NV +# as well as all stale transient handles in +# the endorsement hierarchy. +# Since ResourceMgr has a number of stability, +# and security issues, we will stop it after it +# initializes the NV and Handle space +startResourceMgr +stopResourceMgr + +# Create the Endorsement Primary Key hierarchy which will be used +# for wrapping the private key. Use RSA as the primary key encryption +# and SHA 256 for hashing. Allow TPM to output the object +# handle as a file context +PRIMARY_HANDLE=`tss2_createprimary -hi e -rsa -halg sha256 | grep "Handle" | awk '{print $2}'` +[ ! -z "$PRIMARY_HANDLE" ] || error_exit "Unable to create TPM Key Hierarchy" +PRIMARY_HANDLE="0x$PRIMARY_HANDLE" + +# The object context will be lost over node reboots, and needs to +# be persistently stored in TPM NV. +# evict the persistent handle if it exists previously +tss2_evictcontrol -hi o -ho $TPM_KEY_HIERARCHY_HANDLE -hp $TPM_KEY_HIERARCHY_HANDLE +tss2_evictcontrol -hi o -ho $PRIMARY_HANDLE -hp $TPM_KEY_HIERARCHY_HANDLE &>> $LOGFILE +[ $? -eq 0 ] || error_exit "Unable to persist Key Hierarchy in TPM memory" + +tss2_flushcontext -ha $PRIMARY_HANDLE + +# wrap the original private key in TPM's Endorsement key hierarchy +# this will generate a TSS key blob in ASN 1 encoding +create_tpm2_key -p $TPM_KEY_HIERARCHY_HANDLE -w $ORIGINAL_KEY $TPM_OBJECT_CONTEXT &>> $LOGFILE +[ $? -eq 0 ] || error_exit "Unable to wrap provided private key into TPM Key Hierarchy" + +# the apps will also need to the public key, place it in +# the certificate dirpath +mv $PUBLIC_KEY $CERTIFICATE_DIR/$CERTIFICATE_FILE + +# ensure that the TPM object and the public cert are only readable by root +chown root $CERTIFICATE_DIR/$CERTIFICATE_FILE $TPM_OBJECT_CONTEXT +chmod 0600 $CERTIFICATE_DIR/$CERTIFICATE_FILE $TPM_OBJECT_CONTEXT + +# remove all sysinv key copy artifacts +rm -f $ORIGINAL_KEY "${ORIGINAL_KEY}.sysinv" "${PUBLIC_KEY}.sysinv" &> /dev/null + +exit 0 diff --git a/security/stx-ssl/server-csr.conf b/security/stx-ssl/server-csr.conf new file mode 100644 index 00000000..d754cfa1 --- /dev/null +++ b/security/stx-ssl/server-csr.conf @@ -0,0 +1,13 @@ +[ req ] +default_bits = 1024 +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] +C = CA +ST = Ontario +L = Ottawa +O = Wind River Inc. +OU = Carrier Grade Communications Server +CN = *.wrs.com + diff --git a/security/tpm2-openssl-engine/PKG_INFO b/security/tpm2-openssl-engine/PKG_INFO new file mode 100644 index 00000000..9f29aad3 --- /dev/null +++ b/security/tpm2-openssl-engine/PKG_INFO @@ -0,0 +1,14 @@ +Metadata-Version: 1.1 +Name: tpm2-openssl-engine +Version: 1.0 +Summary: TPM 2.0 Openssl Engine +Home-page: +Author: Windriver +Author-email: info@windriver.com +License: openssl + +Description: Titanium Control's TPM 2.0 OpenSSL Engine. Leveraged by + Titanium applications to provide secure TLS Decryption and Signing + capabilities to Titanium host applications. + +Platform: UNKNOWN diff --git a/security/tpm2-openssl-engine/centos/build_srpm.data b/security/tpm2-openssl-engine/centos/build_srpm.data new file mode 100644 index 00000000..9c445bbb --- /dev/null +++ b/security/tpm2-openssl-engine/centos/build_srpm.data @@ -0,0 +1,2 @@ +SRC_DIR="tpm2-openssl-engine" +TIS_PATCH_VER=2 diff --git a/security/tpm2-openssl-engine/centos/tpm2-openssl-engine.spec b/security/tpm2-openssl-engine/centos/tpm2-openssl-engine.spec new file mode 100644 index 00000000..b2719a1e --- /dev/null +++ b/security/tpm2-openssl-engine/centos/tpm2-openssl-engine.spec @@ -0,0 +1,39 @@ +Name: tpm2-openssl-engine +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +Summary: TPM 2.0 Openssl Engine +License: openssl +Group: base +Packager: Wind River +URL: unknown + +Source0: %{name}-%{version}.tar.gz + +BuildRequires: openssl-devel +BuildRequires: openssl +BuildRequires: tss2-devel +Requires: tss2 + +%description +TPM 2.0 OpenSSL engine. Leveraged by applications +to provide secure TLS Decryption and Signing capabilities + +%prep +%setup -q + +%build +make %{?_smp_mflags} + +%install +make install ENGINEDIR=%{buildroot}/%{_libdir}/openssl/engines UTILDIR=%{buildroot}/usr/sbin + + +%files +%license LICENSE + +%defattr(-,root,root,-) + +%{_libdir}/openssl/engines/libtpm2.so +/usr/sbin/create_tpm2_key + + diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/LICENSE b/security/tpm2-openssl-engine/tpm2-openssl-engine/LICENSE new file mode 100644 index 00000000..0adcabd4 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/LICENSE @@ -0,0 +1,57 @@ +OpenSSL License +==================================================================== +Copyright (c) 1998-2007 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + +4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + endorse or promote products derived from this software without + prior written permission. For written permission, please contact + openssl-core@openssl.org. + +5. Products derived from this software may not be called "OpenSSL" + nor may "OpenSSL" appear in their names without prior written + permission of the OpenSSL Project. + +6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit (http://www.openssl.org/)" + +THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +EXPRESSED 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 OpenSSL PROJECT OR +ITS 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. +==================================================================== + +This product includes cryptographic software written by Eric Young +(eay@cryptsoft.com). This product includes software written by Tim +Hudson (tjh@cryptsoft.com). +This product is inspired by the original TPM 1.2 openssl engine written +by Kent Yoder for the Trousers Project. This product +includes TPM key blob ASN-1 encoding scheme from James Bottomley + + diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/Makefile b/security/tpm2-openssl-engine/tpm2-openssl-engine/Makefile new file mode 100644 index 00000000..b6d1f8f3 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (c) 2013-2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +#### Installation options +ENGINEDIR= +UTILDIR= + +#### Toolchain options +CC = gcc +LD = $(CC) + +#### Debug flags (typically "-g"). +# Those flags only feed CFLAGS so it is not mandatory to use this form. +DEBUG_CFLAGS = -g -O2 -Werror -Wno-unused-parameter -Wno-missing-braces + +#### Compiler-specific flags that may be used to disable some negative over- +# optimization or to silence some warnings. -fno-strict-aliasing is needed with +# gcc >= 4.4. +SPEC_CFLAGS = -fno-strict-aliasing + +#### Common CFLAGS +CFLAGS = $(DEBUG_CFLAGS) $(SPEC_CFLAGS) + +#### Common LDFLAGS +LDFLAGS = -g + +DYNAMIC_ENGINE=libtpm2.so +UTIL=create_tpm2_key + +INCLUDES+=-I${SYSTEM_DIR}/usr/include/ +LDFLAGS +=-lcrypto -lc -ltss +SRCS += e_tpm2.c e_tpm2_err.c +HEADERS += e_tpm2.h + +OBJS = $(SRCS:.c=.o) + +all: $(DYNAMIC_ENGINE) ${UTIL} + +${UTIL}: $(OBJS) + $(CC) -Wall ${CFLAGS} ${INCLUDES} create_tpm2_key.c ${LDFLAGS} -o ${UTIL} + +$(DYNAMIC_ENGINE): $(OBJS) + $(CC) -Wall ${CFLAGS} ${INCLUDES} ${LDFLAGS} -fPIC -c ${SRCS} + $(CC) -shared -Wl,-soname,${DYNAMIC_ENGINE} ${LDFLAGS} -o ${DYNAMIC_ENGINE} $(OBJS) + +install: all + install -D -m 755 ${DYNAMIC_ENGINE} ${ENGINEDIR}/${DYNAMIC_ENGINE} + install -D -m 755 ${UTIL} ${UTILDIR}/${UTIL} + +clean: + $(RM) *.o *.so *.so.0 diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/create_tpm2_key.c b/security/tpm2-openssl-engine/tpm2-openssl-engine/create_tpm2_key.c new file mode 100644 index 00000000..06c854b7 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/create_tpm2_key.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +/* ==================================================================== + * + * Copyright (c) 1999-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product is inspired by the original TPM 1.2 openssl engine written + * by Kent Yoder for the Trousers Project. This product + * includes TPM key blob ASN-1 encoding scheme from James Bottomley + * + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tpm2-asn.h" + +static struct option long_options[] = { + {"auth", 0, 0, 'a'}, + {"help", 0, 0, 'h'}, + {"name-scheme", 1, 0, 'n'}, + {"parent-handle", 1, 0, 'p'}, + {"wrap", 1, 0, 'w'}, + {0, 0, 0, 0} +}; + +static TPM_ALG_ID name_alg = TPM_ALG_SHA256; +static int name_alg_size = SHA256_DIGEST_SIZE; + +void +usage(char *argv0) +{ + fprintf(stderr, "\t%s: create a TPM key and write it to disk\n" + "\tusage: %s [options] \n\n" + "\tOptions:\n" + "\t\t-a|--auth require a password for the key [NO]\n" + "\t\t-h|--help print this help message\n" + "\t\t-n|--name-scheme name algorithm to use sha1 [sha256] sha384 sha512\n" + "\t\t-p|--parent-handle persistent handle of parent key\n" + "\t\t-w|--wrap [file] wrap an existing openssl PEM key\n", + argv0, argv0); + exit(-1); +} + +void tpm2_error(TPM_RC rc, const char *reason) +{ + const char *msg, *submsg, *num; + + fprintf(stderr, "%s failed with %d\n", reason, rc); + TSS_ResponseCode_toString(&msg, &submsg, &num, rc); + fprintf(stderr, "%s%s%s\n", msg, submsg, num); +} + +void +openssl_print_errors() +{ + ERR_load_ERR_strings(); + ERR_load_crypto_strings(); + ERR_print_errors_fp(stderr); +} + +int +openssl_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len, + BYTE *privkey, int privkey_len, int empty_auth, + TPM_HANDLE parent) +{ + TSSLOADABLE tssl; + BIO *outb; + + /* clear structure so as not to have to set optional parameters */ + memset(&tssl, 0, sizeof(tssl)); + if ((outb = BIO_new_file(file, "w")) == NULL) { + fprintf(stderr, "Error opening file for write: %s\n", file); + return 1; + } + tssl.type = OBJ_txt2obj(OID_loadableKey, 1); + tssl.emptyAuth = empty_auth; + if ((parent & 0xff000000) == 0x81000000) { + tssl.parent = ASN1_INTEGER_new(); + ASN1_INTEGER_set(tssl.parent, parent); + } + tssl.pubkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(tssl.pubkey, pubkey, pubkey_len); + tssl.privkey = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(tssl.privkey, privkey, privkey_len); + + PEM_write_bio_TSSLOADABLE(outb, &tssl); + BIO_free(outb); + return 0; +} + +EVP_PKEY * +openssl_read_key(char *filename) +{ + BIO *b = NULL; + EVP_PKEY *pkey; + + b = BIO_new_file(filename, "r"); + if (b == NULL) { + fprintf(stderr, "Error opening file for read: %s\n", filename); + return NULL; + } + + if ((pkey = PEM_read_bio_PrivateKey(b, NULL, PEM_def_callback, NULL)) == NULL) { + fprintf(stderr, "Reading key %s from disk failed.\n", filename); + openssl_print_errors(); + } + BIO_free(b); + + return pkey; +} + +void tpm2_public_template_rsa(TPMT_PUBLIC *pub) +{ + pub->type = TPM_ALG_RSA; + pub->nameAlg = name_alg; + /* note: all our keys are decrypt only. This is because + * we use the TPM2_RSA_Decrypt operation for both signing + * and decryption (see e_tpm2.c for details) */ + pub->objectAttributes.val = TPMA_OBJECT_NODA | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_SIGN | + TPMA_OBJECT_USERWITHAUTH; + pub->authPolicy.t.size = 0; + pub->parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL; + pub->parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; +} + +TPM_RC openssl_to_tpm_public_rsa(TPMT_PUBLIC *pub, EVP_PKEY *pkey) +{ + RSA *rsa = EVP_PKEY_get1_RSA(pkey); + BIGNUM *n, *e; + int size = RSA_size(rsa); + unsigned long exp; + + if (size > MAX_RSA_KEY_BYTES) + return TPM_RC_KEY_SIZE; + +#if OPENSSL_VERSION_NUMBER < 0x10100000 + n = rsa->n; + e = rsa->e; +#else + RSA_get0_key(&n, &e, NULL); +#endif + exp = BN_get_word(e); + /* TPM limitations means exponents must be under a word in size */ + if (exp == 0xffffffffL) + return TPM_RC_KEY_SIZE; + tpm2_public_template_rsa(pub); + pub->parameters.rsaDetail.keyBits = size*8; + if (exp == 0x10001) + pub->parameters.rsaDetail.exponent = 0; + else + pub->parameters.rsaDetail.exponent = exp; + + pub->unique.rsa.t.size = BN_bn2bin(n, pub->unique.rsa.t.buffer); + + return 0; +} + +TPM_RC openssl_to_tpm_public(TPM2B_PUBLIC *pub, EVP_PKEY *pkey) +{ + TPMT_PUBLIC *tpub = &pub->publicArea; + pub->size = sizeof(*pub); + + switch (EVP_PKEY_type(pkey->type)) { + case EVP_PKEY_RSA: + return openssl_to_tpm_public_rsa(tpub, pkey); + default: + break; + } + return TPM_RC_ASYMMETRIC; +} + +TPM_RC openssl_to_tpm_private_rsa(TPMT_SENSITIVE *s, EVP_PKEY *pkey) +{ + BIGNUM *q; + TPM2B_PRIVATE_KEY_RSA *t2brsa = &s->sensitive.rsa; + RSA *rsa = EVP_PKEY_get1_RSA(pkey); + +#if OPENSSL_VERSION_NUMBER < 0x10100000 + q = rsa->q; +#else + BIGNUM *p; + + RSA_get0_factors(rsa, &p, &q); +#endif + + if (!q) + return TPM_RC_ASYMMETRIC; + + s->sensitiveType = TPM_ALG_RSA; + s->seedValue.b.size = 0; + + t2brsa->t.size = BN_bn2bin(q, t2brsa->t.buffer); + return 0; +} + +TPM_RC openssl_to_tpm_private(TPMT_SENSITIVE *priv, EVP_PKEY *pkey) +{ + switch (EVP_PKEY_type(pkey->type)) { + case EVP_PKEY_RSA: + return openssl_to_tpm_private_rsa(priv, pkey); + default: + break; + } + return TPM_RC_ASYMMETRIC; +} + +TPM_RC wrap_key(TPM2B_PRIVATE *priv, const char *password, EVP_PKEY *pkey) +{ + TPMT_SENSITIVE s; + TPM2B_SENSITIVE b; + BYTE *buf; + int32_t size; + TPM_RC rc; + + memset(&b, 0, sizeof(b)); + memset(&s, 0, sizeof(s)); + + openssl_to_tpm_private(&s, pkey); + + if (password) { + int len = strlen(password); + + memcpy(s.authValue.b.buffer, password, len); + s.authValue.b.size = len; + } else { + s.authValue.b.size = 0; + } + size = sizeof(s); + buf = b.b.buffer; + rc = TSS_TPMT_SENSITIVE_Marshal(&s, &b.b.size, &buf, &size); + if (rc) + tpm2_error(rc, "TSS_TPMT_SENSITIVE_Marshal"); + + size = sizeof(*priv); + buf = priv->b.buffer; + priv->b.size = 0; + /* no encryption means innerIntegrity and outerIntegrity are + * absent, so the TPM2B_PRIVATE is a TPMT_SENSITIVE*/ + rc = TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)&b, &priv->b.size, &buf, &size); + if (rc) + tpm2_error(rc, "TSS_TPM2B_PRIVATE_Marshal"); + + return TPM_RC_ASYMMETRIC; +} + +int main(int argc, char **argv) +{ + char *filename, c, *wrap = NULL, *auth = NULL; + int option_index; + const char *reason; + TSS_CONTEXT *tssContext = NULL; + TPM_HANDLE parent = 0; + TPM_RC rc = 0; + BYTE pubkey[sizeof(TPM2B_PUBLIC)],privkey[sizeof(TPM2B_PRIVATE)], *buffer; + uint16_t pubkey_len, privkey_len; + int32_t size = 0; + TPM2B_PUBLIC *pub; + TPM2B_PRIVATE *priv; + + + while (1) { + option_index = 0; + c = getopt_long(argc, argv, "n:ap:hw:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'a': + auth = malloc(128); + break; + case 'h': + usage(argv[0]); + break; + case 'n': + if (!strcasecmp("sha1", optarg)) { + name_alg = TPM_ALG_SHA1; + name_alg_size = SHA1_DIGEST_SIZE; + } else if (strcasecmp("sha256", optarg)) { + /* default, do nothing */ + } else if (strcasecmp("sha384", optarg)) { + name_alg = TPM_ALG_SHA384; + name_alg_size = SHA384_DIGEST_SIZE; +#ifdef TPM_ALG_SHA512 + } else if (strcasecmp("sha512", optarg)) { + name_alg = TPM_ALG_SHA512; + name_alg_size = SHA512_DIGEST_SIZE; +#endif + } else { + usage(argv[0]); + } + break; + case 'p': + parent = strtol(optarg, NULL, 16); + break; + case 'w': + wrap = optarg; + break; + default: + usage(argv[0]); + break; + } + } + + filename = argv[argc - 1]; + + if (argc < 2) + usage(argv[0]); + + if (!wrap) { + fprintf(stderr, "wrap is a compulsory option\n"); + usage(argv[0]); + } + + if (!parent) { + fprintf(stderr, "parent handle is a compulsory option\n"); + usage(argv[0]); + } + + if (parent && (parent & 0xff000000) != 0x81000000) { + fprintf(stderr, "you must specify a persistent parent handle\n"); + usage(argv[0]); + } + + if (auth) { + if (EVP_read_pw_string(auth, 128, "Enter TPM key authority: ", 1)) { + fprintf(stderr, "Passwords do not match\n"); + exit(1); + } + } + + rc = TSS_Create(&tssContext); + if (rc) { + reason = "TSS_Create"; + goto out_err; + } + + /* + * avoid using the device TCTI as that will bind + * exclusively to the TPM device. Instead + * use the Kernel TPM Resource Manager as that + * allows concurrent access + * + * N.B: This assumes that the kernel-modules-tpm + * pkg is installed with the modified tpm_crb KLM + */ + rc = TSS_SetProperty(tssContext, TPM_DEVICE, "/dev/tpmrm0"); + if (rc) { + reason = "TSS_SetProperty: TPM_USE_RESOURCE_MANAGER"; + goto out_err; + } + + if (wrap) { + Import_In iin; + Import_Out iout; + EVP_PKEY *pkey; + + /* may be needed to decrypt the key */ + OpenSSL_add_all_ciphers(); + pkey = openssl_read_key(wrap); + if (!pkey) { + reason = "unable to read key"; + goto out_delete; + } + + iin.parentHandle = parent; + iin.encryptionKey.t.size = 0; + openssl_to_tpm_public(&iin.objectPublic, pkey); + /* set random iin.symSeed */ + iin.inSymSeed.t.size = 0; + iin.symmetricAlg.algorithm = TPM_ALG_NULL; + wrap_key(&iin.duplicate, auth, pkey); + openssl_to_tpm_public(&iin.objectPublic, pkey); + rc = TSS_Execute(tssContext, + (RESPONSE_PARAMETERS *)&iout, + (COMMAND_PARAMETERS *)&iin, + NULL, + TPM_CC_Import, + TPM_RS_PW, NULL, 0, + TPM_RH_NULL, NULL, 0, + TPM_RH_NULL, NULL, 0, + TPM_RH_NULL, NULL, 0); + if (rc) { + reason = "TPM2_Import"; + goto out_flush; + } + pub = &iin.objectPublic; + priv = &iout.outPrivate; + } + + buffer = pubkey; + pubkey_len = 0; + size = sizeof(pubkey); + TSS_TPM2B_PUBLIC_Marshal(pub, &pubkey_len, &buffer, &size); + buffer = privkey; + privkey_len = 0; + size = sizeof(privkey); + TSS_TPM2B_PRIVATE_Marshal(priv, &privkey_len, &buffer, &size); + openssl_write_tpmfile(filename, pubkey, pubkey_len, privkey, privkey_len, auth == NULL, parent); + TSS_Delete(tssContext); + exit(0); + + out_flush: + out_delete: + TSS_Delete(tssContext); + out_err: + tpm2_error(rc, reason); + + exit(1); +} diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.c b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.c new file mode 100644 index 00000000..5b5ca2e4 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.c @@ -0,0 +1,852 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +/* ==================================================================== + * Copyright (c) 1999-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product is inspired by the original TPM 1.2 openssl engine written + * by Kent Yoder for the Trousers Project. This product + * includes TPM key blob ASN-1 encoding scheme from James Bottomley + * + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "e_tpm2.h" + +#include "tpm2-asn.h" + +//IMPLEMENT_ASN1_FUNCTIONS(TSSLOADABLE) + +/* IBM TSS2 library functions */ +static const char *TPM_F_File_ReadStructure = "TSS_File_ReadStructure"; +static const char *TPM_F_Context_Create = "TSS_Create"; +static const char *TPM_F_Context_Close = "TSS_Delete"; +static const char *TPM_F_TPM_Execute = "TSS_Execute"; +static const char *TPM_F_Hash_Generate = "TSS_Hash_Generate"; +static const char *TPM_F_Structure_Marshal = "TSS_Structure_Marshal"; +static const char *TPM_F_PrivateKey_Unmarshal = "TPM2B_PRIVATE_Unmarshal"; +static const char *TPM_F_PublicKey_Unmarshal = "TPM2B_PUBLIC_Unmarshal"; +static const char *TPM_F_Set_Property = "TSS_SetProperty"; + +/* engine specific functions */ +static int tpm_engine_destroy(ENGINE *); +static int tpm_engine_init(ENGINE *); +static int tpm_engine_finish(ENGINE *); +static int tpm_engine_ctrl(ENGINE *, int, long, void *, void (*)()); +static EVP_PKEY *tpm_engine_load_key(ENGINE *, const char *, UI_METHOD *, void *); +static int tpm_engine_flush_key_context(TPMI_DH_OBJECT hKey); + +#ifndef OPENSSL_NO_RSA +/* rsa functions */ +static int tpm_rsa_init(RSA *rsa); +static int tpm_rsa_finish(RSA *rsa); +static int tpm_rsa_priv_dec(int, const unsigned char *, unsigned char *, RSA *, int); +static int tpm_rsa_priv_enc(int, const unsigned char *, unsigned char *, RSA *, int); +#endif + + +/* The definitions for control commands specific to this engine */ +#define TPM_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN tpm_cmd_defns[] = { + {TPM_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the libtpm2.so shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} +}; + +// for now we will only overwrite the RSA decryption +// operation to go over TPM 2.0. +// Add additional hooks as new use cases pop up +#ifndef OPENSSL_NO_RSA +static RSA_METHOD tpm_rsa = { + "TPM 2.0 RSA method", // name + NULL, // rsa_pub_enc (encrypt) + NULL, // rsa_pub_dec (verify arbitrary data) + tpm_rsa_priv_enc, // rsa_priv_enc (sign) + tpm_rsa_priv_dec, // rsa_priv_dec (decrypt) + NULL, // rsa_mod_exp + BN_mod_exp_mont, // bn_mod_exp + tpm_rsa_init, // init + tpm_rsa_finish, // free + (RSA_FLAG_SIGN_VER | RSA_FLAG_NO_BLINDING | RSA_FLAG_EXT_PKEY), + NULL, // app_data + NULL, /* sign */ // rsa_sign + NULL, /* verify */ // rsa_verify + NULL // rsa_keygen +}; +#endif + +/* Constants used when creating the ENGINE */ +static const char *engine_tpm_id = "tpm2"; +static const char *engine_tpm_name = "TPM 2.0 hardware engine support for"; +static const char *TPM_LIBNAME = "tpm2"; + +static TSS_CONTEXT *hContext = NULL_HCONTEXT; +static TPMI_DH_OBJECT hKey = NULL_HKEY; +/* varibles used to get/set CRYPTO_EX_DATA values */ +int ex_app_data = TPM_ENGINE_EX_DATA_UNINIT; + +/* This is a process-global DSO handle used for loading and unloading + * the TSS library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ + +static DSO *tpm_dso = NULL; + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ +static unsigned int (*p_tpm2_File_ReadStructure)(); +static unsigned int (*p_tpm2_Context_Create)(); +static unsigned int (*p_tpm2_Context_Close)(); +static unsigned int (*p_tpm2_TPM_Execute)(); +static unsigned int (*p_tpm2_Hash_Generate)(); +static unsigned int (*p_tpm2_Structure_Marshal)(); +static unsigned int (*p_tpm2_TPM_PrivateKey_Unmarshal)(); +static unsigned int (*p_tpm2_TPM_PublicKey_Unmarshal)(); +static unsigned int (*p_tpm2_Set_Property)(); + + +/* This internal function is used by ENGINE_tpm() and possibly by the + * "dynamic" ENGINE support too */ +static int bind_helper(ENGINE * e) +{ +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *meth1; +#endif + if (!ENGINE_set_id(e, engine_tpm_id) || + !ENGINE_set_name(e, engine_tpm_name) || +#ifndef OPENSSL_NO_RSA + !ENGINE_set_RSA(e, &tpm_rsa) || +#endif + !ENGINE_set_destroy_function(e, tpm_engine_destroy) || + !ENGINE_set_init_function(e, tpm_engine_init) || + !ENGINE_set_finish_function(e, tpm_engine_finish) || + !ENGINE_set_ctrl_function(e, tpm_engine_ctrl) || + !ENGINE_set_load_privkey_function(e, tpm_engine_load_key) || + !ENGINE_set_cmd_defns(e, tpm_cmd_defns)) + return 0; + +#ifndef OPENSSL_NO_RSA + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the tpm-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + if (meth1) + { + tpm_rsa.rsa_mod_exp = meth1->rsa_mod_exp; + tpm_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + tpm_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + } +#endif + + /* Ensure the tpm error handling is set up */ + ERR_load_TPM_strings(); + return 1; +} + +static ENGINE *engine_tpm(void) +{ + ENGINE *ret = ENGINE_new(); + if (!ret) + return NULL; + if (!bind_helper(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void ENGINE_load_tpm(void) +{ + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_tpm(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +} + +/* Destructor (complements the "ENGINE_tpm()" constructor) */ +static int tpm_engine_destroy(ENGINE * e) +{ + /* Unload the tpm error strings so any error state including our + * functs or reasons won't lead to a segfault (they simply get displayed + * without corresponding string data because none will be found). */ + ERR_unload_TPM_strings(); + return 1; +} + +/* initialisation function */ +static int tpm_engine_init(ENGINE * e) +{ + void (*p1) (); + void (*p2) (); + void (*p3) (); + void (*p4) (); + void (*p5) (); + void (*p6) (); + void (*p7) (); + void (*p8) (); + void (*p9) (); + TPM_RC result; + + if (tpm_dso != NULL) { + TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_ALREADY_LOADED); + return 1; + } + + if ((tpm_dso = DSO_load(NULL, TPM_LIBNAME, NULL, 0)) == NULL) { + TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_DSO_FAILURE); + goto err; + } + + if (!(p1 = DSO_bind_func(tpm_dso, TPM_F_File_ReadStructure)) || + !(p2 = DSO_bind_func(tpm_dso, TPM_F_Context_Create)) || + !(p3 = DSO_bind_func(tpm_dso, TPM_F_Context_Close)) || + !(p4 = DSO_bind_func(tpm_dso, TPM_F_TPM_Execute)) || + !(p5 = DSO_bind_func(tpm_dso, TPM_F_Hash_Generate)) || + !(p6 = DSO_bind_func(tpm_dso, TPM_F_Structure_Marshal)) || + !(p7 = DSO_bind_func(tpm_dso, TPM_F_PrivateKey_Unmarshal)) || + !(p8 = DSO_bind_func(tpm_dso, TPM_F_PublicKey_Unmarshal)) || + !(p9 = DSO_bind_func(tpm_dso, TPM_F_Set_Property)) + ) { + TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_DSO_FAILURE); + goto err; + } + + /* Copy the pointers */ + p_tpm2_File_ReadStructure = (unsigned int (*) ()) p1; + p_tpm2_Context_Create = (unsigned int (*) ()) p2; + p_tpm2_Context_Close = (unsigned int (*) ()) p3; + p_tpm2_TPM_Execute = (unsigned int (*) ()) p4; + p_tpm2_Hash_Generate = (unsigned int (*) ()) p5; + p_tpm2_Structure_Marshal = (unsigned int (*) ()) p6; + p_tpm2_TPM_PrivateKey_Unmarshal = (unsigned int (*) ()) p7; + p_tpm2_TPM_PublicKey_Unmarshal = (unsigned int (*) ()) p8; + p_tpm2_Set_Property = (unsigned int (*) ()) p9; + + if ((result = p_tpm2_Context_Create(&hContext))) { + TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_UNIT_FAILURE); + goto err; + } + + /* + * avoid using the tpm0 device TCTI as that will bind + * exclusively to the TPM device. Instead + * use the Kernel TPM Resource Manager as that + * allows concurrent access + * + * N.B: This assumes that the kernel-modules-tpm + * pkg is installed with the modified tpm_crb KLM + */ + if ((result = p_tpm2_Set_Property(hContext, + TPM_DEVICE, "/dev/tpmrm0"))) { + DBG("Failed to set Resource Manager in context (%p): rc %d", + hContext, (int)result); + TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_UNIT_FAILURE); + goto err; + } + + return 1; +err: + if (hContext != NULL_HCONTEXT) { + p_tpm2_Context_Close(hContext); + hContext = NULL_HCONTEXT; + } + + if (tpm_dso) { + DSO_free(tpm_dso); + tpm_dso = NULL; + } + + p_tpm2_File_ReadStructure = NULL; + p_tpm2_Context_Create = NULL; + p_tpm2_Context_Close = NULL; + p_tpm2_TPM_Execute = NULL; + p_tpm2_Hash_Generate = NULL; + p_tpm2_Structure_Marshal = NULL; + p_tpm2_TPM_PrivateKey_Unmarshal = NULL; + p_tpm2_TPM_PublicKey_Unmarshal = NULL; + p_tpm2_Set_Property = NULL; + + return 0; +} + +static int tpm_engine_finish(ENGINE * e) +{ + if (tpm_dso == NULL) { + TSSerr(TPM_F_TPM_ENGINE_FINISH, TPM_R_NOT_LOADED); + return 0; + } + + if (hKey != NULL_HKEY) { + tpm_engine_flush_key_context(hKey); + hKey = NULL_HKEY; + } + + if (hContext != NULL_HCONTEXT) { + p_tpm2_Context_Close(hContext); + hContext = NULL_HCONTEXT; + } + + if (!DSO_free(tpm_dso)) { + TSSerr(TPM_F_TPM_ENGINE_FINISH, TPM_R_DSO_FAILURE); + return 0; + } + tpm_dso = NULL; + + return 1; +} + +int fill_out_rsa_object(RSA *rsa, TPMT_PUBLIC *pub, TPMI_DH_OBJECT hKey) +{ + struct rsa_app_data *app_data; + unsigned long exp; + + if ((app_data = OPENSSL_malloc(sizeof(struct rsa_app_data))) == NULL) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* set e in the RSA object */ + if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (pub->parameters.rsaDetail.exponent == 0) + exp = 65537; + else + exp = pub->parameters.rsaDetail.exponent; + + if (!BN_set_word(rsa->e, exp)) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, TPM_R_REQUEST_FAILED); + BN_free(rsa->e); + return 0; + } + + /* set n in the RSA object */ + if (!rsa->n && ((rsa->n = BN_new()) == NULL)) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); + BN_free(rsa->e); + return 0; + } + + if (!BN_bin2bn(pub->unique.rsa.t.buffer, pub->unique.rsa.t.size, + rsa->n)) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); + BN_free(rsa->e); + BN_free(rsa->n); + return 0; + } + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + RSA_set0_key(rsa, rsa->n, rsa->e, NULL); +#endif + + DBG("Setting hKey(0x%x) in RSA object", hKey); + + memset(app_data, 0, sizeof(struct rsa_app_data)); + app_data->hKey = hKey; + RSA_set_ex_data(rsa, ex_app_data, app_data); + + return 1; +} + +static int tpm_engine_flush_key_context(TPMI_DH_OBJECT hKey) +{ + TPM_RC rc; + FlushContext_In input; + + if (hKey == NULL_HKEY) { + TSSerr(TPM_F_TPM_FLUSH_OBJECT_CONTEXT, TPM_R_INVALID_KEY); + return -1; + } + input.flushHandle = hKey; + + if ((rc = p_tpm2_TPM_Execute(hContext, + NULL, + (COMMAND_PARAMETERS *)&input, + NULL, + TPM_CC_FlushContext, + TPM_RH_NULL, NULL, 0))) { + DBG("Context Flush Failed: Ret code %d", rc); + TSSerr(TPM_F_TPM_FLUSH_OBJECT_CONTEXT, + TPM_R_REQUEST_FAILED); + return -1; + } + + return 0; +} + +static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, + UI_METHOD *ui, void *cb_data) +{ + RSA *rsa; + EVP_PKEY *pkey; + BIO *bf; + char oid[128]; + TPM_RC rc; + TSSLOADABLE *tssl; // the TPM key + Load_In input; + Load_Out output; + + const char *parentPassword = NULL; + TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW; + unsigned int sessionAttributes0 = 0; + TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL; + unsigned int sessionAttributes1 = 0; + TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL; + unsigned int sessionAttributes2 = 0; + + + if (!key_id) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + // check if the file exists + if ((bf = BIO_new_file(key_id, "r")) == NULL) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_FILE_NOT_FOUND); + return NULL; + } + + tssl = PEM_read_bio_TSSLOADABLE(bf, NULL, NULL, NULL); + BIO_free(bf); + + + if (!tssl) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_FILE_READ_FAILED); + goto load_err; + } + + if (OBJ_obj2txt(oid, sizeof(oid), tssl->type, 1) == 0) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_FILE_READ_FAILED); + goto load_err; + } + + if (strcmp(OID_loadableKey, oid) == 0) { + DBG ("TSSL key type is of format that can be loaded in TPM 2.0"); + } else if (strcmp(OID_12Key, oid) == 0) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_TPM_1_2_KEY); + goto load_err; + } else if (strcmp(OID_importableKey, oid) == 0) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_KEY_UNSUPPORTED); + goto load_err; + } else { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_KEY_UNRECOGNIZED); + goto err; + } + + // since this TPM key was wrapped in the Endorsement + // Key hierarchy and its handle was persisted, we will + // specify that as the Parent Handle for the Load operation + if (!tssl->parent) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_KEY_NO_PARENT_HANDLE); + goto load_err; + } + + input.parentHandle = ASN1_INTEGER_get(tssl->parent); + DBG ("Got parent handle 0x%x", input.parentHandle); + // unmarshal the public and private key portions from + // within the TPM ASN1 key blob + p_tpm2_TPM_PrivateKey_Unmarshal(&input.inPrivate, + &(tssl->privkey->data), + &(tssl->privkey->length)); + p_tpm2_TPM_PublicKey_Unmarshal(&input.inPublic, + &(tssl->pubkey->data), + &(tssl->pubkey->length), + FALSE); + if ((rc = p_tpm2_TPM_Execute(hContext, + (RESPONSE_PARAMETERS *)&output, + (COMMAND_PARAMETERS *)&input, + NULL, + TPM_CC_Load, + sessionHandle0, + parentPassword, + sessionAttributes0, + sessionHandle1, + NULL, + sessionAttributes1, + sessionHandle2, + NULL, + sessionAttributes2, + TPM_RH_NULL, NULL, 0))) { + DBG("Context Load Failed: Ret code %08x", rc); + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_REQUEST_FAILED); + goto load_err; + } + hKey = output.objectHandle; + + /* create the new objects to return */ + if ((pkey = EVP_PKEY_new()) == NULL) { + goto err; + } + pkey->type = EVP_PKEY_RSA; + + if ((rsa = RSA_new()) == NULL) { + EVP_PKEY_free(pkey); + goto err; + } + rsa->meth = &tpm_rsa; + /* call our local init function here */ + rsa->meth->init(rsa); + pkey->pkey.rsa = rsa; + + if (!fill_out_rsa_object(rsa, + &input.inPublic.publicArea, + hKey)) { + EVP_PKEY_free(pkey); + RSA_free(rsa); + goto err; + } + + EVP_PKEY_assign_RSA(pkey, rsa); + return pkey; + +err: + tpm_engine_flush_key_context(hKey); + hKey = NULL_HKEY; + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE); + +load_err: + //TSSLOADABLE_free(tssl); + return NULL; +} + +static int tpm_engine_ctrl(ENGINE * e, int cmd, long i, void *p, void (*f) ()) +{ + int initialised = ((tpm_dso == NULL) ? 0 : 1); + switch (cmd) { + case TPM_CMD_SO_PATH: + if (p == NULL) { + TSSerr(TPM_F_TPM_ENGINE_CTRL, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (initialised) { + TSSerr(TPM_F_TPM_ENGINE_CTRL, + TPM_R_ALREADY_LOADED); + return 0; + } + TPM_LIBNAME = (const char *) p; + return 1; + default: + break; + } + TSSerr(TPM_F_TPM_ENGINE_CTRL, TPM_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; +} + +static int tpm_rsa_init(RSA *rsa) +{ + if (ex_app_data == TPM_ENGINE_EX_DATA_UNINIT) + ex_app_data = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL); + + if (ex_app_data == TPM_ENGINE_EX_DATA_UNINIT) { + TSSerr(TPM_F_TPM_RSA_INIT, TPM_R_REQUEST_FAILED); + return 0; + } + + return 1; +} + +static int tpm_rsa_finish(RSA *rsa) +{ + struct rsa_app_data *app_data = RSA_get_ex_data(rsa, ex_app_data); + + OPENSSL_free(app_data); + + return 1; +} + +static int tpm_rsa_priv_dec(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + struct rsa_app_data *app_data = RSA_get_ex_data(rsa, ex_app_data); + TPM_RC result; + UINT32 out_len; + int rv; + RSA_Decrypt_In input; + RSA_Decrypt_Out output; + // the parent object is not passwod protected + // but it may be in the future. + const char *parentPassword = NULL; + TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW; + unsigned int sessionAttributes0 = 0; + TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL; + unsigned int sessionAttributes1 = 0; + TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL; + unsigned int sessionAttributes2 = 0; + + + if (!app_data) { + TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_NO_APP_DATA); + if ((rv = RSA_PKCS1_SSLeay()->rsa_priv_dec(flen, from, to, rsa, + padding)) < 0) { + TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_REQUEST_FAILED); + } + + return rv; + } + + // hKey is the handle of the private key that is used for decrypt + if (app_data->hKey == NULL_HKEY) { + TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_INVALID_KEY); + return 0; + } + /* handler of the private key that will perform rsa decrypt */ + input.keyHandle = app_data->hKey; + + // fill in the TPM2RB_PUBLIC_KEY_RSA structure with the + // cipher text and cipher lenght + { + input.label.t.size = 0; + input.cipherText.t.size = flen; + memcpy(input.cipherText.t.buffer, from, flen); + } + + /* + * Table 157 - Definition of {RSA} TPMT_RSA_DECRYPT Structure: + * we MAY set the input scheme to TPM_ALG_NULL to allow + * for the encryption algorithm prescribed in the digital + * certificate to be used for encryption + */ + input.inScheme.scheme = TPM_ALG_RSAES; /* TPM_ALG_NULL; */ + + // decrypt this cipher text using the private key stored inside + // tpm and referenced by hKey + if ((result = p_tpm2_TPM_Execute(hContext, + (RESPONSE_PARAMETERS *)&output, + (COMMAND_PARAMETERS *)&input, + NULL, + TPM_CC_RSA_Decrypt, + sessionHandle0, + parentPassword, + sessionAttributes0, + sessionHandle1, + NULL, + sessionAttributes1, + sessionHandle2, + NULL, + sessionAttributes2, + TPM_RH_NULL, NULL, 0))) { + DBG("RSA Decrypt Failed: Ret code %d", result); + TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_REQUEST_FAILED); + return 0; + } + DBG ("Doing RSA Decryption"); + + // Unmarshal the output data and return decrypted cipher text + // and output length + rv = p_tpm2_Structure_Marshal(&to, &out_len, + &output.message, + (MarshalFunction_t) + TSS_TPM2B_PUBLIC_KEY_RSA_Marshal); + if (rv == 0) { + DBG("writing out %d bytes as a signature", out_len); + return out_len; + } + return 0; +} + +static int tpm_rsa_priv_enc(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + struct rsa_app_data *app_data = RSA_get_ex_data(rsa, ex_app_data); + TPM_RC result = 0; + UINT32 sig_len; + int rv; + RSA_Decrypt_In input; + RSA_Decrypt_Out output; + // the parent object is not passwod protected + // but it may be in the future. + const char *parentPassword = NULL; + TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW; + unsigned int sessionAttributes0 = 0; + TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL; + unsigned int sessionAttributes1 = 0; + TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL; + unsigned int sessionAttributes2 = 0; + + if (!app_data) { + TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_NO_APP_DATA); + if ((rv = RSA_PKCS1_SSLeay()->rsa_priv_enc(flen, from, to, rsa, + padding)) < 0) { + TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_REQUEST_FAILED); + } + return rv; + } + + if (padding != RSA_PKCS1_PADDING) { + TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_INVALID_PADDING_TYPE); + return 0; + } + + // hKey is the handle to the private key that is used for hashing + if (app_data->hKey == NULL_HKEY) { + TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_INVALID_KEY); + return 0; + } + /* handler of the private key that will perform signing */ + input.keyHandle = app_data->hKey; + + /* + * Table 145 - Definition of TPMT_SIG_SCHEME inscheme: + * we will set the input scheme to TPM_ALG_NULL to allow + * for the hash algorithm prescribed in the digital certificate + * to be used for signing. + * + * Note that we are using a Decryption operation instead of ] + * a TPM 2.0 Sign operation because of a serious limitation in the + * IBM TSS that it will only sign digests which it has hashed itself, + * i.e. the hash has a corresponding TPM_ST_HASHCHECK validation + * ticket in TPM memory. Long story short, TPM will only sign + * stuff it knows the OID to. + * + * We will therefore specify a Decyrption operation with our + * own padding applied upto the RSA block size and specify + * a TPM_ALG_NULL hashing scheme so that a decrypt operation + * essentially becomes an encrypt op + */ + input.inScheme.scheme = TPM_ALG_NULL; + + /* digest to be signed */ + int size = RSA_size(rsa); + input.cipherText.t.size = size; + RSA_padding_add_PKCS1_type_1(input.cipherText.t.buffer, + size, from, flen); + input.label.t.size = 0; + + // sign this digest using the private key stored inside + // tpm and referenced by hKey + if ((result = p_tpm2_TPM_Execute(hContext, + (RESPONSE_PARAMETERS *)&output, + (COMMAND_PARAMETERS *)&input, + NULL, + TPM_CC_RSA_Decrypt, + sessionHandle0, + parentPassword, + sessionAttributes0, + sessionHandle1, + NULL, + sessionAttributes1, + sessionHandle2, + NULL, + sessionAttributes2, + TPM_RH_NULL, NULL, 0))) { + DBG("RSA Sign Failed: Ret code %d", result); + TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_REQUEST_FAILED); + return 0; + } + + // thats right son!!! finally signed + sig_len = output.message.t.size; + memcpy(to, output.message.t.buffer, sig_len); + + DBG("writing out %d bytes as a signature", sig_len); + return sig_len; +} + +/* This stuff is needed if this ENGINE is being compiled into a self-contained + * shared-library. */ +static int bind_fn(ENGINE * e, const char *id) +{ + if (id && (strcmp(id, engine_tpm_id) != 0)) { + TSSerr(TPM_F_TPM_BIND_FN, TPM_R_ID_INVALID); + return 0; + } + if (!bind_helper(e)) { + TSSerr(TPM_F_TPM_BIND_FN, TPM_R_REQUEST_FAILED); + return 0; + } + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.h b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.h new file mode 100644 index 00000000..9b8f7a50 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +/* ==================================================================== + * Copyright (c) 1999-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product is inspired by the original TPM 1.2 openssl engine written + * by Kent Yoder for the Trousers Project. This product + * includes TPM key blob ASN-1 encoding scheme from James Bottomley + * + * + */ + +#ifndef _E_TPM_H +#define _E_TPM_H + +#include +#include +#include +#include +#include +#include + +#define TPM_LIB_NAME "tpm2 engine" + +#define NULL_HCONTEXT NULL +#define NULL_HKEY 0 + +void ERR_load_TPM_strings(void); +void ERR_unload_TPM_strings(void); +void ERR_TSS_error(int function, int reason, char *file, int line); + +#define TSSerr(f,r) ERR_TSS_error((f),(r),__FILE__,__LINE__) +#define DBG(x, ...) fprintf(stderr, "DEBUG %s:%d %s " x "\n", __FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__) + +/* Error codes for the TPM functions. */ + +/* Function codes. */ +#define TPM_F_TPM_ENGINE_CTRL 100 +#define TPM_F_TPM_ENGINE_FINISH 101 +#define TPM_F_TPM_ENGINE_INIT 102 +#define TPM_F_TPM_RSA_PRIV_ENC 103 +#define TPM_F_TPM_RSA_PRIV_DEC 104 +#define TPM_F_TPM_RSA_FINISH 105 +#define TPM_F_TPM_RSA_INIT 106 +#define TPM_F_TPM_ENGINE_LOAD_KEY 107 +#define TPM_F_TPM_BIND_FN 108 +#define TPM_F_TPM_FILL_RSA_OBJECT 109 +#define TPM_F_TPM_FLUSH_OBJECT_CONTEXT 110 + +/* Reason codes. */ +#define TPM_R_ALREADY_LOADED 100 +#define TPM_R_CTRL_COMMAND_NOT_IMPLEMENTED 101 +#define TPM_R_DSO_FAILURE 102 +#define TPM_R_MEXP_LENGTH_TO_LARGE 103 +#define TPM_R_MISSING_KEY_COMPONENTS 104 +#define TPM_R_NOT_INITIALISED 105 +#define TPM_R_NOT_LOADED 106 +#define TPM_R_OPERANDS_TOO_LARGE 107 +#define TPM_R_OUTLEN_TO_LARGE 108 +#define TPM_R_REQUEST_FAILED 109 +#define TPM_R_UNDERFLOW_CONDITION 110 +#define TPM_R_UNDERFLOW_KEYRECORD 111 +#define TPM_R_UNIT_FAILURE 112 +#define TPM_R_INVALID_KEY_SIZE 113 +#define TPM_R_BN_CONVERSION_FAILED 114 +#define TPM_R_INVALID_EXPONENT 115 +#define TPM_R_REQUEST_TOO_BIG 116 +#define TPM_R_NO_APP_DATA 117 +#define TPM_R_INVALID_ENC_SCHEME 118 +#define TPM_R_INVALID_MSG_SIZE 119 +#define TPM_R_INVALID_PADDING_TYPE 120 +#define TPM_R_INVALID_KEY 121 +#define TPM_R_FILE_NOT_FOUND 122 +#define TPM_R_FILE_READ_FAILED 123 +#define TPM_R_ID_INVALID 124 +#define TPM_R_TPM_1_2_KEY 125 +#define TPM_R_KEY_UNSUPPORTED 126 +#define TPM_R_KEY_UNRECOGNIZED 127 +#define TPM_R_KEY_NO_PARENT_HANDLE 128 + +/* structure pointed to by the RSA object's app_data pointer. + * this is used to tag TPM meta data in the RSA object and + * use that to distinguish between a vanilla Openssl RSA object + * and a TPM RSA object + */ +struct rsa_app_data +{ + TPMI_DH_OBJECT hKey; + // add additional meta data as need be +}; + +#define TPM_ENGINE_EX_DATA_UNINIT -1 +#define RSA_PKCS1_OAEP_PADDING_SIZE (2 * SHA_DIGEST_LENGTH + 2) + +#endif diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2_err.c b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2_err.c new file mode 100644 index 00000000..6a584a96 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/e_tpm2_err.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +/* ==================================================================== + * Copyright (c) 1999-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product is inspired by the original TPM 1.2 openssl engine written + * by Kent Yoder for the Trousers Project. This product + * includes TPM key blob ASN-1 encoding scheme from James Bottomley + * + * + */ +#include + +#include +#include +#include + +#include "e_tpm2.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA TPM_str_functs[] = { + {ERR_PACK(0, TPM_F_TPM_ENGINE_CTRL, 0), "TPM_ENGINE_CTRL"}, + {ERR_PACK(0, TPM_F_TPM_ENGINE_FINISH, 0), "TPM_ENGINE_FINISH"}, + {ERR_PACK(0, TPM_F_TPM_ENGINE_INIT, 0), "TPM_ENGINE_INIT"}, + {ERR_PACK(0, TPM_F_TPM_RSA_PRIV_ENC, 0), "TPM_RSA_PRIV_ENC"}, + {ERR_PACK(0, TPM_F_TPM_RSA_PRIV_DEC, 0), "TPM_RSA_PRIV_DEC"}, + {ERR_PACK(0, TPM_F_TPM_RSA_FINISH, 0), "TPM_RSA_FINISH"}, + {ERR_PACK(0, TPM_F_TPM_RSA_INIT, 0), "TPM_RSA_INIT"}, + {ERR_PACK(0, TPM_F_TPM_ENGINE_LOAD_KEY, 0), "TPM_ENGINE_LOAD_KEY"}, + {ERR_PACK(0, TPM_F_TPM_BIND_FN, 0), "TPM_BIND_FN"}, + {ERR_PACK(0, TPM_F_TPM_FILL_RSA_OBJECT, 0), "TPM_FILL_RSA_OBJECT"}, + {ERR_PACK(0, TPM_F_TPM_FLUSH_OBJECT_CONTEXT, 0), "TPM_FLUSH_OBJECT_CONTEXT"}, + {0, NULL} +}; + +static ERR_STRING_DATA TPM_str_reasons[] = { + {TPM_R_ALREADY_LOADED, "already loaded"}, + {TPM_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctrl command not implemented"}, + {TPM_R_DSO_FAILURE, "dso failure"}, + {TPM_R_MISSING_KEY_COMPONENTS, "missing key components"}, + {TPM_R_NOT_INITIALISED, "not initialised"}, + {TPM_R_NOT_LOADED, "not loaded"}, + {TPM_R_OPERANDS_TOO_LARGE, "operands too large"}, + {TPM_R_OUTLEN_TO_LARGE, "outlen to large"}, + {TPM_R_REQUEST_FAILED, "request failed"}, + {TPM_R_REQUEST_TOO_BIG, "requested number of random bytes > 4096"}, + {TPM_R_UNDERFLOW_CONDITION, "underflow condition"}, + {TPM_R_UNDERFLOW_KEYRECORD, "underflow keyrecord"}, + {TPM_R_UNIT_FAILURE, "unit failure"}, + {TPM_R_INVALID_KEY_SIZE, "invalid key size"}, + {TPM_R_BN_CONVERSION_FAILED, "bn conversion failed"}, + {TPM_R_INVALID_EXPONENT, "invalid exponent"}, + {TPM_R_NO_APP_DATA, "no app data in RSA object"}, + {TPM_R_INVALID_ENC_SCHEME, "invalid encryption scheme"}, + {TPM_R_INVALID_MSG_SIZE, "invalid message size to sign"}, + {TPM_R_INVALID_PADDING_TYPE, "invalid padding type"}, + {TPM_R_INVALID_KEY, "invalid key"}, + {TPM_R_FILE_NOT_FOUND, "file to load not found"}, + {TPM_R_FILE_READ_FAILED, "failed reading the key file"}, + {TPM_R_ID_INVALID, "engine id doesn't match"}, + {TPM_R_TPM_1_2_KEY, "tpm 1.2 key format not supported"}, + {TPM_R_KEY_UNSUPPORTED, "unsupported TPM key format"}, + {TPM_R_KEY_UNRECOGNIZED, "unrecognized TPM key format"}, + {TPM_R_KEY_NO_PARENT_HANDLE, "TPM key has no parent handle"}, + {0, NULL} +}; + +#endif + +static ERR_STRING_DATA TPM_lib_name[] = { + {0, TPM_LIB_NAME}, + {0, NULL} +}; + + +static int TPM_lib_error_code = 0; +static int TPM_error_init = 1; + +void ERR_load_TPM_strings(void) +{ + if (TPM_lib_error_code == 0) { + TPM_lib_error_code = ERR_get_next_error_library(); + DBG("TPM_lib_error_code is %d", TPM_lib_error_code); + } + + if (TPM_error_init) { + TPM_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(TPM_lib_error_code, TPM_str_functs); + ERR_load_strings(TPM_lib_error_code, TPM_str_reasons); +#endif + TPM_lib_name[0].error = ERR_PACK(TPM_lib_error_code, 0, 0); + ERR_load_strings(0, TPM_lib_name); + } +} + +void ERR_unload_TPM_strings(void) +{ + if (TPM_error_init == 0) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(TPM_lib_error_code, TPM_str_functs); + ERR_unload_strings(TPM_lib_error_code, TPM_str_reasons); +#endif + + ERR_load_strings(0, TPM_lib_name); + TPM_error_init = 1; + } +} + +void ERR_TSS_error(int function, int reason, char *file, int line) +{ + if (TPM_lib_error_code == 0) + TPM_lib_error_code = ERR_get_next_error_library(); + + ERR_PUT_error(TPM_lib_error_code, function, reason, file, line); +} + diff --git a/security/tpm2-openssl-engine/tpm2-openssl-engine/tpm2-asn.h b/security/tpm2-openssl-engine/tpm2-openssl-engine/tpm2-asn.h new file mode 100644 index 00000000..20c8c074 --- /dev/null +++ b/security/tpm2-openssl-engine/tpm2-openssl-engine/tpm2-asn.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +/* ==================================================================== + * Copyright (c) 1999-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product is inspired by the original TPM 1.2 openssl engine written + * by Kent Yoder for the Trousers Project. This product + * includes TPM key blob ASN-1 encoding scheme from James Bottomley + * + * + */ + +#ifndef _TPM2_ASN_H +#define _TPM2_ASN_H + +#include +#include + +/* + * Define the format of a TPM key file. The current format covers + * both TPM1.2 keys as well as symmetrically encrypted private keys + * produced by TSS2_Import and the TPM2 format public key which + * contains things like the policy but which is cryptographically tied + * to the private key. + * + * TPMKey ::= SEQUENCE { + * type OBJECT IDENTIFIER + * emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL + * parent [1] EXPLICIT INTEGER OPTIONAL + * pubkey [2] EXPLICIT OCTET STRING OPTIONAL + * privkey OCTET STRING + * } + */ + +typedef struct { + ASN1_OBJECT *type; + ASN1_BOOLEAN emptyAuth; + ASN1_INTEGER *parent; + ASN1_OCTET_STRING *pubkey; + ASN1_OCTET_STRING *privkey; +} TSSLOADABLE; + +/* the two type oids are in the TCG namespace 2.23.133; we choose an + * unoccupied child (10) for keytype file and two values: + * 1 : Key that is directly loadable + * 2 : Key that must first be imported then loaded + */ +#define OID_12Key "2.23.133.10.1" +#define OID_loadableKey "2.23.133.10.2" +#define OID_importableKey "2.23.133.10.3" + +ASN1_SEQUENCE(TSSLOADABLE) = { + ASN1_SIMPLE(TSSLOADABLE, type, ASN1_OBJECT), + ASN1_EXP_OPT(TSSLOADABLE, emptyAuth, ASN1_BOOLEAN, 0), + ASN1_EXP_OPT(TSSLOADABLE, parent, ASN1_INTEGER, 1), + ASN1_EXP_OPT(TSSLOADABLE, pubkey, ASN1_OCTET_STRING, 2), + ASN1_SIMPLE(TSSLOADABLE, privkey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(TSSLOADABLE) + +IMPLEMENT_ASN1_FUNCTIONS(TSSLOADABLE) +//DECLARE_ASN1_FUNCTIONS(TSSLOADABLE) + +/* This is the PEM guard tag */ +#define TSSLOADABLE_PEM_STRING "TSS2 KEY BLOB" + +static IMPLEMENT_PEM_write_bio(TSSLOADABLE, TSSLOADABLE, TSSLOADABLE_PEM_STRING, TSSLOADABLE) +static IMPLEMENT_PEM_read_bio(TSSLOADABLE, TSSLOADABLE, TSSLOADABLE_PEM_STRING, TSSLOADABLE) + +#endif