├── .github ├── docker │ ├── docker.env │ ├── launcher.sh │ └── script.sh └── workflows │ └── main.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── nginx ├── default-pem ├── default-persistent ├── nginx.conf └── openssl.cnf ├── openssl-lib-convert-to-pem-key └── convert.c ├── openssl1-cli-tls ├── tpm-on-client │ ├── 0_clean-up.sh │ ├── 1_init-tpm.sh │ ├── 2_gen-ca-crt.sh │ ├── 3_gen-client-crt.sh │ ├── 4_start-server.sh │ ├── 5_start-good-client.sh │ ├── 6_start-bad-client.sh │ └── config └── tpm-on-server │ ├── 0_clean-up.sh │ ├── 1_init-tpm.sh │ ├── 2_gen-ca-crt.sh │ ├── 3_gen-server-crt.sh │ ├── 4_gen-client-crt.sh │ ├── 5_start-server.sh │ ├── 6_start-client.sh │ └── config ├── openssl1-lib-general-examples └── examples.c ├── openssl1-lib-tls ├── tpm-on-client │ ├── 0_clean-up.sh │ ├── 1_init-tpm-key.sh │ ├── 2_init-software-key.sh │ ├── 3_gen-ca-crt.sh │ ├── 4_gen-tpm-client-crt.sh │ ├── 5_gen-software-client-crt.sh │ ├── 6_build-server-client.sh │ ├── 7_start-server.sh │ ├── 8_start-software-client.sh │ ├── 9_start-tpm-client.sh │ ├── client.c │ ├── config │ └── server.c └── tpm-on-server │ ├── 0_clean-up.sh │ ├── 1_init-tpm-key.sh │ ├── 2_init-software-key.sh │ ├── 3_gen-ca-crt.sh │ ├── 4_gen-tpm-client-crt.sh │ ├── 5_gen-software-client-crt.sh │ ├── 6_build-server-client.sh │ ├── 7_start-server.sh │ ├── 8_start-software-client.sh │ ├── client.c │ ├── config │ └── server.c ├── openssl3-cli-tls ├── tpm-on-client │ ├── 0_clean-up.sh │ ├── 1_init-tpm.sh │ ├── 2_gen-ca-crt.sh │ ├── 3_gen-client-crt.sh │ ├── 4_start-server.sh │ ├── 5_start-good-client.sh │ ├── 6_start-bad-client.sh │ └── config └── tpm-on-server │ ├── 0_clean-up.sh │ ├── 1_init-tpm.sh │ ├── 2_gen-ca-crt.sh │ ├── 3_gen-server-crt.sh │ ├── 4_gen-client-crt.sh │ ├── 5_start-server.sh │ ├── 6_start-client.sh │ └── config ├── openssl3-lib-general-examples └── examples.c └── openssl3-lib-tls ├── tpm-on-client ├── 0_clean-up.sh ├── 1_init-tpm-key.sh ├── 2_init-software-key.sh ├── 3_gen-ca-crt.sh ├── 4_gen-tpm-client-crt.sh ├── 5_gen-software-client-crt.sh ├── 6_build-server-client.sh ├── 7_start-server.sh ├── 8_start-software-client.sh ├── 9_start-tpm-client.sh ├── client.c ├── config └── server.c └── tpm-on-server ├── 0_clean-up.sh ├── 1_init-tpm-key.sh ├── 2_init-software-key.sh ├── 3_gen-ca-crt.sh ├── 4_gen-tpm-client-crt.sh ├── 5_gen-software-client-crt.sh ├── 6_build-server-client.sh ├── 7_start-server.sh ├── 8_start-software-client.sh ├── client.c ├── config └── server.c /.github/docker/docker.env: -------------------------------------------------------------------------------- 1 | DEBIAN_FRONTEND=noninteractive 2 | TZ=Etc/UCT 3 | -------------------------------------------------------------------------------- /.github/docker/launcher.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | # GITHUB_WORKSPACE is set by actions/checkout@v3 9 | 10 | export DOCKER_WORKSPACE_DIR="/root/$PROJECT_NAME" 11 | export WORKSPACE_DIR=~/${PLATFORM}_${DOCKER_IMAGE} 12 | 13 | # Do not share the same workspace 14 | cp -rf $GITHUB_WORKSPACE $WORKSPACE_DIR 15 | 16 | docker run \ 17 | --memory-swap -1 \ 18 | --platform `echo $PLATFORM | sed 's/-/\//'` \ 19 | --env WORKSPACE_DIR=$DOCKER_WORKSPACE_DIR \ 20 | --env DOCKER_IMAGE=$DOCKER_IMAGE \ 21 | --env PLATFORM=$PLATFORM \ 22 | --env-file .github/docker/docker.env \ 23 | -v "${WORKSPACE_DIR}:${DOCKER_WORKSPACE_DIR}" \ 24 | `echo $DOCKER_IMAGE | sed 's/-/:/'` \ 25 | /bin/bash -c "${DOCKER_WORKSPACE_DIR}/.github/docker/script.sh" 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /.github/docker/script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | SCRIPT_NAME=${PLATFORM}_${DOCKER_IMAGE} 9 | 10 | cd $WORKSPACE_DIR 11 | 12 | # Mark generic commands 13 | cat README.md | sed '/^ *```all.*$/,/^ *```$/ s/^ *\$/_M_/' > ${SCRIPT_NAME}_parse 14 | # Mark distro dependent commands 15 | sed -i '/^ *```.*'"${DOCKER_IMAGE}"'.*/,/^ *```$/ s/^ *\$/_M_/' ${SCRIPT_NAME}_parse 16 | # Comment all lines without the marker 17 | sed -i '/^_M_/! s/^/# /' ${SCRIPT_NAME}_parse 18 | # Remove the appended comment from all marked lines 19 | sed -i '/^_M_/ s/<--.*//' ${SCRIPT_NAME}_parse 20 | # Remove the marker and prepend the time command 21 | sed -i 's/^_M_ /time /' ${SCRIPT_NAME}_parse 22 | # Remove time command if requested 23 | sed -i '/^# *```.*'timeless'.*/,/^# *```$/ s/^time //' ${SCRIPT_NAME}_parse 24 | # Remove sudo, it is not necessary in docker 25 | sed -i 's/sudo //g' ${SCRIPT_NAME}_parse 26 | 27 | # Initialize an executable script 28 | cat > ${SCRIPT_NAME}.sh << EOF 29 | #!/usr/bin/env bash 30 | set -exo pipefail 31 | 32 | EOF 33 | 34 | cat ${SCRIPT_NAME}_parse >> ${SCRIPT_NAME}.sh 35 | echo -e '\nexit 0' >> ${SCRIPT_NAME}.sh 36 | 37 | # set parameters for tzdata configuration use 38 | TZ=Etc/UCT 39 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 40 | 41 | chmod a+x ${SCRIPT_NAME}.sh 42 | ./${SCRIPT_NAME}.sh 43 | 44 | exit 0 45 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: 2 | CI 3 | on: 4 | workflow_dispatch: 5 | push: 6 | pull_request: 7 | schedule: 8 | - cron: '0 0 * * MON' 9 | jobs: 10 | test: 11 | name: 'Cross Platform Testing' 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | docker_image: ["debian-buster", "debian-bullseye", "debian-bookworm", "ubuntu-18.04", "ubuntu-20.04", "ubuntu-22.04", "ubuntu-24.04"] 16 | platform: ["linux-arm64", "linux-amd64"] 17 | steps: 18 | - name: 'Set up QEMU for cross-platform emulation' 19 | uses: docker/setup-qemu-action@v2 20 | - name: 'Check out repository' 21 | uses: actions/checkout@v3 22 | with: 23 | fetch-depth: 0 24 | - name: 'Test README.md Instructions' 25 | env: 26 | PROJECT_NAME: ${{ github.event.repository.name }} 27 | DOCKER_IMAGE: ${{ matrix.docker_image }} 28 | PLATFORM: ${{ matrix.platform }} 29 | run: | 30 | .github/docker/launcher.sh 31 | shell: bash 32 | - name: 'Upload artifacts' 33 | uses: actions/upload-artifact@v3 34 | with: 35 | name: 'executed-test-scripts' 36 | path: | 37 | ~/${{ matrix.platform }}_${{ matrix.docker_image }}/${{ matrix.platform }}_${{ matrix.docker_image }}.sh 38 | release: 39 | name: 'Create Release' 40 | needs: test 41 | if: startsWith(github.ref, 'refs/tags/') 42 | runs-on: ubuntu-latest 43 | steps: 44 | - name: 'Check out repository' 45 | uses: actions/checkout@v3 46 | with: 47 | fetch-depth: 0 48 | - name: 'Changelog Pruning' 49 | run: | 50 | sed -n `awk '/## \[${{ github.ref_name }}/{c++} c==1{ print NR; exit }' CHANGELOG.md`',$p' CHANGELOG.md > .CHANGELOG.md.tmp 51 | sed `awk '/## \[[x0-9]/{c++} c==2{ print NR; exit }' .CHANGELOG.md.tmp`',$d' .CHANGELOG.md.tmp > ${{ github.workspace }}-CHANGELOG.txt 52 | - name: 'Download artifacts' 53 | uses: actions/download-artifact@v4.1.7 54 | with: 55 | name: 'executed-test-scripts' 56 | path: ci-script-collection 57 | - name: 'Create release' 58 | uses: softprops/action-gh-release@v1 59 | with: 60 | body_path: ${{ github.workspace }}-CHANGELOG.txt 61 | token: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 62 | draft: false 63 | prerelease: false 64 | files: | 65 | LICENSE 66 | ci-script-collection/* 67 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). 5 | 6 | ## [1.1] - 2022-10-20 7 | ### Changed 8 | - CI improvement, splitted test and release into separate jobs 9 | 10 | ### Fixed 11 | - Fixed version number typo on CHANGELOG.md 12 | 13 | ## [1.0] - 2022-10-19 14 | ### Added 15 | - Tag pushing will now trigger CI workflow to perform test then release. 16 | - Add cross platform support for docker in CI workflow. 17 | - More tests are added to CI workflow: 18 | - debian:buster/bullseye in linux/arm64 platform. 19 | - ubuntu:18.04/20.04 in linux/arm64 platform. Test failed in ubuntu:22.04 with error "swtpm: seccomp_load failed with errno 125: Operation canceled", to be investigated. 20 | 21 | ## [MAJOR.MINOR] - YYYY-MM-DD 22 | ### Added 23 | ### Changed 24 | ### Fixed 25 | ### Removed 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2023 Infineon Technologies AG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /nginx/default-pem: -------------------------------------------------------------------------------- 1 | ## 2 | # You should look at the following URL's in order to grasp a solid understanding 3 | # of Nginx configuration files in order to fully unleash the power of Nginx. 4 | # https://www.nginx.com/resources/wiki/start/ 5 | # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ 6 | # https://wiki.debian.org/Nginx/DirectoryStructure 7 | # 8 | # In most cases, administrators will remove this file from sites-enabled/ and 9 | # leave it as reference inside of sites-available where it will continue to be 10 | # updated by the nginx packaging team. 11 | # 12 | # This file will automatically load configuration files provided by other 13 | # applications, such as Drupal or Wordpress. These applications will be made 14 | # available underneath a path with that package name, such as /drupal8. 15 | # 16 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 17 | ## 18 | 19 | # Default server configuration 20 | # 21 | 22 | server { 23 | listen 80 default_server; 24 | listen [::]:80 default_server; 25 | 26 | # SSL configuration 27 | # 28 | listen 443 ssl default_server; 29 | listen [::]:443 ssl default_server; 30 | 31 | ssl_certificate /tmp/rsakey.crt.pem; 32 | ssl_certificate_key engine:tpm2tss:/tmp/rsakey.pem; 33 | 34 | # 35 | # Note: You should disable gzip for SSL traffic. 36 | # See: https://bugs.debian.org/773332 37 | # 38 | # Read up on ssl_ciphers to ensure a secure configuration. 39 | # See: https://bugs.debian.org/765782 40 | # 41 | # Self signed certs generated by the ssl-cert package 42 | # Don't use them in a production server! 43 | # 44 | # include snippets/snakeoil.conf; 45 | 46 | root /var/www/html; 47 | 48 | # Add index.php to the list if you are using PHP 49 | index index.html index.htm index.nginx-debian.html; 50 | 51 | server_name _; 52 | 53 | location / { 54 | # First attempt to serve request as file, then 55 | # as directory, then fall back to displaying a 404. 56 | try_files $uri $uri/ =404; 57 | } 58 | 59 | # pass PHP scripts to FastCGI server 60 | # 61 | #location ~ \.php$ { 62 | # include snippets/fastcgi-php.conf; 63 | # 64 | # # With php-fpm (or other unix sockets): 65 | # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; 66 | # # With php-cgi (or other tcp sockets): 67 | # fastcgi_pass 127.0.0.1:9000; 68 | #} 69 | 70 | # deny access to .htaccess files, if Apache's document root 71 | # concurs with nginx's one 72 | # 73 | #location ~ /\.ht { 74 | # deny all; 75 | #} 76 | } 77 | 78 | 79 | # Virtual Host configuration for example.com 80 | # 81 | # You can move that to a different file under sites-available/ and symlink that 82 | # to sites-enabled/ to enable it. 83 | # 84 | #server { 85 | # listen 80; 86 | # listen [::]:80; 87 | # 88 | # server_name example.com; 89 | # 90 | # root /var/www/example.com; 91 | # index index.html; 92 | # 93 | # location / { 94 | # try_files $uri $uri/ =404; 95 | # } 96 | #} 97 | -------------------------------------------------------------------------------- /nginx/default-persistent: -------------------------------------------------------------------------------- 1 | ## 2 | # You should look at the following URL's in order to grasp a solid understanding 3 | # of Nginx configuration files in order to fully unleash the power of Nginx. 4 | # https://www.nginx.com/resources/wiki/start/ 5 | # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ 6 | # https://wiki.debian.org/Nginx/DirectoryStructure 7 | # 8 | # In most cases, administrators will remove this file from sites-enabled/ and 9 | # leave it as reference inside of sites-available where it will continue to be 10 | # updated by the nginx packaging team. 11 | # 12 | # This file will automatically load configuration files provided by other 13 | # applications, such as Drupal or Wordpress. These applications will be made 14 | # available underneath a path with that package name, such as /drupal8. 15 | # 16 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 17 | ## 18 | 19 | # Default server configuration 20 | # 21 | 22 | server { 23 | listen 80 default_server; 24 | listen [::]:80 default_server; 25 | 26 | # SSL configuration 27 | # 28 | listen 443 ssl default_server; 29 | listen [::]:443 ssl default_server; 30 | 31 | ssl_certificate /tmp/rsakey.crt.pem; 32 | ssl_certificate_key engine:tpm2tss:0x81000002; 33 | 34 | # 35 | # Note: You should disable gzip for SSL traffic. 36 | # See: https://bugs.debian.org/773332 37 | # 38 | # Read up on ssl_ciphers to ensure a secure configuration. 39 | # See: https://bugs.debian.org/765782 40 | # 41 | # Self signed certs generated by the ssl-cert package 42 | # Don't use them in a production server! 43 | # 44 | # include snippets/snakeoil.conf; 45 | 46 | root /var/www/html; 47 | 48 | # Add index.php to the list if you are using PHP 49 | index index.html index.htm index.nginx-debian.html; 50 | 51 | server_name _; 52 | 53 | location / { 54 | # First attempt to serve request as file, then 55 | # as directory, then fall back to displaying a 404. 56 | try_files $uri $uri/ =404; 57 | } 58 | 59 | # pass PHP scripts to FastCGI server 60 | # 61 | #location ~ \.php$ { 62 | # include snippets/fastcgi-php.conf; 63 | # 64 | # # With php-fpm (or other unix sockets): 65 | # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; 66 | # # With php-cgi (or other tcp sockets): 67 | # fastcgi_pass 127.0.0.1:9000; 68 | #} 69 | 70 | # deny access to .htaccess files, if Apache's document root 71 | # concurs with nginx's one 72 | # 73 | #location ~ /\.ht { 74 | # deny all; 75 | #} 76 | } 77 | 78 | 79 | # Virtual Host configuration for example.com 80 | # 81 | # You can move that to a different file under sites-available/ and symlink that 82 | # to sites-enabled/ to enable it. 83 | # 84 | #server { 85 | # listen 80; 86 | # listen [::]:80; 87 | # 88 | # server_name example.com; 89 | # 90 | # root /var/www/example.com; 91 | # index index.html; 92 | # 93 | # location / { 94 | # try_files $uri $uri/ =404; 95 | # } 96 | #} 97 | -------------------------------------------------------------------------------- /nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | include /etc/nginx/modules-enabled/*.conf; 5 | 6 | events { 7 | worker_connections 768; 8 | # multi_accept on; 9 | } 10 | 11 | ssl_engine tpm2tss; 12 | 13 | http { 14 | 15 | ## 16 | # Basic Settings 17 | ## 18 | 19 | sendfile on; 20 | tcp_nopush on; 21 | tcp_nodelay on; 22 | keepalive_timeout 65; 23 | types_hash_max_size 2048; 24 | # server_tokens off; 25 | 26 | # server_names_hash_bucket_size 64; 27 | # server_name_in_redirect off; 28 | 29 | include /etc/nginx/mime.types; 30 | default_type application/octet-stream; 31 | 32 | ## 33 | # SSL Settings 34 | ## 35 | 36 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE 37 | ssl_prefer_server_ciphers on; 38 | 39 | ## 40 | # Logging Settings 41 | ## 42 | 43 | access_log /var/log/nginx/access.log; 44 | error_log /var/log/nginx/error.log; 45 | 46 | ## 47 | # Gzip Settings 48 | ## 49 | 50 | gzip on; 51 | 52 | # gzip_vary on; 53 | # gzip_proxied any; 54 | # gzip_comp_level 6; 55 | # gzip_buffers 16 8k; 56 | # gzip_http_version 1.1; 57 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 58 | 59 | ## 60 | # Virtual Host Configs 61 | ## 62 | 63 | include /etc/nginx/conf.d/*.conf; 64 | include /etc/nginx/sites-enabled/*; 65 | } 66 | 67 | 68 | #mail { 69 | # # See sample authentication script at: 70 | # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript 71 | # 72 | # # auth_http localhost/auth.php; 73 | # # pop3_capabilities "TOP" "USER"; 74 | # # imap_capabilities "IMAP4rev1" "UIDPLUS"; 75 | # 76 | # server { 77 | # listen localhost:110; 78 | # protocol pop3; 79 | # proxy on; 80 | # } 81 | # 82 | # server { 83 | # listen localhost:143; 84 | # protocol imap; 85 | # proxy on; 86 | # } 87 | #} 88 | -------------------------------------------------------------------------------- /nginx/openssl.cnf: -------------------------------------------------------------------------------- 1 | openssl_conf = openssl_init 2 | 3 | [openssl_init] 4 | engines = engine_section 5 | 6 | [engine_section] 7 | tpm2tss = tpm2tss_section 8 | 9 | [tpm2tss_section] 10 | engine_id = tpm2tss 11 | dynamic_path = /usr/lib/any-linux-gnu/engines-1.1/libtpm2tss.so 12 | default_algorithms = RSA 13 | init = 1 14 | SET_TCTI = mssim:host=127.0.0.1,port=2321 15 | 16 | [req] 17 | distinguished_name = subject 18 | 19 | [subject] 20 | 21 | -------------------------------------------------------------------------------- /openssl-lib-convert-to-pem-key/convert.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define PRINT(...) printf(__VA_ARGS__); \ 34 | printf("\n"); 35 | 36 | #define LOG_ERR(...) PRINT(__VA_ARGS__); 37 | #define xstr(s) str(s) 38 | #define str(s) #s 39 | 40 | #define LOAD_TYPE(type, name) \ 41 | bool files_load_##name(const char *path, type *name) { \ 42 | \ 43 | UINT8 buffer[sizeof(*name)]; \ 44 | UINT16 size = sizeof(buffer); \ 45 | bool res = files_load_bytes_from_path(path, buffer, &size); \ 46 | if (!res) { \ 47 | return false; \ 48 | } \ 49 | \ 50 | size_t offset = 0; \ 51 | TSS2_RC rc = Tss2_MU_##type##_Unmarshal(buffer, size, &offset, name); \ 52 | if (rc != TSS2_RC_SUCCESS) { \ 53 | LOG_ERR("Error deserializing "str(name)" structure: 0x%x", rc); \ 54 | LOG_ERR("The input file needs to be a valid "xstr(type)" data structure"); \ 55 | return false; \ 56 | } \ 57 | \ 58 | return rc == TPM2_RC_SUCCESS; \ 59 | } 60 | 61 | static size_t readx(FILE *f, UINT8 *data, size_t size) { 62 | 63 | size_t bread = 0; 64 | do { 65 | bread += fread(&data[bread], 1, size-bread, f); 66 | } while (bread < size && !feof(f) && errno == EINTR); 67 | 68 | return bread; 69 | } 70 | 71 | bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path) { 72 | 73 | long current = ftell(fp); 74 | if (current < 0) { 75 | if (path) { 76 | LOG_ERR("Error getting current file offset for file \"%s\" error: " 77 | "%s", path, strerror(errno)); 78 | } 79 | return false; 80 | } 81 | 82 | int rc = fseek(fp, 0, SEEK_END); 83 | if (rc < 0) { 84 | if (path) { 85 | LOG_ERR("Error seeking to end of file \"%s\" error: %s", path, 86 | strerror(errno)); 87 | } 88 | return false; 89 | } 90 | 91 | long size = ftell(fp); 92 | if (size < 0) { 93 | if (path) { 94 | LOG_ERR("ftell on file \"%s\" failed: %s", path, strerror(errno)); 95 | } 96 | return false; 97 | } 98 | 99 | rc = fseek(fp, current, SEEK_SET); 100 | if (rc < 0) { 101 | if (path) { 102 | LOG_ERR( 103 | "Could not restore initial stream position for file \"%s\" " 104 | "failed: %s", path, strerror(errno)); 105 | } 106 | return false; 107 | } 108 | 109 | /* size cannot be negative at this point */ 110 | *file_size = (unsigned long) size; 111 | return true; 112 | } 113 | 114 | bool file_read_bytes_from_file(FILE *f, UINT8 *buf, UINT16 *size, 115 | const char *path) { 116 | 117 | unsigned long file_size; 118 | bool result = files_get_file_size(f, &file_size, path); 119 | if (!result) { 120 | /* get_file_size() logs errors */ 121 | return false; 122 | } 123 | 124 | /* max is bounded on *size */ 125 | if (file_size > *size) { 126 | if (path) { 127 | LOG_ERR( 128 | "File \"%s\" size is larger than buffer, got %lu expected " 129 | "less than or equal to %u", path, file_size, *size); 130 | } 131 | return false; 132 | } 133 | 134 | /* The reported file size is not always correct, e.g. for sysfs files 135 | generated on the fly by the kernel when they are read, which appear as 136 | having size 0. Read as many bytes as we can until EOF is reached or the 137 | provided buffer is full. As a small sanity check, fail if the number of 138 | bytes read is smaller than the reported file size. */ 139 | *size = readx(f, buf, *size); 140 | if (*size < file_size) { 141 | if (path) { 142 | LOG_ERR("Could not read data from file \"%s\"", path); 143 | } 144 | return false; 145 | } 146 | 147 | return true; 148 | } 149 | 150 | bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size) { 151 | 152 | if (!buf || !size || !path) { 153 | return false; 154 | } 155 | 156 | FILE *f = fopen(path, "rb"); 157 | if (!f) { 158 | LOG_ERR("Could not open file \"%s\" error %s", path, strerror(errno)); 159 | return false; 160 | } 161 | 162 | bool result = file_read_bytes_from_file(f, buf, size, path); 163 | 164 | fclose(f); 165 | return result; 166 | } 167 | 168 | LOAD_TYPE(TPM2B_PUBLIC, public) 169 | LOAD_TYPE(TPM2B_PRIVATE, private) 170 | 171 | int main(int argc, char **argv) 172 | { 173 | char *keyPubPath = NULL; 174 | char *keyPrivPath = NULL; 175 | char *outPath = NULL; 176 | bool res = false; 177 | TPM2B_PUBLIC pub = {0}; 178 | TPM2B_PRIVATE priv = {0}; 179 | TPM2_DATA *tpm2Data = NULL; 180 | TPM2_HANDLE parentHandle = 0; 181 | 182 | PRINT("Starting..."); 183 | 184 | if (argc != 5) { 185 | PRINT("invalid inputs. Usage: convert 0x81000001 key.pub key.priv key.pem"); 186 | goto err1; 187 | } 188 | 189 | parentHandle = strtoul(argv[1], NULL, 16); 190 | keyPubPath = argv[2]; 191 | keyPrivPath = argv[3]; 192 | outPath = argv[4]; 193 | PRINT("parent handle: %04x", parentHandle); 194 | PRINT("path to key.pub: %s", keyPubPath); 195 | PRINT("path to key.priv: %s", keyPrivPath); 196 | PRINT("path to key.pem: %s", outPath); 197 | 198 | res = files_load_public(keyPubPath, &pub); 199 | if (!res) { 200 | PRINT("files_load_public failed"); 201 | goto err1; 202 | } 203 | 204 | res = files_load_private(keyPrivPath, &priv); 205 | if (!res) { 206 | PRINT("files_load_private failed"); 207 | goto err1; 208 | } 209 | 210 | tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data)); 211 | if (tpm2Data == NULL) { 212 | PRINT("OPENSSL_malloc failed"); 213 | goto err1; 214 | } 215 | memset(tpm2Data, 0, sizeof(*tpm2Data)); 216 | 217 | tpm2Data->emptyAuth = 1; 218 | /* 219 | * To support auth value: 220 | * 221 | * tpm2Data->userauth.size = strlen(password); 222 | * memcpy(&tpm2Data->userauth.buffer[0], password, 223 | * tpm2Data->userauth.size); 224 | */ 225 | tpm2Data->parent = parentHandle; 226 | tpm2Data->pub = pub; 227 | tpm2Data->priv = priv; 228 | 229 | if (!tpm2tss_tpm2data_write(tpm2Data, outPath)) { 230 | PRINT("tpm2tss_tpm2data_write failed"); 231 | free(tpm2Data); 232 | return 1; 233 | } 234 | 235 | OPENSSL_free(tpm2Data); 236 | err1: 237 | PRINT("Exiting..."); 238 | return 0; 239 | } 240 | 241 | 242 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr 2> /dev/null 9 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/1_init-tpm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa2048 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/2_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/3_gen-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -engine tpm2tss -keyform engine -key 0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo '01' > ca/serial 17 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 18 | 19 | # Generate self-signed client cert to demonstrate an invalid client cert (not CA signed) 20 | openssl req -x509 -sha256 -engine tpm2tss -keyform engine -key 0x81000001 -in tpm.csr -out bad-tpm.crt 21 | 22 | # Read cert 23 | #openssl x509 -in tpm.crt -text -noout 24 | #openssl x509 -in bad-tpm.crt -text -noout 25 | 26 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/4_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # 5 | # CAfile: A file containing trusted certificates to use during client authentication 6 | # cert: Server certificate 7 | # key: Server private key 8 | # 9 | openssl s_server -Verify 1 -tls1_2 -CAfile local-ca.crt -cert local-ca.crt -key local-ca.key -verify_return_error -quiet -accept 8443 10 | 11 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/5_start-good-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -engine tpm2tss -keyform engine -key 0x81000001 -cert tpm.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/6_start-bad-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -engine tpm2tss -keyform engine -key 0x81000001 -cert bad-tpm.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-client/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | #certificate = ../assessment-remote-server/remote-ca.crt # the remote CA cert 14 | #private_key = ../assessment-remote-server/remote-ca.key # the remote CA private key 15 | 16 | default_days = 365 # how long to certify for 17 | default_crl_days= 30 # how long before next CRL 18 | default_md = sha256 # md to use 19 | 20 | policy = policy_any # default policy 21 | email_in_dn = no # Don't add the email into cert DN 22 | 23 | name_opt = ca_default # Subject name display option 24 | cert_opt = ca_default # Certificate display option 25 | copy_extensions = none # Don't copy extensions from request 26 | 27 | [ policy_any ] 28 | countryName = supplied 29 | stateOrProvinceName = optional 30 | organizationName = optional 31 | organizationalUnitName = optional 32 | commonName = supplied 33 | emailAddress = optional 34 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | rm -rf *.key *.crt ca local-ca.* *.ctx rsakey.* *.csr 2> /dev/null 9 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/1_init-tpm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa2048 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/2_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/3_gen-server-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -engine tpm2tss -keyform engine -key 0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out server.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo '01' > ca/serial 17 | (yes || true) | openssl ca -config config -in server.csr -out server.crt 18 | 19 | # Read cert 20 | #openssl x509 -in server.crt -text -noout 21 | 22 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/4_gen-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate client key 9 | openssl genrsa -out client.key 2048 10 | 11 | # Generate CSR 12 | openssl req -new -key client.key -subj "/CN=TPM/O=Infineon/C=SG" -out client.csr 13 | 14 | # Generate CA signed client cert 15 | rm -rf ca 2> /dev/null 16 | mkdir ca 2> /dev/null 17 | touch ca/index.txt 18 | touch ca/index.txt.attr 19 | echo '01' > ca/serial 20 | (yes || true) | openssl ca -config config -in client.csr -out client.crt 21 | 22 | # Read cert 23 | #openssl x509 -in client.crt -text -noout 24 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/5_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # 5 | # CAfile: A file containing trusted certificates to use during client authentication 6 | # cert: Server certificate 7 | # key: Server private key 8 | # 9 | openssl s_server -engine tpm2tss -keyform engine -Verify 1 -tls1_2 -CAfile local-ca.crt -cert server.crt -key 0x81000001 -verify_return_error -quiet -accept 8443 10 | 11 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/6_start-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -key client.key -cert client.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl1-cli-tls/tpm-on-server/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | #certificate = ../assessment-remote-server/remote-ca.crt # the remote CA cert 14 | #private_key = ../assessment-remote-server/remote-ca.key # the remote CA private key 15 | 16 | default_days = 365 # how long to certify for 17 | default_crl_days= 30 # how long before next CRL 18 | default_md = sha256 # md to use 19 | 20 | policy = policy_any # default policy 21 | email_in_dn = no # Don't add the email into cert DN 22 | 23 | name_opt = ca_default # Subject name display option 24 | cert_opt = ca_default # Certificate display option 25 | copy_extensions = none # Don't copy extensions from request 26 | 27 | [ policy_any ] 28 | countryName = supplied 29 | stateOrProvinceName = optional 30 | organizationName = optional 31 | organizationalUnitName = optional 32 | commonName = supplied 33 | emailAddress = optional 34 | -------------------------------------------------------------------------------- /openssl1-lib-general-examples/examples.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define PRINT(...) printf(__VA_ARGS__); \ 35 | printf("\n"); 36 | 37 | //#define TPM_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/libtpm2tss.so" 38 | #define RSA_KEY_PATH "/tmp/rsa-key" 39 | #define EC_KEY_PATH "/tmp/ec-key" 40 | 41 | void init_openssl() 42 | { 43 | OpenSSL_add_all_algorithms(); 44 | SSL_load_error_strings(); 45 | SSL_library_init(); 46 | } 47 | 48 | void cleanup_openssl() 49 | { 50 | EVP_cleanup(); 51 | } 52 | 53 | int 54 | gen_random() 55 | { 56 | unsigned char buf[4]; 57 | 58 | int rc = RAND_bytes(buf, sizeof(buf)); 59 | 60 | if(rc != 1) { 61 | PRINT("RAND_bytes failed"); 62 | return -1; 63 | } 64 | 65 | PRINT("Obtained random: %02x%02x%02x%02x", buf[0], buf[1], buf[2], buf[3]); 66 | 67 | return 0; 68 | } 69 | 70 | int 71 | rsa_genkey() 72 | { 73 | RSA *rsa = NULL; 74 | int ret = -1; 75 | 76 | PRINT("Generating RSA key using TPM"); 77 | 78 | BIGNUM *e = BN_new(); 79 | if (!e) { 80 | PRINT("out of memory"); 81 | goto err1; 82 | } 83 | BN_set_word(e, /* exponent */ 65537); 84 | 85 | rsa = RSA_new(); 86 | if (!rsa) { 87 | PRINT("out of memory"); 88 | goto err2; 89 | } 90 | if (!tpm2tss_rsa_genkey(rsa, /* key size */ 2048, e, /* password */ NULL, /* parent keyhandle or TPM2_RH_OWNER or 0 */ 0)) { 91 | PRINT("tpm2tss_rsa_genkey failed"); 92 | goto err3; 93 | } 94 | 95 | PRINT("RSA Key generated"); 96 | 97 | TPM2_DATA *tpm2Data = calloc(1, sizeof(*tpm2Data)); 98 | if (tpm2Data == NULL) { 99 | PRINT("out of memory"); 100 | goto err3; 101 | } 102 | 103 | memcpy(tpm2Data, RSA_get_app_data(rsa), sizeof(*tpm2Data)); 104 | 105 | if (!tpm2tss_tpm2data_write(tpm2Data, RSA_KEY_PATH)) { 106 | PRINT("Error writing file"); 107 | goto err4; 108 | } 109 | 110 | PRINT("RSA Key written to %s", RSA_KEY_PATH); 111 | 112 | ret = 0; 113 | 114 | err4: 115 | free(tpm2Data); 116 | err3: 117 | RSA_free(rsa); 118 | err2: 119 | BN_free(e); 120 | err1: 121 | return ret; 122 | } 123 | 124 | int 125 | ec_genkey() 126 | { 127 | EC_KEY *eckey = NULL; 128 | int ret = -1; 129 | 130 | PRINT("Generating EC key using TPM"); 131 | 132 | eckey = EC_KEY_new(); 133 | if (!eckey) { 134 | PRINT("out of memory"); 135 | goto err1; 136 | } 137 | 138 | //TPM2_ECC_NIST_P256, TPM2_ECC_NIST_P384 139 | if (!tpm2tss_ecc_genkey(eckey, TPM2_ECC_NIST_P256, /* password */ NULL, /* parent keyhandle or TPM2_RH_OWNER or 0 */ 0)) { 140 | PRINT("tpm2tss_rsa_genkey failed"); 141 | goto err2; 142 | } 143 | 144 | PRINT("EC Key generated"); 145 | 146 | TPM2_DATA *tpm2Data = calloc(1, sizeof(*tpm2Data)); 147 | if (tpm2Data == NULL) { 148 | PRINT("out of memory"); 149 | goto err2; 150 | } 151 | 152 | memcpy(tpm2Data, tpm2tss_ecc_getappdata(eckey), sizeof(*tpm2Data)); 153 | 154 | if (!tpm2tss_tpm2data_write(tpm2Data, EC_KEY_PATH)) { 155 | PRINT("Error writing file"); 156 | goto err3; 157 | } 158 | 159 | PRINT("EC Key written to %s", EC_KEY_PATH); 160 | 161 | ret = 0; 162 | 163 | err3: 164 | free(tpm2Data); 165 | err2: 166 | EC_KEY_free(eckey); 167 | err1: 168 | return ret; 169 | } 170 | 171 | int 172 | ec_evp_pkey_sign_verify(EVP_PKEY *pKey) 173 | { 174 | EVP_PKEY_CTX *ctx = NULL; 175 | unsigned char sha256[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 176 | unsigned char *sig = NULL; 177 | size_t sha256Len = 32, sigLen = 0; 178 | int ret = -1; 179 | 180 | ctx = EVP_PKEY_CTX_new(pKey, NULL); 181 | if (!ctx) { 182 | PRINT("EC EVP_PKEY_CTX_new error"); 183 | goto err1; 184 | } 185 | 186 | /* Signing */ 187 | 188 | PRINT("EC signing"); 189 | 190 | if (EVP_PKEY_sign_init(ctx) <= 0 || 191 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0 || 192 | EVP_PKEY_sign(ctx, NULL, &sigLen, sha256, sha256Len) <= 0) { 193 | PRINT("EC sign init error"); 194 | goto err2; 195 | } 196 | 197 | sig = OPENSSL_malloc(sigLen); 198 | 199 | if (!sig) { 200 | PRINT("EC malloc error"); 201 | goto err2; 202 | } 203 | 204 | PRINT("EC generating signature"); 205 | 206 | if (EVP_PKEY_sign(ctx, sig, &sigLen, sha256, sha256Len) <= 0) { 207 | PRINT("EC signing error"); 208 | goto err3; 209 | } 210 | 211 | /* Verification */ 212 | 213 | PRINT("EC verify signature"); 214 | 215 | if (EVP_PKEY_verify_init(ctx) <= 0 || 216 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) { 217 | PRINT("EC verification init error"); 218 | goto err2; 219 | } 220 | 221 | /* ret == 1 indicates success, 0 verify failure and < 0 for some 222 | * other error. 223 | */ 224 | if (EVP_PKEY_verify(ctx, sig, sigLen, sha256, sha256Len) <= 0) { 225 | PRINT("EC signature verification error"); 226 | goto err3; 227 | } 228 | 229 | PRINT("EC signature verification ok"); 230 | 231 | // corrupt the hash 232 | sha256[3] = 1; 233 | if (EVP_PKEY_verify(ctx, sig, sigLen, sha256, sha256Len) == 0) { 234 | PRINT("EC signature verification expected to fail, ok"); 235 | } else { 236 | PRINT("EC signature verification error"); 237 | goto err3; 238 | } 239 | 240 | ret = 0; 241 | 242 | err3: 243 | OPENSSL_free(sig); 244 | err2: 245 | EVP_PKEY_CTX_free(ctx); 246 | err1: 247 | return ret; 248 | } 249 | 250 | int 251 | rsa_evp_pkey_sign_verify(EVP_PKEY *pKey) 252 | { 253 | EVP_PKEY_CTX *ctx = NULL; 254 | unsigned char sha256[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 255 | unsigned char *sig = NULL; 256 | size_t sha256Len = 32, sigLen = 0; 257 | int ret = -1; 258 | 259 | ctx = EVP_PKEY_CTX_new(pKey, NULL); 260 | if (!ctx) { 261 | PRINT("RSA EVP_PKEY_CTX_new error"); 262 | goto err1; 263 | } 264 | 265 | /* Signing */ 266 | 267 | PRINT("RSA signing"); 268 | 269 | if (EVP_PKEY_sign_init(ctx) <= 0 || 270 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || 271 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0 || 272 | EVP_PKEY_sign(ctx, NULL, &sigLen, sha256, sha256Len) <= 0) { 273 | PRINT("RSA sign init error"); 274 | goto err2; 275 | } 276 | 277 | sig = OPENSSL_malloc(sigLen); 278 | 279 | if (!sig) { 280 | PRINT("RSA malloc error"); 281 | goto err2; 282 | } 283 | 284 | PRINT("RSA generating signature"); 285 | 286 | if (EVP_PKEY_sign(ctx, sig, &sigLen, sha256, sha256Len) <= 0) { 287 | PRINT("RSA signing error"); 288 | goto err3; 289 | } 290 | 291 | /* Verification */ 292 | 293 | PRINT("RSA verify signature"); 294 | 295 | if (EVP_PKEY_verify_init(ctx) <= 0 || 296 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || 297 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) { 298 | PRINT("RSA verification init error"); 299 | goto err2; 300 | } 301 | 302 | /* ret == 1 indicates success, 0 verify failure and < 0 for some 303 | * other error. 304 | */ 305 | if (EVP_PKEY_verify(ctx, sig, sigLen, sha256, sha256Len) <= 0) { 306 | PRINT("RSA signature verification error"); 307 | goto err3; 308 | } 309 | 310 | PRINT("RSA signature verification ok"); 311 | 312 | // corrupt the hash 313 | sha256[3] = 1; 314 | if (EVP_PKEY_verify(ctx, sig, sigLen, sha256, sha256Len) == 0) { 315 | PRINT("RSA signature verification expected to fail, ok"); 316 | } else { 317 | PRINT("RSA signature verification error"); 318 | goto err3; 319 | } 320 | 321 | ret = 0; 322 | 323 | err3: 324 | OPENSSL_free(sig); 325 | err2: 326 | EVP_PKEY_CTX_free(ctx); 327 | err1: 328 | return ret; 329 | } 330 | 331 | int 332 | ec_sign_verify(EVP_PKEY *pKey) 333 | { 334 | EC_KEY *eckey = NULL; 335 | unsigned char sha256[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 336 | unsigned char *sig = NULL; 337 | unsigned int sigLen = 0; 338 | int ret = -1; 339 | 340 | eckey = EVP_PKEY_get1_EC_KEY(pKey); 341 | if (eckey == NULL) { 342 | PRINT("EC EVP_PKEY_get1_EC_KEY error"); 343 | goto err1; 344 | } 345 | 346 | /* Signing */ 347 | 348 | sig = OPENSSL_malloc(ECDSA_size(eckey)); 349 | if (!sig) { 350 | PRINT("EC malloc error"); 351 | goto err2; 352 | } 353 | 354 | PRINT("EC Generating signature"); 355 | 356 | if (!ECDSA_sign(0, sha256, sizeof(sha256), sig, &sigLen, eckey)) { 357 | PRINT("EC signing error"); 358 | goto err3; 359 | } 360 | 361 | /* optionally use ECDSA_do_sign(...) -> https://www.openssl.org/docs/man1.1.0/man3/ECDSA_sign.html */ 362 | 363 | 364 | /* Verification */ 365 | 366 | PRINT("EC verify signature"); 367 | 368 | if (ECDSA_verify(0, sha256, sizeof(sha256), sig, sigLen, eckey) != 1) { 369 | PRINT("EC signature verification error"); 370 | goto err3; 371 | } 372 | 373 | PRINT("EC signature verification ok"); 374 | 375 | sha256[2] = 1; 376 | if (ECDSA_verify(0, sha256, sizeof(sha256), sig, sigLen, eckey) == 0) { 377 | PRINT("EC signature verification expected to fail, ok"); 378 | } else { 379 | PRINT("EC signature verification error"); 380 | goto err3; 381 | } 382 | 383 | /* optionally use ECDSA_do_verify(...) -> https://www.openssl.org/docs/man1.1.0/man3/ECDSA_sign.html */ 384 | 385 | ret = 0; 386 | 387 | err3: 388 | OPENSSL_free(sig); 389 | err2: 390 | EC_KEY_free(eckey); 391 | err1: 392 | return ret; 393 | } 394 | 395 | int 396 | rsa_sign_verify(EVP_PKEY *pKey) 397 | { 398 | RSA *rsa = NULL; 399 | unsigned char message[] = {1,2,3}; 400 | unsigned char *sig = NULL; 401 | unsigned int sigLen = 0; 402 | int ret = -1; 403 | 404 | rsa = EVP_PKEY_get1_RSA(pKey); 405 | if (rsa == NULL) { 406 | PRINT("RSA EVP_PKEY_get1_RSA error"); 407 | goto err1; 408 | } 409 | 410 | /* Signing */ 411 | 412 | sig = OPENSSL_malloc(RSA_size(rsa)); 413 | if (!sig) { 414 | PRINT("RSA malloc error"); 415 | goto err2; 416 | } 417 | 418 | PRINT("RSA generating signature"); 419 | 420 | if (!RSA_sign(RSA_PKCS1_PADDING, message, sizeof(message), sig, &sigLen, rsa)) { 421 | PRINT("RSA signing error"); 422 | goto err3; 423 | } 424 | 425 | /* Verification */ 426 | 427 | PRINT("RSA verify signature"); 428 | 429 | if (!RSA_verify(RSA_PKCS1_PADDING, message, sizeof(message), sig, sigLen, rsa)) { 430 | PRINT("RSA signature verification error"); 431 | goto err3; 432 | } 433 | 434 | PRINT("RSA signature verification ok"); 435 | 436 | message[2] = 1; 437 | if (!RSA_verify(RSA_PKCS1_PADDING, message, sizeof(message), sig, sigLen, rsa)) { 438 | PRINT("RSA signature verification expected to fail, ok"); 439 | } else { 440 | PRINT("RSA signature verification error"); 441 | goto err3; 442 | } 443 | 444 | ret = 0; 445 | 446 | err3: 447 | OPENSSL_free(sig); 448 | err2: 449 | RSA_free(rsa); 450 | err1: 451 | return ret; 452 | } 453 | 454 | int 455 | rsa_evp_pkey_encrypt_decrypt(EVP_PKEY *pKey) 456 | { 457 | EVP_PKEY_CTX *ctx = NULL; 458 | unsigned char clear[] = {1,2,3}; 459 | unsigned char *ciphered = NULL, *deciphered = NULL; 460 | size_t cipheredLen = 0, decipheredLen = 0, clearLen = 3; 461 | int ret = -1; 462 | 463 | ctx = EVP_PKEY_CTX_new(pKey, NULL); 464 | if (!ctx) { 465 | PRINT("EVP_PKEY_CTX_new error"); 466 | goto err1; 467 | } 468 | 469 | /* Encryption (RSA_PKCS1_PADDING) */ 470 | 471 | if (EVP_PKEY_encrypt_init(ctx) <= 0 || 472 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || 473 | EVP_PKEY_encrypt(ctx, NULL, &cipheredLen, clear, clearLen) <= 0) { 474 | PRINT("Encryption init error"); 475 | goto err2; 476 | } 477 | 478 | ciphered = OPENSSL_malloc(cipheredLen); 479 | if (!ciphered) { 480 | PRINT("malloc error"); 481 | goto err2; 482 | } 483 | 484 | PRINT("Generating encryption blob"); 485 | 486 | if (EVP_PKEY_encrypt(ctx, ciphered, &cipheredLen, clear, clearLen) <= 0) { 487 | PRINT("Encryption error"); 488 | goto err3; 489 | } 490 | 491 | /* Decryption (support only RSA_PKCS1_PADDING, https://github.com/tpm2-software/tpm2-tss-engine/pull/89) */ 492 | 493 | if (EVP_PKEY_decrypt_init(ctx) <= 0 || 494 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || 495 | EVP_PKEY_decrypt(ctx, NULL, &decipheredLen, ciphered, cipheredLen) <= 0) { 496 | PRINT("Decryption init error"); 497 | goto err2; 498 | } 499 | 500 | deciphered = OPENSSL_malloc(decipheredLen); 501 | if (!deciphered) { 502 | PRINT("malloc error"); 503 | goto err2; 504 | } 505 | 506 | memset(deciphered, 0, decipheredLen); 507 | 508 | PRINT("Decrypting encrypted blob"); 509 | 510 | if (EVP_PKEY_decrypt(ctx, deciphered, &decipheredLen, ciphered, cipheredLen) <= 0) { 511 | PRINT("Decryption error"); 512 | goto err3; 513 | } 514 | 515 | if((decipheredLen != clearLen) || (strncmp((const char *)clear, (const char *)deciphered, decipheredLen) != 0)) 516 | { 517 | PRINT("Decryption error, value not the same"); 518 | goto err3; 519 | } 520 | 521 | PRINT("Decryption verification ok"); 522 | 523 | ret = 0; 524 | 525 | err3: 526 | OPENSSL_free(ciphered); 527 | OPENSSL_free(deciphered); 528 | err2: 529 | EVP_PKEY_CTX_free(ctx); 530 | err1: 531 | return ret; 532 | } 533 | 534 | int 535 | rsa_encrypt_decrypt(EVP_PKEY *pKey) 536 | { 537 | RSA *rsa = NULL; 538 | unsigned char clear[] = {1,2,3}; 539 | unsigned char *ciphered = NULL, *deciphered = NULL; 540 | int cipheredLen = 0, decipheredLen = 0, clearLen = 3; 541 | int ret = -1; 542 | 543 | rsa = EVP_PKEY_get1_RSA(pKey); 544 | if (rsa == NULL) { 545 | PRINT("EVP_PKEY_get1_RSA error"); 546 | goto err1; 547 | } 548 | 549 | /* Encrypt (RSA_PKCS1_OAEP_PADDING) */ 550 | 551 | ciphered = OPENSSL_malloc(RSA_size(rsa)); 552 | if (!ciphered) { 553 | PRINT("malloc error"); 554 | goto err2; 555 | } 556 | 557 | PRINT("Generating encryption blob"); 558 | 559 | cipheredLen = RSA_public_encrypt (clearLen, clear, ciphered, rsa, RSA_PKCS1_OAEP_PADDING); 560 | if (cipheredLen == -1) { 561 | PRINT("Encryption error"); 562 | goto err3; 563 | } 564 | 565 | /* Decrypt (RSA_PKCS1_OAEP_PADDING) */ 566 | 567 | deciphered = OPENSSL_malloc(RSA_size(rsa)); 568 | if (!deciphered) { 569 | PRINT("malloc error"); 570 | goto err2; 571 | } 572 | 573 | PRINT("Decrypting encrypted blob"); 574 | 575 | decipheredLen = RSA_private_decrypt(cipheredLen, ciphered, deciphered, rsa, RSA_PKCS1_OAEP_PADDING); 576 | if (decipheredLen == -1) { 577 | PRINT("Decryption error"); 578 | goto err3; 579 | } 580 | 581 | if((decipheredLen != clearLen) || (strncmp((const char *)clear, (const char *)deciphered, decipheredLen) != 0)) 582 | { 583 | PRINT("Decryption error, value not the same"); 584 | goto err3; 585 | } 586 | 587 | PRINT("Decryption verification ok"); 588 | 589 | ret = 0; 590 | 591 | err3: 592 | OPENSSL_free(ciphered); 593 | OPENSSL_free(deciphered); 594 | err2: 595 | RSA_free(rsa); 596 | err1: 597 | return ret; 598 | } 599 | 600 | int main(int argc, char **argv) 601 | { 602 | (void) argc; 603 | (void) argv; 604 | 605 | ENGINE *pEngine = NULL; 606 | EVP_PKEY *pRsaKey = NULL; 607 | EVP_PKEY *pEcKey = NULL; 608 | 609 | PRINT("Starting..."); 610 | 611 | init_openssl(); 612 | 613 | #ifdef TPM_ENGINE_PATH 614 | ENGINE_load_dynamic(); 615 | pEngine = ENGINE_by_id("dynamic"); 616 | if (!pEngine) 617 | { 618 | PRINT("Unable to load dynamic engine."); 619 | goto err1; 620 | } 621 | 622 | if (!ENGINE_ctrl_cmd_string(pEngine, "SO_PATH", TPM_ENGINE_PATH, 0) 623 | || !ENGINE_ctrl_cmd_string(pEngine, "ID", "tpm2tss", 0) 624 | || !ENGINE_ctrl_cmd_string(pEngine, "LOAD", NULL, 0)) { 625 | PRINT("Unable to load TPM OpenSSL engine ENGINE_ctrl_cmd_string."); 626 | goto err2; 627 | } 628 | #else 629 | /* Load TPM OpenSSL engine. */ 630 | ENGINE_load_builtin_engines(); 631 | pEngine = ENGINE_by_id("tpm2tss"); 632 | if (!pEngine) 633 | { 634 | PRINT("Unable to load tpm2tss engine."); 635 | goto err1; 636 | } 637 | #endif 638 | 639 | if (!ENGINE_init(pEngine)) 640 | { 641 | PRINT("Unable to init TPM2 Engine."); 642 | goto err2; 643 | } 644 | 645 | if (!ENGINE_set_default(pEngine, ENGINE_METHOD_ALL)) 646 | { 647 | PRINT("Unable to set TPM2 Engine."); 648 | goto err2; 649 | } 650 | 651 | #ifdef ENABLE_OPTIGA_TPM 652 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "device:/dev/tpmrm0", NULL)) 653 | { 654 | PRINT("Unable to switch to TPM device mode (/dev/tpmrm0)."); 655 | #else 656 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "tabrmd:bus_type=session", NULL)) 657 | { 658 | PRINT("Unable to switch to TPM simulator mode."); 659 | #endif 660 | goto err2; 661 | } 662 | 663 | /* Generate true random */ 664 | if (gen_random()) 665 | goto err2; 666 | 667 | /* Generate TPM RSA key using tpm2-tss-engine library */ 668 | if (rsa_genkey()) 669 | goto err2; 670 | 671 | /* Generate TPM EC key using tpm2-tss-engine library */ 672 | if (ec_genkey()) 673 | goto err2; 674 | 675 | /* Load RSA Key */ 676 | //pRsaKey = ENGINE_load_private_key(pEngine, "0x81000002", NULL, NULL); 677 | pRsaKey = ENGINE_load_private_key(pEngine, RSA_KEY_PATH, NULL, NULL); 678 | if (pRsaKey == NULL) { 679 | PRINT("RSA Key loading error"); 680 | goto err2; 681 | } 682 | PRINT("Loaded RSA key"); 683 | 684 | /* Load EC Key */ 685 | pEcKey = ENGINE_load_private_key(pEngine, EC_KEY_PATH, NULL, NULL); 686 | if (pEcKey == NULL) { 687 | PRINT("EC Key loading error"); 688 | goto err2; 689 | } 690 | PRINT("Loaded EC key"); 691 | 692 | /* EC signing & verification */ 693 | if (ec_evp_pkey_sign_verify(pEcKey)) 694 | goto err3; 695 | if (ec_sign_verify(pEcKey)) 696 | goto err3; 697 | 698 | /* RSA signing & verification */ 699 | if (rsa_evp_pkey_sign_verify(pRsaKey)) 700 | goto err3; 701 | if (rsa_sign_verify(pRsaKey)) 702 | goto err3; 703 | 704 | /* RSA encryption & decryption */ 705 | if (rsa_evp_pkey_encrypt_decrypt(pRsaKey)) 706 | goto err3; 707 | if (rsa_encrypt_decrypt(pRsaKey)) 708 | goto err3; 709 | 710 | PRINT("Exiting..."); 711 | 712 | err3: 713 | EVP_PKEY_free(pRsaKey); 714 | EVP_PKEY_free(pEcKey); 715 | err2: 716 | ENGINE_free(pEngine); 717 | err1: 718 | cleanup_openssl(); 719 | 720 | } 721 | 722 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr *.key server client-software client-tpm 2> /dev/null 5 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/1_init-tpm-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa2048 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/2_init-software-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | openssl genrsa -out software.key 2048 5 | 6 | 7 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/3_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/4_gen-tpm-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -engine tpm2tss -keyform engine -key 0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo '01' > ca/serial 17 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 18 | 19 | # Read cert 20 | #openssl x509 -in tpm.crt -text -noout 21 | 22 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/5_gen-software-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CSR 7 | openssl req -new -key software.key -subj "/CN=Software/O=Infineon/C=SG" -out software.csr 8 | 9 | # Generate CA signed client cert 10 | rm -rf ca 2> /dev/null 11 | mkdir ca 2> /dev/null 12 | touch ca/index.txt 13 | touch ca/index.txt.attr 14 | echo '01' > ca/serial 15 | (yes || true) | openssl ca -config config -in software.csr -out software.crt 16 | 17 | # Read cert 18 | #openssl x509 -in software.crt -text -noout 19 | 20 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/6_build-server-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | gcc -Wall -o server server.c -lssl -lcrypto 5 | gcc -Wall -o client-software client.c -lssl -lcrypto 6 | gcc -Wall -o client-tpm client.c -lssl -lcrypto -DENABLE_TPM_TSS_ENGINE 7 | 8 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/7_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./server 5 | 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/8_start-software-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-software 5 | 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/9_start-tpm-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-tpm 5 | 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | * https://aticleworld.com/ssl-server-client-using-openssl-in-c/ 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #ifdef ENABLE_TPM_TSS_ENGINE 39 | #include 40 | #endif 41 | 42 | int connect_socket(const char *hostname, int port) 43 | { 44 | int s; 45 | struct hostent *host; 46 | struct sockaddr_in addr; 47 | 48 | if ((host = gethostbyname(hostname)) == NULL) { 49 | perror("Unable to find server"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | bzero(&addr, sizeof(addr)); 54 | addr.sin_family = AF_INET; 55 | addr.sin_port = htons(port); 56 | addr.sin_addr.s_addr = *(long*)(host->h_addr); 57 | 58 | s = socket(AF_INET, SOCK_STREAM, 0); 59 | if (s < 0) { 60 | perror("Unable to create socket"); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 65 | perror("Unable to connect to server"); 66 | exit(EXIT_FAILURE); 67 | } 68 | 69 | return s; 70 | } 71 | 72 | void init_openssl() 73 | { 74 | OpenSSL_add_all_algorithms(); 75 | SSL_load_error_strings(); 76 | SSL_library_init(); 77 | } 78 | 79 | void cleanup_openssl() 80 | { 81 | EVP_cleanup(); 82 | } 83 | 84 | SSL_CTX *create_context() 85 | { 86 | const SSL_METHOD *method; 87 | SSL_CTX *ctx; 88 | 89 | method = SSLv23_client_method(); 90 | 91 | ctx = SSL_CTX_new(method); 92 | if (!ctx) { 93 | perror("Unable to create SSL context"); 94 | ERR_print_errors_fp(stderr); 95 | exit(EXIT_FAILURE); 96 | } 97 | 98 | return ctx; 99 | } 100 | 101 | void configure_context(SSL_CTX *pSslContext, const char *clientCert, const char *clientKey, 102 | const char *caCert) 103 | { 104 | int32_t sslStatus = -1; 105 | 106 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 107 | 108 | /* Set the client cert */ 109 | if (SSL_CTX_use_certificate_chain_file(pSslContext, clientCert) <= 0) { 110 | ERR_print_errors_fp(stderr); 111 | exit(EXIT_FAILURE); 112 | } 113 | 114 | #ifdef ENABLE_TPM_TSS_ENGINE 115 | /* Set TPM-based key */ 116 | { 117 | const char *pEngineName = "tpm2tss"; 118 | ENGINE *pEngine = NULL; 119 | UI_METHOD *pUiMethod = NULL; 120 | EVP_PKEY *pKey = NULL; 121 | 122 | /* Load TPM OpenSSL engine. */ 123 | ENGINE_load_builtin_engines(); 124 | pEngine = ENGINE_by_id(pEngineName); 125 | 126 | if (!pEngine) 127 | { 128 | perror("Unable to load TPM OpenSSL engine."); 129 | exit(EXIT_FAILURE); 130 | } 131 | 132 | if (!ENGINE_init(pEngine)) 133 | { 134 | perror("Unable to init TPM2 Engine."); 135 | exit(EXIT_FAILURE); 136 | } 137 | 138 | if (!ENGINE_set_default(pEngine, ENGINE_METHOD_ALL)) 139 | { 140 | perror("Unable to set TPM2 Engine."); 141 | exit(EXIT_FAILURE); 142 | } 143 | 144 | #ifdef ENABLE_OPTIGA_TPM 145 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "device:/dev/tpmrm0", NULL)) 146 | { 147 | perror("Unable to switch to TPM device mode (/dev/tpmrm0)."); 148 | #else 149 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "tabrmd:bus_type=session", NULL)) 150 | { 151 | perror("Unable to switch to TPM simulator mode."); 152 | #endif 153 | exit(EXIT_FAILURE); 154 | } 155 | 156 | pUiMethod = UI_OpenSSL(); 157 | if (!pUiMethod) 158 | { 159 | perror("Unable to get OpenSSL UI method."); 160 | exit(EXIT_FAILURE); 161 | } 162 | 163 | pKey = ENGINE_load_private_key(pEngine, "0x81000001", pUiMethod, NULL); 164 | 165 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 166 | if (sslStatus <= 0) { 167 | ERR_print_errors_fp(stderr); 168 | exit(EXIT_FAILURE); 169 | } 170 | } 171 | #else 172 | (void)sslStatus; 173 | /* Set software-based key */ 174 | if (SSL_CTX_use_PrivateKey_file(pSslContext, clientKey, SSL_FILETYPE_PEM) <= 0 ) { 175 | ERR_print_errors_fp(stderr); 176 | exit(EXIT_FAILURE); 177 | } 178 | #endif 179 | 180 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify server 181 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify server certificate 182 | 183 | /* Set CA certificate for server verification */ 184 | { 185 | FILE * rootCaFile = NULL; 186 | X509 *rootCa = NULL; 187 | 188 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 189 | perror("Unable to find CA certificate"); 190 | exit(EXIT_FAILURE); 191 | } 192 | 193 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 194 | perror("Unable to decode CA certificate"); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 199 | perror("Unable to load CA certificate"); 200 | exit(EXIT_FAILURE); 201 | } 202 | 203 | if (rootCaFile != NULL) 204 | fclose(rootCaFile); 205 | } 206 | } 207 | 208 | void showCert(SSL* ssl) 209 | { 210 | X509 *cert; 211 | char *line; 212 | 213 | cert = SSL_get_peer_certificate(ssl); 214 | if (cert != NULL) { 215 | printf("Server certificate:\n"); 216 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 217 | printf("Subject: %s\n", line); 218 | free(line); 219 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 220 | printf("Issuer: %s\n", line); 221 | free(line); 222 | X509_free(cert); 223 | } 224 | } 225 | 226 | int main(int argc, char **argv) 227 | { 228 | int sock; 229 | SSL_CTX *ctx; 230 | SSL *ssl; 231 | 232 | init_openssl(); 233 | ctx = create_context(); 234 | #ifdef ENABLE_TPM_TSS_ENGINE 235 | configure_context(ctx, "tpm.crt", "0x81000001", "local-ca.crt"); 236 | #else 237 | configure_context(ctx, "software.crt", "software.key", "local-ca.crt"); 238 | #endif 239 | 240 | sock = connect_socket("localhost", 8443); 241 | ssl = SSL_new(ctx); 242 | SSL_set_fd(ssl, sock); 243 | 244 | if (SSL_connect(ssl) <= 0) { 245 | ERR_print_errors_fp(stderr); 246 | } else { 247 | const char msg[] = "\nHello from client...\n"; 248 | int bytes = 0; 249 | char buf[256]; 250 | 251 | showCert(ssl); 252 | 253 | SSL_write(ssl, msg, strlen(msg)); // send message to server 254 | bytes = SSL_read(ssl, buf, sizeof(buf) - 1); // receive message from server 255 | if (bytes) { 256 | buf[bytes] = '\0'; 257 | printf("\nReceived: \"%s\"\n", buf); 258 | } 259 | } 260 | 261 | SSL_shutdown(ssl); 262 | SSL_free(ssl); 263 | 264 | close(sock); 265 | SSL_CTX_free(ctx); 266 | cleanup_openssl(); 267 | } 268 | 269 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | 14 | default_days = 365 # how long to certify for 15 | default_crl_days= 30 # how long before next CRL 16 | default_md = sha256 # md to use 17 | 18 | policy = policy_any # default policy 19 | email_in_dn = no # Don't add the email into cert DN 20 | 21 | name_opt = ca_default # Subject name display option 22 | cert_opt = ca_default # Certificate display option 23 | copy_extensions = none # Don't copy extensions from request 24 | 25 | [ policy_any ] 26 | countryName = supplied 27 | stateOrProvinceName = optional 28 | organizationName = optional 29 | organizationalUnitName = optional 30 | commonName = supplied 31 | emailAddress = optional 32 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-client/server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | int create_socket(int port) 38 | { 39 | int s; 40 | struct sockaddr_in addr; 41 | const int enable = 1; 42 | 43 | bzero(&addr, sizeof(addr)); 44 | addr.sin_family = AF_INET; 45 | addr.sin_port = htons(port); 46 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 47 | //addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 48 | 49 | s = socket(AF_INET, SOCK_STREAM, 0); 50 | if (s < 0) { 51 | perror("Unable to create socket"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { 56 | perror("Unable to set SO_REUSEADDR"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 61 | perror("Unable to bind"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (listen(s, 1) < 0) { 66 | perror("Unable to listen"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | return s; 71 | } 72 | 73 | void init_openssl() 74 | { 75 | OpenSSL_add_all_algorithms(); 76 | SSL_load_error_strings(); 77 | SSL_library_init(); 78 | } 79 | 80 | void cleanup_openssl() 81 | { 82 | EVP_cleanup(); 83 | } 84 | 85 | SSL_CTX *create_context() 86 | { 87 | const SSL_METHOD *method; 88 | SSL_CTX *ctx; 89 | 90 | method = SSLv23_server_method(); 91 | //method = TLSv1_2_server_method(); 92 | 93 | ctx = SSL_CTX_new(method); 94 | if (!ctx) { 95 | perror("Unable to create SSL context"); 96 | ERR_print_errors_fp(stderr); 97 | exit(EXIT_FAILURE); 98 | } 99 | 100 | return ctx; 101 | } 102 | 103 | void configure_context(SSL_CTX *ctx, const char *serverCert, const char *serverKey, 104 | const char *caCert) 105 | { 106 | SSL_CTX_set_ecdh_auto(ctx, 1); 107 | 108 | /* Set the key and cert */ 109 | if (SSL_CTX_use_certificate_file(ctx, serverCert, SSL_FILETYPE_PEM) <= 0) { 110 | ERR_print_errors_fp(stderr); 111 | exit(EXIT_FAILURE); 112 | } 113 | 114 | if (SSL_CTX_use_PrivateKey_file(ctx, serverKey, SSL_FILETYPE_PEM) <= 0 ) { 115 | ERR_print_errors_fp(stderr); 116 | exit(EXIT_FAILURE); 117 | } 118 | 119 | //SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); // not to verify client 120 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); // to verify client certificate 121 | 122 | /* Set CA certificate for client verification */ 123 | { 124 | FILE * rootCaFile = NULL; 125 | X509 *rootCa = NULL; 126 | 127 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 128 | perror("Unable to find CA certificate"); 129 | exit(EXIT_FAILURE); 130 | } 131 | 132 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 133 | perror("Unable to decode CA certificate"); 134 | exit(EXIT_FAILURE); 135 | } 136 | 137 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), rootCa) <= 0) { 138 | perror("Unable to load CA certificate"); 139 | exit(EXIT_FAILURE); 140 | } 141 | 142 | if (rootCaFile != NULL) 143 | fclose(rootCaFile); 144 | } 145 | } 146 | 147 | void showCert(SSL* ssl) 148 | { 149 | X509 *cert; 150 | char *line; 151 | 152 | cert = SSL_get_peer_certificate(ssl); 153 | if (cert != NULL) { 154 | printf("Client certificate:\n"); 155 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 156 | printf("Subject: %s\n", line); 157 | free(line); 158 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 159 | printf("Issuer: %s\n", line); 160 | free(line); 161 | X509_free(cert); 162 | } 163 | } 164 | 165 | int main(int argc, char **argv) 166 | { 167 | int sock; 168 | SSL_CTX *ctx; 169 | 170 | init_openssl(); 171 | ctx = create_context(); 172 | configure_context(ctx, "local-ca.crt", "local-ca.key", "local-ca.crt"); 173 | 174 | sock = create_socket(8443); 175 | 176 | /* Handle connections */ 177 | while(1) { 178 | struct sockaddr_in addr; 179 | uint len = sizeof(addr); 180 | SSL *ssl; 181 | const char reply[] = "\nHello from server.\n"; 182 | 183 | int client = accept(sock, (struct sockaddr*)&addr, &len); 184 | if (client < 0) { 185 | perror("Unable to accept"); 186 | exit(EXIT_FAILURE); 187 | } 188 | 189 | ssl = SSL_new(ctx); 190 | SSL_set_fd(ssl, client); 191 | 192 | if (SSL_accept(ssl) <= 0) { 193 | ERR_print_errors_fp(stderr); 194 | } 195 | else { 196 | int bytes = 0; 197 | char buf[256]; 198 | 199 | showCert(ssl); 200 | 201 | SSL_write(ssl, reply, strlen(reply)); 202 | bytes = SSL_read(ssl, buf, sizeof(buf)); // receive message from client 203 | if (bytes) { 204 | buf[bytes] = '\0'; 205 | printf("\nReceived: \"%s\"\n", buf); 206 | } 207 | 208 | } 209 | 210 | SSL_shutdown(ssl); 211 | SSL_free(ssl); 212 | close(client); 213 | } 214 | 215 | close(sock); 216 | SSL_CTX_free(ctx); 217 | cleanup_openssl(); 218 | } 219 | 220 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr *.key server client-software client-tpm 2> /dev/null 5 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/1_init-tpm-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa2048 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/2_init-software-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | openssl genrsa -out software.key 2048 5 | 6 | 7 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/3_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/4_gen-tpm-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -engine tpm2tss -keyform engine -key 0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo '01' > ca/serial 17 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 18 | 19 | # Read cert 20 | #openssl x509 -in tpm.crt -text -noout 21 | 22 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/5_gen-software-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CSR 7 | openssl req -new -key software.key -subj "/CN=Software/O=Infineon/C=SG" -out software.csr 8 | 9 | # Generate CA signed client cert 10 | rm -rf ca 2> /dev/null 11 | mkdir ca 2> /dev/null 12 | touch ca/index.txt 13 | touch ca/index.txt.attr 14 | echo '01' > ca/serial 15 | (yes || true) | openssl ca -config config -in software.csr -out software.crt 16 | 17 | # Read cert 18 | #openssl x509 -in software.crt -text -noout 19 | 20 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/6_build-server-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | gcc -Wall -o server server.c -lssl -lcrypto -DENABLE_TPM_TSS_ENGINE 5 | gcc -Wall -o client-software client.c -lssl -lcrypto 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/7_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./server 5 | 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/8_start-software-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-software 5 | 6 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | * https://aticleworld.com/ssl-server-client-using-openssl-in-c/ 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #ifdef ENABLE_TPM_TSS_ENGINE 39 | #include 40 | #endif 41 | 42 | int connect_socket(const char *hostname, int port) 43 | { 44 | int s; 45 | struct hostent *host; 46 | struct sockaddr_in addr; 47 | 48 | if ((host = gethostbyname(hostname)) == NULL) { 49 | perror("Unable to find server"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | bzero(&addr, sizeof(addr)); 54 | addr.sin_family = AF_INET; 55 | addr.sin_port = htons(port); 56 | addr.sin_addr.s_addr = *(long*)(host->h_addr); 57 | 58 | s = socket(AF_INET, SOCK_STREAM, 0); 59 | if (s < 0) { 60 | perror("Unable to create socket"); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 65 | perror("Unable to connect to server"); 66 | exit(EXIT_FAILURE); 67 | } 68 | 69 | return s; 70 | } 71 | 72 | void init_openssl() 73 | { 74 | OpenSSL_add_all_algorithms(); 75 | SSL_load_error_strings(); 76 | SSL_library_init(); 77 | } 78 | 79 | void cleanup_openssl() 80 | { 81 | EVP_cleanup(); 82 | } 83 | 84 | SSL_CTX *create_context() 85 | { 86 | const SSL_METHOD *method; 87 | SSL_CTX *ctx; 88 | 89 | method = SSLv23_client_method(); 90 | 91 | ctx = SSL_CTX_new(method); 92 | if (!ctx) { 93 | perror("Unable to create SSL context"); 94 | ERR_print_errors_fp(stderr); 95 | exit(EXIT_FAILURE); 96 | } 97 | 98 | return ctx; 99 | } 100 | 101 | void configure_context(SSL_CTX *pSslContext, const char *clientCert, const char *clientKey, 102 | const char *caCert) 103 | { 104 | int32_t sslStatus = -1; 105 | 106 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 107 | 108 | /* Set the client cert */ 109 | if (SSL_CTX_use_certificate_chain_file(pSslContext, clientCert) <= 0) { 110 | ERR_print_errors_fp(stderr); 111 | exit(EXIT_FAILURE); 112 | } 113 | 114 | #ifdef ENABLE_TPM_TSS_ENGINE 115 | /* Set TPM-based key */ 116 | { 117 | const char *pEngineName = "tpm2tss"; 118 | ENGINE *pEngine = NULL; 119 | UI_METHOD *pUiMethod = NULL; 120 | EVP_PKEY *pKey = NULL; 121 | 122 | /* Load TPM OpenSSL engine. */ 123 | ENGINE_load_builtin_engines(); 124 | pEngine = ENGINE_by_id(pEngineName); 125 | 126 | if (!pEngine) 127 | { 128 | perror("Unable to load TPM OpenSSL engine."); 129 | exit(EXIT_FAILURE); 130 | } 131 | 132 | if (!ENGINE_init(pEngine)) 133 | { 134 | perror("Unable to init TPM2 Engine."); 135 | exit(EXIT_FAILURE); 136 | } 137 | 138 | if (!ENGINE_set_default(pEngine, ENGINE_METHOD_ALL)) 139 | { 140 | perror("Unable to set TPM2 Engine."); 141 | exit(EXIT_FAILURE); 142 | } 143 | 144 | #ifdef ENABLE_OPTIGA_TPM 145 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "device:/dev/tpmrm0", NULL)) 146 | { 147 | perror("Unable to switch to TPM device mode (/dev/tpmrm0)."); 148 | #else 149 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "tabrmd:bus_type=session", NULL)) 150 | { 151 | perror("Unable to switch to TPM simulator mode."); 152 | #endif 153 | exit(EXIT_FAILURE); 154 | } 155 | 156 | pUiMethod = UI_OpenSSL(); 157 | if (!pUiMethod) 158 | { 159 | perror("Unable to get OpenSSL UI method."); 160 | exit(EXIT_FAILURE); 161 | } 162 | 163 | pKey = ENGINE_load_private_key(pEngine, "0x81000001", pUiMethod, NULL); 164 | 165 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 166 | if (sslStatus <= 0) { 167 | ERR_print_errors_fp(stderr); 168 | exit(EXIT_FAILURE); 169 | } 170 | } 171 | #else 172 | (void)sslStatus; 173 | /* Set software-based key */ 174 | if (SSL_CTX_use_PrivateKey_file(pSslContext, clientKey, SSL_FILETYPE_PEM) <= 0 ) { 175 | ERR_print_errors_fp(stderr); 176 | exit(EXIT_FAILURE); 177 | } 178 | #endif 179 | 180 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify server 181 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify server certificate 182 | 183 | /* Set CA certificate for server verification */ 184 | { 185 | FILE * rootCaFile = NULL; 186 | X509 *rootCa = NULL; 187 | 188 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 189 | perror("Unable to find CA certificate"); 190 | exit(EXIT_FAILURE); 191 | } 192 | 193 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 194 | perror("Unable to decode CA certificate"); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 199 | perror("Unable to load CA certificate"); 200 | exit(EXIT_FAILURE); 201 | } 202 | 203 | if (rootCaFile != NULL) 204 | fclose(rootCaFile); 205 | } 206 | } 207 | 208 | void showCert(SSL* ssl) 209 | { 210 | X509 *cert; 211 | char *line; 212 | 213 | cert = SSL_get_peer_certificate(ssl); 214 | if (cert != NULL) { 215 | printf("Server certificate:\n"); 216 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 217 | printf("Subject: %s\n", line); 218 | free(line); 219 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 220 | printf("Issuer: %s\n", line); 221 | free(line); 222 | X509_free(cert); 223 | } 224 | } 225 | 226 | int main(int argc, char **argv) 227 | { 228 | int sock; 229 | SSL_CTX *ctx; 230 | SSL *ssl; 231 | 232 | init_openssl(); 233 | ctx = create_context(); 234 | #ifdef ENABLE_TPM_TSS_ENGINE 235 | configure_context(ctx, "tpm.crt", "0x81000001", "local-ca.crt"); 236 | #else 237 | configure_context(ctx, "software.crt", "software.key", "local-ca.crt"); 238 | #endif 239 | 240 | sock = connect_socket("localhost", 8443); 241 | ssl = SSL_new(ctx); 242 | SSL_set_fd(ssl, sock); 243 | 244 | if (SSL_connect(ssl) <= 0) { 245 | ERR_print_errors_fp(stderr); 246 | } else { 247 | const char msg[] = "\nHello from client...\n"; 248 | int bytes = 0; 249 | char buf[256]; 250 | 251 | showCert(ssl); 252 | 253 | SSL_write(ssl, msg, strlen(msg)); // send message to server 254 | bytes = SSL_read(ssl, buf, sizeof(buf) - 1); // receive message from server 255 | if (bytes) { 256 | buf[bytes] = '\0'; 257 | printf("\nReceived: \"%s\"\n", buf); 258 | } 259 | } 260 | 261 | SSL_shutdown(ssl); 262 | SSL_free(ssl); 263 | 264 | close(sock); 265 | SSL_CTX_free(ctx); 266 | cleanup_openssl(); 267 | } 268 | 269 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | 14 | default_days = 365 # how long to certify for 15 | default_crl_days= 30 # how long before next CRL 16 | default_md = sha256 # md to use 17 | 18 | policy = policy_any # default policy 19 | email_in_dn = no # Don't add the email into cert DN 20 | 21 | name_opt = ca_default # Subject name display option 22 | cert_opt = ca_default # Certificate display option 23 | copy_extensions = none # Don't copy extensions from request 24 | 25 | [ policy_any ] 26 | countryName = supplied 27 | stateOrProvinceName = optional 28 | organizationName = optional 29 | organizationalUnitName = optional 30 | commonName = supplied 31 | emailAddress = optional 32 | -------------------------------------------------------------------------------- /openssl1-lib-tls/tpm-on-server/server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #ifdef ENABLE_TPM_TSS_ENGINE 37 | #include 38 | #endif 39 | 40 | int create_socket(int port) 41 | { 42 | int s; 43 | struct sockaddr_in addr; 44 | const int enable = 1; 45 | 46 | bzero(&addr, sizeof(addr)); 47 | addr.sin_family = AF_INET; 48 | addr.sin_port = htons(port); 49 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 50 | //addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 51 | 52 | s = socket(AF_INET, SOCK_STREAM, 0); 53 | if (s < 0) { 54 | perror("Unable to create socket"); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { 59 | perror("Unable to set SO_REUSEADDR"); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 64 | perror("Unable to bind"); 65 | exit(EXIT_FAILURE); 66 | } 67 | 68 | if (listen(s, 1) < 0) { 69 | perror("Unable to listen"); 70 | exit(EXIT_FAILURE); 71 | } 72 | 73 | return s; 74 | } 75 | 76 | void init_openssl() 77 | { 78 | OpenSSL_add_all_algorithms(); 79 | SSL_load_error_strings(); 80 | SSL_library_init(); 81 | } 82 | 83 | void cleanup_openssl() 84 | { 85 | EVP_cleanup(); 86 | } 87 | 88 | SSL_CTX *create_context() 89 | { 90 | const SSL_METHOD *method; 91 | SSL_CTX *ctx; 92 | 93 | method = SSLv23_server_method(); 94 | //method = TLSv1_2_server_method(); 95 | 96 | ctx = SSL_CTX_new(method); 97 | if (!ctx) { 98 | perror("Unable to create SSL context"); 99 | ERR_print_errors_fp(stderr); 100 | exit(EXIT_FAILURE); 101 | } 102 | 103 | return ctx; 104 | } 105 | 106 | void configure_context(SSL_CTX *pSslContext, const char *serverCert, const char *serverKey, 107 | const char *caCert) 108 | { 109 | int32_t sslStatus = -1; 110 | 111 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 112 | 113 | /* Set the server cert */ 114 | if (SSL_CTX_use_certificate_chain_file(pSslContext, serverCert) <= 0) { 115 | ERR_print_errors_fp(stderr); 116 | exit(EXIT_FAILURE); 117 | } 118 | 119 | #ifdef ENABLE_TPM_TSS_ENGINE 120 | /* Set TPM-based key */ 121 | { 122 | const char *pEngineName = "tpm2tss"; 123 | ENGINE *pEngine = NULL; 124 | UI_METHOD *pUiMethod = NULL; 125 | EVP_PKEY *pKey = NULL; 126 | 127 | /* Load TPM OpenSSL engine. */ 128 | ENGINE_load_builtin_engines(); 129 | pEngine = ENGINE_by_id(pEngineName); 130 | 131 | if (!pEngine) 132 | { 133 | perror("Unable to load TPM OpenSSL engine."); 134 | exit(EXIT_FAILURE); 135 | } 136 | 137 | if (!ENGINE_init(pEngine)) 138 | { 139 | perror("Unable to init TPM2 Engine."); 140 | exit(EXIT_FAILURE); 141 | } 142 | 143 | if (!ENGINE_set_default(pEngine, ENGINE_METHOD_ALL)) 144 | { 145 | perror("Unable to set TPM2 Engine."); 146 | exit(EXIT_FAILURE); 147 | } 148 | 149 | #ifdef ENABLE_OPTIGA_TPM 150 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "device:/dev/tpmrm0", NULL)) 151 | { 152 | perror("Unable to switch to TPM device mode (/dev/tpmrm0)."); 153 | #else 154 | if (!ENGINE_ctrl(pEngine, ENGINE_CMD_BASE + 1, 0, "tabrmd:bus_type=session", NULL)) 155 | { 156 | perror("Unable to switch to TPM simulator mode."); 157 | #endif 158 | exit(EXIT_FAILURE); 159 | } 160 | 161 | pUiMethod = UI_OpenSSL(); 162 | if (!pUiMethod) 163 | { 164 | perror("Unable to get OpenSSL UI method."); 165 | exit(EXIT_FAILURE); 166 | } 167 | 168 | pKey = ENGINE_load_private_key(pEngine, "0x81000001", pUiMethod, NULL); 169 | 170 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 171 | if (sslStatus <= 0) { 172 | ERR_print_errors_fp(stderr); 173 | exit(EXIT_FAILURE); 174 | } 175 | } 176 | #else 177 | (void)sslStatus; 178 | /* Set software-based key */ 179 | if (SSL_CTX_use_PrivateKey_file(pSslContext, serverKey, SSL_FILETYPE_PEM) <= 0 ) { 180 | ERR_print_errors_fp(stderr); 181 | exit(EXIT_FAILURE); 182 | } 183 | #endif 184 | 185 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify client 186 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify client certificate 187 | 188 | /* Set CA certificate for client verification */ 189 | { 190 | FILE * rootCaFile = NULL; 191 | X509 *rootCa = NULL; 192 | 193 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 194 | perror("Unable to find CA certificate"); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 199 | perror("Unable to decode CA certificate"); 200 | exit(EXIT_FAILURE); 201 | } 202 | 203 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 204 | perror("Unable to load CA certificate"); 205 | exit(EXIT_FAILURE); 206 | } 207 | 208 | if (rootCaFile != NULL) 209 | fclose(rootCaFile); 210 | } 211 | } 212 | 213 | void showCert(SSL* ssl) 214 | { 215 | X509 *cert; 216 | char *line; 217 | 218 | cert = SSL_get_peer_certificate(ssl); 219 | if (cert != NULL) { 220 | printf("Client certificate:\n"); 221 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 222 | printf("Subject: %s\n", line); 223 | free(line); 224 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 225 | printf("Issuer: %s\n", line); 226 | free(line); 227 | X509_free(cert); 228 | } 229 | } 230 | 231 | int main(int argc, char **argv) 232 | { 233 | int sock; 234 | SSL_CTX *ctx; 235 | 236 | init_openssl(); 237 | ctx = create_context(); 238 | #ifdef ENABLE_TPM_TSS_ENGINE 239 | configure_context(ctx, "tpm.crt", "0x81000001", "local-ca.crt"); 240 | #else 241 | configure_context(ctx, "local-ca.crt", "local-ca.key", "local-ca.crt"); 242 | #endif 243 | 244 | sock = create_socket(8443); 245 | 246 | /* Handle connections */ 247 | while(1) { 248 | struct sockaddr_in addr; 249 | uint len = sizeof(addr); 250 | SSL *ssl; 251 | const char reply[] = "\nHello from server.\n"; 252 | 253 | int client = accept(sock, (struct sockaddr*)&addr, &len); 254 | if (client < 0) { 255 | perror("Unable to accept"); 256 | exit(EXIT_FAILURE); 257 | } 258 | 259 | ssl = SSL_new(ctx); 260 | SSL_set_fd(ssl, client); 261 | 262 | if (SSL_accept(ssl) <= 0) { 263 | ERR_print_errors_fp(stderr); 264 | } 265 | else { 266 | int bytes = 0; 267 | char buf[256]; 268 | 269 | showCert(ssl); 270 | 271 | SSL_write(ssl, reply, strlen(reply)); 272 | bytes = SSL_read(ssl, buf, sizeof(buf)); // receive message from client 273 | if (bytes) { 274 | buf[bytes] = '\0'; 275 | printf("\nReceived: \"%s\"\n", buf); 276 | } 277 | 278 | } 279 | 280 | SSL_shutdown(ssl); 281 | SSL_free(ssl); 282 | close(client); 283 | } 284 | 285 | close(sock); 286 | SSL_CTX_free(ctx); 287 | cleanup_openssl(); 288 | } 289 | 290 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr 2> /dev/null 9 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/1_init-tpm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa3072 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/2_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/3_gen-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -provider tpm2 -key handle:0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo 'unique_subject = no' >> ca/index.txt.attr 17 | echo '01' > ca/serial 18 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 19 | 20 | # Generate self-signed client cert to demonstrate an invalid client cert (not CA signed) 21 | openssl req -x509 -sha256 -provider tpm2 -provider default -key handle:0x81000001 -in tpm.csr -out bad-tpm.crt 22 | 23 | # Read cert 24 | #openssl x509 -in tpm.crt -text -noout 25 | #openssl x509 -in bad-tpm.crt -text -noout 26 | 27 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/4_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # 5 | # CAfile: A file containing trusted certificates to use during client authentication 6 | # cert: Server certificate 7 | # key: Server private key 8 | # 9 | openssl s_server -Verify 1 -tls1_2 -CAfile local-ca.crt -cert local-ca.crt -key local-ca.key -verify_return_error -quiet -accept 8443 10 | 11 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/5_start-good-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -provider tpm2 -provider default -key handle:0x81000001 -cert tpm.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/6_start-bad-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -provider tpm2 -provider default -key handle:0x81000001 -cert bad-tpm.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-client/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | #certificate = ../assessment-remote-server/remote-ca.crt # the remote CA cert 14 | #private_key = ../assessment-remote-server/remote-ca.key # the remote CA private key 15 | 16 | default_days = 365 # how long to certify for 17 | default_crl_days= 30 # how long before next CRL 18 | default_md = sha256 # md to use 19 | 20 | policy = policy_any # default policy 21 | email_in_dn = no # Don't add the email into cert DN 22 | 23 | name_opt = ca_default # Subject name display option 24 | cert_opt = ca_default # Certificate display option 25 | copy_extensions = none # Don't copy extensions from request 26 | 27 | [ policy_any ] 28 | countryName = supplied 29 | stateOrProvinceName = optional 30 | organizationName = optional 31 | organizationalUnitName = optional 32 | commonName = supplied 33 | emailAddress = optional 34 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -e: exit when any command fails 4 | # -x: all executed commands are printed to the terminal 5 | # -o pipefail: prevents errors in a pipeline from being masked 6 | set -exo pipefail 7 | 8 | rm -rf *.key *.crt ca local-ca.* *.ctx rsakey.* *.csr 2> /dev/null 9 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/1_init-tpm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa3072 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/2_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/3_gen-server-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -provider tpm2 -key handle:0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out server.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo 'unique_subject = no' >> ca/index.txt.attr 17 | echo '01' > ca/serial 18 | (yes || true) | openssl ca -config config -in server.csr -out server.crt 19 | 20 | # Read cert 21 | #openssl x509 -in server.crt -text -noout 22 | 23 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/4_gen-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate client key 9 | openssl genrsa -out client.key 2048 10 | 11 | # Generate CSR 12 | openssl req -new -key client.key -subj "/CN=TPM/O=Infineon/C=SG" -out client.csr 13 | 14 | # Generate CA signed client cert 15 | rm -rf ca 2> /dev/null 16 | mkdir ca 2> /dev/null 17 | touch ca/index.txt 18 | touch ca/index.txt.attr 19 | echo 'unique_subject = no' >> ca/index.txt.attr 20 | echo '01' > ca/serial 21 | (yes || true) | openssl ca -config config -in client.csr -out client.crt 22 | 23 | # Read cert 24 | #openssl x509 -in client.crt -text -noout 25 | 26 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/5_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | # 5 | # CAfile: A file containing trusted certificates to use during client authentication 6 | # cert: Server certificate 7 | # key: Server private key 8 | # 9 | openssl s_server -provider tpm2 -provider default -Verify 1 -tls1_2 -CAfile local-ca.crt -cert server.crt -key handle:0x81000001 -verify_return_error -quiet -accept 8443 10 | 11 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/6_start-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # 7 | # CAfile: A file containing trusted certificates to use during server authentication 8 | # cert: Client certificate 9 | # key: Client private key 10 | # 11 | echo "Q" | openssl s_client -key client.key -cert client.crt -CAfile local-ca.crt -connect localhost:8443 -verify_return_error -quiet -no_ign_eof 12 | 13 | -------------------------------------------------------------------------------- /openssl3-cli-tls/tpm-on-server/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | #certificate = ../assessment-remote-server/remote-ca.crt # the remote CA cert 14 | #private_key = ../assessment-remote-server/remote-ca.key # the remote CA private key 15 | 16 | default_days = 365 # how long to certify for 17 | default_crl_days= 30 # how long before next CRL 18 | default_md = sha256 # md to use 19 | 20 | policy = policy_any # default policy 21 | email_in_dn = no # Don't add the email into cert DN 22 | 23 | name_opt = ca_default # Subject name display option 24 | cert_opt = ca_default # Certificate display option 25 | copy_extensions = none # Don't copy extensions from request 26 | 27 | [ policy_any ] 28 | countryName = supplied 29 | stateOrProvinceName = optional 30 | organizationName = optional 31 | organizationalUnitName = optional 32 | commonName = supplied 33 | emailAddress = optional 34 | -------------------------------------------------------------------------------- /openssl3-lib-general-examples/examples.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #define PRINT(...) printf(__VA_ARGS__); \ 33 | printf("\n"); 34 | 35 | #define RSA_KEY_PATH "/tmp/rsa-key" 36 | #define EC_KEY_PATH "/tmp/ec-key" 37 | 38 | int 39 | gen_random() 40 | { 41 | unsigned char buf[4]; 42 | 43 | int rc = RAND_bytes(buf, sizeof(buf)); 44 | 45 | if(rc != 1) { 46 | PRINT("RAND_bytes failed"); 47 | return -1; 48 | } 49 | 50 | PRINT("Obtained random: %02x%02x%02x%02x", buf[0], buf[1], buf[2], buf[3]); 51 | 52 | return 0; 53 | } 54 | 55 | int 56 | gen_rsaKey() 57 | { 58 | int ret = 1; 59 | EVP_PKEY *pkey = NULL; 60 | EVP_PKEY_CTX *ctx = NULL; 61 | OSSL_PARAM params[2]; 62 | unsigned int bits = 3072; 63 | BIO *out = NULL; 64 | 65 | /** 66 | * For more options please refer to the tpm2 provider: 67 | * https://github.com/tpm2-software/tpm2-openssl/blob/1.1.0/src/tpm2-provider-keymgmt-rsa.c#L224 68 | */ 69 | params[0] = OSSL_PARAM_construct_uint("bits", &bits); 70 | params[1] = OSSL_PARAM_construct_end(); 71 | 72 | if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", "provider=tpm2")) == NULL || 73 | EVP_PKEY_keygen_init(ctx) <= 0 || 74 | EVP_PKEY_CTX_set_params(ctx, params) <= 0 || 75 | EVP_PKEY_generate(ctx, &pkey) <= 0) { 76 | PRINT("Failed to generate RSA key"); 77 | goto exit; 78 | } 79 | 80 | // Print the public component (modulus) 81 | EVP_PKEY_print_public_fp(stdout, pkey, 0, NULL); 82 | 83 | // Store the key object on disk 84 | if ((out = BIO_new_file(RSA_KEY_PATH, "w")) == NULL) { 85 | PRINT("Failed to create a new file"); 86 | goto exit; 87 | } 88 | if (!PEM_write_bio_PrivateKey(out, pkey, 0, NULL, 0, 0, NULL)) { 89 | PRINT("Failed to write RSA key to disk"); 90 | goto exit; 91 | } 92 | 93 | ret = 0; 94 | PRINT("Generated RSA key and saved to disk"); 95 | 96 | exit: 97 | out ? BIO_free_all(out) : 0; 98 | pkey ? EVP_PKEY_free(pkey) : 0; 99 | return ret; 100 | } 101 | 102 | int 103 | gen_ecKey() 104 | { 105 | int ret = 1; 106 | EVP_PKEY *pkey = NULL; 107 | EVP_PKEY_CTX *ctx = NULL; 108 | OSSL_PARAM params[2]; 109 | BIO *out = NULL; 110 | char *group = "P-256"; 111 | 112 | /** 113 | * For more options please refer to the tpm2 provider: 114 | * https://github.com/tpm2-software/tpm2-openssl/blob/1.1.0/src/tpm2-provider-keymgmt-ec.c#L183 115 | */ 116 | params[0] = OSSL_PARAM_construct_utf8_string("group", group, sizeof(group)); 117 | params[1] = OSSL_PARAM_construct_end(); 118 | 119 | if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "provider=tpm2")) == NULL || 120 | EVP_PKEY_keygen_init(ctx) <= 0 || 121 | EVP_PKEY_CTX_set_params(ctx, params) <= 0 || 122 | EVP_PKEY_generate(ctx, &pkey) <= 0) { 123 | PRINT("Failed to generate EC key"); 124 | goto exit; 125 | } 126 | 127 | // Print the public component 128 | EVP_PKEY_print_public_fp(stdout, pkey, 0, NULL); 129 | 130 | // Store the key object on disk 131 | if ((out = BIO_new_file(EC_KEY_PATH, "w")) == NULL) { 132 | PRINT("Failed to create a new file"); 133 | goto exit; 134 | } 135 | if (!PEM_write_bio_PrivateKey(out, pkey, 0, NULL, 0, 0, NULL)) { 136 | PRINT("Failed to write EC key to disk"); 137 | goto exit; 138 | } 139 | 140 | ret = 0; 141 | PRINT("Generated EC key and saved to disk"); 142 | 143 | exit: 144 | out ? BIO_free_all(out) : 0; 145 | pkey ? EVP_PKEY_free(pkey) : 0; 146 | return ret; 147 | } 148 | 149 | EVP_PKEY * 150 | load_rsa_key() 151 | { 152 | EVP_PKEY *pKey = NULL; 153 | BIO *bio = NULL; 154 | 155 | if ((bio = BIO_new_file(RSA_KEY_PATH, "r")) == NULL) { 156 | PRINT("Failed to open RSA_KEY_PATH"); 157 | goto exit; 158 | } 159 | 160 | if ((pKey = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL)) == NULL) { 161 | PRINT("Failed to read RSA key"); 162 | goto exit; 163 | } 164 | 165 | PRINT("Loaded RSA key from disk"); 166 | 167 | exit: 168 | bio ? BIO_free_all(bio) : 0; 169 | return pKey; 170 | } 171 | 172 | EVP_PKEY * 173 | load_ec_key() 174 | { 175 | EVP_PKEY *pKey = NULL; 176 | BIO *bio = NULL; 177 | 178 | if ((bio = BIO_new_file(EC_KEY_PATH, "r")) == NULL) { 179 | PRINT("Failed to open RSA_KEY_PATH"); 180 | goto exit; 181 | } 182 | 183 | if ((pKey = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL)) == NULL) { 184 | PRINT("Failed to read EC key"); 185 | goto exit; 186 | } 187 | 188 | PRINT("Loaded EC key from disk"); 189 | 190 | exit: 191 | bio ? BIO_free_all(bio) : 0; 192 | return pKey; 193 | } 194 | 195 | int 196 | ec_evp_pkey_sign_verify(EVP_PKEY *pKey) 197 | { 198 | BIO *bio = NULL; 199 | EVP_PKEY *pPubKey = NULL; 200 | EVP_PKEY_CTX *ctx = NULL; 201 | EVP_PKEY_CTX *ctx2 = NULL; 202 | unsigned char sha256[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 203 | unsigned char *sig = NULL; 204 | size_t sha256Len = 32, sigLen = 0; 205 | int ret = -1; 206 | 207 | //ctx = EVP_PKEY_CTX_new(pKey, NULL); 208 | ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pKey, "provider=tpm2"); 209 | if (!ctx) { 210 | PRINT("EC sign EVP_PKEY_CTX_new_from_pkey error"); 211 | goto exit; 212 | } 213 | 214 | /* Signing */ 215 | 216 | PRINT("EC signing"); 217 | 218 | if (EVP_PKEY_sign_init(ctx) <= 0 || 219 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0 || 220 | EVP_PKEY_sign(ctx, NULL, &sigLen, sha256, sha256Len) <= 0) { 221 | PRINT("EC sign init error"); 222 | goto exit; 223 | } 224 | 225 | sig = OPENSSL_malloc(sigLen); 226 | 227 | if (!sig) { 228 | PRINT("EC malloc error"); 229 | goto exit; 230 | } 231 | 232 | PRINT("EC generating signature"); 233 | 234 | if (EVP_PKEY_sign(ctx, sig, &sigLen, sha256, sha256Len) <= 0) { 235 | PRINT("EC signing error"); 236 | goto exit; 237 | } 238 | 239 | /* Verification */ 240 | 241 | PRINT("EC verify signature"); 242 | 243 | if (!(bio = BIO_new(BIO_s_mem()))) { 244 | PRINT("BIO_new error"); 245 | goto exit; 246 | } 247 | 248 | if (PEM_write_bio_PUBKEY(bio, pKey) <= 0) { 249 | PRINT("PEM_write_bio_PUBKEY error"); 250 | goto exit; 251 | } 252 | 253 | if (!(pPubKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) { 254 | PRINT("PEM_read_bio_PUBKEY error"); 255 | goto exit; 256 | } 257 | 258 | if (!(ctx2 = EVP_PKEY_CTX_new_from_pkey(NULL, pPubKey, "provider=default"))) { 259 | PRINT("EVP_PKEY_CTX_new_from_pkey error"); 260 | goto exit; 261 | } 262 | 263 | if (EVP_PKEY_verify_init(ctx2) <= 0 || 264 | EVP_PKEY_CTX_set_signature_md(ctx2, EVP_sha256()) <= 0) { 265 | PRINT("EC verification init error"); 266 | goto exit; 267 | } 268 | 269 | if (EVP_PKEY_verify(ctx2, sig, sigLen, sha256, sha256Len) <= 0) { 270 | PRINT("EC signature verification error"); 271 | goto exit; 272 | } 273 | 274 | PRINT("EC signature verification ok"); 275 | 276 | // corrupt the hash 277 | sha256[3] = ~sha256[3]; 278 | if (EVP_PKEY_verify(ctx2, sig, sigLen, sha256, sha256Len) == 0) { 279 | PRINT("EC signature verification expected to fail, ok"); 280 | } else { 281 | PRINT("EC signature verification error"); 282 | goto exit; 283 | } 284 | 285 | ret = 0; 286 | 287 | exit: 288 | ctx2 ? EVP_PKEY_CTX_free(ctx2) : 0; 289 | pPubKey ? EVP_PKEY_free(pPubKey) : 0; 290 | bio ? BIO_free(bio) : 0; 291 | sig ? OPENSSL_free(sig) : 0; 292 | ctx ? EVP_PKEY_CTX_free(ctx) : 0; 293 | return ret; 294 | } 295 | 296 | int 297 | rsa_evp_pkey_sign_verify(EVP_PKEY *pKey) 298 | { 299 | BIO *bio = NULL; 300 | EVP_PKEY *pPubKey = NULL; 301 | EVP_PKEY_CTX *ctx = NULL; 302 | EVP_PKEY_CTX *ctx2 = NULL; 303 | unsigned char sha256[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 304 | unsigned char *sig = NULL; 305 | size_t sha256Len = 32, sigLen = 0; 306 | int ret = -1; 307 | 308 | ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pKey, "provider=tpm2"); 309 | if (!ctx) { 310 | PRINT("RSA sign EVP_PKEY_CTX_new_from_pkey error"); 311 | goto exit; 312 | } 313 | 314 | /* Signing */ 315 | 316 | PRINT("RSA signing"); 317 | if (EVP_PKEY_sign_init(ctx) <= 0 ) { 318 | PRINT("RSA sign init error"); 319 | goto exit; 320 | } 321 | if ( EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <=0) { 322 | PRINT("set md error"); 323 | goto exit; 324 | } 325 | 326 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0 || 327 | EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) { 328 | PRINT("EVP_PKEY_CTX_set_rsa_padding error"); 329 | goto exit; 330 | } 331 | 332 | if (EVP_PKEY_sign(ctx, NULL, &sigLen, sha256, sha256Len) <= 0) { 333 | PRINT("get siglen error"); 334 | goto exit; 335 | } 336 | 337 | sig = OPENSSL_malloc(sigLen); 338 | 339 | if (!sig) { 340 | PRINT("RSA malloc error"); 341 | goto exit; 342 | } 343 | 344 | PRINT("RSA generating signature"); 345 | 346 | if (EVP_PKEY_sign(ctx, sig, &sigLen, sha256, sha256Len) <= 0) { 347 | PRINT("RSA signing error"); 348 | goto exit; 349 | } 350 | 351 | /* Verification */ 352 | 353 | PRINT("RSA verify signature"); 354 | 355 | if (!(bio = BIO_new(BIO_s_mem()))) { 356 | PRINT("BIO_new error"); 357 | goto exit; 358 | } 359 | 360 | if (PEM_write_bio_PUBKEY(bio, pKey) <= 0) { 361 | PRINT("PEM_write_bio_PUBKEY error"); 362 | goto exit; 363 | } 364 | 365 | if (!(pPubKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) { 366 | PRINT("PEM_read_bio_PUBKEY error"); 367 | goto exit; 368 | } 369 | 370 | if (!(ctx2 = EVP_PKEY_CTX_new_from_pkey(NULL, pPubKey, "provider=default"))) { 371 | PRINT("EVP_PKEY_CTX_new_from_pkey error"); 372 | goto exit; 373 | } 374 | 375 | if (EVP_PKEY_verify_init(ctx2) <= 0 || 376 | EVP_PKEY_CTX_set_rsa_padding(ctx2, RSA_PKCS1_PSS_PADDING) <= 0 || 377 | EVP_PKEY_CTX_set_signature_md(ctx2, EVP_sha256()) <= 0) { 378 | PRINT("RSA verification init error"); 379 | goto exit; 380 | } 381 | 382 | if (EVP_PKEY_verify(ctx2, sig, sigLen, sha256, sha256Len) <= 0) { 383 | PRINT("RSA signature verification error"); 384 | goto exit; 385 | } 386 | 387 | PRINT("RSA signature verification ok"); 388 | 389 | // corrupt the hash 390 | sha256[3] = ~sha256[3]; 391 | if (EVP_PKEY_verify(ctx2, sig, sigLen, sha256, sha256Len) == 0) { 392 | PRINT("RSA signature verification expected to fail, ok"); 393 | } else { 394 | PRINT("RSA signature verification error"); 395 | goto exit; 396 | } 397 | 398 | ret = 0; 399 | 400 | exit: 401 | ctx2 ? EVP_PKEY_CTX_free(ctx2) : 0; 402 | pPubKey ? EVP_PKEY_free(pPubKey) : 0; 403 | bio ? BIO_free(bio) : 0; 404 | sig ? OPENSSL_free(sig) : 0; 405 | ctx ? EVP_PKEY_CTX_free(ctx) : 0; 406 | return ret; 407 | } 408 | 409 | int 410 | rsa_evp_pkey_encrypt_decrypt(EVP_PKEY *pKey) 411 | { 412 | BIO *bio = NULL; 413 | EVP_PKEY *pPubKey = NULL; 414 | EVP_PKEY_CTX *ctx = NULL; 415 | EVP_PKEY_CTX *ctx2 = NULL; 416 | unsigned char clear[] = {1,2,3}; 417 | unsigned char *ciphered = NULL, *deciphered = NULL; 418 | size_t cipheredLen = 0, decipheredLen = 0, clearLen = 3; 419 | int ret = -1; 420 | 421 | /* Encryption (RSA_PKCS1_PADDING == TPM2_ALG_RSAES) */ 422 | 423 | if (!(bio = BIO_new(BIO_s_mem()))) { 424 | PRINT("BIO_new error"); 425 | goto exit; 426 | } 427 | 428 | if (PEM_write_bio_PUBKEY(bio, pKey) <= 0) { 429 | PRINT("PEM_write_bio_PUBKEY error"); 430 | goto exit; 431 | } 432 | 433 | if (!(pPubKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) { 434 | PRINT("PEM_read_bio_PUBKEY error"); 435 | goto exit; 436 | } 437 | 438 | if (!(ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pPubKey, "provider=default"))) { 439 | PRINT("EVP_PKEY_CTX_new_from_pkey error"); 440 | goto exit; 441 | } 442 | 443 | if (EVP_PKEY_encrypt_init(ctx) <= 0 || 444 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || 445 | EVP_PKEY_encrypt(ctx, NULL, &cipheredLen, clear, clearLen) <= 0) { 446 | PRINT("Encryption init error"); 447 | goto exit; 448 | } 449 | 450 | ciphered = OPENSSL_malloc(cipheredLen); 451 | if (!ciphered) { 452 | PRINT("malloc error"); 453 | goto exit; 454 | } 455 | 456 | PRINT("Generating encryption blob"); 457 | 458 | if (EVP_PKEY_encrypt(ctx, ciphered, &cipheredLen, clear, clearLen) <= 0) { 459 | PRINT("Encryption error"); 460 | goto exit; 461 | } 462 | 463 | /* Decryption (RSA_PKCS1_PADDING == TPM2_ALG_RSAES) */ 464 | 465 | ctx2 = EVP_PKEY_CTX_new_from_pkey(NULL, pKey, "provider=tpm2"); 466 | if (!ctx2) { 467 | PRINT("RSA decrypt EVP_PKEY_CTX_new_from_pkey error"); 468 | goto exit; 469 | } 470 | 471 | if (EVP_PKEY_decrypt_init(ctx2) <= 0 || 472 | EVP_PKEY_CTX_set_rsa_padding(ctx2, RSA_PKCS1_PADDING) <= 0 || 473 | EVP_PKEY_decrypt(ctx2, NULL, &decipheredLen, ciphered, cipheredLen) <= 0) { 474 | PRINT("Decryption init error"); 475 | goto exit; 476 | } 477 | 478 | deciphered = OPENSSL_malloc(decipheredLen); 479 | if (!deciphered) { 480 | PRINT("malloc error"); 481 | goto exit; 482 | } 483 | 484 | memset(deciphered, 0, decipheredLen); 485 | 486 | PRINT("Decrypting encrypted blob"); 487 | 488 | if (EVP_PKEY_decrypt(ctx2, deciphered, &decipheredLen, ciphered, cipheredLen) <= 0) { 489 | PRINT("Decryption error"); 490 | goto exit; 491 | } 492 | 493 | if((decipheredLen != clearLen) || (strncmp((const char *)clear, (const char *)deciphered, decipheredLen) != 0)) 494 | { 495 | PRINT("Decryption error, value not the same"); 496 | goto exit; 497 | } 498 | 499 | PRINT("Decryption verification ok"); 500 | 501 | ret = 0; 502 | 503 | exit: 504 | deciphered ? OPENSSL_free(deciphered) : 0; 505 | ctx2 ? EVP_PKEY_CTX_free(ctx2) : 0; 506 | ciphered ? OPENSSL_free(ciphered) : 0; 507 | ctx ? EVP_PKEY_CTX_free(ctx) : 0; 508 | pPubKey ? EVP_PKEY_free(pPubKey) : 0; 509 | bio ? BIO_free(bio) : 0; 510 | return ret; 511 | } 512 | 513 | int main(int argc, char **argv) 514 | { 515 | (void) argc; 516 | (void) argv; 517 | 518 | int ret = 1; 519 | OSSL_PROVIDER *prov_default = NULL; 520 | OSSL_PROVIDER *prov_tpm2 = NULL; 521 | EVP_PKEY *pRsaKey = NULL; 522 | EVP_PKEY *pEcKey = NULL; 523 | 524 | PRINT("Starting..."); 525 | 526 | /* 527 | * Known issue: 528 | * 529 | * Cant set tcti programmatically 530 | * Open topic: https://github.com/openssl/openssl/issues/17182 531 | * Tentatively, set parameters feature will be implemented in OpenSSL 3.1 532 | * 533 | * Here we relies on ENV TPM2OPENSSL_TCTI 534 | */ 535 | 536 | /* Load TPM2 provider */ 537 | if ((prov_tpm2 = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL) 538 | goto exit; 539 | 540 | /* Self-test */ 541 | if (!OSSL_PROVIDER_self_test(prov_tpm2)) 542 | goto exit; 543 | 544 | /* Load default provider */ 545 | if ((prov_default = OSSL_PROVIDER_load(NULL, "default")) == NULL) 546 | goto exit; 547 | 548 | /* Self-test */ 549 | if (!OSSL_PROVIDER_self_test(prov_default)) 550 | goto exit; 551 | 552 | /* Generate true random */ 553 | if (gen_random()) 554 | goto exit; 555 | 556 | /* Generate RSA key */ 557 | if (gen_rsaKey()) 558 | goto exit; 559 | 560 | /* Generate EC key */ 561 | if (gen_ecKey()) 562 | goto exit; 563 | 564 | /* Load RSA key */ 565 | if ((pRsaKey = load_rsa_key()) == NULL) 566 | goto exit; 567 | 568 | /* Load EC key */ 569 | if ((pEcKey = load_ec_key()) == NULL) 570 | goto exit; 571 | 572 | /* RSA signing & verification */ 573 | if (rsa_evp_pkey_sign_verify(pRsaKey)) 574 | goto exit; 575 | 576 | /* EC signing & verification */ 577 | if (ec_evp_pkey_sign_verify(pEcKey)) 578 | goto exit; 579 | 580 | /* RSA encryption & decryption */ 581 | if (rsa_evp_pkey_encrypt_decrypt(pRsaKey)) 582 | goto exit; 583 | 584 | PRINT("Completed without err..."); 585 | 586 | ret = 0; 587 | 588 | exit: 589 | pEcKey ? EVP_PKEY_free(pEcKey) : 0; 590 | pRsaKey ? EVP_PKEY_free(pRsaKey) : 0; 591 | prov_tpm2 ? OSSL_PROVIDER_unload(prov_tpm2) : 0; 592 | prov_default ? OSSL_PROVIDER_unload(prov_default) : 0; 593 | 594 | return ret; 595 | } 596 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr *.key server client-software client-tpm 2> /dev/null 5 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/1_init-tpm-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa3072 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/2_init-software-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | openssl genrsa -out software.key 2048 5 | 6 | 7 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/3_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/4_gen-tpm-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -provider tpm2 -key handle:0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo 'unique_subject = no' >> ca/index.txt.attr 17 | echo '01' > ca/serial 18 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 19 | 20 | # Read cert 21 | #openssl x509 -in tpm.crt -text -noout 22 | 23 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/5_gen-software-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CSR 7 | openssl req -new -key software.key -subj "/CN=Software/O=Infineon/C=SG" -out software.csr 8 | 9 | # Generate CA signed client cert 10 | rm -rf ca 2> /dev/null 11 | mkdir ca 2> /dev/null 12 | touch ca/index.txt 13 | touch ca/index.txt.attr 14 | echo 'unique_subject = no' >> ca/index.txt.attr 15 | echo '01' > ca/serial 16 | (yes || true) | openssl ca -config config -in software.csr -out software.crt 17 | 18 | # Read cert 19 | #openssl x509 -in software.crt -text -noout 20 | 21 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/6_build-server-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | gcc -Wall -o server server.c -lssl -lcrypto 5 | gcc -Wall -o client-software client.c -lssl -lcrypto 6 | gcc -Wall -o client-tpm client.c -lssl -lcrypto -DENABLE_TPM_TSS_PROVIDER 7 | 8 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/7_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./server 5 | 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/8_start-software-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-software 5 | 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/9_start-tpm-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-tpm 5 | 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | * https://aticleworld.com/ssl-server-client-using-openssl-in-c/ 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #ifdef ENABLE_TPM_TSS_PROVIDER 39 | #include 40 | #include 41 | #endif 42 | 43 | int connect_socket(const char *hostname, int port) 44 | { 45 | int s; 46 | struct hostent *host; 47 | struct sockaddr_in addr; 48 | 49 | if ((host = gethostbyname(hostname)) == NULL) { 50 | perror("Unable to find server"); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | bzero(&addr, sizeof(addr)); 55 | addr.sin_family = AF_INET; 56 | addr.sin_port = htons(port); 57 | addr.sin_addr.s_addr = *(long*)(host->h_addr); 58 | 59 | s = socket(AF_INET, SOCK_STREAM, 0); 60 | if (s < 0) { 61 | perror("Unable to create socket"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 66 | perror("Unable to connect to server"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | return s; 71 | } 72 | 73 | void init_openssl() 74 | { 75 | OpenSSL_add_all_algorithms(); 76 | SSL_load_error_strings(); 77 | SSL_library_init(); 78 | } 79 | 80 | void cleanup_openssl() 81 | { 82 | EVP_cleanup(); 83 | } 84 | 85 | SSL_CTX *create_ssl_context() 86 | { 87 | const SSL_METHOD *method; 88 | SSL_CTX *ctx; 89 | 90 | method = SSLv23_client_method(); 91 | 92 | ctx = SSL_CTX_new_ex(NULL, "provider=default,provider=tpm2", method); 93 | if (!ctx) { 94 | perror("Unable to create SSL context"); 95 | ERR_print_errors_fp(stderr); 96 | exit(EXIT_FAILURE); 97 | } 98 | 99 | return ctx; 100 | } 101 | 102 | SSL_CTX *configure_context(const char *clientCert, const char *clientKey, 103 | const char *caCert) 104 | { 105 | int32_t sslStatus = -1; 106 | SSL_CTX *pSslContext = NULL; 107 | 108 | #ifdef ENABLE_TPM_TSS_PROVIDER 109 | /* Set TPM-based key */ 110 | { 111 | OSSL_PROVIDER *prov_tpm2 = NULL; 112 | OSSL_PROVIDER *prov_default = NULL; 113 | OSSL_STORE_CTX *ctx = NULL; 114 | OSSL_STORE_INFO *info = NULL; 115 | EVP_PKEY *pKey = NULL; 116 | 117 | /* Load TPM2 provider */ 118 | if ((prov_tpm2 = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL) 119 | { 120 | perror("Unable to load OpenSSL provider: tpm2."); 121 | exit(EXIT_FAILURE); 122 | } 123 | 124 | /* Self-test */ 125 | if (!OSSL_PROVIDER_self_test(prov_tpm2)) 126 | { 127 | perror("OpenSSL provider (tpm2) self test failed."); 128 | exit(EXIT_FAILURE); 129 | } 130 | 131 | /* Load default provider */ 132 | if ((prov_default = OSSL_PROVIDER_load(NULL, "default")) == NULL) 133 | { 134 | perror("Unable to load OpenSSL provider: default."); 135 | exit(EXIT_FAILURE); 136 | } 137 | 138 | /* Self-test */ 139 | if (!OSSL_PROVIDER_self_test(prov_default)) 140 | { 141 | perror("OpenSSL provider (default) self test failed."); 142 | exit(EXIT_FAILURE); 143 | } 144 | 145 | if ((ctx = OSSL_STORE_open_ex(clientKey, NULL, "provider=tpm2", 146 | NULL, NULL, NULL, NULL, NULL)) == NULL || 147 | !OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY) || 148 | (info = OSSL_STORE_load(ctx)) == NULL || 149 | (pKey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL) { 150 | perror("OpenSSL provider (tpm2) key loading failed."); 151 | exit(EXIT_FAILURE); 152 | } 153 | 154 | OSSL_STORE_close(ctx); 155 | 156 | pSslContext = create_ssl_context(); 157 | 158 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 159 | if (sslStatus <= 0) { 160 | ERR_print_errors_fp(stderr); 161 | exit(EXIT_FAILURE); 162 | } 163 | 164 | /* Free these to avoid memory leak? */ 165 | //OSSL_STORE_INFO_free(info); 166 | //EVP_PKEY_free(pKey); 167 | //OSSL_PROVIDER_unload(prov_default); 168 | //OSSL_PROVIDER_unload(prov_tpm2); 169 | } 170 | #else 171 | (void) sslStatus; 172 | 173 | pSslContext = create_ssl_context(); 174 | 175 | /* Set software-based key */ 176 | if (SSL_CTX_use_PrivateKey_file(pSslContext, clientKey, SSL_FILETYPE_PEM) <= 0 ) { 177 | ERR_print_errors_fp(stderr); 178 | exit(EXIT_FAILURE); 179 | } 180 | #endif 181 | 182 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 183 | 184 | /* Set the client cert */ 185 | if (SSL_CTX_use_certificate_chain_file(pSslContext, clientCert) <= 0) { 186 | ERR_print_errors_fp(stderr); 187 | exit(EXIT_FAILURE); 188 | } 189 | 190 | /* Verify client cert */ 191 | if (!SSL_CTX_check_private_key(pSslContext)) { 192 | perror("Private key does not match with certificate public key."); 193 | exit(EXIT_FAILURE); 194 | } 195 | 196 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify server 197 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify server certificate 198 | 199 | /* Set CA certificate for server verification */ 200 | { 201 | FILE * rootCaFile = NULL; 202 | X509 *rootCa = NULL; 203 | 204 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 205 | perror("Unable to find CA certificate"); 206 | exit(EXIT_FAILURE); 207 | } 208 | 209 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 210 | perror("Unable to decode CA certificate"); 211 | exit(EXIT_FAILURE); 212 | } 213 | 214 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 215 | perror("Unable to load CA certificate"); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | if (rootCaFile != NULL) 220 | fclose(rootCaFile); 221 | } 222 | 223 | return pSslContext; 224 | } 225 | 226 | void showCert(SSL* ssl) 227 | { 228 | X509 *cert; 229 | char *line; 230 | 231 | cert = SSL_get_peer_certificate(ssl); 232 | if (cert != NULL) { 233 | printf("Server certificate:\n"); 234 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 235 | printf("Subject: %s\n", line); 236 | free(line); 237 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 238 | printf("Issuer: %s\n", line); 239 | free(line); 240 | X509_free(cert); 241 | } 242 | } 243 | 244 | int main(int argc, char **argv) 245 | { 246 | int sock; 247 | SSL_CTX *ctx; 248 | SSL *ssl; 249 | 250 | init_openssl(); 251 | 252 | #ifdef ENABLE_TPM_TSS_PROVIDER 253 | ctx = configure_context("tpm.crt", "handle:0x81000001", "local-ca.crt"); 254 | #else 255 | ctx = configure_context("software.crt", "software.key", "local-ca.crt"); 256 | #endif 257 | 258 | sock = connect_socket("localhost", 8443); 259 | ssl = SSL_new(ctx); 260 | SSL_set_fd(ssl, sock); 261 | 262 | if (SSL_connect(ssl) <= 0) { 263 | ERR_print_errors_fp(stderr); 264 | } else { 265 | const char msg[] = "\nHello from client...\n"; 266 | int bytes = 0; 267 | char buf[256]; 268 | 269 | showCert(ssl); 270 | 271 | SSL_write(ssl, msg, strlen(msg)); // send message to server 272 | bytes = SSL_read(ssl, buf, sizeof(buf) - 1); // receive message from server 273 | if (bytes) { 274 | buf[bytes] = '\0'; 275 | printf("\nReceived: \"%s\"\n", buf); 276 | } 277 | } 278 | 279 | SSL_shutdown(ssl); 280 | SSL_free(ssl); 281 | 282 | close(sock); 283 | SSL_CTX_free(ctx); 284 | cleanup_openssl(); 285 | } 286 | 287 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | 14 | default_days = 365 # how long to certify for 15 | default_crl_days= 30 # how long before next CRL 16 | default_md = sha256 # md to use 17 | 18 | policy = policy_any # default policy 19 | email_in_dn = no # Don't add the email into cert DN 20 | 21 | name_opt = ca_default # Subject name display option 22 | cert_opt = ca_default # Certificate display option 23 | copy_extensions = none # Don't copy extensions from request 24 | 25 | [ policy_any ] 26 | countryName = supplied 27 | stateOrProvinceName = optional 28 | organizationName = optional 29 | organizationalUnitName = optional 30 | commonName = supplied 31 | emailAddress = optional 32 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-client/server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | int create_socket(int port) 38 | { 39 | int s; 40 | struct sockaddr_in addr; 41 | const int enable = 1; 42 | 43 | bzero(&addr, sizeof(addr)); 44 | addr.sin_family = AF_INET; 45 | addr.sin_port = htons(port); 46 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 47 | //addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 48 | 49 | s = socket(AF_INET, SOCK_STREAM, 0); 50 | if (s < 0) { 51 | perror("Unable to create socket"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { 56 | perror("Unable to set SO_REUSEADDR"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 61 | perror("Unable to bind"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (listen(s, 1) < 0) { 66 | perror("Unable to listen"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | return s; 71 | } 72 | 73 | void init_openssl() 74 | { 75 | OpenSSL_add_all_algorithms(); 76 | SSL_load_error_strings(); 77 | SSL_library_init(); 78 | } 79 | 80 | void cleanup_openssl() 81 | { 82 | EVP_cleanup(); 83 | } 84 | 85 | SSL_CTX *create_context() 86 | { 87 | const SSL_METHOD *method; 88 | SSL_CTX *ctx; 89 | 90 | method = SSLv23_server_method(); 91 | //method = TLSv1_2_server_method(); 92 | 93 | ctx = SSL_CTX_new(method); 94 | if (!ctx) { 95 | perror("Unable to create SSL context"); 96 | ERR_print_errors_fp(stderr); 97 | exit(EXIT_FAILURE); 98 | } 99 | 100 | return ctx; 101 | } 102 | 103 | void configure_context(SSL_CTX *ctx, const char *serverCert, const char *serverKey, 104 | const char *caCert) 105 | { 106 | SSL_CTX_set_ecdh_auto(ctx, 1); 107 | 108 | /* Set the key and cert */ 109 | if (SSL_CTX_use_certificate_file(ctx, serverCert, SSL_FILETYPE_PEM) <= 0) { 110 | ERR_print_errors_fp(stderr); 111 | exit(EXIT_FAILURE); 112 | } 113 | 114 | if (SSL_CTX_use_PrivateKey_file(ctx, serverKey, SSL_FILETYPE_PEM) <= 0 ) { 115 | ERR_print_errors_fp(stderr); 116 | exit(EXIT_FAILURE); 117 | } 118 | 119 | //SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); // not to verify client 120 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); // to verify client certificate 121 | 122 | /* Set CA certificate for client verification */ 123 | { 124 | FILE * rootCaFile = NULL; 125 | X509 *rootCa = NULL; 126 | 127 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 128 | perror("Unable to find CA certificate"); 129 | exit(EXIT_FAILURE); 130 | } 131 | 132 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 133 | perror("Unable to decode CA certificate"); 134 | exit(EXIT_FAILURE); 135 | } 136 | 137 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), rootCa) <= 0) { 138 | perror("Unable to load CA certificate"); 139 | exit(EXIT_FAILURE); 140 | } 141 | 142 | if (rootCaFile != NULL) 143 | fclose(rootCaFile); 144 | } 145 | } 146 | 147 | void showCert(SSL* ssl) 148 | { 149 | X509 *cert; 150 | char *line; 151 | 152 | cert = SSL_get_peer_certificate(ssl); 153 | if (cert != NULL) { 154 | printf("Client certificate:\n"); 155 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 156 | printf("Subject: %s\n", line); 157 | free(line); 158 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 159 | printf("Issuer: %s\n", line); 160 | free(line); 161 | X509_free(cert); 162 | } 163 | } 164 | 165 | int main(int argc, char **argv) 166 | { 167 | int sock; 168 | SSL_CTX *ctx; 169 | 170 | init_openssl(); 171 | ctx = create_context(); 172 | configure_context(ctx, "local-ca.crt", "local-ca.key", "local-ca.crt"); 173 | 174 | sock = create_socket(8443); 175 | 176 | /* Handle connections */ 177 | while(1) { 178 | struct sockaddr_in addr; 179 | uint len = sizeof(addr); 180 | SSL *ssl; 181 | const char reply[] = "\nHello from server.\n"; 182 | 183 | int client = accept(sock, (struct sockaddr*)&addr, &len); 184 | if (client < 0) { 185 | perror("Unable to accept"); 186 | exit(EXIT_FAILURE); 187 | } 188 | 189 | ssl = SSL_new(ctx); 190 | SSL_set_fd(ssl, client); 191 | 192 | if (SSL_accept(ssl) <= 0) { 193 | ERR_print_errors_fp(stderr); 194 | } 195 | else { 196 | int bytes = 0; 197 | char buf[256]; 198 | 199 | showCert(ssl); 200 | 201 | SSL_write(ssl, reply, strlen(reply)); 202 | bytes = SSL_read(ssl, buf, sizeof(buf)); // receive message from client 203 | if (bytes) { 204 | buf[bytes] = '\0'; 205 | printf("\nReceived: \"%s\"\n", buf); 206 | } 207 | 208 | } 209 | 210 | SSL_shutdown(ssl); 211 | SSL_free(ssl); 212 | close(client); 213 | } 214 | 215 | close(sock); 216 | SSL_CTX_free(ctx); 217 | cleanup_openssl(); 218 | } 219 | 220 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/0_clean-up.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | rm -rf *.crt ca local-ca.* *.ctx rsakey.* *.csr *.key server client-software client-tpm 2> /dev/null 5 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/1_init-tpm-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TOOLS_TCTI="mssim:host=localhost,port=2321" 5 | 6 | # perform tpm startup 7 | tpm2_startup -c 8 | # clear tpm 9 | tpm2_clear -c p 10 | # create primary key under owner hierarchy 11 | tpm2_createprimary -G ecc -c primary.ctx 12 | # make primary key persisted at handle 0x81000000 13 | tpm2_evictcontrol -c primary.ctx 0x81000000 14 | # remove all transient objects 15 | tpm2_flushcontext -t 16 | # create and output an rsa keypair (rsakey.pub, rsakey.priv) which is protected by the primary key 17 | tpm2_create -G rsa3072 -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign|noda" -C 0x81000000 -u rsakey.pub -r rsakey.priv 18 | # remove all transient objects 19 | tpm2_flushcontext -t 20 | # load the rsa keypair into tpm 21 | tpm2_load -C primary.ctx -u rsakey.pub -r rsakey.priv -c rsakey.ctx 22 | # make rsa keypair persisted at handle 0x81000001 23 | tpm2_evictcontrol -c rsakey.ctx 0x81000001 24 | # remove all transient objects 25 | tpm2_flushcontext -t 26 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/2_init-software-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | openssl genrsa -out software.key 2048 5 | 6 | 7 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/3_gen-ca-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CA 7 | openssl req -x509 -sha256 -nodes -days 365 -subj "/CN=CA/O=Infineon/C=SG" -newkey rsa:2048 -keyout local-ca.key -out local-ca.crt 8 | 9 | # Read cert 10 | #openssl x509 -in local-ca.crt -text -noout 11 | 12 | 13 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/4_gen-tpm-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | #export TPM2TSSENGINE_TCTI="mssim:host=localhost,port=2321" 5 | 6 | touch ~/.rnd 7 | 8 | # Generate CSR 9 | openssl req -new -provider tpm2 -key handle:0x81000001 -subj "/CN=TPM/O=Infineon/C=SG" -out tpm.csr 10 | 11 | # Generate CA signed client cert 12 | rm -rf ca 2> /dev/null 13 | mkdir ca 2> /dev/null 14 | touch ca/index.txt 15 | touch ca/index.txt.attr 16 | echo 'unique_subject = no' >> ca/index.txt.attr 17 | echo '01' > ca/serial 18 | (yes || true) | openssl ca -config config -in tpm.csr -out tpm.crt 19 | 20 | # Read cert 21 | #openssl x509 -in tpm.crt -text -noout 22 | 23 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/5_gen-software-client-crt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | touch ~/.rnd 5 | 6 | # Generate CSR 7 | openssl req -new -key software.key -subj "/CN=Software/O=Infineon/C=SG" -out software.csr 8 | 9 | # Generate CA signed client cert 10 | rm -rf ca 2> /dev/null 11 | mkdir ca 2> /dev/null 12 | touch ca/index.txt 13 | touch ca/index.txt.attr 14 | echo 'unique_subject = no' >> ca/index.txt.attr 15 | echo '01' > ca/serial 16 | (yes || true) | openssl ca -config config -in software.csr -out software.crt 17 | 18 | # Read cert 19 | #openssl x509 -in software.crt -text -noout 20 | 21 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/6_build-server-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | gcc -Wall -o server server.c -lssl -lcrypto -DENABLE_TPM_TSS_PROVIDER 5 | gcc -Wall -o client-software client.c -lssl -lcrypto 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/7_start-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./server 5 | 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/8_start-software-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | ./client-software 5 | 6 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | * https://aticleworld.com/ssl-server-client-using-openssl-in-c/ 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #ifdef ENABLE_TPM_TSS_PROVIDER 39 | #include 40 | #include 41 | #endif 42 | 43 | int connect_socket(const char *hostname, int port) 44 | { 45 | int s; 46 | struct hostent *host; 47 | struct sockaddr_in addr; 48 | 49 | if ((host = gethostbyname(hostname)) == NULL) { 50 | perror("Unable to find server"); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | bzero(&addr, sizeof(addr)); 55 | addr.sin_family = AF_INET; 56 | addr.sin_port = htons(port); 57 | addr.sin_addr.s_addr = *(long*)(host->h_addr); 58 | 59 | s = socket(AF_INET, SOCK_STREAM, 0); 60 | if (s < 0) { 61 | perror("Unable to create socket"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 66 | perror("Unable to connect to server"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | return s; 71 | } 72 | 73 | void init_openssl() 74 | { 75 | OpenSSL_add_all_algorithms(); 76 | SSL_load_error_strings(); 77 | SSL_library_init(); 78 | } 79 | 80 | void cleanup_openssl() 81 | { 82 | EVP_cleanup(); 83 | } 84 | 85 | SSL_CTX *create_ssl_context() 86 | { 87 | const SSL_METHOD *method; 88 | SSL_CTX *ctx; 89 | 90 | method = SSLv23_client_method(); 91 | 92 | ctx = SSL_CTX_new_ex(NULL, "provider=default,provider=tpm2", method); 93 | if (!ctx) { 94 | perror("Unable to create SSL context"); 95 | ERR_print_errors_fp(stderr); 96 | exit(EXIT_FAILURE); 97 | } 98 | 99 | return ctx; 100 | } 101 | 102 | SSL_CTX *configure_context(const char *clientCert, const char *clientKey, 103 | const char *caCert) 104 | { 105 | int32_t sslStatus = -1; 106 | SSL_CTX *pSslContext = NULL; 107 | 108 | #ifdef ENABLE_TPM_TSS_PROVIDER 109 | /* Set TPM-based key */ 110 | { 111 | OSSL_PROVIDER *prov_tpm2 = NULL; 112 | OSSL_PROVIDER *prov_default = NULL; 113 | OSSL_STORE_CTX *ctx = NULL; 114 | OSSL_STORE_INFO *info = NULL; 115 | EVP_PKEY *pKey = NULL; 116 | 117 | /* Load TPM2 provider */ 118 | if ((prov_tpm2 = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL) 119 | { 120 | perror("Unable to load OpenSSL provider: tpm2."); 121 | exit(EXIT_FAILURE); 122 | } 123 | 124 | /* Self-test */ 125 | if (!OSSL_PROVIDER_self_test(prov_tpm2)) 126 | { 127 | perror("OpenSSL provider (tpm2) self test failed."); 128 | exit(EXIT_FAILURE); 129 | } 130 | 131 | /* Load default provider */ 132 | if ((prov_default = OSSL_PROVIDER_load(NULL, "default")) == NULL) 133 | { 134 | perror("Unable to load OpenSSL provider: default."); 135 | exit(EXIT_FAILURE); 136 | } 137 | 138 | /* Self-test */ 139 | if (!OSSL_PROVIDER_self_test(prov_default)) 140 | { 141 | perror("OpenSSL provider (default) self test failed."); 142 | exit(EXIT_FAILURE); 143 | } 144 | 145 | if ((ctx = OSSL_STORE_open_ex(clientKey, NULL, "provider=tpm2", 146 | NULL, NULL, NULL, NULL, NULL)) == NULL || 147 | !OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY) || 148 | (info = OSSL_STORE_load(ctx)) == NULL || 149 | (pKey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL) { 150 | perror("OpenSSL provider (tpm2) key loading failed."); 151 | exit(EXIT_FAILURE); 152 | } 153 | 154 | OSSL_STORE_close(ctx); 155 | 156 | pSslContext = create_ssl_context(); 157 | 158 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 159 | if (sslStatus <= 0) { 160 | ERR_print_errors_fp(stderr); 161 | exit(EXIT_FAILURE); 162 | } 163 | 164 | /* Free these to avoid memory leak? */ 165 | //OSSL_STORE_INFO_free(info); 166 | //EVP_PKEY_free(pKey); 167 | //OSSL_PROVIDER_unload(prov_default); 168 | //OSSL_PROVIDER_unload(prov_tpm2); 169 | } 170 | #else 171 | (void) sslStatus; 172 | 173 | pSslContext = create_ssl_context(); 174 | 175 | /* Set software-based key */ 176 | if (SSL_CTX_use_PrivateKey_file(pSslContext, clientKey, SSL_FILETYPE_PEM) <= 0 ) { 177 | ERR_print_errors_fp(stderr); 178 | exit(EXIT_FAILURE); 179 | } 180 | #endif 181 | 182 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 183 | 184 | /* Set the client cert */ 185 | if (SSL_CTX_use_certificate_chain_file(pSslContext, clientCert) <= 0) { 186 | ERR_print_errors_fp(stderr); 187 | exit(EXIT_FAILURE); 188 | } 189 | 190 | /* Verify client cert */ 191 | if (!SSL_CTX_check_private_key(pSslContext)) { 192 | perror("Private key does not match with certificate public key."); 193 | exit(EXIT_FAILURE); 194 | } 195 | 196 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify server 197 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify server certificate 198 | 199 | /* Set CA certificate for server verification */ 200 | { 201 | FILE * rootCaFile = NULL; 202 | X509 *rootCa = NULL; 203 | 204 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 205 | perror("Unable to find CA certificate"); 206 | exit(EXIT_FAILURE); 207 | } 208 | 209 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 210 | perror("Unable to decode CA certificate"); 211 | exit(EXIT_FAILURE); 212 | } 213 | 214 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 215 | perror("Unable to load CA certificate"); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | if (rootCaFile != NULL) 220 | fclose(rootCaFile); 221 | } 222 | 223 | return pSslContext; 224 | } 225 | 226 | void showCert(SSL* ssl) 227 | { 228 | X509 *cert; 229 | char *line; 230 | 231 | cert = SSL_get_peer_certificate(ssl); 232 | if (cert != NULL) { 233 | printf("Server certificate:\n"); 234 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 235 | printf("Subject: %s\n", line); 236 | free(line); 237 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 238 | printf("Issuer: %s\n", line); 239 | free(line); 240 | X509_free(cert); 241 | } 242 | } 243 | 244 | int main(int argc, char **argv) 245 | { 246 | int sock; 247 | SSL_CTX *ctx; 248 | SSL *ssl; 249 | 250 | init_openssl(); 251 | 252 | #ifdef ENABLE_TPM_TSS_PROVIDER 253 | ctx = configure_context("tpm.crt", "handle:0x81000001", "local-ca.crt"); 254 | #else 255 | ctx = configure_context("software.crt", "software.key", "local-ca.crt"); 256 | #endif 257 | 258 | sock = connect_socket("localhost", 8443); 259 | ssl = SSL_new(ctx); 260 | SSL_set_fd(ssl, sock); 261 | 262 | if (SSL_connect(ssl) <= 0) { 263 | ERR_print_errors_fp(stderr); 264 | } else { 265 | const char msg[] = "\nHello from client...\n"; 266 | int bytes = 0; 267 | char buf[256]; 268 | 269 | showCert(ssl); 270 | 271 | SSL_write(ssl, msg, strlen(msg)); // send message to server 272 | bytes = SSL_read(ssl, buf, sizeof(buf) - 1); // receive message from server 273 | if (bytes) { 274 | buf[bytes] = '\0'; 275 | printf("\nReceived: \"%s\"\n", buf); 276 | } 277 | } 278 | 279 | SSL_shutdown(ssl); 280 | SSL_free(ssl); 281 | 282 | close(sock); 283 | SSL_CTX_free(ctx); 284 | cleanup_openssl(); 285 | } 286 | 287 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/config: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default # The default ca section 3 | 4 | [ CA_default ] 5 | 6 | dir = ./ca # top dir 7 | database = $dir/index.txt # index file. 8 | new_certs_dir = $dir # new certs dir 9 | 10 | serial = $dir/serial # serial no file 11 | certificate = ./local-ca.crt # the local CA cert 12 | private_key = ./local-ca.key # the local CA private key 13 | 14 | default_days = 365 # how long to certify for 15 | default_crl_days= 30 # how long before next CRL 16 | default_md = sha256 # md to use 17 | 18 | policy = policy_any # default policy 19 | email_in_dn = no # Don't add the email into cert DN 20 | 21 | name_opt = ca_default # Subject name display option 22 | cert_opt = ca_default # Certificate display option 23 | copy_extensions = none # Don't copy extensions from request 24 | 25 | [ policy_any ] 26 | countryName = supplied 27 | stateOrProvinceName = optional 28 | organizationName = optional 29 | organizationalUnitName = optional 30 | commonName = supplied 31 | emailAddress = optional 32 | -------------------------------------------------------------------------------- /openssl3-lib-tls/tpm-on-server/server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2021 Infineon Technologies AG 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE 23 | */ 24 | /* 25 | * References: 26 | * https://wiki.openssl.org/index.php/Simple_TLS_Server 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #ifdef ENABLE_TPM_TSS_PROVIDER 37 | #include 38 | #include 39 | #endif 40 | 41 | int create_socket(int port) 42 | { 43 | int s; 44 | struct sockaddr_in addr; 45 | const int enable = 1; 46 | 47 | bzero(&addr, sizeof(addr)); 48 | addr.sin_family = AF_INET; 49 | addr.sin_port = htons(port); 50 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 51 | //addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 52 | 53 | s = socket(AF_INET, SOCK_STREAM, 0); 54 | if (s < 0) { 55 | perror("Unable to create socket"); 56 | exit(EXIT_FAILURE); 57 | } 58 | 59 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { 60 | perror("Unable to set SO_REUSEADDR"); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 65 | perror("Unable to bind"); 66 | exit(EXIT_FAILURE); 67 | } 68 | 69 | if (listen(s, 1) < 0) { 70 | perror("Unable to listen"); 71 | exit(EXIT_FAILURE); 72 | } 73 | 74 | return s; 75 | } 76 | 77 | void init_openssl() 78 | { 79 | OpenSSL_add_all_algorithms(); 80 | SSL_load_error_strings(); 81 | SSL_library_init(); 82 | } 83 | 84 | void cleanup_openssl() 85 | { 86 | EVP_cleanup(); 87 | } 88 | 89 | SSL_CTX *create_ssl_context() 90 | { 91 | const SSL_METHOD *method; 92 | SSL_CTX *ctx; 93 | 94 | method = SSLv23_server_method(); 95 | //method = TLSv1_2_server_method(); 96 | 97 | ctx = SSL_CTX_new_ex(NULL, "provider=default,provider=tpm2", method); 98 | if (!ctx) { 99 | perror("Unable to create SSL context"); 100 | ERR_print_errors_fp(stderr); 101 | exit(EXIT_FAILURE); 102 | } 103 | 104 | return ctx; 105 | } 106 | 107 | SSL_CTX *configure_context(const char *serverCert, const char *serverKey, 108 | const char *caCert) 109 | { 110 | int32_t sslStatus = -1; 111 | SSL_CTX *pSslContext = NULL; 112 | 113 | #ifdef ENABLE_TPM_TSS_PROVIDER 114 | /* Set TPM-based key */ 115 | { 116 | OSSL_PROVIDER *prov_tpm2 = NULL; 117 | OSSL_PROVIDER *prov_default = NULL; 118 | OSSL_STORE_CTX *ctx = NULL; 119 | OSSL_STORE_INFO *info = NULL; 120 | EVP_PKEY *pKey = NULL; 121 | 122 | /* Load TPM2 provider */ 123 | if ((prov_tpm2 = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL) 124 | { 125 | perror("Unable to load OpenSSL provider: tpm2."); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | /* Self-test */ 130 | if (!OSSL_PROVIDER_self_test(prov_tpm2)) 131 | { 132 | perror("OpenSSL provider (tpm2) self test failed."); 133 | exit(EXIT_FAILURE); 134 | } 135 | 136 | /* Load default provider */ 137 | if ((prov_default = OSSL_PROVIDER_load(NULL, "default")) == NULL) 138 | { 139 | perror("Unable to load OpenSSL provider: default."); 140 | exit(EXIT_FAILURE); 141 | } 142 | 143 | /* Self-test */ 144 | if (!OSSL_PROVIDER_self_test(prov_default)) 145 | { 146 | perror("OpenSSL provider (default) self test failed."); 147 | exit(EXIT_FAILURE); 148 | } 149 | 150 | if ((ctx = OSSL_STORE_open_ex(serverKey, NULL, "provider=tpm2", 151 | NULL, NULL, NULL, NULL, NULL)) == NULL || 152 | !OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY) || 153 | (info = OSSL_STORE_load(ctx)) == NULL || 154 | (pKey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL) { 155 | perror("OpenSSL provider (tpm2) key loading failed."); 156 | exit(EXIT_FAILURE); 157 | } 158 | 159 | OSSL_STORE_close(ctx); 160 | 161 | pSslContext = create_ssl_context(); 162 | 163 | sslStatus = SSL_CTX_use_PrivateKey(pSslContext, pKey); 164 | if (sslStatus <= 0) { 165 | ERR_print_errors_fp(stderr); 166 | exit(EXIT_FAILURE); 167 | } 168 | 169 | /* Free these to avoid memory leak? */ 170 | //OSSL_STORE_INFO_free(info); 171 | //EVP_PKEY_free(pKey); 172 | //OSSL_PROVIDER_unload(prov_default); 173 | //OSSL_PROVIDER_unload(prov_tpm2); 174 | } 175 | #else 176 | (void) sslStatus; 177 | 178 | pSslContext = create_ssl_context(); 179 | 180 | /* Set software-based key */ 181 | if (SSL_CTX_use_PrivateKey_file(pSslContext, serverKey, SSL_FILETYPE_PEM) <= 0 ) { 182 | ERR_print_errors_fp(stderr); 183 | exit(EXIT_FAILURE); 184 | } 185 | #endif 186 | 187 | SSL_CTX_set_ecdh_auto(pSslContext, 1); 188 | 189 | /* Set the server cert */ 190 | if (SSL_CTX_use_certificate_chain_file(pSslContext, serverCert) <= 0) { 191 | ERR_print_errors_fp(stderr); 192 | exit(EXIT_FAILURE); 193 | } 194 | 195 | /* Verify server cert */ 196 | if (!SSL_CTX_check_private_key(pSslContext)) { 197 | perror("Private key does not match with certificate public key."); 198 | exit(EXIT_FAILURE); 199 | } 200 | 201 | //SSL_CTX_set_verify(pSslContext, SSL_VERIFY_NONE, NULL); // not to verify client 202 | SSL_CTX_set_verify(pSslContext, SSL_VERIFY_PEER, NULL); // to verify client certificate 203 | 204 | /* Set CA certificate for client verification */ 205 | { 206 | FILE * rootCaFile = NULL; 207 | X509 *rootCa = NULL; 208 | 209 | if ((rootCaFile = fopen(caCert, "r")) == NULL) { 210 | perror("Unable to find CA certificate"); 211 | exit(EXIT_FAILURE); 212 | } 213 | 214 | if ((rootCa = PEM_read_X509(rootCaFile, NULL, NULL, NULL)) == NULL) { 215 | perror("Unable to decode CA certificate"); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | if (X509_STORE_add_cert(SSL_CTX_get_cert_store(pSslContext), rootCa) <= 0) { 220 | perror("Unable to load CA certificate"); 221 | exit(EXIT_FAILURE); 222 | } 223 | 224 | if (rootCaFile != NULL) 225 | fclose(rootCaFile); 226 | } 227 | 228 | return pSslContext; 229 | } 230 | 231 | void showCert(SSL* ssl) 232 | { 233 | X509 *cert; 234 | char *line; 235 | 236 | cert = SSL_get_peer_certificate(ssl); 237 | if (cert != NULL) { 238 | printf("Client certificate:\n"); 239 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 240 | printf("Subject: %s\n", line); 241 | free(line); 242 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 243 | printf("Issuer: %s\n", line); 244 | free(line); 245 | X509_free(cert); 246 | } 247 | } 248 | 249 | int main(int argc, char **argv) 250 | { 251 | int sock; 252 | SSL_CTX *ctx; 253 | 254 | init_openssl(); 255 | #ifdef ENABLE_TPM_TSS_PROVIDER 256 | ctx = configure_context("tpm.crt", "handle:0x81000001", "local-ca.crt"); 257 | #else 258 | ctx = configure_context("software.crt", "software.key", "local-ca.crt"); 259 | #endif 260 | 261 | sock = create_socket(8443); 262 | 263 | /* Handle connections */ 264 | while(1) { 265 | struct sockaddr_in addr; 266 | uint len = sizeof(addr); 267 | SSL *ssl; 268 | const char reply[] = "\nHello from server.\n"; 269 | 270 | int client = accept(sock, (struct sockaddr*)&addr, &len); 271 | if (client < 0) { 272 | perror("Unable to accept"); 273 | exit(EXIT_FAILURE); 274 | } 275 | 276 | ssl = SSL_new(ctx); 277 | SSL_set_fd(ssl, client); 278 | 279 | if (SSL_accept(ssl) <= 0) { 280 | ERR_print_errors_fp(stderr); 281 | } 282 | else { 283 | int bytes = 0; 284 | char buf[256]; 285 | 286 | showCert(ssl); 287 | 288 | SSL_write(ssl, reply, strlen(reply)); 289 | bytes = SSL_read(ssl, buf, sizeof(buf)); // receive message from client 290 | if (bytes) { 291 | buf[bytes] = '\0'; 292 | printf("\nReceived: \"%s\"\n", buf); 293 | } 294 | 295 | } 296 | 297 | SSL_shutdown(ssl); 298 | SSL_free(ssl); 299 | close(client); 300 | } 301 | 302 | close(sock); 303 | SSL_CTX_free(ctx); 304 | cleanup_openssl(); 305 | } 306 | 307 | --------------------------------------------------------------------------------