diff mbox series

[v5,09/12] test: py: Setup capsule files for testing

Message ID 20230725085725.350917-10-sughosh.ganu@linaro.org
State New
Headers show
Series Integrate EFI capsule tasks into u-boot's build flow | expand

Commit Message

Sughosh Ganu July 25, 2023, 8:57 a.m. UTC
Support has being added through earlier commits to build capsules and
embed the public key needed for capsule authentication as part of
u-boot build.

From the testing point-of-view, this means the input files needed for
the above have to be setup before invoking the build. Set this up in
the pytest configuration file for testing the capsule update feature.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since V4: None

 test/py/conftest.py | 84 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

Comments

Simon Glass July 25, 2023, 10:52 p.m. UTC | #1
Hi Sughosh,

On Tue, 25 Jul 2023 at 02:58, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> Support has being added through earlier commits to build capsules and
> embed the public key needed for capsule authentication as part of
> u-boot build.
>
> From the testing point-of-view, this means the input files needed for
> the above have to be setup before invoking the build. Set this up in
> the pytest configuration file for testing the capsule update feature.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> Changes since V4: None
>
>  test/py/conftest.py | 84 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 84 insertions(+)
>
> diff --git a/test/py/conftest.py b/test/py/conftest.py
> index fc9dd3a83f..1092cb713b 100644
> --- a/test/py/conftest.py
> +++ b/test/py/conftest.py
> @@ -80,6 +80,86 @@ def pytest_addoption(parser):
>          help='Run sandbox under gdbserver. The argument is the channel '+
>          'over which gdbserver should communicate, e.g. localhost:1234')
>
> +def setup_capsule_build(source_dir, build_dir, board_type, log):
> +    """Setup the platform's build for testing capsule updates
> +
> +    This generates the payload/input files needed for testing the
> +    capsule update functionality, along with the keys for signing
> +    the capsules. An EFI Signature List(ESL) file, which houses the
> +    public key for capsule authentication is generated as
> +    well.
> +
> +    The ESL file is subsequently embedded into the platform's
> +    dtb during the u-boot build, to be used for capsule
> +    authentication.
> +
> +    Two sets of keys are generated, namely SIGNER and SIGNER2.
> +    The SIGNER2 key pair is used as a malicious key for testing the
> +    the capsule authentication functionality.
> +
> +    All the generated files are placed under the /tmp/capsules/
> +    directory.
> +
> +    Args:
> +        soruce_dir (str): Directory containing source code
> +        build_dir (str): Directory to build in
> +        board_type (str): board_type parameter (e.g. 'sandbox')
> +        log (Logfile): Log file to use
> +
> +    Returns:
> +        Nothing.
> +    """
> +    def run_command(name, cmd, source_dir):
> +        with log.section(name):
> +            if isinstance(cmd, str):
> +                cmd = cmd.split()
> +                runner = log.get_runner(name, None)
> +                runner.run(cmd, cwd=source_dir)
> +                runner.close()
> +                log.status_pass('OK')
> +
> +    def gen_capsule_payloads(capsule_dir):
> +        fname = f'{capsule_dir}u-boot.bin.old'
> +        with open(fname, 'w') as fd:
> +            fd.write('u-boot:Old')
> +
> +        fname = f'{capsule_dir}u-boot.bin.new'
> +        with open(fname, 'w') as fd:
> +            fd.write('u-boot:New')
> +
> +        fname = f'{capsule_dir}u-boot.env.old'
> +        with open(fname, 'w') as fd:
> +            fd.write('u-boot-env:Old')
> +
> +        fname = f'{capsule_dir}u-boot.env.new'
> +        with open(fname, 'w') as fd:
> +            fd.write('u-boot-env:New')
> +
> +    capsule_sig_dir = '/tmp/capsules/'
> +    sig_name = 'SIGNER'
> +    mkdir_p(capsule_sig_dir)
> +    name = 'openssl'
> +    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
> +            '-subj /CN=TEST_SIGNER/ -keyout '
> +            f'{capsule_sig_dir}{sig_name}.key '
> +            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
> +    run_command(name, cmd, source_dir)

