blob: 0a532fe275e61a079e49f70452d37564384e301d [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2018 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.
""""Unittest ChromeOS image signer logic"""
from __future__ import print_function
from chromite.lib import cros_test_lib
from chromite.signing.lib import keys
from chromite.signing.lib import signer
from chromite.signing.lib import keys_unittest
class MockBaseSigner(signer.BaseSigner):
"""Configurable Signer for testing."""
def __init__(self, required_keys=None,
required_keys_public=None,
required_keys_private=None,
required_keyblocks=None):
"""Create a Signer based on the passed required lists."""
self._required_keys = required_keys or []
self._required_keys_public = required_keys_public or []
self._required_keys_private = required_keys_private or []
self._required_keyblocks = required_keyblocks or []
def Sign(self, keyset, input_name, output_name):
"""Always return True on signing."""
return True
class TestSigner(cros_test_lib.TempDirTestCase):
"""Test Signer."""
def testSign(self):
ks = keys.Keyset()
s = signer.BaseSigner()
with self.assertRaises(NotImplementedError):
s.Sign(ks, 'input', 'output')
def testCheck(self):
ks = keys.Keyset()
s = signer.BaseSigner()
self.assertTrue(s.CheckKeyset(ks))
def testCheckRequiredKeysMissing(self):
ks_empty = keys.Keyset()
s0 = MockBaseSigner(required_keys=['key1'])
self.assertFalse(s0.CheckKeyset(ks_empty))
def testCheckRequiredKeys(self):
s0 = MockBaseSigner(required_keys=['key1'])
ks0 = KeysetFromSigner(s0, self.tempdir)
self.assertTrue(s0.CheckKeyset(ks0))
def testCheckRequiredPublicKeysMissing(self):
ks_empty = keys.Keyset()
s0 = MockBaseSigner(required_keys_public=['key1'])
self.assertFalse(s0.CheckKeyset(ks_empty))
def testCheckRequiredPublicKeys(self):
s0 = MockBaseSigner(required_keys_public=['key1'])
ks0 = KeysetFromSigner(s0, self.tempdir)
self.assertTrue(s0.CheckKeyset(ks0))
def testCheckRequiredPrivateKeysMissing(self):
ks_empty = keys.Keyset()
s0 = MockBaseSigner(required_keys_private=['key1'])
self.assertFalse(s0.CheckKeyset(ks_empty))
def testCheckRequiredPrivateKeys(self):
s0 = MockBaseSigner(required_keys_private=['key1'])
ks0 = KeysetFromSigner(s0, self.tempdir)
self.assertTrue(s0.CheckKeyset(ks0))
def testCheckRequiredKeyblocksEmpty(self):
ks_empty = keys.Keyset()
s0 = MockBaseSigner(required_keyblocks=['keyblock1'])
self.assertFalse(s0.CheckKeyset(ks_empty))
def testCheckRequiredKeyblocks(self):
s0 = MockBaseSigner(required_keyblocks=['keyblock1'])
ks0 = KeysetFromSigner(s0, self.tempdir)
self.assertTrue(s0.CheckKeyset(ks0))
def KeysetFromSigner(s, keydir):
"""Returns a valid keyset containing required keys and keyblocks."""
ks = keys.Keyset()
# pylint: disable=protected-access
for key_name in s._required_keys:
key = keys.KeyPair(key_name, keydir=keydir)
ks.AddKey(key)
keys_unittest.CreateDummyKeys(key)
for key_name in s._required_keys_public:
key = keys.KeyPair(key_name, keydir=keydir)
ks.AddKey(key)
keys_unittest.CreateDummyPublic(key)
for key_name in s._required_keys_private:
key = keys.KeyPair(key_name, keydir=keydir)
ks.AddKey(key)
keys_unittest.CreateDummyPrivateKey(key)
for keyblock_name in s._required_keyblocks:
keyblock = keys.Keyblock(keyblock_name, keydir=keydir)
ks.AddKeyblock(keyblock)
keys_unittest.CreateDummyKeyblock(keyblock)
return ks
class MockFutilitySigner(signer.FutilitySigner):
"""Basic implementation of a FutilitySigner."""
_required_keys = ('foo',)
def GetFutilityArgs(self, keyset, input_name, output_name):
"""Returns a list of [input_name, output_name]."""
return [input_name, output_name]
class TestFutilitySigner(cros_test_lib.RunCommandTestCase,
cros_test_lib.TempDirTestCase):
"""Test Futility Signer."""
def testSign(self):
keyset = keys.Keyset()
fs = signer.FutilitySigner()
self.assertRaises(NotImplementedError, fs.Sign, keyset, 'dummy', 'dummy')
def testSignWithMock(self):
foo_key = keys.KeyPair('foo', self.tempdir)
keys_unittest.CreateDummyKeys(foo_key)
keyset = keys.Keyset()
keyset.AddKey(foo_key)
fsm = MockFutilitySigner()
self.assertTrue(fsm.Sign(keyset, 'foo', 'bar'))
self.assertCommandContains(['foo', 'bar'])
def testSignWithMockMissingKey(self):
keyset = keys.Keyset()
fsm = MockFutilitySigner()
self.assertFalse(fsm.Sign(keyset, 'foo', 'bar'))
def testGetCmdArgs(self):
keyset = keys.Keyset()
fs = signer.FutilitySigner()
self.assertRaises(NotImplementedError,
fs.GetFutilityArgs, keyset, 'foo', 'bar')
class TestFutilityFunction(cros_test_lib.RunCommandTestCase):
"""Test Futility command."""
def testCommand(self):
self.assertTrue(signer.RunFutility([]),
msg='Futility should pass w/ mock')
self.assertCommandContains(['futility'])
def testCommandWithArgs(self):
args = ['--privkey', 'foo.priv2']
signer.RunFutility(args)
self.assertCommandContains(args)