[libcamera-devel] [PATCH v2 3/4] libcamera: pub_key: Support openssl as an alternative to gnutls

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Aug 9 01:18:23 CEST 2022


On Tue, Aug 09, 2022 at 02:08:32AM +0300, Laurent Pinchart via libcamera-devel wrote:
> 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 <laurent.pinchart at ideasonboard.com>
> ---
> 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 <libcamera/base/span.h>
>  
> -#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)

This should have been

libcrypto = dependency('gnutls', required : false)

It was a test left-over, sorry.

> +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 <openssl/evp.h>
> +#include <openssl/rsa.h>
> +#include <openssl/sha.h>
> +#include <openssl/x509.h>
> +#elif HAVE_GNUTLS
>  #include <gnutls/abstract.h>
>  #endif
>  
> @@ -33,7 +38,14 @@ namespace libcamera {
>  PubKey::PubKey([[maybe_unused]] Span<const uint8_t> 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<const uint8_t> 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<const uint8_t> 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<unsigned char *>(data.data()),
>  		static_cast<unsigned int>(data.size())

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list