Can you drop this now that the docker file does it?

> +
> +    name = 'cert-to-efi-sig-list'
> +    cmd = ( f'cert-to-efi-sig-list {capsule_sig_dir}{sig_name}.crt '
> +            f'{capsule_sig_dir}{sig_name}.esl' )
> +    run_command(name, cmd, source_dir)
> +
> +    sig_name = 'SIGNER2'
> +    name = 'openssl'
> +    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
> +            '-subj /CN=TEST_SIGNER/ -keyout '
> +            f'{capsule_sig_dir}{sig_name}.key '
> +            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
> +    run_command(name, cmd, source_dir)
> +
> +    gen_capsule_payloads(capsule_sig_dir)
> +
>  def run_build(config, source_dir, build_dir, board_type, log):
>      """run_build: Build U-Boot
>
> @@ -90,6 +170,10 @@ def run_build(config, source_dir, build_dir, board_type, log):
>          board_type (str): board_type parameter (e.g. 'sandbox')
>          log (Logfile): Log file to use
>      """
> +    capsule_boards = ( 'sandbox', 'sandbox64', 'sandbox_flattree' )
> +    if board_type in capsule_boards:
> +        setup_capsule_build(source_dir, build_dir, board_type, log)
> +
>      if config.getoption('buildman'):
>          if build_dir != source_dir:
>              dest_args = ['-o', build_dir, '-w']
> --
> 2.34.1
>

Regards,
Simon
Sughosh Ganu July 26, 2023, 9 a.m. UTC | #2
hi Simon,

On Wed, 26 Jul 2023 at 04:23, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Tue, 25 Jul 2023 at 02:58, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > Support has being added through earlier commits to build capsules and
> > embed the public key needed for capsule authentication as part of
> > u-boot build.
> >
> > From the testing point-of-view, this means the input files needed for
> > the above have to be setup before invoking the build. Set this up in
> > the pytest configuration file for testing the capsule update feature.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > ---
> > Changes since V4: None
> >
> >  test/py/conftest.py | 84 +++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 84 insertions(+)
> >
> > diff --git a/test/py/conftest.py b/test/py/conftest.py
> > index fc9dd3a83f..1092cb713b 100644
> > --- a/test/py/conftest.py
> > +++ b/test/py/conftest.py
> > @@ -80,6 +80,86 @@ def pytest_addoption(parser):
> >          help='Run sandbox under gdbserver. The argument is the channel '+
> >          'over which gdbserver should communicate, e.g. localhost:1234')
> >
> > +def setup_capsule_build(source_dir, build_dir, board_type, log):
> > +    """Setup the platform's build for testing capsule updates
> > +
> > +    This generates the payload/input files needed for testing the
> > +    capsule update functionality, along with the keys for signing
> > +    the capsules. An EFI Signature List(ESL) file, which houses the
> > +    public key for capsule authentication is generated as
> > +    well.
> > +
> > +    The ESL file is subsequently embedded into the platform's
> > +    dtb during the u-boot build, to be used for capsule
> > +    authentication.
> > +
> > +    Two sets of keys are generated, namely SIGNER and SIGNER2.
> > +    The SIGNER2 key pair is used as a malicious key for testing the
> > +    the capsule authentication functionality.
> > +
> > +    All the generated files are placed under the /tmp/capsules/
> > +    directory.
> > +
> > +    Args:
> > +        soruce_dir (str): Directory containing source code
> > +        build_dir (str): Directory to build in
> > +        board_type (str): board_type parameter (e.g. 'sandbox')
> > +        log (Logfile): Log file to use
> > +
> > +    Returns:
> > +        Nothing.
> > +    """
> > +    def run_command(name, cmd, source_dir):
> > +        with log.section(name):
> > +            if isinstance(cmd, str):
> > +                cmd = cmd.split()
> > +                runner = log.get_runner(name, None)
> > +                runner.run(cmd, cwd=source_dir)
> > +                runner.close()
> > +                log.status_pass('OK')
> > +
> > +    def gen_capsule_payloads(capsule_dir):
> > +        fname = f'{capsule_dir}u-boot.bin.old'
> > +        with open(fname, 'w') as fd:
> > +            fd.write('u-boot:Old')
> > +
> > +        fname = f'{capsule_dir}u-boot.bin.new'
> > +        with open(fname, 'w') as fd:
> > +            fd.write('u-boot:New')
> > +
> > +        fname = f'{capsule_dir}u-boot.env.old'
> > +        with open(fname, 'w') as fd:
> > +            fd.write('u-boot-env:Old')
> > +
> > +        fname = f'{capsule_dir}u-boot.env.new'
> > +        with open(fname, 'w') as fd:
> > +            fd.write('u-boot-env:New')
> > +
> > +    capsule_sig_dir = '/tmp/capsules/'
> > +    sig_name = 'SIGNER'
> > +    mkdir_p(capsule_sig_dir)
> > +    name = 'openssl'
> > +    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
> > +            '-subj /CN=TEST_SIGNER/ -keyout '
> > +            f'{capsule_sig_dir}{sig_name}.key '
> > +            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
> > +    run_command(name, cmd, source_dir)
>
> Can you drop this now that the docker file does it?

