Skip to content

Commit 58e4209

Browse files
authored
Merge pull request #2876 from mtrmac/signature-sequoia
Add containers_image_sequoia build tag to do simple signing verification using Sequoia-PGP, and add a signature/simplesequoia implementation
2 parents 19834a0 + 8cec77c commit 58e4209

31 files changed

+1460
-67
lines changed

.cirrus.yml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@ env:
3030
SKOPEO_PR:
3131

3232
# Google-cloud VM Images
33-
IMAGE_SUFFIX: "c20250721t181111z-f42f41d13"
33+
# If you are updating IMAGE_SUFFIX: We are currently using rawhide for
34+
# the containers_image_sequoia tests because the rust-podman-sequoia
35+
# package is not available in earlier releases; once we update to a future
36+
# Fedora release (or if the package is backported), switch back from Rawhide
37+
# to the latest Fedora release.
38+
IMAGE_SUFFIX: "c20250812t173301z-f42f41d13"
3439
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
40+
RAWHIDE_CACHE_IMAGE_NAME: "rawhide-${IMAGE_SUFFIX}"
3541

3642
# Container FQIN's (include bleeding-edge development-level container deps.)
3743
FEDORA_CONTAINER_FQIN: "quay.io/libpod/fedora_podman:${IMAGE_SUFFIX}"
@@ -55,9 +61,12 @@ validate_task:
5561
# Required to be 200gig, do not modify - has i/o performance impact
5662
# according to gcloud CLI tool warning messages.
5763
disk: 200
58-
image_name: ${FEDORA_CACHE_IMAGE_NAME}
64+
# Eventually, hard-code FEDORA_CACHE_IMAGE_NAME here again and remove the
65+
# VM_IMAGE_NAME parameter.
66+
image_name: ${VM_IMAGE_NAME}
5967
env:
6068
HOME: "/root" # default unset, needed by golangci-lint.
69+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
6170
script: |
6271
git remote update
6372
make tools
@@ -68,6 +77,8 @@ validate_task:
6877
cross_task:
6978
only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
7079
gce_instance: *fedora_vm
80+
env:
81+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
7182
script: make cross
7283

7384

@@ -81,9 +92,15 @@ test_task:
8192
- name: "Test"
8293
env:
8394
BUILDTAGS: ''
95+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
8496
- name: "Test w/ opengpg"
8597
env:
8698
BUILDTAGS: &withopengpg 'containers_image_openpgp'
99+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
100+
- name: "Test w/ Sequoia (currently Rawhide)"
101+
env:
102+
BUILDTAGS: &withsequoia 'containers_image_sequoia'
103+
VM_IMAGE_NAME: ${RAWHIDE_CACHE_IMAGE_NAME}
87104
script: ${GOSRC}/${SCRIPT_BASE}/runner.sh image_tests
88105

89106

@@ -102,9 +119,15 @@ test_skopeo_task:
102119
- name: "Skopeo Test"
103120
env:
104121
BUILDTAGS: ''
122+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
105123
- name: "Skopeo Test w/ opengpg"
106124
env:
107125
BUILDTAGS: *withopengpg
126+
VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
127+
- name: "Skopeo Test w/ Sequoia (currently Rawhide)"
128+
env:
129+
BUILDTAGS: *withsequoia
130+
VM_IMAGE_NAME: ${RAWHIDE_CACHE_IMAGE_NAME}
108131
setup_script: >-
109132
"${GOSRC}/${SCRIPT_BASE}/runner.sh" setup
110133
vendor_script: >-
@@ -133,6 +156,7 @@ meta_task:
133156
# Space-separated list of images used by this repository state
134157
IMGNAMES: |
135158
${FEDORA_CACHE_IMAGE_NAME}
159+
${RAWHIDE_CACHE_IMAGE_NAME}
136160
BUILDID: "${CIRRUS_BUILD_ID}"
137161
REPOREF: "${CIRRUS_REPO_NAME}"
138162
GCPJSON: ENCRYPTED[04306103eee1933f87deb8a5af6514a7e3164aa589d6079abc0451eb2360879430ed020d6e025ca64ef667138ce9d786]

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ endif
99
# when cross compiling _for_ a Darwin or windows host, then we must use openpgp
1010
BUILD_TAGS_WINDOWS_CROSS = containers_image_openpgp
1111
BUILD_TAGS_DARWIN_CROSS = containers_image_openpgp
12+
SEQUOIA_SONAME_DIR =
1213

