Ejemplo n.º 1
0
    def _test_encrypt_decrypt(self, input_plaintext, expected_ciphertext, key_path, offset, flash_crypt_conf=0xf, aes_xts=None):

        original_plaintext = self._open(input_plaintext)
        keyfile = self._open(key_path)
        ciphertext = io.BytesIO()

        args = self.EncryptArgs(keyfile,
                                ciphertext,
                                offset,
                                flash_crypt_conf,
                                aes_xts,
                                original_plaintext)
        espsecure.encrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertNotEqual(original_plaintext.read(), ciphertext.getvalue())
        with self._open(expected_ciphertext) as f:
            self.assertEqual(f.read(), ciphertext.getvalue())

        ciphertext.seek(0)
        keyfile.seek(0)
        plaintext = io.BytesIO()
        args = self.DecryptArgs(keyfile,
                                plaintext,
                                offset,
                                flash_crypt_conf,
                                aes_xts,
                                ciphertext)
        espsecure.decrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertEqual(original_plaintext.read(), plaintext.getvalue())
Ejemplo n.º 2
0
def test_examples_security_flash_encryption(env, extra_data):
    dut = env.get_dut('flash_encryption',
                      'examples/security/flash_encryption',
                      dut_class=ttfw_idf.ESP32DUT)
    # start test
    dut.start_app()

    # calculate the expected ciphertext
    flash_addr = dut.app.partition_table["storage"]["offset"]
    plain_hex_str = '00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f'
    plain_data = binascii.unhexlify(plain_hex_str.replace(' ', ''))

    # Emulate espsecure encrypt_flash_data command
    EncryptFlashDataArgs = namedtuple(
        'EncryptFlashDataArgs',
        ['output', 'plaintext_file', 'address', 'keyfile', 'flash_crypt_conf'])
    args = EncryptFlashDataArgs(BytesIO(), BytesIO(plain_data), flash_addr,
                                BytesIO(b'\x00' * 32), 0xF)
    espsecure.encrypt_flash_data(args)

    expected_ciphertext = args.output.getvalue()
    hex_ciphertext = binascii.hexlify(expected_ciphertext).decode('ascii')
    expected_str = (' '.join(hex_ciphertext[i:i + 2]
                             for i in range(0, 16, 2)) + '  ' +
                    ' '.join(hex_ciphertext[i:i + 2]
                             for i in range(16, 32, 2)))

    lines = [
        'FLASH_CRYPT_CNT eFuse value is 1',
        'Flash encryption feature is enabled in DEVELOPMENT mode',
        'with esp_partition_write', plain_hex_str, 'with esp_partition_read',
        plain_hex_str, 'with spi_flash_read', expected_str
    ]
    for line in lines:
        dut.expect(line, timeout=2)
    def test_encrypt_decrypt(self):
        EncryptArgs = namedtuple('encrypt_flash_data_args', [
            'keyfile', 'output', 'address', 'flash_crypt_conf',
            'plaintext_file'
        ])

        DecryptArgs = namedtuple('decrypt_flash_data_args', [
            'keyfile', 'output', 'address', 'flash_crypt_conf',
            'encrypted_file'
        ])

        original_plaintext = self._open('bootloader.bin')
        keyfile = self._open('256bit_key.bin')
        ciphertext = io.BytesIO()

        args = EncryptArgs(keyfile, ciphertext, 0x1000, 0xFF,
                           original_plaintext)
        espsecure.encrypt_flash_data(args)

        self.assertNotEqual(original_plaintext, ciphertext.getvalue())
        # use compressed size as entropy estimate for effectiveness
        compressed_cipher = zlib.compress(ciphertext.getvalue())
        self.assertGreaterEqual(len(compressed_cipher),
                                len(ciphertext.getvalue()))

        ciphertext.seek(0)
        keyfile.seek(0)
        plaintext = io.BytesIO()
        args = DecryptArgs(keyfile, plaintext, 0x1000, 0xFF, ciphertext)
        espsecure.decrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertEqual(original_plaintext.read(), plaintext.getvalue())
