Subject: [bug#52610] [PATCH 39/42] gnu: Add libsequoia.

From: Hartmut Goebel <[email-masked]>
Date: Sat, 18 Dec 2021 21:49:50 +0100

* gnu/packages/sequoia.scm (sequoia-package-origin): New variable.
  (libsequoia): New variable.
* gnu/packages/patches/sequoia-fix-ffi-Makefile.patch,
  gnu/packages/patches/sequoia-remove-store.patch New files.
* gnu/local.mk (dist_patch_DATA): Add them.
---
 gnu/local.mk                                  |   2 +
 .../patches/libsequoia-fix-ffi-Makefile.patch |  32 ++
 .../patches/libsequoia-remove-store.patch     | 432 ++++++++++++++++++
 gnu/packages/sequoia.scm                      | 120 +++++
 4 files changed, 586 insertions(+)
 create mode 100644 gnu/packages/patches/libsequoia-fix-ffi-Makefile.patch
 create mode 100644 gnu/packages/patches/libsequoia-remove-store.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 33e108c752..598a85f512 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1785,6 +1785,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/sendgmail-accept-ignored-gsuite-flag.patch	\
   %D%/packages/patches/sendgmail-remove-domain-restriction.patch	\
   %D%/packages/patches/seq24-rename-mutex.patch			\
+  %D%/packages/patches/libsequoia-fix-ffi-Makefile.patch	\
+  %D%/packages/patches/libsequoia-remove-store.patch		\
   %D%/packages/patches/serf-python3.patch			\
   %D%/packages/patches/shakespeare-spl-fix-grammar.patch		\
   %D%/packages/patches/sharutils-CVE-2018-1000097.patch		\
diff --git a/gnu/packages/patches/libsequoia-fix-ffi-Makefile.patch b/gnu/packages/patches/libsequoia-fix-ffi-Makefile.patch
new file mode 100644
index 0000000000..21f5a1e4df
--- /dev/null
+++ b/gnu/packages/patches/libsequoia-fix-ffi-Makefile.patch
@@ -0,0 +1,32 @@
+From ed641d2048d131e077f54043764741b7e7b7fe03 Mon Sep 17 00:00:00 2001
+From: Hartmut Goebel <[email-masked]>
+Date: Tue, 7 Dec 2021 16:42:43 +0100
+Subject: [PATCH] ffi: Update Makefile, remove rule remaining from store
+ removal.
+
+---
+ ffi/Makefile | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/ffi/Makefile b/ffi/Makefile
+index a5540db3..07328589 100644
+--- a/ffi/Makefile
++++ b/ffi/Makefile
+@@ -62,7 +62,6 @@ build-release:
+ 	    $(CARGO) build $(CARGO_FLAGS) --release --package sequoia-ffi
+ 	$(MAKE) -Clang/python build-release
+ 	$(call sequoia_pc,$(CARGO_TARGET_DIR)/release,true)
+-	$(MAKE) -C../store build-release
+ 
+ .PHONY: install
+ install: build-release
+@@ -82,7 +82,6 @@ install: build-release
+ 		$(DESTDIR)$(PREFIX)/lib/libsequoia_ffi.$(_SEQ_LIB_EXT)
+ 	$(INSTALL) $(CARGO_TARGET_DIR)/release/libsequoia_ffi.a \
+ 		$(DESTDIR)$(PREFIX)/lib/libsequoia_ffi.a
+-	$(MAKE) -C../store install
+ 	# Now the bindings.
+ 	$(MAKE) -Clang/python install
+ 
+-- 
+
diff --git a/gnu/packages/patches/libsequoia-remove-store.patch b/gnu/packages/patches/libsequoia-remove-store.patch
new file mode 100644
index 0000000000..e7e1a91ee3
--- /dev/null
+++ b/gnu/packages/patches/libsequoia-remove-store.patch
@@ -0,0 +1,432 @@
+Shortend version of
+From 351ad5e5e2dd67f427b7eb2e4d5d0b35d90ffaf7 Mon Sep 17 00:00:00 2001
+From: Justus Winter <[email-masked]>
+Date: Wed, 24 Nov 2021 15:09:34 +0100
+Subject: [PATCH] store: Drop crate.
+
+  - The store has never been really used, and never reached a maturity
+    where it was useful.  And, we're on the verge of replacing it with
+    the Shared PGP Certificate Directory.
+---
+ Cargo.toml                               |    1 -
+ ffi/Cargo.toml                           |    4 +-
+ ffi/include/sequoia.h                    |    1 -
+ ffi/include/sequoia/store.h              |  409 ------
+ ffi/lang/python/sequoia/__init__.py      |    1 -
+ ffi/lang/python/sequoia/prelude.py       |    1 -
+ ffi/lang/python/sequoia/sequoia_build.py |    3 +-
+ ffi/lang/python/sequoia/store.py         |  246 ----
+ ffi/lang/python/tests/test_store.py      |   47 -
+ ffi/src/lib.rs                           |    2 -
+ ffi/src/store.rs                         |  659 ----------
+ 25 files changed, 3 insertions(+), 5064 deletions(-)
+ delete mode 100644 ffi/include/sequoia/store.h
+ delete mode 100644 ffi/lang/python/sequoia/store.py
+ delete mode 100644 ffi/lang/python/tests/test_store.py
+ delete mode 100644 ffi/src/store.rs
+
+diff --git a/Cargo.toml b/Cargo.toml
+index a4f48520..a573ddbf 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -10,7 +10,6 @@ members = [
+     "openpgp",
+     "openpgp-ffi",
+     "sq",
+-    "store",
+ ]
+ 
+ [profile.release]
+diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml
+index 53ddaf68..2ec84e6e 100644
+--- a/ffi/Cargo.toml
++++ b/ffi/Cargo.toml
+@@ -24,7 +24,6 @@ maintenance = { status = "actively-developed" }
+ [dependencies]
+ sequoia-ffi-macros = { path = "../ffi-macros", version = "0.22" }
+ sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false }
+-sequoia-store = { path = "../store", version = "0.22", default-features = false }
+ sequoia-net = { path = "../net", version = "0.23", default-features = false }
+ sequoia-ipc = { path = "../ipc", version = "0.26", default-features = false }
+ anyhow = "1.0.18"
+@@ -42,10 +41,9 @@ crate-type = ["cdylib", "staticlib"]
+ bench = false
+ 
+ [features]
+-default = ["sequoia-openpgp/default", "sequoia-store/default"]
++default = ["sequoia-openpgp/default"]
+ crypto-nettle = ["sequoia-openpgp/crypto-nettle"]
+ crypto-cng = ["sequoia-openpgp/crypto-cng"]
+ compression = ["sequoia-openpgp/compression"]
+ compression-deflate = ["sequoia-openpgp/compression-deflate"]
+ compression-bzip2 = ["sequoia-openpgp/compression-bzip2"]
+-background-services = ["sequoia-store/background-services"]
+diff --git a/ffi/include/sequoia.h b/ffi/include/sequoia.h
+index 8c62ba8f..c32a2f3e 100644
+--- a/ffi/include/sequoia.h
++++ b/ffi/include/sequoia.h
+@@ -5,6 +5,5 @@
+ #include <sequoia/core.h>
+ #include <sequoia/openpgp.h>
+ #include <sequoia/net.h>
+-#include <sequoia/store.h>
+ 
+ #endif
+diff --git a/ffi/lang/python/sequoia/__init__.py b/ffi/lang/python/sequoia/__init__.py
+index 4f84346e..fc170e20 100644
+--- a/ffi/lang/python/sequoia/__init__.py
++++ b/ffi/lang/python/sequoia/__init__.py
+@@ -4,5 +4,4 @@ from . import (
+     openpgp,
+     core,
+     net,
+-    store,
+ )
+diff --git a/ffi/lang/python/sequoia/prelude.py b/ffi/lang/python/sequoia/prelude.py
+index 42b0156a..61efbab0 100644
+--- a/ffi/lang/python/sequoia/prelude.py
++++ b/ffi/lang/python/sequoia/prelude.py
+@@ -3,4 +3,3 @@ from .error import *
+ from .openpgp import *
+ from .core import *
+ from .net import *
+-from .store import *
+diff --git a/ffi/lang/python/sequoia/sequoia_build.py b/ffi/lang/python/sequoia/sequoia_build.py
+index a3ce2786..058f1380 100644
+--- a/ffi/lang/python/sequoia/sequoia_build.py
++++ b/ffi/lang/python/sequoia/sequoia_build.py
+@@ -14,8 +14,7 @@ defs = "".join(l
+                               open(join(pgp_inc, "openpgp/serialize.h")).readlines(),
+                               open(join(pgp_inc, "openpgp.h")).readlines(),
+                               open(join(sq_inc, "core.h")).readlines(),
+-                              open(join(sq_inc, "net.h")).readlines(),
+-                              open(join(sq_inc, "store.h")).readlines())
++                              open(join(sq_inc, "net.h")).readlines())
+                if not l.startswith('#'))
+ 
+ defs = defs.replace("INT_MAX", "{}".format(1<<31))
+diff --git a/ffi/lang/python/sequoia/store.py b/ffi/lang/python/sequoia/store.py
+deleted file mode 100644
+index 57d1b18f..00000000
+--- a/ffi/lang/python/sequoia/store.py
++++ /dev/null
+@@ -1,246 +0,0 @@
+-from _sequoia import ffi, lib
+-
+-from .error import Error
+-from .glue import _str, _static_str, SQObject, sq_iterator, sq_time
+-from .net import NetworkPolicy
+-from .openpgp import Fingerprint, Cert
+-
+-class Store(object):
+-    @classmethod
+-    def log(cls, ctx):
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_store_server_log(ctx.ref()),
+-                lib.sq_log_iter_free),
+-            lib.sq_log_iter_next,
+-            lambda x: Log(x, context=ctx))
+-
+-    @classmethod
+-    def list_keys(cls, ctx):
+-        def next_fn(i):
+-            fpp = ffi.new("pgp_fingerprint_t[1]")
+-            key = lib.sq_key_iter_next(i, fpp)
+-            if key == ffi.NULL:
+-                return ffi.NULL
+-            else:
+-                return (Fingerprint(fpp[0], ctx),
+-                        Key(key, ctx))
+-
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_store_list_keys(ctx.ref()),
+-                lib.sq_key_iter_free),
+-            next_fn)
+-
+-class Mapping(SQObject):
+-    _del = lib.sq_mapping_free
+-
+-    # Keys used for communications.
+-    REALM_CONTACTS = _static_str(lib.SQ_REALM_CONTACTS)
+-
+-    # Keys used for signing software updates.
+-    REALM_SOFTWARE_UPDATES = _static_str(lib.SQ_REALM_SOFTWARE_UPDATES)
+-
+-    @classmethod
+-    def open(cls, ctx, network_policy=NetworkPolicy.Encrypted, realm=REALM_CONTACTS, name="default"):
+-        return Mapping(lib.sq_mapping_open(ctx.ref(), network_policy.value,
+-                                        realm.encode(), name.encode()),
+-                        context=ctx)
+-
+-
+-    def add(self, label, fingerprint):
+-        return Binding(lib.sq_mapping_add(self.context().ref(), self.ref(),
+-                                        label.encode(), fingerprint.ref()),
+-                       context=self.context())
+-
+-    def import_(self, label, cert):
+-        return Cert(lib.sq_mapping_import(self.context().ref(), self.ref(),
+-                                       label.encode(), cert.ref()),
+-                   context=self.context())
+-
+-    def lookup(self, label):
+-        return Binding(lib.sq_mapping_lookup(self.context().ref(), self.ref(),
+-                                           label.encode()),
+-                       self.context())
+-
+-    def delete(self):
+-        if lib.sq_mapping_delete(self.ref()):
+-            raise Error._last(self.context())
+-        super(Mapping, self)._delete(skip_free=True)
+-
+-    def iter(self):
+-        def next_fn(i):
+-            labelp = ffi.new("char *[1]")
+-            fpp = ffi.new("pgp_fingerprint_t[1]")
+-            binding = lib.sq_binding_iter_next(i, labelp, fpp)
+-            if binding == ffi.NULL:
+-                return ffi.NULL
+-            else:
+-                return (_str(labelp[0]),
+-                        Fingerprint(fpp[0], self.context()),
+-                        Binding(binding, self.context()))
+-
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_mapping_iter(self.context().ref(), self.ref()),
+-                lib.sq_binding_iter_free),
+-            next_fn)
+-
+-    def log(self):
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_mapping_log(self.context().ref(), self.ref()),
+-                lib.sq_log_iter_free),
+-            lib.sq_log_iter_next,
+-            lambda x: Log(x, context=self.context()))
+-
+-class Binding(SQObject):
+-    _del = lib.sq_binding_free
+-
+-    def stats(self):
+-        return Stats(lib.sq_binding_stats(self.context().ref(), self.ref()),
+-                     self.context())
+-
+-    def key(self):
+-        return Key(lib.sq_binding_key(self.context().ref(), self.ref()),
+-                   self.context())
+-
+-    def cert(self):
+-        return Cert(lib.sq_binding_cert(self.context().ref(), self.ref()),
+-                   self.context())
+-
+-    def import_(self, cert):
+-        return Cert(lib.sq_binding_import(self.context().ref(), self.ref(), cert),
+-                   self.context())
+-
+-    def rotate(self, cert):
+-        return Cert(lib.sq_binding_rotate(self.context().ref(), self.ref(), cert),
+-                   self.context())
+-
+-    def delete(self):
+-        if lib.sq_binding_delete(self.ref()):
+-            raise Error._last(self.context())
+-        super(Binding, self)._delete(skip_free=True)
+-
+-    def log(self):
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_binding_log(self.context().ref(), self.ref()),
+-                lib.sq_log_iter_free),
+-            lib.sq_log_iter_next,
+-            lambda x: Log(x, context=self.context()))
+-
+-class Key(SQObject):
+-    _del = lib.sq_key_free
+-
+-    def stats(self):
+-        return Stats(lib.sq_key_stats(self.context().ref(), self.ref()),
+-                     self.context())
+-
+-    def cert(self):
+-        return Cert(lib.sq_key_cert(self.context().ref(), self.ref()),
+-                   self.context())
+-
+-    def import_(self, cert):
+-        return Cert(lib.sq_key_import(self.context().ref(), self.ref(), cert),
+-                   self.context())
+-
+-    def log(self):
+-        yield from sq_iterator(
+-            ffi.gc(
+-                lib.sq_key_log(self.context().ref(), self.ref()),
+-                lib.sq_log_iter_free),
+-            lib.sq_log_iter_next)
+-
+-
+-class Stats(SQObject):
+-    _del = lib.sq_stats_free
+-    def __init__(self, o, context=None):
+-        super(Stats, self).__init__(o, context=context)
+-        self.encryption = Stamps(ffi.addressof(o, "encryption"))
+-        self.verification = Stamps(ffi.addressof(o, "verification"))
+-
+-    @property
+-    def created(self):
+-        return sq_time(self.ref().created)
+-
+-    @property
+-    def updated(self):
+-        return sq_time(self.ref().updated)
+-
+-    def __str__(self):
+-        return \
+-            "Stats{{created={}, updated={}, encryption={}, verification={}}}" \
+-            .format(self.created, self.updated, self.encryption,
+-                    self.verification)
+-
+-class Stamps(SQObject):
+-    @property
+-    def count(self):
+-        return self.ref().count
+-
+-    @property
+-    def first(self):
+-        return sq_time(self.ref().first)
+-
+-    @property
+-    def last(self):
+-        return sq_time(self.ref().last)
+-
+-    def __str__(self):
+-        return "Stamps{{count={}, first={}, last={}}}".format(
+-            self.count, self.first, self.last)
+-
+-class Log(SQObject):
+-    _del = lib.sq_log_free
+-
+-    @property
+-    def timestamp(self):
+-        return sq_time(self.ref().timestamp)
+-
+-    @property
+-    def store(self):
+-        if self.ref().store == ffi.NULL:
+-            return None
+-        else:
+-            return Store(self.ref().store, context=self.context(),
+-                         owner=self)
+-
+-    @property
+-    def binding(self):
+-        if self.ref().binding == ffi.NULL:
+-            return None
+-        else:
+-            return Binding(self.ref().binding, context=self.context(),
+-                           owner=self)
+-
+-    @property
+-    def key(self):
+-        if self.ref().key == ffi.NULL:
+-            return None
+-        else:
+-            return Key(self.ref().key, context=self.context(),
+-                       owner=self)
+-
+-    @property
+-    def slug(self):
+-        return ffi.string(self.ref().slug).decode()
+-
+-    @property
+-    def status(self):
+-        return ffi.string(self.ref().status).decode()
+-
+-    @property
+-    def error(self):
+-        if self.ref().error == ffi.NULL:
+-            return None
+-        else:
+-            return ffi.string(self.ref().error).decode()
+-
+-    def __str__(self):
+-        if self.error:
+-            return "{}: {}: {}: {}".format(
+-                self.timestamp, self.slug, self.status, self.error)
+-        else:
+-            return "{}: {}: {}".format(
+-                self.timestamp, self.slug, self.status)
+diff --git a/ffi/lang/python/tests/test_store.py b/ffi/lang/python/tests/test_store.py
+deleted file mode 100644
+index 7b06cc1a..00000000
+--- a/ffi/lang/python/tests/test_store.py
++++ /dev/null
+@@ -1,47 +0,0 @@
+-from sequoia.prelude import Context, Store, Mapping, Fingerprint
+-
+-def test_open():
+-    c = Context(ephemeral=True)
+-    Mapping.open(c)
+-
+-def test_add():
+-    c = Context(ephemeral=True)
+-    s = Mapping.open(c)
+-    fp = Fingerprint.from_hex("7DCA58B54EB143169DDEE15F247F6DABC84914FE")
+-    s.add("Ἀριστοτέλης", fp)
+-
+-def test_iterate():
+-    c = Context(ephemeral=True)
+-    s = Mapping.open(c)
+-    fp = Fingerprint.from_hex("7DCA58B54EB143169DDEE15F247F6DABC84914FE")
+-    s.add("Ἀριστοτέλης", fp)
+-    l = list(s.iter())
+-    assert len(l) == 1
+-    l = list(Store.list_keys(c))
+-    assert len(l) == 1
+-    fpi, key = l[0]
+-    assert fpi == fp
+-
+-def test_logs():
+-    c = Context(ephemeral=True)
+-    s = Mapping.open(c)
+-    fp = Fingerprint.from_hex("7DCA58B54EB143169DDEE15F247F6DABC84914FE")
+-    b = s.add("Ἀριστοτέλης", fp)
+-    l = list(s.iter())
+-    assert len(l) == 1
+-
+-    # global logs
+-    logs = list(Store.log(c))
+-    assert len(logs) > 0
+-
+-    # per store logs
+-    logs = list(s.log())
+-    assert len(logs) > 0
+-
+-    # per binding logs
+-    logs = list(b.log())
+-    assert len(logs) > 0
+-
+-    # per key logs
+-    logs = list(b.key().log())
+-    assert len(logs) > 0
+diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs
+index 40e3672e..9b4577eb 100644
+--- a/ffi/src/lib.rs
++++ b/ffi/src/lib.rs
+@@ -130,7 +130,6 @@ pub(crate) use crate::openpgp::{
+     MoveResultIntoRaw,
+     Maybe,
+     maybe_time,
+-    to_time_t,
+ };
+ 
+ /* Error handling with implicit context.  */
+@@ -146,5 +145,4 @@ macro_rules! ffi_make_fry_from_ctx {
+ pub mod core;
+ pub mod error;
+ pub mod net;
+-pub mod store;
+ 
+GitLab
+
diff --git a/gnu/packages/sequoia.scm b/gnu/packages/sequoia.scm
index 70ac2e89cd..811beb823a 100644
--- a/gnu/packages/sequoia.scm
+++ b/gnu/packages/sequoia.scm
@@ -346,6 +346,126 @@ constraints on the signature into account.
 This Guix package is built to use the nettle cryptographic library.")
     (license license:lgpl2.0+)))
 
