From patchwork Mon Aug 8 23:08:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17034 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 0478FC3272 for ; Mon, 8 Aug 2022 23:08:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A7A863332; Tue, 9 Aug 2022 01:08:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1660000129; bh=esSq5v0LGM77PEc6KrP1DoQbZGb2PDMIzBVo+hxUrvc=; 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=kWSElzr9CFzkQgQzTa8Pdm+DjJqXDnudFQxW4k5/lwpXIf6yVO66jcVbKZcs3+QqQ PPmiyavkt3gww0SH7sFsJ0Zd15NVPu6/++I7jZMHVLBc7KZN+feEcOzkVYrJvhojh4 cgmSM7/L1l8aMFtCWTpQWUCA7gFEmgcTcCfnEod05Ie+Y8GFGaDbncoB4r/rd8nb8k AehDCJu1gX/Tec1fTT4r7orfDwctedG0cEmn6To7oXrC8pIt5jksSegTGwCTcizS7e 4pd44g6UI2DVXNVTheH7YvFYMgnUBG5uoVJ3t3DTuosILXa4323qJoDor3tAukEQuS +aSiCC7d0wsxA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0B55A6332A for ; Tue, 9 Aug 2022 01:08:48 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="jr2U574n"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 96C5273E; Tue, 9 Aug 2022 01:08:47 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1660000127; bh=esSq5v0LGM77PEc6KrP1DoQbZGb2PDMIzBVo+hxUrvc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jr2U574nzIuckM0MsWXB/BWjNBIxJlgsZ/1J5BaYGn6BG8yoXlAblvcbHSTVfGNHP 1mRR5cuiGV+/XqkrgVveHb443sCoXX6wqXLdD3ucxBlD3dgt8/ROUJcusxNp2lADQL 1Fvw/gXfZbo+95CPowwCewguAX/V+a4/ee/DsKBU= To: libcamera-devel@lists.libcamera.org Date: Tue, 9 Aug 2022 02:08:32 +0300 Message-Id: <20220808230833.16275-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220808230833.16275-1-laurent.pinchart@ideasonboard.com> References: <20220808230833.16275-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/4] libcamera: pub_key: Support openssl as an alternative to gnutls 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" Support verify IPA signatures with openssl as an alternative to gnutls, to offer more flexibility in the selection of dependencies. Use gnutls by default, for no specific reason as both are equally well supported. Signed-off-by: Laurent Pinchart Reviewed-by: Eric Curtin Reviewed-by: Kieran Bingham --- Changes since v1: - Don't use functions deprecated in OpenSSL 3.0 --- README.rst | 2 +- include/libcamera/internal/pub_key.h | 8 +++-- src/libcamera/meson.build | 10 ++++-- src/libcamera/pub_key.cpp | 47 +++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 77374c6a72b1..3bf4685b0e15 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ for the libcamera core: [required] libyaml-dev python3-yaml python3-ply python3-jinja2 for IPA module signing: [required] - libgnutls28-dev openssl + Either libgnutls28-dev or libssl-dev, openssl for improved debugging: [optional] libdw-dev libunwind-dev diff --git a/include/libcamera/internal/pub_key.h b/include/libcamera/internal/pub_key.h index a22ba037cff6..8653a912b2d5 100644 --- a/include/libcamera/internal/pub_key.h +++ b/include/libcamera/internal/pub_key.h @@ -11,7 +11,9 @@ #include -#if HAVE_GNUTLS +#if HAVE_CRYPTO +struct evp_pkey_st; +#elif HAVE_GNUTLS struct gnutls_pubkey_st; #endif @@ -28,7 +30,9 @@ public: private: bool valid_; -#if HAVE_GNUTLS +#if HAVE_CRYPTO + struct evp_pkey_st *pubkey_; +#elif HAVE_GNUTLS struct gnutls_pubkey_st *pubkey_; #endif }; diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 7cc06de4aedc..401fc498cfbc 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -65,12 +65,16 @@ subdir('pipeline') subdir('proxy') libdl = cc.find_library('dl') -libgnutls = dependency('gnutls', required : true) libudev = dependency('libudev', required : false) libyaml = dependency('yaml-0.1', required : false) -if libgnutls.found() +# Use one of gnutls or libcrypto (provided by OpenSSL), trying gnutls first. +libcrypto = dependency('gnutls2', required : false) +if libcrypto.found() config_h.set('HAVE_GNUTLS', 1) +else + libcrypto = dependency('libcrypto', required : true) + config_h.set('HAVE_CRYPTO', 1) endif if liblttng.found() @@ -135,8 +139,8 @@ libcamera_deps = [ libatomic, libcamera_base, libcamera_base_private, + libcrypto, libdl, - libgnutls, liblttng, libudev, libyaml, diff --git a/src/libcamera/pub_key.cpp b/src/libcamera/pub_key.cpp index b2045a103bc0..64dfa23497c2 100644 --- a/src/libcamera/pub_key.cpp +++ b/src/libcamera/pub_key.cpp @@ -7,7 +7,12 @@ #include "libcamera/internal/pub_key.h" -#if HAVE_GNUTLS +#if HAVE_CRYPTO +#include +#include +#include +#include +#elif HAVE_GNUTLS #include #endif @@ -33,7 +38,14 @@ namespace libcamera { PubKey::PubKey([[maybe_unused]] Span key) : valid_(false) { -#if HAVE_GNUTLS +#if HAVE_CRYPTO + const uint8_t *data = key.data(); + pubkey_ = d2i_PUBKEY(nullptr, &data, key.size()); + if (!pubkey_) + return; + + valid_ = true; +#elif HAVE_GNUTLS int ret = gnutls_pubkey_init(&pubkey_); if (ret < 0) return; @@ -52,7 +64,9 @@ PubKey::PubKey([[maybe_unused]] Span key) PubKey::~PubKey() { -#if HAVE_GNUTLS +#if HAVE_CRYPTO + EVP_PKEY_free(pubkey_); +#elif HAVE_GNUTLS gnutls_pubkey_deinit(pubkey_); #endif } @@ -79,7 +93,32 @@ bool PubKey::verify([[maybe_unused]] Span data, if (!valid_) return false; -#if HAVE_GNUTLS +#if HAVE_CRYPTO + /* + * Create and initialize a public key algorithm context for signature + * verification. + */ + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pubkey_, nullptr); + if (!ctx) + return false; + + if (EVP_PKEY_verify_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || + EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) { + EVP_PKEY_CTX_free(ctx); + return false; + } + + /* Calculate the SHA256 digest of the data. */ + uint8_t digest[SHA256_DIGEST_LENGTH]; + SHA256(data.data(), data.size(), digest); + + /* Decrypt the signature and verify it matches the digest. */ + int ret = EVP_PKEY_verify(ctx, sig.data(), sig.size(), digest, + SHA256_DIGEST_LENGTH); + EVP_PKEY_CTX_free(ctx); + return ret == 1; +#elif HAVE_GNUTLS const gnutls_datum_t gnuTlsData{ const_cast(data.data()), static_cast(data.size())