Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ or use the build tags described below to avoid the dependencies (e.g. using `go
- `containers_image_docker_daemon_stub`: Don’t import the `docker-daemon:` transport in `github.com/containers/image/transports/alltransports`, to decrease the amount of required dependencies. Use a stub which reports that the transport is not supported instead.
- `containers_image_openpgp`: Use a Golang-only OpenPGP implementation for signature verification instead of the default cgo/gpgme-based implementation;
the primary downside is that creating new signatures with the Golang-only implementation is not supported.
- `containers_image_sequoia`: Use Sequoia-PGP for signature verification instead of the default cgo/gpgme-based or the Golang-only OpenPGP implementations. This requires a support shared library installed on the system. Follow the instructions in [signature/sequoia/rust/README.md](signature/sequoia/rust/README.md).
- `containers_image_storage_stub`: Don’t import the `containers-storage:` transport in `github.com/containers/image/transports/alltransports`, to decrease the amount of required dependencies. Use a stub which reports that the transport is not supported instead.
- `containers_image_fulcio_stub`: Don't import sigstore/fulcio code, all fulcio operations will return an error code
- `containers_image_rekor_stub`: Don't import sigstore/reckor code, all rekor operations will return an error code
Expand Down
200 changes: 200 additions & 0 deletions signature/internal/sequoia/gosequoia.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved. This file is offered as-is,
* without any warranty.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gosequoia.h"

#if defined(GO_SEQUOIA_ENABLE_DLOPEN) && GO_SEQUOIA_ENABLE_DLOPEN

#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>

/* If SEQUOIA_SONAME is defined, dlopen handle can be automatically
* set; otherwise, the caller needs to call
* go_sequoia_ensure_library with soname determined at run time.
*/
#ifdef SEQUOIA_SONAME

static void
ensure_library (void)
{
if (go_sequoia_ensure_library (SEQUOIA_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
abort ();
}

#if defined(GO_SEQUOIA_ENABLE_PTHREAD) && GO_SEQUOIA_ENABLE_PTHREAD
#include <pthread.h>

static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;

#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)

#else /* GO_SEQUOIA_ENABLE_PTHREAD */

#define ENSURE_LIBRARY do { \
if (!go_sequoia_dlhandle) \
ensure_library(); \
} while (0)

#endif /* !GO_SEQUOIA_ENABLE_PTHREAD */

#else /* SEQUOIA_SONAME */

#define ENSURE_LIBRARY do {} while (0)

#endif /* !SEQUOIA_SONAME */

static void *go_sequoia_dlhandle;

/* Define redirection symbols */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"

#if (2 <= __GNUC__ || (4 <= __clang_major__))
#define FUNC(ret, name, args, cargs) \
static __typeof__(name)(*go_sequoia_sym_##name);
#else
#define FUNC(ret, name, args, cargs) \
static ret(*go_sequoia_sym_##name)args;
#endif
#define VOID_FUNC FUNC
#include "gosequoiafuncs.h"
#undef VOID_FUNC
#undef FUNC

#pragma GCC diagnostic pop

/* Define redirection wrapper functions */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"

#define FUNC(ret, name, args, cargs) \
ret go_##name args \
{ \
ENSURE_LIBRARY; \
assert (go_sequoia_sym_##name); \
return go_sequoia_sym_##name cargs; \
}
#define VOID_FUNC(ret, name, args, cargs) \
ret go_##name args \
{ \
ENSURE_LIBRARY; \
assert (go_sequoia_sym_##name); \
go_sequoia_sym_##name cargs; \
}
#include "gosequoiafuncs.h"
#undef VOID_FUNC
#undef FUNC

#pragma GCC diagnostic pop

static int
ensure_symbol (const char *name, void **symp)
{
if (!*symp)
{
void *sym = dlsym (go_sequoia_dlhandle, name);
if (!sym)
return -EINVAL;
*symp = sym;
}
return 0;
}

int
go_sequoia_ensure_library (const char *soname, int flags)
{
int err;

if (!go_sequoia_dlhandle)
{
go_sequoia_dlhandle = dlopen (soname, flags);
if (!go_sequoia_dlhandle)
return -EINVAL;
}

#define ENSURE_SYMBOL(name) \
ensure_symbol(#name, (void **)&go_sequoia_sym_##name)

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"

#define FUNC(ret, name, args, cargs) \
err = ENSURE_SYMBOL(name); \
if (err < 0) \
{ \
dlclose (go_sequoia_dlhandle); \
go_sequoia_dlhandle = NULL; \
return err; \
}
#define VOID_FUNC FUNC
#include "gosequoiafuncs.h"
#undef VOID_FUNC
#undef FUNC

#pragma GCC diagnostic pop

#undef ENSURE_SYMBOL
return 0;
}

void
go_sequoia_unload_library (void)
{
if (go_sequoia_dlhandle)
{
dlclose (go_sequoia_dlhandle);
go_sequoia_dlhandle = NULL;
}

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"

#define FUNC(ret, name, args, cargs) \
go_sequoia_sym_##name = NULL;
#define VOID_FUNC FUNC
#include "gosequoiafuncs.h"
#undef VOID_FUNC
#undef FUNC

#pragma GCC diagnostic pop
}

unsigned
go_sequoia_is_usable (void)
{
return go_sequoia_dlhandle != NULL;
}

#else /* GO_SEQUOIA_ENABLE_DLOPEN */

int
go_sequoia_ensure_library (const char *soname, int flags)
{
(void) soname;
(void) flags;
return 0;
}

void
go_sequoia_unload_library (void)
{
}

unsigned
go_sequoia_is_usable (void)
{
/* The library is linked at build time, thus always usable */
return 1;
}

#endif /* !GO_SEQUOIA_ENABLE_DLOPEN */
54 changes: 54 additions & 0 deletions signature/internal/sequoia/gosequoia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved. This file is offered as-is,
* without any warranty.
*/

#ifndef GO_SEQUOIA_H_
#define GO_SEQUOIA_H_

#include <sequoia.h>

#if defined(GO_SEQUOIA_ENABLE_DLOPEN) && GO_SEQUOIA_ENABLE_DLOPEN

#define FUNC(ret, name, args, cargs) \
ret go_##name args;
#define VOID_FUNC FUNC
#include "gosequoiafuncs.h"
#undef VOID_FUNC
#undef FUNC

#define GO_SEQUOIA_FUNC(name) go_##name

#else

#define GO_SEQUOIA_FUNC(name) name

#endif /* GO_SEQUOIA_ENABLE_DLOPEN */

/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
* symbols are resolved.
*
* Returns 0 on success; negative error code otherwise.
*
* Note that this function is NOT thread-safe; when calling it from
* multi-threaded programs, protect it with a locking mechanism.
*/
int go_sequoia_ensure_library (const char *soname, int flags);

/* Unload library and reset symbols.
*
* Note that this function is NOT thread-safe; when calling it from
* multi-threaded programs, protect it with a locking mechanism.
*/
void go_sequoia_unload_library (void);

/* Return 1 if the library is loaded and usable.
*
* Note that this function is NOT thread-safe; when calling it from
* multi-threaded programs, protect it with a locking mechanism.
*/
unsigned go_sequoia_is_usable (void);

#endif /* GO_SEQUOIA_H_ */
20 changes: 20 additions & 0 deletions signature/internal/sequoia/gosequoiafuncs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* This file was automatically generated from sequoia.h,
* which is covered by the following license:
* SPDX-License-Identifier: Apache-2.0
*/
VOID_FUNC(void, sequoia_error_free, (struct SequoiaError *err_ptr), (err_ptr))
FUNC(struct SequoiaMechanism *, sequoia_mechanism_new_from_directory, (const char *dir_ptr, struct SequoiaError **err_ptr), (dir_ptr, err_ptr))
FUNC(struct SequoiaMechanism *, sequoia_mechanism_new_ephemeral, (struct SequoiaError **err_ptr), (err_ptr))
VOID_FUNC(void, sequoia_mechanism_free, (struct SequoiaMechanism *mechanism_ptr), (mechanism_ptr))
VOID_FUNC(void, sequoia_signature_free, (struct SequoiaSignature *signature_ptr), (signature_ptr))
FUNC(const uint8_t *, sequoia_signature_get_data, (const struct SequoiaSignature *signature_ptr, size_t *data_len), (signature_ptr, data_len))
VOID_FUNC(void, sequoia_verification_result_free, (struct SequoiaVerificationResult *result_ptr), (result_ptr))
FUNC(const uint8_t *, sequoia_verification_result_get_content, (const struct SequoiaVerificationResult *result_ptr, size_t *data_len), (result_ptr, data_len))
FUNC(const char *, sequoia_verification_result_get_signer, (const struct SequoiaVerificationResult *result_ptr), (result_ptr))
FUNC(struct SequoiaSignature *, sequoia_sign, (struct SequoiaMechanism *mechanism_ptr, const char *key_handle_ptr, const char *password_ptr, const uint8_t *data_ptr, size_t data_len, struct SequoiaError **err_ptr), (mechanism_ptr, key_handle_ptr, password_ptr, data_ptr, data_len, err_ptr))
FUNC(struct SequoiaVerificationResult *, sequoia_verify, (struct SequoiaMechanism *mechanism_ptr, const uint8_t *signature_ptr, size_t signature_len, struct SequoiaError **err_ptr), (mechanism_ptr, signature_ptr, signature_len, err_ptr))
VOID_FUNC(void, sequoia_import_result_free, (struct SequoiaImportResult *result_ptr), (result_ptr))
FUNC(size_t, sequoia_import_result_get_count, (const struct SequoiaImportResult *result_ptr), (result_ptr))
FUNC(const char *, sequoia_import_result_get_content, (const struct SequoiaImportResult *result_ptr, size_t index, struct SequoiaError **err_ptr), (result_ptr, index, err_ptr))
FUNC(struct SequoiaImportResult *, sequoia_import_keys, (struct SequoiaMechanism *mechanism_ptr, const uint8_t *blob_ptr, size_t blob_len, struct SequoiaError **err_ptr), (mechanism_ptr, blob_ptr, blob_len, err_ptr))
Loading