1ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart# Use of this source code is governed by a BSD-style license that can be 3ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart# found in the LICENSE file. 4ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 5ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewartimport tempfile 6ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 7ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewartfrom autotest_lib.client.bin import utils 8088c75f64155b89255e9ebd324230f5c34eda74eKris Rambishfrom autotest_lib.client.common_lib import error 9088c75f64155b89255e9ebd324230f5c34eda74eKris Rambishfrom autotest_lib.client.cros import cryptohome 10ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 11ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewartclass TPMStore(object): 12ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Context enclosing the use of the TPM.""" 13ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 14ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CHAPS_CLIENT_COMMAND = 'chaps_client' 15ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CONVERT_TYPE_RSA = 'rsa' 16ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CONVERT_TYPE_X509 = 'x509' 17ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CRYPTOHOME_ACTION_TAKE_OWNERSHIP = 'tpm_take_ownership' 18ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CRYPTOHOME_ACTION_WAIT_OWNERSHIP = 'tpm_wait_ownership' 19ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart CRYPTOHOME_COMMAND = '/usr/sbin/cryptohome' 20ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart OPENSSL_COMMAND = 'openssl' 21ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart OUTPUT_TYPE_CERTIFICATE = 'cert' 22ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart OUTPUT_TYPE_PRIVATE_KEY = 'privkey' 23ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart PIN = '11111' 2413372b17e81e16243b50a4c73384a86f31fed802Peter Qiu # TPM maintain two slots for certificates, slot 0 for system specific 2513372b17e81e16243b50a4c73384a86f31fed802Peter Qiu # certificates, slot 1 for user specific certificates. Currently, all 2613372b17e81e16243b50a4c73384a86f31fed802Peter Qiu # certificates are programmed in slot 1. So hardcode this slot ID for now. 2713372b17e81e16243b50a4c73384a86f31fed802Peter Qiu SLOT_ID = '1' 2813372b17e81e16243b50a4c73384a86f31fed802Peter Qiu PKCS11_REPLAY_COMMAND = 'p11_replay --slot=%s' % SLOT_ID 29ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart TPM_GROUP = 'chronos-access' 30ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart TPM_USER = 'chaps' 31ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 32ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 33ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def __enter__(self): 34ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.setup() 35ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart return self 36ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 37ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def __exit__(self, exception, value, traceback): 38ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.reset() 39ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 40ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 41ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def _cryptohome_action(self, action): 42ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Set the TPM up for operation in tests.""" 43ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('%s --action=%s' % (self.CRYPTOHOME_COMMAND, action), 44ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart ignore_status=True) 45ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 46ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 47ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def _install_object(self, pem, identifier, conversion_type, output_type): 48ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Convert a PEM object to DER and store it in the TPM. 49ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 50ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param pem string PEM encoded object to be stored. 51ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param identifier string associated with the new object. 52ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param conversion_type the object type to use in PEM to DER conversion. 53ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param output_type the object type to use in inserting into the TPM. 54ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 55ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """ 56037f8dfe77e077aca44226ef9c555094e52973cfKris Rambish if cryptohome.is_tpm_lockout_in_effect(): 57037f8dfe77e077aca44226ef9c555094e52973cfKris Rambish raise error.TestError('The TPM is in dictonary defend mode. ' 58037f8dfe77e077aca44226ef9c555094e52973cfKris Rambish 'The TPMStore may behave in unexpected ' 59037f8dfe77e077aca44226ef9c555094e52973cfKris Rambish 'ways, exiting.') 60ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart pem_file = tempfile.NamedTemporaryFile() 61ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart pem_file.file.write(pem) 62ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart pem_file.file.flush() 63ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart der_file = tempfile.NamedTemporaryFile() 64ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('%s %s -in %s -out %s -inform PEM -outform DER' % 65ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart (self.OPENSSL_COMMAND, conversion_type, pem_file.name, 66ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart der_file.name)) 67ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('%s --import --type=%s --path=%s --id="%s"' % 68ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart (self.PKCS11_REPLAY_COMMAND, output_type, der_file.name, 69ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart identifier)) 70ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 71ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 72ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def setup(self): 73ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Set the TPM up for operation in tests.""" 74ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.reset() 75ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self._directory = tempfile.mkdtemp() 76ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('chown %s:%s %s' % 77ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart (self.TPM_USER, self.TPM_GROUP, self._directory)) 78ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('%s --load --path=%s --auth="%s"' % 79ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart (self.CHAPS_CLIENT_COMMAND, self._directory, self.PIN)) 80ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 81ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 82ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def reset(self): 83ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Reset the crypto store and take ownership of the device.""" 84ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart utils.system('initctl restart chapsd') 85ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self._cryptohome_action(self.CRYPTOHOME_ACTION_TAKE_OWNERSHIP) 86ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self._cryptohome_action(self.CRYPTOHOME_ACTION_WAIT_OWNERSHIP) 87ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 88ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 89ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def install_certificate(self, certificate, identifier): 90ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Install a certificate into the TPM, returning the certificate ID. 91ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 92ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param certificate string PEM x509 contents of the certificate. 93ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param identifier string associated with this certificate in the TPM. 94ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 95ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """ 96ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart return self._install_object(certificate, 97ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart identifier, 98ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.CONVERT_TYPE_X509, 99ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.OUTPUT_TYPE_CERTIFICATE) 100ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 101ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 102ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart def install_private_key(self, key, identifier): 103ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """Install a private key into the TPM, returning the certificate ID. 104ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 105ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param key string PEM RSA private key contents. 106ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart @param identifier string associated with this private key in the TPM. 107ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart 108ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart """ 109ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart return self._install_object(key, 110ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart identifier, 111ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.CONVERT_TYPE_RSA, 112ea00bc8fb56a93ebe34924b94cdea9019db0bf8bPaul Stewart self.OUTPUT_TYPE_PRIVATE_KEY) 113