Merge ~sylvain-pineau/plainbox-provider-tpm2:clevis-jobs into plainbox-provider-tpm2:master

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: b27dd6873f03ef4f6fef94ad1ecc41df60b9a6ca
Merged at revision: 4da022d7832047f6dc9ea72dd244dadac3942e75
Proposed branch: ~sylvain-pineau/plainbox-provider-tpm2:clevis-jobs
Merge into: plainbox-provider-tpm2:master
Diff against target: 320 lines (+284/-0)
5 files modified
bin/tpm2_capabilities.py (+190/-0)
units/clevis.pxu (+68/-0)
units/packaging.pxu (+5/-0)
units/resource.pxu (+9/-0)
units/test-plan.pxu (+12/-0)
Reviewer Review Type Date Requested Status
Jonathan Cave (community) Approve
Sylvain Pineau (community) Needs Resubmitting
Review via email: mp+404262@code.launchpad.net

Description of the change

App-level tests using clevis

To post a comment you must log in.
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

--------------[ Running job 3 / 6. Estimated time left: unknown ]---------------
----------------------[ clevis encrypt/decrypt precheck ]-----------------------
ID: com.canonical.certification::clevis-encrypt-tpm2/precheck
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
------------------------------------------------------------------------- >8 ---
Outcome: job passed
--------------[ Running job 4 / 6. Estimated time left: unknown ]---------------
----------------[ tpm2 capabilities (algorithms and pcr banks) ]----------------
ID: com.canonical.certification::tpm2_cap
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
assymetric: ecc ecc224 ecc256 rsa rsa1024 rsa2048
symmetric: aes aes128 aes192 aes256 symcipher
hash: sha1 sha256
keyed_hash: hmac keyedhash xor
mask_generation_functions: mgf1
signature_schemes: ecdaa ecdsa ecschnorr rsapss rsassa
assymetric_encryption_scheme: ecdh oaep rsaes
key_derivation_functions: kdf1_sp800_108 kdf1_sp800_56a
aes_modes: cbc cfb ctr ecb ofb
pcr_banks: sha1 sha256
------------------------------------------------------------------------- >8 ---
Outcome: job passed
--------------[ Running job 5 / 6. Estimated time left: unknown ]---------------
-----------------------[ clevis encrypt/decrypt key rsa ]-----------------------
ID: com.canonical.certification::clevis-encrypt-tpm2/rsa
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
hello world
------------------------------------------------------------------------- >8 ---
Outcome: job passed
--------------[ Running job 6 / 6. Estimated time left: unknown ]---------------
-----------------------[ clevis encrypt/decrypt key ecc ]-----------------------
ID: com.canonical.certification::clevis-encrypt-tpm2/ecc
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
hello world
------------------------------------------------------------------------- >8 ---
Outcome: job passed
 ☑ : Hardware Manifest
 ☑ : Enumerate available system executables
 ☑ : clevis encrypt/decrypt precheck
 ☑ : tpm2 capabilities (algorithms and pcr banks)
 ☑ : clevis encrypt/decrypt key rsa
 ☑ : clevis encrypt/decrypt key ecc

Revision history for this message
Jonathan Cave (jocave) wrote :

Thanks for the effort going through the specs on this one. Looks really clean and gives us something much more like a realistic use-case.

Good to land as it. Some small improvements might be more verbosity in the tests, which might seem like overkill given they are one-liners, but I think it's reassuring to seem what might is going on.

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

One last commit to process larger strings (random strings) and some info msg

review: Needs Resubmitting
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

-----------------------[ clevis encrypt/decrypt key rsa ]-----------------------
ID: com.canonical.certification::clevis-encrypt-tpm2/rsa
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
+ Generate a random string
+ Encrypt and decrypt the string using the TPM
+ Compare with the original string
------------------------------------------------------------------------- >8 ---
Outcome: job passed
--------------[ Running job 6 / 6. Estimated time left: unknown ]---------------
-----------------------[ clevis encrypt/decrypt key ecc ]-----------------------
ID: com.canonical.certification::clevis-encrypt-tpm2/ecc
Category: com.canonical.certification::tpm2
... 8< -------------------------------------------------------------------------
+ Generate a random string
+ Encrypt and decrypt the string using the TPM
+ Compare with the original string
------------------------------------------------------------------------- >8 ---
Outcome: job passed

Revision history for this message
Jonathan Cave (jocave) wrote :

