[libcamera-devel] [PATCH v1 2/2] apps: Add ipa-verify application
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue May 9 02:41:42 CEST 2023
Quoting Laurent Pinchart via libcamera-devel (2023-05-06 12:10:25)
> When packaging libcamera, distributions may break IPA module signatures
> if the packaging process strips binaries. This can be fixed by resigning
> the modules, but the process is error-prone.
>
> Add a command line ipa-verify utility that tests the signature on an IPA
> module to help packagers. The tool takes a single argument, the path to
> an IPA module shared object, and expects the signature file (.sign) to
> be in the same directory.
>
> In order to access the public key needed for signature verification, add
> a static function to the IPAManager class. As the class is internal to
> libcamera, this doesn't affect the public API.
But requires this tool to be built with access to the private internal
APIs... I think that's ok in our build though, and this is a very
specific tool ... and certainly would warrant this being a 'utility'
rather than an 'app' indeed.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> include/libcamera/internal/ipa_manager.h | 7 +++
> src/apps/ipa-verify/main.cpp | 64 ++++++++++++++++++++++++
> src/apps/ipa-verify/meson.build | 15 ++++++
> src/apps/meson.build | 2 +
> src/libcamera/ipa_manager.cpp | 13 +++++
> 5 files changed, 101 insertions(+)
> create mode 100644 src/apps/ipa-verify/main.cpp
> create mode 100644 src/apps/ipa-verify/meson.build
>
> diff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h
> index 7f36e58e8bfa..bf823563c91c 100644
> --- a/include/libcamera/internal/ipa_manager.h
> +++ b/include/libcamera/internal/ipa_manager.h
> @@ -47,6 +47,13 @@ public:
> return proxy;
> }
>
> +#if HAVE_IPA_PUBKEY
> + static const PubKey &pubKey()
> + {
> + return pubKey_;
> + }
> +#endif
> +
> private:
> static IPAManager *self_;
>
> diff --git a/src/apps/ipa-verify/main.cpp b/src/apps/ipa-verify/main.cpp
> new file mode 100644
> index 000000000000..76ba5073d25a
> --- /dev/null
> +++ b/src/apps/ipa-verify/main.cpp
> @@ -0,0 +1,64 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2023, Ideas on Board Oy
> + *
> + * ipa_verify.cpp - Verify signature on an IPA module
> + */
> +
> +#include <iostream>
> +#include <libgen.h>
> +
> +#include <libcamera/base/file.h>
> +#include <libcamera/base/span.h>
> +
> +#include "libcamera/internal/ipa_manager.h"
> +#include "libcamera/internal/ipa_module.h"
> +
> +using namespace libcamera;
> +
> +namespace {
> +
> +bool isSignatureValid(IPAModule *ipa)
> +{
> + File file{ ipa->path() };
> + if (!file.open(File::OpenModeFlag::ReadOnly))
> + return false;
> +
> + Span<uint8_t> data = file.map();
> + if (data.empty())
> + return false;
> +
> + return IPAManager::pubKey().verify(data, ipa->signature());
What happens if HAVE_IPA_PUBKEY is not defined?
Admitedly - there won't be much to check - but will this build? break?
report failure?
I think I'd expect the tool to still exist but report something on the
output.
Anyway, I'm actually very pleased to see such a tool. I'd carved up a
script to do the same but that relies on having the build tree, while
this could actually be installed to a target and validate a full install
when needed. Much nicer.
> +}
> +
> +void usage(char *argv0)
> +{
> + std::cout << "Usage: " << basename(argv0) << " ipa_name.so" << std::endl;
> + std::cout << std::endl;
> + std::cout << "Verify the signature of an IPA module. The signature file ipa_name.so.sign is" << std::endl;
> + std::cout << "expected to be in the same directory as the IPA module." << std::endl;
> +}
> +
> +} /* namespace */
> +
> +int main(int argc, char **argv)
> +{
> + if (argc != 2) {
> + usage(argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + IPAModule module{ argv[1] };
> + if (!module.isValid()) {
> + std::cout << "Invalid IPA module " << argv[1] << std::endl;
> + return EXIT_FAILURE;
> + }
> +
> + if (!isSignatureValid(&module)) {
> + std::cout << "IPA module signature is invalid" << std::endl;
> + return EXIT_FAILURE;
> + }
> +
> + std::cout << "IPA module signature is valid" << std::endl;
> + return 0;
> +}
> diff --git a/src/apps/ipa-verify/meson.build b/src/apps/ipa-verify/meson.build
> new file mode 100644
> index 000000000000..7fdda3b9af4b
> --- /dev/null
> +++ b/src/apps/ipa-verify/meson.build
> @@ -0,0 +1,15 @@
> +# SPDX-License-Identifier: CC0-1.0
> +
> +if not ipa_sign_module
> + subdir_done()
> +endif
> +
> +ipa_verify_sources = files([
> + 'main.cpp',
> +])
> +
> +ipa_verify = executable('ipa_verify', ipa_verify_sources,
> + dependencies : [
> + libcamera_private,
> + ],
> + install : false)
> diff --git a/src/apps/meson.build b/src/apps/meson.build
> index 099876356bd1..af632b9a7b0b 100644
> --- a/src/apps/meson.build
> +++ b/src/apps/meson.build
> @@ -18,3 +18,5 @@ subdir('lc-compliance')
>
> subdir('cam')
> subdir('qcam')
> +
> +subdir('ipa-verify')
> diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp
> index 030ef43fb994..6d18d09b019c 100644
> --- a/src/libcamera/ipa_manager.cpp
> +++ b/src/libcamera/ipa_manager.cpp
> @@ -279,6 +279,19 @@ IPAModule *IPAManager::module(PipelineHandler *pipe, uint32_t minVersion,
> * found or if the IPA proxy fails to initialize
> */
>
> +#if HAVE_IPA_PUBKEY
> +/**
> + * \fn IPAManager::pubKey()
> + * \brief Retrieve the IPA module signing public key
> + *
> + * IPA module signature verification is normally handled internally by the
> + * IPAManager class. This function is meant to be used by utilities that need to
> + * verify signatures externally.
> + *
> + * \return The IPA module signing public key
> + */
> +#endif
> +
> bool IPAManager::isSignatureValid([[maybe_unused]] IPAModule *ipa) const
> {
> #if HAVE_IPA_PUBKEY
> --
> Regards,
>
> Laurent Pinchart
>
More information about the libcamera-devel
mailing list