File Coverage

File:Dpkg/OpenPGP/Backend/SOP.pm
Coverage:83.8%

linestmtbrancondsubpodtimecode
1# Copyright © 2021-2022 Guillem Jover <guillem@debian.org>
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16=encoding utf8
17
18 - 30
=head1 NAME

Dpkg::OpenPGP::Backend::SOP - OpenPGP backend for SOP

=head1 DESCRIPTION

This module provides a class that implements the OpenPGP backend
for the Stateless OpenPGP Command-Line Interface, as described in
L<https://datatracker.ietf.org/doc/draft-dkg-openpgp-stateless-cli>.

B<Note>: This is a private module, its API can change at any time.

=cut
31
32package Dpkg::OpenPGP::Backend::SOP 0.01;
33
34
216
216
216
576
213
4551
use strict;
35
216
216
216
495
141
6717
use warnings;
36
37
216
216
216
501
216
717
use POSIX qw(:sys_wait_h);
38
39
216
216
216
21135
75
8844
use Dpkg::ErrorHandling;
40
216
216
216
426
216
4788
use Dpkg::IPC;
41
216
216
216
432
144
7932
use Dpkg::OpenPGP::ErrorCodes;
42
43
216
216
216
291
279
576
use parent qw(Dpkg::OpenPGP::Backend);
44
45# - Once "gosop" implements inline-verify and inline-sign, add as alternative.
46#   Ref: https://github.com/ProtonMail/gosop/issues/6
47# - Once "gosop" can handle big keyrings.
48#   Ref: https://github.com/ProtonMail/gosop/issues/25
49# - Once "hop" implements the new SOP draft, add as alternative.
50#   Ref: https://salsa.debian.org/clint/hopenpgp-tools/-/issues/4
51# - Once the SOP MR !23 is finalized and merged, implement a way to select
52#   whether the SOP instance supports the expected draft.
53#   Ref: https://gitlab.com/dkg/openpgp-stateless-cli/-/merge_requests/23
54# - Once the SOP issue #42 is resolved we can perhaps remove the alternative
55#   dependencies and commands to check?
56#   Ref: https://gitlab.com/dkg/openpgp-stateless-cli/-/issues/42
57
58sub DEFAULT_CMD {
59
354
0
862
    return [ qw(sqop pgpainless-cli) ];
60}
61
62sub _sop_exec
63{
64
3315
7232
    my ($self, $io, @exec) = @_;
65
66
3315
7858
    return OPENPGP_MISSING_CMD unless $self->{cmd};
67
68
3315
15227
    $io->{out} //= '/dev/null';
69
3315
3016
    my $stderr;
70    spawn(exec => [ $self->{cmd}, @exec ],
71          wait_child => 1, nocheck => 1, timeout => 10,
72          from_file => $io->{in}, to_file => $io->{out},
73
3315
20724
          error_to_string => \$stderr);
74
3210
37347
    if (WIFEXITED($?)) {
75
3210
8106
        my $status = WEXITSTATUS($?);
76
3210
0
8059
0
        print { *STDERR } "$stderr" if $status;
77
3210
98214
        return $status;
78    } else {
79
0
0
        subprocerr("$self->{cmd} @exec");
80    }
81}
82
83sub armor
84{
85
996
0
2004
    my ($self, $type, $in, $out) = @_;
86
87    # We ignore the $type, and let "sop" handle this automatically.
88
996
4127
    return $self->_sop_exec({ in => $in, out => $out }, 'armor');
89}
90
91sub dearmor
92{
93
654
0
1164
    my ($self, $type, $in, $out) = @_;
94
95    # We ignore the $type, and let "sop" handle this automatically.
96
654
2478
    return $self->_sop_exec({ in => $in, out => $out }, 'dearmor');
97}
98
99sub inline_verify
100{
101
846
0
1495
    my ($self, $inlinesigned, $data, @certs) = @_;
102
103
846
3445
    return $self->_sop_exec({ in => $inlinesigned, out => $data },
104                            'inline-verify', @certs);
105}
106
107sub verify
108{
109
555
0
1483
    my ($self, $data, $sig, @certs) = @_;
110
111
555
2052
    return $self->_sop_exec({ in => $data }, 'verify', $sig, @certs);
112}
113
114sub inline_sign
115{
116
264
0
469
    my ($self, $data, $inlinesigned, $key) = @_;
117
118
264
475
    return OPENPGP_NEEDS_KEYSTORE if $key->needs_keystore();
119
120
264
1353
    return $self->_sop_exec({ in => $data, out => $inlinesigned },
121                            qw(inline-sign --as clearsigned --), $key->handle);
122}
123
124 - 130
=head1 CHANGES

=head2 Version 0.xx

This is a private module.

=cut
131
1321;