This handles the scenario of running the pytest on the host machine.
We can run the tests on our host machine as well, and the capsule
tests need to be supported even for that test scenario. The docker
file will only handle the CI environment.

-sughosh

>
> > +
> > +    name = 'cert-to-efi-sig-list'
> > +    cmd = ( f'cert-to-efi-sig-list {capsule_sig_dir}{sig_name}.crt '
> > +            f'{capsule_sig_dir}{sig_name}.esl' )
> > +    run_command(name, cmd, source_dir)
> > +
> > +    sig_name = 'SIGNER2'
> > +    name = 'openssl'
> > +    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
> > +            '-subj /CN=TEST_SIGNER/ -keyout '
> > +            f'{capsule_sig_dir}{sig_name}.key '
> > +            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
> > +    run_command(name, cmd, source_dir)
> > +
> > +    gen_capsule_payloads(capsule_sig_dir)
> > +
> >  def run_build(config, source_dir, build_dir, board_type, log):
> >      """run_build: Build U-Boot
> >
> > @@ -90,6 +170,10 @@ def run_build(config, source_dir, build_dir, board_type, log):
> >          board_type (str): board_type parameter (e.g. 'sandbox')
> >          log (Logfile): Log file to use
> >      """
> > +    capsule_boards = ( 'sandbox', 'sandbox64', 'sandbox_flattree' )
> > +    if board_type in capsule_boards:
> > +        setup_capsule_build(source_dir, build_dir, board_type, log)
> > +
> >      if config.getoption('buildman'):
> >          if build_dir != source_dir:
> >              dest_args = ['-o', build_dir, '-w']
> > --
> > 2.34.1
> >
>
> Regards,
> Simon
Simon Glass July 26, 2023, 2:26 p.m. UTC | #3
Hi Sughosh,

