summaryrefslogtreecommitdiff
path: root/test/py/tests/test_efi_secboot/conftest.py
blob: 5d99b8b7189eddcb531bdcc9fa80445ee31d0443 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# SPDX-License-Identifier:      GPL-2.0+
# Copyright (c) 2019, Linaro Limited
# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>

import os
import os.path
import pytest
import re
from subprocess import call, check_call, check_output, CalledProcessError
from defs import *

# from test/py/conftest.py
def tool_is_in_path(tool):
    for path in os.environ["PATH"].split(os.pathsep):
        fn = os.path.join(path, tool)
        if os.path.isfile(fn) and os.access(fn, os.X_OK):
            return True
    return False

#
# Fixture for UEFI secure boot test
#
@pytest.fixture(scope='session')
def efi_boot_env(request, u_boot_config):
    """Set up a file system to be used in UEFI secure boot test.

    Args:
        request: Pytest request object.
	u_boot_config: U-boot configuration.

    Return:
        A path to disk image to be used for testing
    """
    global HELLO_PATH

    image_path = u_boot_config.persistent_data_dir
    image_path = image_path + '/' + EFI_SECBOOT_IMAGE_NAME
    image_size = EFI_SECBOOT_IMAGE_SIZE
    part_size = EFI_SECBOOT_PART_SIZE
    fs_type = EFI_SECBOOT_FS_TYPE

    if HELLO_PATH == '':
        HELLO_PATH = u_boot_config.build_dir + '/lib/efi_loader/helloworld.efi'

    try:
        mnt_point = u_boot_config.persistent_data_dir + '/mnt_efisecure'
        check_call('mkdir -p {}'.format(mnt_point), shell=True)

        # create a disk/partition
        check_call('dd if=/dev/zero of=%s bs=1MiB count=%d'
                            % (image_path, image_size), shell=True)
        check_call('sgdisk %s -n 1:0:+%dMiB'
                            % (image_path, part_size), shell=True)
        # create a file system
        check_call('dd if=/dev/zero of=%s.tmp bs=1MiB count=%d'
                            % (image_path, part_size), shell=True)
        check_call('mkfs -t %s %s.tmp' % (fs_type, image_path), shell=True)
        check_call('dd if=%s.tmp of=%s bs=1MiB seek=1 count=%d conv=notrunc'
                            % (image_path, image_path, 1), shell=True)
        check_call('rm %s.tmp' % image_path, shell=True)
        loop_dev = check_output('sudo losetup -o 1MiB --sizelimit %dMiB --show -f %s | tr -d "\n"'
                                % (part_size, image_path), shell=True).decode()
        check_output('sudo mount -t %s -o umask=000 %s %s'
                                % (fs_type, loop_dev, mnt_point), shell=True)

        # suffix
        # *.key: RSA private key in PEM
        # *.crt: X509 certificate (self-signed) in PEM
        # *.esl: signature list
        # *.hash: message digest of image as signature list
        # *.auth: signed signature list in signature database format
        # *.efi: UEFI image
        # *.efi.signed: signed UEFI image

        # Create signature database
        ## PK
        check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365'
                            % mnt_point, shell=True)
        check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth'
                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                            shell=True)
        ## PK_null for deletion
        check_call('cd %s; sleep 2; touch PK_null.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK_null.esl PK_null.auth'
                            % (mnt_point, EFITOOLS_PATH), shell=True)
        ## KEK
        check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout KEK.key -out KEK.crt -nodes -days 365'
                            % mnt_point, shell=True)
        check_call('cd %s; %scert-to-efi-sig-list -g %s KEK.crt KEK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth'
                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                            shell=True)
        ## db
        check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ -keyout db.key -out db.crt -nodes -days 365'
                            % mnt_point, shell=True)
        check_call('cd %s; %scert-to-efi-sig-list -g %s db.crt db.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth'
                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                            shell=True)
        ## db1
        check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db1/ -keyout db1.key -out db1.crt -nodes -days 365'
                            % mnt_point, shell=True)
        check_call('cd %s; %scert-to-efi-sig-list -g %s db1.crt db1.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db1.esl db1.auth'
                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                            shell=True)
        ## db1-update
        check_call('cd %s; %ssign-efi-sig-list -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth'
                            % (mnt_point, EFITOOLS_PATH), shell=True)
        ## dbx
        check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_dbx/ -keyout dbx.key -out dbx.crt -nodes -days 365'
                            % mnt_point, shell=True)
        check_call('cd %s; %scert-to-efi-sig-list -g %s dbx.crt dbx.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx.esl dbx.auth'
                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                            shell=True)

        # Copy image
        check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True)

        ## Sign image
        check_call('cd %s; sbsign --key db.key --cert db.crt helloworld.efi'
                            % mnt_point, shell=True)
        ## Digest image
        check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth'
                            % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
                            shell=True)

        check_call('sudo umount %s' % loop_dev, shell=True)
        check_call('sudo losetup -d %s' % loop_dev, shell=True)

    except CalledProcessError as e:
        pytest.skip('Setup failed: %s' % e.cmd)
        return
    else:
        yield image_path
    finally:
        call('rm -f %s' % image_path, shell=True)