Ejemplo n.º 4
0
    def test_padding(self):
        # Random 2048 bits hex string
        plaintext = binascii.unhexlify("c33b7c49f12a969a9bb45af5f660b73f"
                                       "3b372685012da570df1cf99d1a82eabb"
                                       "fdf6aa16b9675bd8a2f95e871513e175"
                                       "3bc89f57986ecfb2707a3d3b59a46968"
                                       "5e6609d2e9c21d4b2310571175e6e3de"
                                       "2656ee22243f557b925ef39ff782ab56"
                                       "f821e6859ee852000daae7c03a7c77ce"
                                       "58744f15fbdf0ad4ae6e964aedd6316a"
                                       "cf0e36935eef895cd14a60fe682fb971"
                                       "eb239eae38b770bdf969017c9decfd91"
                                       "b7c60329fb0c896684f0e7415f99dec1"
                                       "da0572fac360a3e6d7219973a7de07e5"
                                       "33b5abfdf5917ed5bfe54d660a6f5047"
                                       "32fdb8d07259bfcdc67da87293857c11"
                                       "427b2bae5f00da4a4b2b00b588ff5109"
                                       "4c41f07f02f680f8826841b43da3f25b")

        plaintext_file = io.BytesIO(plaintext)
        ciphertext_full_block = io.BytesIO()

        keyfile = self._open('256bit_key.bin')
        address = 0x1000

        encrypt_args_padded = self.EncryptArgs(keyfile,
                                               ciphertext_full_block,
                                               address,
                                               None,
                                               'aes_xts',
                                               plaintext_file)

        espsecure.encrypt_flash_data(encrypt_args_padded)

        # Test with different number of bytes per encryption call
        # Final ciphertext should still be the same if padding is done correctly
        bytes_per_encrypt = [16, 32, 64, 128]

        for b in bytes_per_encrypt:
            ciphertext = io.BytesIO()
            num_enc_calls = len(plaintext) // b

            for i in range(0, num_enc_calls):
                keyfile.seek(0)
                offset = b * i

                # encrypt the whole plaintext a substring of b bytes at a time
                plaintext_sub = io.BytesIO(plaintext[offset:offset + b])

                encrypt_args = self.EncryptArgs(keyfile,
                                                ciphertext,
                                                address + offset,
                                                None,
                                                'aes_xts',
                                                plaintext_sub)

                espsecure.encrypt_flash_data(encrypt_args)

            self.assertEqual(ciphertext_full_block.getvalue(), ciphertext.getvalue())
Ejemplo n.º 5
0
def test_examples_security_flash_encryption(env, extra_data):
    dut = env.get_dut('flash_encryption', 'examples/security/flash_encryption')

    dut.erase_flash()
    # start test
    dut.start_app()
    # calculate the expected ciphertext
    flash_addr = dut.app.partition_table['storage']['offset']
    plain_hex_str = '00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f'
    plain_data = binascii.unhexlify(plain_hex_str.replace(' ', ''))

    # espsecure uses the cryptography package for encrypting
    # with aes-xts, but does not allow for a symmetric key
    # so the key for later chips are not all zeros
    if dut.TARGET == 'esp32':
        key_bytes = b'\x00' * 32
        aes_xts = False
    else:
        key_bytes = b'\xff' + b'\x00' * 31
        aes_xts = True

    # Emulate espsecure encrypt_flash_data command
    EncryptFlashDataArgs = namedtuple('EncryptFlashDataArgs', [
        'output', 'plaintext_file', 'address', 'keyfile', 'flash_crypt_conf',
        'aes_xts'
    ])
    args = EncryptFlashDataArgs(BytesIO(), BytesIO(plain_data), flash_addr,
                                BytesIO(key_bytes), 0xF, aes_xts)
    espsecure.encrypt_flash_data(args)

    expected_ciphertext = args.output.getvalue()
    hex_ciphertext = binascii.hexlify(expected_ciphertext).decode('ascii')
    expected_str = (' '.join(hex_ciphertext[i:i + 2]
                             for i in range(0, 16, 2)) + '  ' +
                    ' '.join(hex_ciphertext[i:i + 2]
                             for i in range(16, 32, 2)))

    lines = [
        'FLASH_CRYPT_CNT eFuse value is 1',
        'Flash encryption feature is enabled in DEVELOPMENT mode',
        'with esp_partition_write',
        plain_hex_str,
        'with esp_partition_read',
        plain_hex_str,
        'with spi_flash_read',
        expected_str,
        # The status of NVS encryption for the "nvs" partition
        'NVS partition "nvs" is encrypted.'
    ]
    for line in lines:
        dut.expect(line, timeout=2)
