diff options
-rw-r--r-- | src/libcamera/include/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/include/pub_key.h | 38 | ||||
-rw-r--r-- | src/libcamera/meson.build | 7 | ||||
-rw-r--r-- | src/libcamera/pub_key.cpp | 97 |
4 files changed, 143 insertions, 0 deletions
diff --git a/src/libcamera/include/meson.build b/src/libcamera/include/meson.build index 921ed5a0..5aaa9947 100644 --- a/src/libcamera/include/meson.build +++ b/src/libcamera/include/meson.build @@ -21,6 +21,7 @@ libcamera_headers = files([ 'message.h', 'pipeline_handler.h', 'process.h', + 'pub_key.h', 'semaphore.h', 'thread.h', 'utils.h', diff --git a/src/libcamera/include/pub_key.h b/src/libcamera/include/pub_key.h new file mode 100644 index 00000000..f35bf373 --- /dev/null +++ b/src/libcamera/include/pub_key.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * pub_key.h - Public key signature verification + */ +#ifndef __LIBCAMERA_PUB_KEY_H__ +#define __LIBCAMERA_PUB_KEY_H__ + +#include <stdint.h> + +#include <libcamera/span.h> + +#if HAVE_GNUTLS +struct gnutls_pubkey_st; +#endif + +namespace libcamera { + +class PubKey +{ +public: + PubKey(Span<const uint8_t> key); + ~PubKey(); + + bool isValid() const { return valid_; } + bool verify(Span<const uint8_t> data, Span<const uint8_t> sig) const; + +private: + bool valid_; +#if HAVE_GNUTLS + struct gnutls_pubkey_st *pubkey_; +#endif +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_PUB_KEY_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 4f5c4167..c2a657e4 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -34,6 +34,7 @@ libcamera_sources = files([ 'pipeline_handler.cpp', 'pixelformats.cpp', 'process.cpp', + 'pub_key.cpp', 'request.cpp', 'semaphore.cpp', 'signal.cpp', @@ -61,8 +62,13 @@ subdir('proxy') libatomic = cc.find_library('atomic', required : false) libdl = cc.find_library('dl') +libgnutls = cc.find_library('gnutls', required : false) libudev = dependency('libudev', required : false) +if libgnutls.found() + config_h.set('HAVE_GNUTLS', 1) +endif + if libudev.found() config_h.set('HAVE_LIBUDEV', 1) libcamera_sources += files([ @@ -98,6 +104,7 @@ libcamera_sources += version_cpp libcamera_deps = [ libatomic, libdl, + libgnutls, libudev, dependency('threads'), ] diff --git a/src/libcamera/pub_key.cpp b/src/libcamera/pub_key.cpp new file mode 100644 index 00000000..064d2dd2 --- /dev/null +++ b/src/libcamera/pub_key.cpp @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * pub_key.cpp - Public key signature verification + */ + +#include "pub_key.h" + +#if HAVE_GNUTLS +#include <gnutls/abstract.h> +#endif + +/** + * \file pub_key.h + * \brief Public key signature verification + */ + +namespace libcamera { + +/** + * \class PubKey + * \brief Public key wrapper for signature verification + * + * The PubKey class wraps a public key and implements signature verification. It + * only supports RSA keys and the RSA-SHA256 signature algorithm. + */ + +/** + * \brief Construct a PubKey from key data + * \param[in] key Key data encoded in DER format + */ +PubKey::PubKey(Span<const uint8_t> key) + : valid_(false) +{ +#if HAVE_GNUTLS + int ret = gnutls_pubkey_init(&pubkey_); + if (ret < 0) + return; + + const gnutls_datum_t gnuTlsKey{ + const_cast<unsigned char *>(key.data()), + static_cast<unsigned int>(key.size()) + }; + ret = gnutls_pubkey_import(pubkey_, &gnuTlsKey, GNUTLS_X509_FMT_DER); + if (ret < 0) + return; + + valid_ = true; +#endif +} + +PubKey::~PubKey() +{ +#if HAVE_GNUTLS + gnutls_pubkey_deinit(pubkey_); +#endif +} + +/** + * \fn bool PubKey::isValid() const + * \brief Check is the public key is valid + * \return True if the public key is valid, false otherwise + */ + +/** + * \brief Verify signature on data + * \param[in] data The signed data + * \param[in] sig The signature + * + * Verify that the signature \a sig matches the signed \a data for the public + * key. The signture algorithm is hardcoded to RSA-SHA256. + * + * \return True if the signature is valid, false otherwise + */ +bool PubKey::verify(Span<const uint8_t> data, Span<const uint8_t> sig) const +{ +#if HAVE_GNUTLS + const gnutls_datum_t gnuTlsData{ + const_cast<unsigned char *>(data.data()), + static_cast<unsigned int>(data.size()) + }; + + const gnutls_datum_t gnuTlsSig{ + const_cast<unsigned char *>(sig.data()), + static_cast<unsigned int>(sig.size()) + }; + + int ret = gnutls_pubkey_verify_data2(pubkey_, GNUTLS_SIGN_RSA_SHA256, 0, + &gnuTlsData, &gnuTlsSig); + return ret >= 0; +#else + return false; +#endif +} + +} /* namespace libcamera */ |