From patchwork Sat May 6 11:10:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 18608 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9F62DC0DA4 for ; Sat, 6 May 2023 11:10:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FF7E633B6; Sat, 6 May 2023 13:10:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1683371426; bh=9Sj3uq4t8/OCeIITS4eByka7FgoQBqN0P+ieilYVgYk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=LtGGJq9AfSI05TrixkkK+4+I9Q2AAk3pZw5UuyYhq0GmsZOppW5R0ZS2pD0I0Ef+Q 9b9M9REp/flgbndcIplmEOwkPAzmjECWOzCjkTpNVcqSJgCThRbKtHi9EDqHR8J1NL Lw00i8Vt9lnDShZG5heJoFp0KgQYhRzlyjkq2tPv4hRGrP3ZM1TBaBhxI93+QHRL2H qxgtGhHHGjteuBpT1oBf6/gtdfdrn20L201Jy47gRVOyZH5zna2qFbPHO0NDAVxFof syCU+QcIuWdJH7cTaZV5X53Ti0l+nTvoUqSq91z+rMWget1bLFyTnMwaoKp8dl2vSY sGMvs9ncCpa7g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8A5FE633B7 for ; Sat, 6 May 2023 13:10:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="RDRJs5ID"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (133-32-181-51.west.xps.vectant.ne.jp [133.32.181.51]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 31CE7800; Sat, 6 May 2023 13:10:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1683371420; bh=9Sj3uq4t8/OCeIITS4eByka7FgoQBqN0P+ieilYVgYk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RDRJs5IDE7KYrKjJ/LoO8kppXLECoYkofnQr21rqz6QUhhVjwiM9Cyir6Xrjt9kBD gyMGvHg6Vry3xX2yJxvcC6yIlJVNks4+rZxspre0q6UHd8S0ZVUS1g0wKu6TGKAhZw 5hSk+5ljWONU3P9e8+8U0F/J4J7MFZ+sUZnr5ydM= To: libcamera-devel@lists.libcamera.org Date: Sat, 6 May 2023 14:10:25 +0300 Message-Id: <20230506111025.18669-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20230506111025.18669-1-laurent.pinchart@ideasonboard.com> References: <20230506111025.18669-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 2/2] apps: Add ipa-verify application X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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. Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain --- 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 +#include + +#include +#include + +#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 data = file.map(); + if (data.empty()) + return false; + + return IPAManager::pubKey().verify(data, ipa->signature()); +} + +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