On Wed, 26 Jul 2023 at 03:00, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Wed, 26 Jul 2023 at 04:23, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Tue, 25 Jul 2023 at 02:58, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > >
> > > Support has being added through earlier commits to build capsules and
> > > embed the public key needed for capsule authentication as part of
> > > u-boot build.
> > >
> > > From the testing point-of-view, this means the input files needed for
> > > the above have to be setup before invoking the build. Set this up in
> > > the pytest configuration file for testing the capsule update feature.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > Reviewed-by: Simon Glass <sjg@chromium.org>
> > > ---
> > > Changes since V4: None
> > >
> > >  test/py/conftest.py | 84 +++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 84 insertions(+)
> > >
> > > diff --git a/test/py/conftest.py b/test/py/conftest.py
> > > index fc9dd3a83f..1092cb713b 100644
> > > --- a/test/py/conftest.py
> > > +++ b/test/py/conftest.py
> > > @@ -80,6 +80,86 @@ def pytest_addoption(parser):
> > >          help='Run sandbox under gdbserver. The argument is the channel '+
> > >          'over which gdbserver should communicate, e.g. localhost:1234')
> > >
> > > +def setup_capsule_build(source_dir, build_dir, board_type, log):
> > > +    """Setup the platform's build for testing capsule updates
> > > +
> > > +    This generates the payload/input files needed for testing the
> > > +    capsule update functionality, along with the keys for signing
> > > +    the capsules. An EFI Signature List(ESL) file, which houses the
> > > +    public key for capsule authentication is generated as
> > > +    well.
> > > +
> > > +    The ESL file is subsequently embedded into the platform's
> > > +    dtb during the u-boot build, to be used for capsule
> > > +    authentication.
> > > +
> > > +    Two sets of keys are generated, namely SIGNER and SIGNER2.
> > > +    The SIGNER2 key pair is used as a malicious key for testing the
> > > +    the capsule authentication functionality.
> > > +
> > > +    All the generated files are placed under the /tmp/capsules/
> > > +    directory.
> > > +
> > > +    Args:
> > > +        soruce_dir (str): Directory containing source code
> > > +        build_dir (str): Directory to build in
> > > +        board_type (str): board_type parameter (e.g. 'sandbox')
> > > +        log (Logfile): Log file to use
> > > +
> > > +    Returns:
> > > +        Nothing.
> > > +    """
> > > +    def run_command(name, cmd, source_dir):
> > > +        with log.section(name):
> > > +            if isinstance(cmd, str):
> > > +                cmd = cmd.split()
> > > +                runner = log.get_runner(name, None)
> > > +                runner.run(cmd, cwd=source_dir)
> > > +                runner.close()
> > > +                log.status_pass('OK')
> > > +
> > > +    def gen_capsule_payloads(capsule_dir):
> > > +        fname = f'{capsule_dir}u-boot.bin.old'
> > > +        with open(fname, 'w') as fd:
> > > +            fd.write('u-boot:Old')
> > > +
> > > +        fname = f'{capsule_dir}u-boot.bin.new'
> > > +        with open(fname, 'w') as fd:
> > > +            fd.write('u-boot:New')
> > > +
> > > +        fname = f'{capsule_dir}u-boot.env.old'
> > > +        with open(fname, 'w') as fd:
> > > +            fd.write('u-boot-env:Old')
> > > +
> > > +        fname = f'{capsule_dir}u-boot.env.new'
> > > +        with open(fname, 'w') as fd:
> > > +            fd.write('u-boot-env:New')
> > > +
> > > +    capsule_sig_dir = '/tmp/capsules/'
> > > +    sig_name = 'SIGNER'
> > > +    mkdir_p(capsule_sig_dir)
> > > +    name = 'openssl'
> > > +    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
> > > +            '-subj /CN=TEST_SIGNER/ -keyout '
> > > +            f'{capsule_sig_dir}{sig_name}.key '
> > > +            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
> > > +    run_command(name, cmd, source_dir)
> >
> > Can you drop this now that the docker file does it?
>
> This handles the scenario of running the pytest on the host machine.
> We can run the tests on our host machine as well, and the capsule
> tests need to be supported even for that test scenario. The docker
> file will only handle the CI environment.

OK I see.

Regards,
Simon
diff mbox series

Patch

