blob: a74990375f41a56df4ddf74ba52520015a29f322 [file] [log] [blame]
Paul Stewartea00bc82013-06-25 10:13:25 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import tempfile
6
7from autotest_lib.client.bin import utils
Kris Rambish088c75f2014-12-11 11:02:38 -08008from autotest_lib.client.common_lib import error
9from autotest_lib.client.cros import cryptohome
Paul Stewartea00bc82013-06-25 10:13:25 -070010
11class TPMStore(object):
12 """Context enclosing the use of the TPM."""
13
14 CHAPS_CLIENT_COMMAND = 'chaps_client'
15 CONVERT_TYPE_RSA = 'rsa'
16 CONVERT_TYPE_X509 = 'x509'
Paul Stewartea00bc82013-06-25 10:13:25 -070017 OPENSSL_COMMAND = 'openssl'
18 OUTPUT_TYPE_CERTIFICATE = 'cert'
19 OUTPUT_TYPE_PRIVATE_KEY = 'privkey'
20 PIN = '11111'
Peter Qiu13372b12014-11-10 19:46:28 -080021 # TPM maintain two slots for certificates, slot 0 for system specific
22 # certificates, slot 1 for user specific certificates. Currently, all
23 # certificates are programmed in slot 1. So hardcode this slot ID for now.
24 SLOT_ID = '1'
25 PKCS11_REPLAY_COMMAND = 'p11_replay --slot=%s' % SLOT_ID
Paul Stewartea00bc82013-06-25 10:13:25 -070026 TPM_GROUP = 'chronos-access'
27 TPM_USER = 'chaps'
28
29
30 def __enter__(self):
31 self.setup()
32 return self
33
34 def __exit__(self, exception, value, traceback):
35 self.reset()
36
37
Paul Stewartea00bc82013-06-25 10:13:25 -070038 def _install_object(self, pem, identifier, conversion_type, output_type):
39 """Convert a PEM object to DER and store it in the TPM.
40
41 @param pem string PEM encoded object to be stored.
42 @param identifier string associated with the new object.
43 @param conversion_type the object type to use in PEM to DER conversion.
44 @param output_type the object type to use in inserting into the TPM.
45
46 """
Kris Rambish037f8df2015-01-26 12:47:35 -080047 if cryptohome.is_tpm_lockout_in_effect():
48 raise error.TestError('The TPM is in dictonary defend mode. '
49 'The TPMStore may behave in unexpected '
50 'ways, exiting.')
Paul Stewartea00bc82013-06-25 10:13:25 -070051 pem_file = tempfile.NamedTemporaryFile()
52 pem_file.file.write(pem)
53 pem_file.file.flush()
54 der_file = tempfile.NamedTemporaryFile()
55 utils.system('%s %s -in %s -out %s -inform PEM -outform DER' %
56 (self.OPENSSL_COMMAND, conversion_type, pem_file.name,
57 der_file.name))
58 utils.system('%s --import --type=%s --path=%s --id="%s"' %
59 (self.PKCS11_REPLAY_COMMAND, output_type, der_file.name,
60 identifier))
61
62
63 def setup(self):
64 """Set the TPM up for operation in tests."""
65 self.reset()
66 self._directory = tempfile.mkdtemp()
67 utils.system('chown %s:%s %s' %
68 (self.TPM_USER, self.TPM_GROUP, self._directory))
69 utils.system('%s --load --path=%s --auth="%s"' %
70 (self.CHAPS_CLIENT_COMMAND, self._directory, self.PIN))
71
72
73 def reset(self):
74 """Reset the crypto store and take ownership of the device."""
75 utils.system('initctl restart chapsd')
Brian Norris7bf96c92019-10-30 18:21:18 -070076 cryptohome.take_tpm_ownership(wait_for_ownership=True)
Paul Stewartea00bc82013-06-25 10:13:25 -070077
78
79 def install_certificate(self, certificate, identifier):
80 """Install a certificate into the TPM, returning the certificate ID.
81
82 @param certificate string PEM x509 contents of the certificate.
83 @param identifier string associated with this certificate in the TPM.
84
85 """
86 return self._install_object(certificate,
87 identifier,
88 self.CONVERT_TYPE_X509,
89 self.OUTPUT_TYPE_CERTIFICATE)
90
91
92 def install_private_key(self, key, identifier):
93 """Install a private key into the TPM, returning the certificate ID.
94
95 @param key string PEM RSA private key contents.
96 @param identifier string associated with this private key in the TPM.
97
98 """
99 return self._install_object(key,
100 identifier,
101 self.CONVERT_TYPE_RSA,
102 self.OUTPUT_TYPE_PRIVATE_KEY)