1314
BUILDTAGS =
14-
BUILDFLAGS := -tags "$(BUILDTAGS)"
15+
BUILDFLAGS := -tags "$(BUILDTAGS)" -ldflags '-X github.com/containers/image/v5/signature/internal/sequoia.sequoiaLibraryDir='"$(SEQUOIA_SONAME_DIR)"
1516

1617
# Extra flags passed to go test
1718
TESTFLAGS :=

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ or use the build tags described below to avoid the dependencies (e.g. using `go
6060
- `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.
6161
- `containers_image_openpgp`: Use a Golang-only OpenPGP implementation for signature verification instead of the default cgo/gpgme-based implementation;
6262
the primary downside is that creating new signatures with the Golang-only implementation is not supported.
63+
- `containers_image_sequoia`: Use Sequoia-PGP for signature verification instead of the default cgo/gpgme-based or the Golang-only OpenPGP implementations, and enable the `signature/simplesequoia` subpackage. This requires a support shared library installed on the system. Install https://github.com/ueno/podman-sequoia , and potentially update build configuration to point at it (compare `SEQUOIA_SONAME_DIR` in `Makefile`).
6364
- `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.
6465

6566
## [Contributing](CONTRIBUTING.md)
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copying and distribution of this file, with or without modification,
3+
* are permitted in any medium without royalty provided the copyright
4+
* notice and this notice are preserved. This file is offered as-is,
5+
* without any warranty.
6+
*/
7+
8+
#ifdef HAVE_CONFIG_H
9+
#include "config.h"
10+
#endif
11+
12+
#include "gosequoia.h"
13+
14+
#if defined(GO_SEQUOIA_ENABLE_DLOPEN) && GO_SEQUOIA_ENABLE_DLOPEN
15+
16+
#include <assert.h>
17+
#include <dlfcn.h>
18+
#include <errno.h>
19+
#include <stdlib.h>
20+
21+
/* If SEQUOIA_SONAME is defined, dlopen handle can be automatically
22+
* set; otherwise, the caller needs to call
23+
* go_sequoia_ensure_library with soname determined at run time.
24+
*/
25+
#ifdef SEQUOIA_SONAME
26+
27+
static void
28+
ensure_library (void)
29+
{
30+
if (go_sequoia_ensure_library (SEQUOIA_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0)
31+
abort ();
32+
}
33+
34+
#if defined(GO_SEQUOIA_ENABLE_PTHREAD) && GO_SEQUOIA_ENABLE_PTHREAD
35+
#include <pthread.h>
36+
37+
static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT;
38+
39+
#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library)
40+
41+
#else /* GO_SEQUOIA_ENABLE_PTHREAD */
42+
43+
#define ENSURE_LIBRARY do { \
44+
if (!go_sequoia_dlhandle) \
45+
ensure_library(); \
46+
} while (0)
47+
48+
#endif /* !GO_SEQUOIA_ENABLE_PTHREAD */
49+
50+
#else /* SEQUOIA_SONAME */
51+
52+
#define ENSURE_LIBRARY do {} while (0)
53+
54+
#endif /* !SEQUOIA_SONAME */
55+
56+
static void *go_sequoia_dlhandle;
57+
58+
/* Define redirection symbols */
59+
#pragma GCC diagnostic push
60+
#pragma GCC diagnostic ignored "-Wunused-macros"
61+
62+
#if (2 <= __GNUC__ || (4 <= __clang_major__))
63+
#define FUNC(ret, name, args, cargs) \
64+
static __typeof__(name)(*go_sequoia_sym_##name);
65+
#else
66+
#define FUNC(ret, name, args, cargs) \
67+
static ret(*go_sequoia_sym_##name)args;
68+
#endif
69+
#define VOID_FUNC FUNC
70+
#include "gosequoiafuncs.h"
71+
#undef VOID_FUNC
72+
#undef FUNC
73+
74+
#pragma GCC diagnostic pop
75+
76+
/* Define redirection wrapper functions */
77+
#pragma GCC diagnostic push
78+
#pragma GCC diagnostic ignored "-Wunused-macros"
79+
80+
#define FUNC(ret, name, args, cargs) \
81+
ret go_##name args \
82+
{ \
83+
ENSURE_LIBRARY; \
84+
assert (go_sequoia_sym_##name); \
85+
return go_sequoia_sym_##name cargs; \
86+
}
87+
#define VOID_FUNC(ret, name, args, cargs) \
88+
ret go_##name args \
89+
{ \
90+
ENSURE_LIBRARY; \
91+
assert (go_sequoia_sym_##name); \
92+
go_sequoia_sym_##name cargs; \
93+
}
94+
#include "gosequoiafuncs.h"
95+
#undef VOID_FUNC
96+
#undef FUNC
97+
98+
#pragma GCC diagnostic pop
99+
100+
static int
101+
ensure_symbol (const char *name, void **symp)
102+
{
103+
if (!*symp)
104+
{
105+
void *sym = dlsym (go_sequoia_dlhandle, name);
106+
if (!sym)
107+
return -EINVAL;
108+
*symp = sym;
109+
}
110+
return 0;
111+
}
112+
113+
int
114+
go_sequoia_ensure_library (const char *soname, int flags)
115+
{
116+
int err;
117+
118+
if (!go_sequoia_dlhandle)
119+
{
120+
go_sequoia_dlhandle = dlopen (soname, flags);
121+
if (!go_sequoia_dlhandle)
122+
return -EINVAL;
123+
}
124+
125+
#define ENSURE_SYMBOL(name) \
126+
ensure_symbol(#name, (void **)&go_sequoia_sym_##name)
127+
128+
#pragma GCC diagnostic push
129+
#pragma GCC diagnostic ignored "-Wunused-macros"
130+
131+
#define FUNC(ret, name, args, cargs) \
132+
err = ENSURE_SYMBOL(name); \
133+
if (err < 0) \
134+
{ \
135+
dlclose (go_sequoia_dlhandle); \
136+
go_sequoia_dlhandle = NULL; \
137+
return err; \
138+
}
139+
#define VOID_FUNC FUNC
140+
#include "gosequoiafuncs.h"
141+
#undef VOID_FUNC
142+
#undef FUNC
143+
144+
#pragma GCC diagnostic pop
145+
146+
#undef ENSURE_SYMBOL
147+
return 0;
148+
}
149+
150+
void
151+
go_sequoia_unload_library (void)
152+
{
153+
if (go_sequoia_dlhandle)
154+
{
155+
dlclose (go_sequoia_dlhandle);
156+
go_sequoia_dlhandle = NULL;
157+
}
158+
159+
#pragma GCC diagnostic push
160+
#pragma GCC diagnostic ignored "-Wunused-macros"
161+
162+
#define FUNC(ret, name, args, cargs) \
163+
go_sequoia_sym_##name = NULL;
164+
#define VOID_FUNC FUNC
165+
#include "gosequoiafuncs.h"
166+
#undef VOID_FUNC
167+
#undef FUNC
168+
169+
#pragma GCC diagnostic pop
170+
}
171+
172+
unsigned
173+
go_sequoia_is_usable (void)
174+
{
175+
return go_sequoia_dlhandle != NULL;
176+
}
177+
178+
#else /* GO_SEQUOIA_ENABLE_DLOPEN */
179+
180+
int
181+
go_sequoia_ensure_library (const char *soname, int flags)
182+
{
183+
(void) soname;
184+
(void) flags;
185+
return 0;
186+
}
187+
188+
void
189+
go_sequoia_unload_library (void)
190+
{
191+
}
192+
193+
unsigned
194+
go_sequoia_is_usable (void)
195+
{
196+
/* The library is linked at build time, thus always usable */
197+
return 1;
198+
}
199+
200+
#endif /* !GO_SEQUOIA_ENABLE_DLOPEN */
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copying and distribution of this file, with or without modification,
3+
* are permitted in any medium without royalty provided the copyright
4+
* notice and this notice are preserved. This file is offered as-is,
5+
* without any warranty.
6+
*/
7+
8+
#ifndef GO_SEQUOIA_H_
9+
#define GO_SEQUOIA_H_
10+
11+
#include <sequoia.h>
12+
13+
#if defined(GO_SEQUOIA_ENABLE_DLOPEN) && GO_SEQUOIA_ENABLE_DLOPEN
14+
15+
#define FUNC(ret, name, args, cargs) \
16+
ret go_##name args;
17+
#define VOID_FUNC FUNC
18+
#include "gosequoiafuncs.h"
19+
#undef VOID_FUNC
20+
#undef FUNC
21+
22+
#define GO_SEQUOIA_FUNC(name) go_##name
23+
24+
#else
25+
26+
#define GO_SEQUOIA_FUNC(name) name
27+
28+
#endif /* GO_SEQUOIA_ENABLE_DLOPEN */
29+
30+
/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary
31+
* symbols are resolved.
32+
*
33+
* Returns 0 on success; negative error code otherwise.
34+
*
35+
* Note that this function is NOT thread-safe; when calling it from
36+
* multi-threaded programs, protect it with a locking mechanism.
37+
*/
38+
int go_sequoia_ensure_library (const char *soname, int flags);
39+
40+
/* Unload library and reset symbols.
41+
*
42+
* Note that this function is NOT thread-safe; when calling it from
43+
* multi-threaded programs, protect it with a locking mechanism.
44+
*/
45+
void go_sequoia_unload_library (void);
46+
47+
/* Return 1 if the library is loaded and usable.
48+
*
49+
* Note that this function is NOT thread-safe; when calling it from
50+
* multi-threaded programs, protect it with a locking mechanism.
51+
*/
52+
unsigned go_sequoia_is_usable (void);
53+
54+
#endif /* GO_SEQUOIA_H_ */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* This file was automatically generated from sequoia.h,
3+
* which is covered by the following license:
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
VOID_FUNC(void, sequoia_error_free, (struct SequoiaError *err_ptr), (err_ptr))
7+
FUNC(struct SequoiaMechanism *, sequoia_mechanism_new_from_directory, (const char *dir_ptr, struct SequoiaError **err_ptr), (dir_ptr, err_ptr))
8+
FUNC(struct SequoiaMechanism *, sequoia_mechanism_new_ephemeral, (struct SequoiaError **err_ptr), (err_ptr))
9+
VOID_FUNC(void, sequoia_mechanism_free, (struct SequoiaMechanism *mechanism_ptr), (mechanism_ptr))
10+
VOID_FUNC(void, sequoia_signature_free, (struct SequoiaSignature *signature_ptr), (signature_ptr))
11+
FUNC(const uint8_t *, sequoia_signature_get_data, (const struct SequoiaSignature *signature_ptr, size_t *data_len), (signature_ptr, data_len))
12+
VOID_FUNC(void, sequoia_verification_result_free, (struct SequoiaVerificationResult *result_ptr), (result_ptr))
13+
FUNC(const uint8_t *, sequoia_verification_result_get_content, (const struct SequoiaVerificationResult *result_ptr, size_t *data_len), (result_ptr, data_len))
14+
FUNC(const char *, sequoia_verification_result_get_signer, (const struct SequoiaVerificationResult *result_ptr), (result_ptr))
15+
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))
16+
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))
17+
VOID_FUNC(void, sequoia_import_result_free, (struct SequoiaImportResult *result_ptr), (result_ptr))
18+
FUNC(size_t, sequoia_import_result_get_count, (const struct SequoiaImportResult *result_ptr), (result_ptr))
19+
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))
20+
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))
21+
FUNC(int, sequoia_set_logger_consumer, (void (*consumer)(enum SequoiaLogLevel, const char *), struct SequoiaError **err_ptr), (consumer, err_ptr))

0 commit comments

Comments
 (0)