Nice, thank you

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/bin/tpm2_capabilities.py b/bin/tpm2_capabilities.py
0new file mode 1007550new file mode 100755
index 0000000..52e4e2f
--- /dev/null
+++ b/bin/tpm2_capabilities.py
@@ -0,0 +1,190 @@
1#!/usr/bin/env python3
2
3import yaml
4import subprocess
5
6
7# From TCG Algorithm Registry: Definition of TPM2_ALG_ID Constants
8# https://trustedcomputinggroup.org/wp-content/uploads/TCG-_Algorithm_Registry_r1p32_pub.pdf
9# https://github.com/tpm2-software/tpm2-tools/blob/master/lib/tpm2_alg_util.c
10
11TPM2_ALG_RSA = 0x0001
12TPM2_ALG_TDES = 0x0003
13TPM2_ALG_SHA1 = 0x0004
14TPM2_ALG_HMAC = 0x0005
15TPM2_ALG_AES = 0x0006
16TPM2_ALG_MGF1 = 0x0007
17TPM2_ALG_KEYEDHASH = 0x0008
18TPM2_ALG_XOR = 0x000A
19TPM2_ALG_SHA256 = 0x000B
20TPM2_ALG_SHA384 = 0x000C
21TPM2_ALG_SHA512 = 0x000D
22TPM2_ALG_NULL = 0x0010
23TPM2_ALG_SM3_256 = 0x0012
24TPM2_ALG_SM4 = 0x0013
25TPM2_ALG_RSASSA = 0x0014
26TPM2_ALG_RSAES = 0x0015
27TPM2_ALG_RSAPSS = 0x0016
28TPM2_ALG_OAEP = 0x0017
29TPM2_ALG_ECDSA = 0x0018
30TPM2_ALG_ECDH = 0x0019
31TPM2_ALG_ECDAA = 0x001A
32TPM2_ALG_SM2 = 0x001B
33TPM2_ALG_ECSCHNORR = 0x001C
34TPM2_ALG_ECMQV = 0x001D
35TPM2_ALG_KDF1_SP800_56A = 0x0020
36TPM2_ALG_KDF2 = 0x0021
37TPM2_ALG_KDF1_SP800_108 = 0x0022
38TPM2_ALG_ECC = 0x0023
39TPM2_ALG_SYMCIPHER = 0x0025
40TPM2_ALG_CAMELLIA = 0x0026
41TPM2_ALG_CMAC = 0x003F
42TPM2_ALG_CTR = 0x0040
43TPM2_ALG_SHA3_256 = 0x0027
44TPM2_ALG_SHA3_384 = 0x0028
45TPM2_ALG_SHA3_512 = 0x0029
46TPM2_ALG_OFB = 0x0041
47TPM2_ALG_CBC = 0x0042
48TPM2_ALG_CFB = 0x0043
49TPM2_ALG_ECB = 0x0044
50
51# Mandatory algorithms
52# https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf
53# Mandatory algorithms for PCRs are defined in Section 4.6
54
55# TPM2_ALG_RSA
56# TPM2_ALG_SHA1
57# TPM2_ALG_HMAC
58# TPM2_ALG_AES
59# TPM2_ALG_MGF1
60# TPM2_ALG_KEYEDHASH
61# TPM2_ALG_XOR
62# TPM2_ALG_SHA256
63# TPM2_ALG_SHA384
64# TPM2_ALG_RSASSA
65# TPM2_ALG_RSAES
66# TPM2_ALG_RSAPSS
67# TPM2_ALG_OAEP
68# TPM2_ALG_ECDSA
69# TPM2_ALG_ECDH
70# TPM2_ALG_ECC
71# TPM2_ALG_SYMCIPHER
72
73TPM2_CAP = {
74 'assymetric': set(),
75 'symmetric': set(),
76 'hash': set(),
77 'keyed_hash': set(),
78 'mask_generation_functions': set(),
79 'signature_schemes': set(),
80 'assymetric_encryption_scheme': set(),
81 'key_derivation_functions': set(),
82 'aes_modes': set(),
83 'pcr_banks': set(),
84}
85
86try:
87 algs_caps = subprocess.check_output(['tpm2_getcap', 'algorithms'])
88 pcrs_caps = subprocess.check_output(['tpm2_getcap', 'pcrs'])
89except subprocess.CalledProcessError:
90 raise SystemExit
91
92algs_list = yaml.load(algs_caps, Loader=yaml.FullLoader)
93pcrs_list = yaml.load(pcrs_caps, Loader=yaml.FullLoader)
94
95for alg, prop in algs_list.items():
96 # Assymetric
97 if prop['value'] in (TPM2_ALG_RSA, TPM2_ALG_ECC):
98 TPM2_CAP['assymetric'].add(alg)
99
100 # Symmetric
101 if prop['value'] in (
102 TPM2_ALG_TDES, TPM2_ALG_AES, TPM2_ALG_CAMELLIA, TPM2_ALG_SYMCIPHER
103 ):
104 TPM2_CAP['symmetric'].add(alg)
105
106 # Hash
107 if prop['value'] in (
108 TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA512,
109 TPM2_ALG_SM3_256, TPM2_ALG_SHA3_256, TPM2_ALG_SHA3_384,
110 TPM2_ALG_SHA3_512
111 ):
112 TPM2_CAP['hash'].add(alg)
113
114 # Keyed hash
115 if prop['value'] in (
116 TPM2_ALG_HMAC, TPM2_ALG_XOR, TPM2_ALG_CMAC, TPM2_ALG_KEYEDHASH
117 ):
118 TPM2_CAP['keyed_hash'].add(alg)
119
120 # Mask Generation Functions
121 if prop['value'] in (TPM2_ALG_MGF1,):
122 TPM2_CAP['mask_generation_functions'].add(alg)
123
124 # Signature Schemes
125 if prop['value'] in (
126 TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS, TPM2_ALG_ECDSA, TPM2_ALG_ECDAA,
127 TPM2_ALG_ECSCHNORR, TPM2_ALG_SM2, TPM2_ALG_SM4
128 ):
129 TPM2_CAP['signature_schemes'].add(alg)
130
131 # Assymetric Encryption Scheme
132 if prop['value'] in (TPM2_ALG_OAEP, TPM2_ALG_RSAES, TPM2_ALG_ECDH):
133 TPM2_CAP['assymetric_encryption_scheme'].add(alg)
134
135 # Key derivation functions
136 if prop['value'] in (
137 TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF2, TPM2_ALG_KDF1_SP800_108,
138 TPM2_ALG_ECMQV
139 ):
140 TPM2_CAP['key_derivation_functions'].add(alg)
141
142 # AES Modes
143 if prop['value'] in (
144 TPM2_ALG_CTR, TPM2_ALG_OFB, TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_ECB
145 ):
146 TPM2_CAP['aes_modes'].add(alg)
147
148if 'aes' in TPM2_CAP['symmetric']:
149 for alg_type in ('aes', 'aes128', 'aes192', 'aes256'):
150 try:
151 subprocess.check_call(
152 ['tpm2_testparms', alg_type], stderr=subprocess.DEVNULL)
153 TPM2_CAP['symmetric'].add(alg_type)
154 except subprocess.CalledProcessError:
155 try:
156 TPM2_CAP['symmetric'].remove(alg_type)
157 except KeyError:
158 pass
159
160if 'ecc' in TPM2_CAP['assymetric']:
161 for alg_type in ('ecc', 'ecc192', 'ecc224', 'ecc256', 'ecc384', 'ecc521'):
162 try:
163 subprocess.check_call(
164 ['tpm2_testparms', alg_type], stderr=subprocess.DEVNULL)
165 TPM2_CAP['assymetric'].add(alg_type)
166 except subprocess.CalledProcessError:
167 try:
168 TPM2_CAP['assymetric'].remove(alg_type)
169 except KeyError:
170 pass
171
172if 'rsa' in TPM2_CAP['assymetric']:
173 for alg_type in ('rsa', 'rsa1024', 'rsa2048', 'rsa4096'):
174 try:
175 subprocess.check_call(
176 ['tpm2_testparms', alg_type], stderr=subprocess.DEVNULL)
177 TPM2_CAP['assymetric'].add(alg_type)
178 except subprocess.CalledProcessError:
179 try:
180 TPM2_CAP['assymetric'].remove(alg_type)
181 except KeyError:
182 pass
183
184for pcr in pcrs_list['selected-pcrs']:
185 for pcr_bank, pcr_ids in pcr.items():
186 if set(range(24)).issubset(set(pcr_ids)):
187 TPM2_CAP['pcr_banks'].add(pcr_bank)
188
189for k, v in TPM2_CAP.items():
190 print("{}: {}".format(k, ' '.join(sorted(v))))
diff --git a/units/clevis.pxu b/units/clevis.pxu
0new file mode 100644191new file mode 100644
index 0000000..c17ef8e
--- /dev/null
+++ b/units/clevis.pxu
@@ -0,0 +1,68 @@
1# This file is part of Checkbox.
2#
3# Copyright 2021 Canonical Ltd.
4# Written by:
5# Sylvain Pineau <sylvain.pineau@canonical.com>
6#
7# Checkbox is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3,
9# as published by the Free Software Foundation.
10#
11# Checkbox is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
18
19id: clevis-encrypt-tpm2/precheck
20category_id: tpm2
21plugin: shell
22imports: from com.canonical.plainbox import manifest
23requires:
24 manifest.has_tpm2_chip == 'True'
25 executable.name == 'clevis-encrypt-tpm2'
26_summary: clevis encrypt/decrypt precheck
27flags: simple
28command: true
29
30id: clevis-encrypt-tpm2/rsa
31category_id: tpm2
32plugin: shell
33depends: clevis-encrypt-tpm2/precheck
34requires:
35 'sha256' in tpm2_cap.hash
36 'sha256' in tpm2_cap.pcr_banks
37 'rsa' in tpm2_cap.assymetric
38estimated_duration: 30
39_summary: clevis encrypt/decrypt key rsa
40flags: simple fail-on-resource
41user: root
42command:
43 echo "+ Generate a random string"
44 rand=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c32768)
45 echo "+ Encrypt and decrypt the string using the TPM"
46 result=$(echo -n $rand | clevis-encrypt-tpm2 '{"hash": "sha256", "key":"rsa", "pcr_bank":"sha256","pcr_ids":"0,1"}' | clevis-decrypt-tpm2)
47 echo "+ Compare with the original string"
48 [[ $result == $rand ]]
49
50id: clevis-encrypt-tpm2/ecc
51category_id: tpm2
52plugin: shell
53depends: clevis-encrypt-tpm2/precheck
54requires:
55 'sha256' in tpm2_cap.hash
56 'sha256' in tpm2_cap.pcr_banks
57 'ecc' in tpm2_cap.assymetric
58estimated_duration: 30
59_summary: clevis encrypt/decrypt key ecc
60flags: simple fail-on-resource
61user: root
62command:
63 echo "+ Generate a random string"
64 rand=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c32768)
65 echo "+ Encrypt and decrypt the string using the TPM"
66 result=$(echo -n $rand | clevis-encrypt-tpm2 '{"hash": "sha256", "key":"ecc", "pcr_bank":"sha256","pcr_ids":"0,1"}' | clevis-decrypt-tpm2)
67 echo "+ Compare with the original string"
68 [[ $result == $rand ]]
diff --git a/units/packaging.pxu b/units/packaging.pxu
index 8aac195..ffa20fb 100644
--- a/units/packaging.pxu
+++ b/units/packaging.pxu
@@ -10,3 +10,8 @@ unit: packaging meta-data
10os-id: ubuntu10os-id: ubuntu
11os-version-id: 20.0411os-version-id: 20.04
12Depends: libtss2-dev12Depends: libtss2-dev
13
14unit: packaging meta-data
15os-id: ubuntu
16os-version-id: 20.04
17Depends: clevis-tpm2
diff --git a/units/resource.pxu b/units/resource.pxu
index 7487095..f58571a 100644
--- a/units/resource.pxu
+++ b/units/resource.pxu
@@ -36,3 +36,12 @@ command:
36 echo tpmrm: unsupported36 echo tpmrm: unsupported
37 echo encryptdecrypt: unsupported37 echo encryptdecrypt: unsupported
38 fi38 fi
39
40id: tpm2_cap
41category_id: tpm2
42plugin: resource
43estimated_duration: 1
44_summary: tpm2 capabilities (algorithms and pcr banks)
45user: root
46command:
47 tpm2_capabilities.py
diff --git a/units/test-plan.pxu b/units/test-plan.pxu
index 927a90a..f7d5eb3 100644
--- a/units/test-plan.pxu
+++ b/units/test-plan.pxu
@@ -80,3 +80,15 @@ include:
80 tpm2.0_4.1.1/.*80 tpm2.0_4.1.1/.*
81mandatory_include:81mandatory_include:
82 com.canonical.plainbox::manifest82 com.canonical.plainbox::manifest
83
84unit: test plan
85id: clevis-automated
86_name:
87 TPM 2.0 (Trusted Platform Module) Clevis encryption tests
88_description:
89 Clevis encryption tests
90estimated_duration: 1m
91include:
92 clevis.*
93mandatory_include:
94 com.canonical.plainbox::manifest

Subscribers

People subscribed via source and target branches

to all changes: