blob: 38955941705e08432ddd4c567086a26057561f97 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package hwsec
import (
"context"
"encoding/base64"
"strings"
"chromiumos/tast/errors"
"chromiumos/tast/shutil"
)
// cryptohomeBinary is used to interact with the cryptohomed process over
// 'cryptohome' executable. For more details of the arguments of the functions in this file,
// please check //src/platform2/cryptohome/cryptohome.cc.
// The arguments here are documented only when they are not directly
// mapped to the ones in so-mentioned cryptohome.cc.
type cryptohomeBinary struct {
runner CmdRunner
}
// newCryptohomeBinary is a factory function to create a
// cryptohomeBinary instance.
func newCryptohomeBinary(r CmdRunner) *cryptohomeBinary {
return &cryptohomeBinary{r}
}
func (c *cryptohomeBinary) call(ctx context.Context, args ...string) ([]byte, error) {
return c.runner.Run(ctx, "cryptohome", args...)
}
func (c *cryptohomeBinary) tempFile(ctx context.Context, prefix string) (string, error) {
out, err := c.runner.Run(ctx, "mktemp", "/tmp/"+prefix+".XXXXX")
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), err
}
func (c *cryptohomeBinary) readFile(ctx context.Context, filename string) ([]byte, error) {
return c.runner.Run(ctx, "cat", "--", filename)
}
func (c *cryptohomeBinary) writeFile(ctx context.Context, filename string, data []byte) error {
tmpFile, err := c.tempFile(ctx, "tast_cryptohome_write")
if err != nil {
return errors.Wrap(err, "failed to create temp file")
}
defer c.removeFile(ctx, tmpFile)
b64String := base64.StdEncoding.EncodeToString(data)
if _, err := c.runner.Run(ctx, "sh", "-c", "echo "+shutil.Escape(b64String)+">"+tmpFile); err != nil {
return errors.Wrap(err, "failed to echo string")
}
_, err = c.runner.Run(ctx, "sh", "-c", "base64 -d "+tmpFile+">"+filename)
return err
}
func (c *cryptohomeBinary) removeFile(ctx context.Context, filename string) error {
_, err := c.runner.Run(ctx, "rm", "-f", "--", filename)
return err
}
// installAttributesGetStatus calls "cryptohome --action=install_attributes_get_status".
func (c *cryptohomeBinary) installAttributesGetStatus(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_get_status")
return string(out), err
}
// installAttributesGet calls "cryptohome --action=install_attributes_get".
func (c *cryptohomeBinary) installAttributesGet(ctx context.Context, attributeName string) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_get", "--name="+attributeName)
return string(out), err
}
// installAttributesSet calls "cryptohome --action=install_attributes_set".
func (c *cryptohomeBinary) installAttributesSet(ctx context.Context, attributeName, attributeValue string) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_set", "--name="+attributeName, "--value="+attributeValue)
return string(out), err
}
// installAttributesFinalize calls "cryptohome --action=install_attributes_finalize".
func (c *cryptohomeBinary) installAttributesFinalize(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_finalize")
return string(out), err
}
// installAttributesCount calls "cryptohome --action=install_attributes_count".
func (c *cryptohomeBinary) installAttributesCount(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_count")
return string(out), err
}
// installAttributesIsReady calls "cryptohome --action=install_attributes_is_ready".
func (c *cryptohomeBinary) installAttributesIsReady(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_is_ready")
return string(out), err
}
// installAttributesIsSecure calls "cryptohome --action=install_attributes_is_secure".
func (c *cryptohomeBinary) installAttributesIsSecure(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_is_secure")
return string(out), err
}
// installAttributesIsInvalid calls "cryptohome --action=install_attributes_is_invalid".
func (c *cryptohomeBinary) installAttributesIsInvalid(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_is_invalid")
return string(out), err
}
// installAttributesIsFirstInstall calls "cryptohome --action=install_attributes_is_first_install".
func (c *cryptohomeBinary) installAttributesIsFirstInstall(ctx context.Context) (string, error) {
out, err := c.call(ctx, "--action=install_attributes_is_first_install")
return string(out), err
}
// isMounted calls "cryptohome --action=is_mounted".
func (c *cryptohomeBinary) isMounted(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=is_mounted")
}
// mountEx calls "cryptohome --action=mount_ex" .
func (c *cryptohomeBinary) mountEx(ctx context.Context, username string, doesCreate bool, label string, extraFlags []string) ([]byte, error) {
args := []string{"--action=mount_ex", "--user=" + username, "--key_label=" + label}
if doesCreate {
args = append(args, "--create")
}
args = append(args, extraFlags...)
return c.call(ctx, args...)
}
// mountGuestEx calls "cryptohome --action=mount_guest_ex".
func (c *cryptohomeBinary) mountGuestEx(ctx context.Context) ([]byte, error) {
args := []string{"--action=mount_guest_ex"}
return c.call(ctx, args...)
}
// getSanitizedUsername calls "cryptohome --action=obfuscate_user".
func (c *cryptohomeBinary) getSanitizedUsername(ctx context.Context, username string, useDBus bool) ([]byte, error) {
args := []string{"--action=obfuscate_user", "--user=" + username}
if useDBus {
args = append(args, "--use_dbus")
}
return c.call(ctx, args...)
}
// getSystemSalt calls "cryptohome --action=get_system_salt".
func (c *cryptohomeBinary) getSystemSalt(ctx context.Context, useDBus bool) ([]byte, error) {
args := []string{"--action=get_system_salt"}
if useDBus {
args = append(args, "--use_dbus")
}
return c.call(ctx, args...)
}
// checkKeyEx calls "cryptohome --action=check_key_ex".
func (c *cryptohomeBinary) checkKeyEx(ctx context.Context, username, label string, unlockWebAuthnSecret bool, extraFlags []string) ([]byte, error) {
args := []string{"--action=check_key_ex", "--user=" + username, "--key_label=" + label}
if unlockWebAuthnSecret {
args = append(args, "--unlock_webauthn_secret=true")
}
args = append(args, extraFlags...)
return c.call(ctx, args...)
}
// listKeysEx calls "cryptohome --action=list_keys_ex".
func (c *cryptohomeBinary) listKeysEx(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=list_keys_ex", "--user="+username)
}
// addKeyEx calls "cryptohome --action=add_key_ex".
func (c *cryptohomeBinary) addKeyEx(ctx context.Context, username, password, label, newPassword, newLabel string, lowEntropy bool) ([]byte, error) {
args := []string{"--action=add_key_ex", "--user=" + username, "--password=" + password, "--key_label=" + label, "--new_password=" + newPassword, "--new_key_label=" + newLabel}
if lowEntropy {
args = append(args, "--key_policy=le")
}
return c.call(ctx, args...)
}
// removeKeyEx calls "cryptohome --action=remove_key_ex".
func (c *cryptohomeBinary) removeKeyEx(ctx context.Context, username, password, removeLabel string) ([]byte, error) {
return c.call(ctx, "--action=remove_key_ex", "--user="+username, "--password="+password, "--remove_key_label="+removeLabel)
}
// migrateKeyEx calls "cryptohome --action=migrate_key_ex".
func (c *cryptohomeBinary) migrateKeyEx(ctx context.Context, username, password, label, newPassword string) ([]byte, error) {
return c.call(ctx, "--action=migrate_key_ex", "--user="+username, "--old_password="+password, "--key_label="+label, "--password="+newPassword)
}
// remove calls "cryptohome --action=remove".
func (c *cryptohomeBinary) remove(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=remove", "--user="+username, "--force")
}
// unmount calls "cryptohome --action=unmount".
func (c *cryptohomeBinary) unmount(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=unmount", "--user="+username)
}
// unmountAll calls "cryptohome --action=unmount", but without the username.
func (c *cryptohomeBinary) unmountAll(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=unmount")
}
// lockToSingleUserMountUntilReboot calls "cryptohome --action=lock_to_single_user_mount_until_reboot"
func (c *cryptohomeBinary) lockToSingleUserMountUntilReboot(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=lock_to_single_user_mount_until_reboot", "--user="+username)
}
// dumpKeyset calls "cryptohome --action=dump_keyset".
func (c *cryptohomeBinary) dumpKeyset(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=dump_keyset", "--user="+username)
}
// pkcs11SystemTokenInfo calls "cryptohome --action=pkcs11_get_system_token_info".
func (c *cryptohomeBinary) pkcs11SystemTokenInfo(ctx context.Context) ([]byte, error) {
out, err := c.call(ctx, "--action=pkcs11_get_system_token_info")
return out, err
}
// pkcs11UserTokenInfo calls "cryptohome --action=pkcs11_get_user_token_info". (and gets the user token status)
func (c *cryptohomeBinary) pkcs11UserTokenInfo(ctx context.Context, username string) ([]byte, error) {
out, err := c.call(ctx, "--action=pkcs11_get_user_token_info", "--user="+username)
return out, err
}
// pkcs11Terminate calls "cryptohome --action=pkcs11_terminate"
func (c *cryptohomeBinary) pkcs11Terminate(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=pkcs11_terminate", "--user="+username)
}
// getFirmwareManagementParameters calls "cryptohome --action=get_firmware_management_parameters".
func (c *cryptohomeBinary) getFirmwareManagementParameters(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=get_firmware_management_parameters")
}
// setFirmwareManagementParameters calls "cryptohome --action=set_firmware_management_parameters".
func (c *cryptohomeBinary) setFirmwareManagementParameters(ctx context.Context, flags, hash string) ([]byte, error) {
return c.call(ctx, "--action=set_firmware_management_parameters", "--flags="+flags, "--developer_key_hash="+hash)
}
// removeFirmwareManagementParameters calls "cryptohome --action=remove_firmware_management_parameters".
func (c *cryptohomeBinary) removeFirmwareManagementParameters(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=remove_firmware_management_parameters")
}
// getAccountDiskUsage calls "cryptohome --action=get_account_disk_usage".
func (c *cryptohomeBinary) getAccountDiskUsage(ctx context.Context, username string) ([]byte, error) {
return c.call(ctx, "--action=get_account_disk_usage", "--user="+username)
}
// getSupportedKeyPolicies calls "cryptohome --action=get_supported_key_policies".
func (c *cryptohomeBinary) getSupportedKeyPolicies(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=get_supported_key_policies")
}
// getKeyData calls "cryptohome --action=get_key_data_ex".
func (c *cryptohomeBinary) getKeyData(ctx context.Context, username, keyLabel string) ([]byte, error) {
return c.call(ctx, "--action=get_key_data_ex", "--user="+username, "--key_label="+keyLabel)
}
// startAuthSession calls "cryptohome --action=start_auth_session".
func (c *cryptohomeBinary) startAuthSession(ctx context.Context, username string, isEphemeral bool) ([]byte, error) {
args := []string{"--action=start_auth_session", "--user=" + username}
if isEphemeral {
args = append(args, "--ensure_ephemeral")
}
return c.call(ctx, args...)
}
// authenticateAuthSession calls "cryptohome --action=authenticate_auth_session".
// password is ignored if publicMount is set to true.
func (c *cryptohomeBinary) authenticateAuthSession(ctx context.Context, password, authSessionID string, publicMount bool) ([]byte, error) {
args := []string{"--action=authenticate_auth_session", "--auth_session_id=" + authSessionID}
if publicMount {
args = append(args, "--public_mount", "--key_label=public_mount")
} else {
args = append(args, "--password="+password, "--key_label=fake_label")
}
return c.call(ctx, args...)
}
// authenticateAuthFactor calls "cryptohome --action=authenticate_auth_factor".
func (c *cryptohomeBinary) authenticateAuthFactor(ctx context.Context, authSessionID, label, password string) ([]byte, error) {
args := []string{"--action=authenticate_auth_factor", "--auth_session_id=" + authSessionID, "--key_label=" + label, "--password=" + password}
return c.call(ctx, args...)
}
// authenticatePinAuthFactor calls "cryptohome --action=authenticate_auth_factor --pin=<pin>".
func (c *cryptohomeBinary) authenticatePinAuthFactor(ctx context.Context, authSessionID, label, pin string) ([]byte, error) {
args := []string{"--action=authenticate_auth_factor", "--auth_session_id=" + authSessionID, "--key_label=" + label, "--pin=" + pin}
return c.call(ctx, args...)
}
// updateCredentialWithAuthSession calls "cryptohome --action=update_credential".
// password is ignored if publicMount is set to true.
func (c *cryptohomeBinary) updateCredentialWithAuthSession(ctx context.Context, password, authSessionID string, publicMount bool) ([]byte, error) {
args := []string{"--action=update_credential", "--auth_session_id=" + authSessionID}
if publicMount {
args = append(args, "--public_mount", "--key_label=public_mount")
} else {
args = append(args, "--password="+password, "--key_label=fake_label")
}
return c.call(ctx, args...)
}
// addCredentialsWithAuthSession calls "cryptohome --action=add_credentials".
// password is ignored if publicMount is set to true.
func (c *cryptohomeBinary) addCredentialsWithAuthSession(ctx context.Context, user, password, authSessionID string, publicMount bool) ([]byte, error) {
args := []string{"--action=add_credentials", "--auth_session_id=" + authSessionID}
if publicMount {
args = append(args, "--public_mount", "--key_label=public_mount")
} else {
args = append(args, "--password="+password, "--key_label=fake_label")
}
return c.call(ctx, args...)
}
// addAuthFactor calls "cryptohome --action=add_auth_factor".
func (c *cryptohomeBinary) addAuthFactor(ctx context.Context, authSessionID, label, password string) ([]byte, error) {
args := []string{"--action=add_auth_factor", "--auth_session_id=" + authSessionID, "--key_label=" + label, "--password=" + password}
return c.call(ctx, args...)
}
// addPinAuthFactor calls "cryptohome --action=add_auth_factor --pin=<pin>".
func (c *cryptohomeBinary) addPinAuthFactor(ctx context.Context, authSessionID, label, pin string) ([]byte, error) {
args := []string{"--action=add_auth_factor", "--auth_session_id=" + authSessionID, "--key_label=" + label, "--pin=" + pin}
return c.call(ctx, args...)
}
// prepareGuestVault calls "cryptohome --action=prepare_guest_vault"
func (c *cryptohomeBinary) prepareGuestVault(ctx context.Context) ([]byte, error) {
return c.call(ctx, "--action=prepare_guest_vault")
}
// prepareEphemeralVault calls "cryptohome --action=prepare_ephemeral_vault" with "--auth_session_id".
func (c *cryptohomeBinary) prepareEphemeralVault(ctx context.Context, authSessionID string) ([]byte, error) {
return c.call(ctx, "--action=prepare_ephemeral_vault", "--auth_session_id="+authSessionID)
}
// preparePersistentVault calls "cryptohome --action=prepare_persistent_vault" with "--auth_session_id"
// and optionally "--ecryptfs".
func (c *cryptohomeBinary) preparePersistentVault(ctx context.Context, authSessionID string, ecryptfs bool) ([]byte, error) {
args := []string{"--action=prepare_persistent_vault", "--auth_session_id=" + authSessionID}
if ecryptfs {
args = append(args, "--ecryptfs")
}
return c.call(ctx, args...)
}
// prepareVaultForMigration calls "cryptohome --action=prepare_vault_for_migration" with "--auth_session_id"
func (c *cryptohomeBinary) prepareVaultForMigration(ctx context.Context, authSessionID string) ([]byte, error) {
return c.call(ctx, "--action=prepare_vault_for_migration", "--auth_session_id="+authSessionID)
}
// createPersistentUser calls "cryptohome --action=create_persistent_user" with "--auth_session_id"
func (c *cryptohomeBinary) createPersistentUser(ctx context.Context, authSessionID string) ([]byte, error) {
return c.call(ctx, "--action=create_persistent_user", "--auth_session_id="+authSessionID)
}
// mountWithAuthSession calls "cryptohome --action=mount_ex" with "--auth_session_id".
// password is ignored if publicMount is set to true.
func (c *cryptohomeBinary) mountWithAuthSession(ctx context.Context, authSessionID string, publicMount bool) ([]byte, error) {
args := []string{"--action=mount_ex", "--auth_session_id=" + authSessionID}
if publicMount {
args = append(args, "--public_mount")
}
return c.call(ctx, args...)
}
// invalidateAuthSession calls "cryptohome --action=invalidate_auth_session".
// password is ignored if publicMount is set to true.
func (c *cryptohomeBinary) invalidateAuthSession(ctx context.Context, authSessionID string) ([]byte, error) {
args := []string{"--action=invalidate_auth_session", "--auth_session_id=" + authSessionID}
return c.call(ctx, args...)
}