+(define (sequoia-package-origin version)
+  (origin
+    (method git-fetch)
+    (uri (git-reference
+          (url "https://gitlab.com/sequoia-pgp/sequoia.git")
+          (commit (string-append "openpgp/v" version))))
+    (sha256
+     (base32 "1cq1xgvllbpii5hfl3wlia2ayznpvhv8lq8g8ygwxga86ijg98lq"))
+    (file-name (git-file-name "sequoia" version))
+    (patches (search-patches "libsequoia-remove-store.patch"
+                             "libsequoia-fix-ffi-Makefile.patch"))))
+
+(define-public libsequoia
+  (package
+    (name "libsequoia")
+    (version "0.22.0")
+    (source (sequoia-package-origin "1.6.0"))
+    (build-system cargo-build-system)
+    (outputs '("out" "python"))
+    (native-inputs
+     (list clang pkg-config python-pytest python-pytest-runner
+           python-wrapper))
+    (inputs
+     (list gmp nettle openssl python python-cffi))
+    (arguments
+     `(#:tests? #f ;; TODO make python tests find the shared object file
+       #:cargo-inputs
+       (("rust-anyhow" ,rust-anyhow-1)
+        ("rust-lazy-static" ,rust-lazy-static-1)
+        ("rust-libc" ,rust-libc-0.2)
+        ("rust-memsec" ,rust-memsec-0.6)
+        ("rust-native-tls" ,rust-native-tls-0.2)
+        ("rust-proc-macro2" ,rust-proc-macro2-1)  ;; for ffi-macros
+        ("rust-quote" ,rust-quote-1)  ;; for ffi-macros
+        ("rust-sequoia-ipc" ,rust-sequoia-ipc-0.26)
+        ("rust-sequoia-net" ,rust-sequoia-net-0.23)
+        ("rust-sequoia-openpgp" ,rust-sequoia-openpgp-1)
+        ("rust-sha2" ,rust-sha2-0.8)  ;; for ffi-macros
+        ("rust-tokio" ,rust-tokio-1.8))
+       #:cargo-development-inputs
+       (("rust-filetime" ,rust-filetime-0.2))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'configure 'set-PREFIX
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (setenv "PREFIX" out)
+               #t)))
+         (replace 'build
+           (lambda _
+             (invoke "make" "-C" "openpgp-ffi" "build-release")
+             (invoke "make" "-C" "ffi" "build-release")))
+         (delete 'package)  ;; cargo can't package a multi-crate workspace
+         (replace 'check
+           (lambda* (#:key tests?  #:allow-other-keys)
+             (if tests?
+                 (begin
+                   (invoke "make" "-C" "openpgp-ffi" "check")
+                   (invoke "make" "-C" "ffi" "check"))
+                 #t)))
+         (replace 'install
+           (lambda _
+             (invoke "make" "-C" "openpgp-ffi" "install")
+             (invoke "make" "-C" "ffi" "install")))
+         (add-after 'configure 'fix-build-environment
+           (lambda _
+             (delete-file "Cargo.toml")
+             (symlink "../.cargo" "openpgp-ffi/.cargo")
+             (symlink "../.cargo" "ffi/.cargo")
+             (for-each delete-file-recursively
+                       (find-files "guix-vendor" "^sequoia-[0-9]+\\.*"
+                                   #:directories? #t))
+             #t))
+         (add-after 'unpack 'fix-for-python-output
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out"))
+                   (pyout (assoc-ref outputs "python")))
+               (substitute* "ffi/lang/python/Makefile"
+                 ;; adjust prefix for python package
+                 (("PREFIX\\s*\\??=.*")
+                  (string-append "PREFIX = " pyout "\n"))
+                 ;; fix rpath to include the main package
+                 (("\\WLDFLAGS=" text)
+                  (string-append text "'-Wl,-rpath=" out "/lib '"))
+                 ;; make setuptools install into the prefix, see
+                 ;; guix/build/python-build-system.scm for explanation
+                 (("\\ssetup.py\\s+install\\s")
+                  " setup.py install --root=/ --single-version-externally-managed "))
+               #t)))
+         (add-after 'unpack 'fix-Makefiles
+           (lambda _
+             (substitute* '("openpgp-ffi/Makefile")
+               (("^check-headers: force-build") "check-headers:"))))
+         (add-after 'unpack 'remove-other-crypto-features
+           (lambda _
+             (substitute* '("openpgp-ffi/Cargo.toml" "ffi/Cargo.toml")
+               (("^crypto-cng =" line) (string-append "# " line))
+               (("^crypto-rust =" line) (string-append "# " line)))
+             #t))
+         (add-after 'unpack 'fix-missing-feature
+           (lambda _
+             (substitute* '("ffi/Cargo.toml")
+               (("^(tokio = .* features = \\[)" line)
+                (string-append line "\"net\", ")))
+             #t))
+         (add-after 'unpack 'unbundle-crates
+           (lambda _
+             (substitute* '("openpgp-ffi/Cargo.toml" "ffi/Cargo.toml")
+               (("path = \"\\.\\./(openpgp|store|net|ipc)\",") ""))
+             #t)))))
+    (home-page "https://sequoia-pgp.org")
+    (synopsis "C/FFI interfaces for Sequoia-PGP")
+    (description "This package provides a C and FFI interface to both the
+low-level and a high-level API of Sequoia-PGP.
+
+Use with caution: This is an \"unofficial\" package, which are not officially
+released, but part of the Sequoia-PGP v1.6.0 archive.  So this package might
+even go away.")
+    (license license:lgpl2.0+)))
+
 (define-public sequoia
   (package
     (name "sequoia")
-- 
2.30.2