diff --git a/test/py/conftest.py b/test/py/conftest.py
index fc9dd3a83f..1092cb713b 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -80,6 +80,86 @@  def pytest_addoption(parser):
         help='Run sandbox under gdbserver. The argument is the channel '+
         'over which gdbserver should communicate, e.g. localhost:1234')
 
+def setup_capsule_build(source_dir, build_dir, board_type, log):
+    """Setup the platform's build for testing capsule updates
+
+    This generates the payload/input files needed for testing the
+    capsule update functionality, along with the keys for signing
+    the capsules. An EFI Signature List(ESL) file, which houses the
+    public key for capsule authentication is generated as
+    well.
+
+    The ESL file is subsequently embedded into the platform's
+    dtb during the u-boot build, to be used for capsule
+    authentication.
+
+    Two sets of keys are generated, namely SIGNER and SIGNER2.
+    The SIGNER2 key pair is used as a malicious key for testing the
+    the capsule authentication functionality.
+
+    All the generated files are placed under the /tmp/capsules/
+    directory.
+
+    Args:
+        soruce_dir (str): Directory containing source code
+        build_dir (str): Directory to build in
+        board_type (str): board_type parameter (e.g. 'sandbox')
+        log (Logfile): Log file to use
+
+    Returns:
+        Nothing.
+    """
+    def run_command(name, cmd, source_dir):
+        with log.section(name):
+            if isinstance(cmd, str):
+                cmd = cmd.split()
+                runner = log.get_runner(name, None)
+                runner.run(cmd, cwd=source_dir)
+                runner.close()
+                log.status_pass('OK')
+
+    def gen_capsule_payloads(capsule_dir):
+        fname = f'{capsule_dir}u-boot.bin.old'
+        with open(fname, 'w') as fd:
+            fd.write('u-boot:Old')
+
+        fname = f'{capsule_dir}u-boot.bin.new'
+        with open(fname, 'w') as fd:
+            fd.write('u-boot:New')
+
+        fname = f'{capsule_dir}u-boot.env.old'
+        with open(fname, 'w') as fd:
+            fd.write('u-boot-env:Old')
+
+        fname = f'{capsule_dir}u-boot.env.new'
+        with open(fname, 'w') as fd:
+            fd.write('u-boot-env:New')
+
+    capsule_sig_dir = '/tmp/capsules/'
+    sig_name = 'SIGNER'
+    mkdir_p(capsule_sig_dir)
+    name = 'openssl'
+    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
+            '-subj /CN=TEST_SIGNER/ -keyout '
+            f'{capsule_sig_dir}{sig_name}.key '
+            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
+    run_command(name, cmd, source_dir)
+
+    name = 'cert-to-efi-sig-list'
+    cmd = ( f'cert-to-efi-sig-list {capsule_sig_dir}{sig_name}.crt '
+            f'{capsule_sig_dir}{sig_name}.esl' )
+    run_command(name, cmd, source_dir)
+
+    sig_name = 'SIGNER2'
+    name = 'openssl'
+    cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
+            '-subj /CN=TEST_SIGNER/ -keyout '
+            f'{capsule_sig_dir}{sig_name}.key '
+            f'-out {capsule_sig_dir}{sig_name}.crt -nodes -days 365' )
+    run_command(name, cmd, source_dir)
+
+    gen_capsule_payloads(capsule_sig_dir)
+
 def run_build(config, source_dir, build_dir, board_type, log):
     """run_build: Build U-Boot
 
@@ -90,6 +170,10 @@  def run_build(config, source_dir, build_dir, board_type, log):
         board_type (str): board_type parameter (e.g. 'sandbox')
         log (Logfile): Log file to use
     """
+    capsule_boards = ( 'sandbox', 'sandbox64', 'sandbox_flattree' )
+    if board_type in capsule_boards:
+        setup_capsule_build(source_dir, build_dir, board_type, log)
+
     if config.getoption('buildman'):
         if build_dir != source_dir:
             dest_args = ['-o', build_dir, '-w']