Ejemplo n.º 6
0
    def _test_encrypt_decrypt(self, input_plaintext, expected_ciphertext, key_path, offset, flash_crypt_conf=0xf):
        EncryptArgs = namedtuple('encrypt_flash_data_args',
                                 [ 'keyfile',
                                   'output',
                                   'address',
                                   'flash_crypt_conf',
                                   'plaintext_file'
                                 ])

        DecryptArgs = namedtuple('decrypt_flash_data_args',
                                 [ 'keyfile',
                                   'output',
                                   'address',
                                   'flash_crypt_conf',
                                   'encrypted_file'
                                 ])

        original_plaintext = self._open(input_plaintext)
        keyfile = self._open(key_path)
        ciphertext = io.BytesIO()

        args = EncryptArgs(keyfile,
                           ciphertext,
                           offset,
                           flash_crypt_conf,
                           original_plaintext)
        espsecure.encrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertNotEqual(original_plaintext.read(), ciphertext.getvalue())
        with self._open(expected_ciphertext) as f:
            self.assertEqual(f.read(), ciphertext.getvalue())

        ciphertext.seek(0)
        keyfile.seek(0)
        plaintext = io.BytesIO()
        args = DecryptArgs(keyfile,
                           plaintext,
                           offset,
                           flash_crypt_conf,
                           ciphertext)
        espsecure.decrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertEqual(original_plaintext.read(), plaintext.getvalue())
Ejemplo n.º 7
0
    def test_encrypt_decrypt(self):
        EncryptArgs = namedtuple('encrypt_flash_data_args',
                                 [ 'keyfile',
                                   'output',
                                   'address',
                                   'flash_crypt_conf',
                                   'plaintext_file'
                                 ])

        DecryptArgs = namedtuple('decrypt_flash_data_args',
                                 [ 'keyfile',
                                   'output',
                                   'address',
                                   'flash_crypt_conf',
                                   'encrypted_file'
                                 ])

        original_plaintext = self._open('bootloader.bin')
        keyfile = self._open('256bit_key.bin')
        ciphertext = io.BytesIO()

        args = EncryptArgs(keyfile,
                           ciphertext,
                           0x1000,
                           0xFF,
                           original_plaintext)
        espsecure.encrypt_flash_data(args)

        self.assertNotEqual(original_plaintext, ciphertext.getvalue())
        # use compressed size as entropy estimate for effectiveness
        compressed_cipher = zlib.compress(ciphertext.getvalue())
        self.assertGreaterEqual(len(compressed_cipher), len(ciphertext.getvalue()))

        ciphertext.seek(0)
        keyfile.seek(0)
        plaintext = io.BytesIO()
        args = DecryptArgs(keyfile,
                           plaintext,
                           0x1000,
                           0xFF,
                           ciphertext)
        espsecure.decrypt_flash_data(args)

        original_plaintext.seek(0)
        self.assertEqual(original_plaintext.read(), plaintext.getvalue())