1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/* This example demonstrates how to use the low-level interface to
decrypt a file. */
#define _GNU_SOURCE
#include <assert.h>
#include <error.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sequoia/openpgp.h>
struct decrypt_cookie {
pgp_tpk_t key;
int get_secret_keys_called;
};
static pgp_status_t
get_public_keys_cb (void *cookie_raw,
pgp_keyid_t *keyids, size_t keyids_len,
pgp_tpk_t **tpks, size_t *tpk_len,
void (**our_free)(void *))
{
/* Feed the TPKs to the verifier here. */
*tpks = NULL;
*tpk_len = 0;
*our_free = free;
return PGP_STATUS_SUCCESS;
}
static pgp_status_t
check_signatures_cb(void *cookie_opaque,
pgp_verification_results_t results, size_t levels)
{
/* Implement your verification policy here. */
return PGP_STATUS_SUCCESS;
}
static pgp_status_t
get_secret_keys_cb (void *cookie_opaque,
pgp_pkesk_t *pkesks, size_t pkesk_count,
pgp_skesk_t *skesks, size_t skesk_count,
pgp_secret_t *secret)
{
pgp_error_t err;
struct decrypt_cookie *cookie = cookie_opaque;
/* Prevent iterations, we only have one key to offer. */
if (cookie->get_secret_keys_called)
return PGP_STATUS_UNKNOWN_ERROR;
cookie->get_secret_keys_called = 1;
for (int i = 0; i < pkesk_count; i++) {
pgp_pkesk_t pkesk = pkesks[i];
pgp_keyid_t keyid = pgp_pkesk_recipient (pkesk);
pgp_tpk_key_iter_t key_iter = pgp_tpk_key_iter_all (cookie->key);
pgp_key_t key;
while ((key = pgp_tpk_key_iter_next (key_iter, NULL, NULL))) {
pgp_keyid_t this_keyid = pgp_key_keyid (key);
int match = pgp_keyid_equal (this_keyid, keyid);
pgp_keyid_free (this_keyid);
if (match)
break;
pgp_key_free (key);
}
pgp_tpk_key_iter_free (key_iter);
pgp_keyid_free (keyid);
if (! key)
continue;
uint8_t algo;
uint8_t session_key[1024];
size_t session_key_len = sizeof session_key;
if (pgp_pkesk_decrypt (&err,
pkesk, key, &algo,
session_key, &session_key_len)) {
error (1, 0, "pgp_pkesk_decrypt: %s", pgp_error_to_string (err));
}
pgp_key_free (key);
*secret = pgp_secret_cached (algo, session_key, session_key_len);
return PGP_STATUS_SUCCESS;
}
return PGP_STATUS_UNKNOWN_ERROR;
}
int
main (int argc, char **argv)
{
pgp_status_t rc;
pgp_error_t err;
pgp_tpk_t tpk;
pgp_reader_t source;
pgp_writer_t sink;
if (argc != 2)
error (1, 0, "Usage: %s <keyfile> <cipher >plain", argv[0]);
tpk = pgp_tpk_from_file (&err, argv[1]);
if (tpk == NULL)
error (1, 0, "pgp_tpk_from_file: %s", pgp_error_to_string (err));
source = pgp_reader_from_fd (STDIN_FILENO);
assert (source);
sink = pgp_writer_from_fd (STDOUT_FILENO);
assert (sink);
struct decrypt_cookie cookie = {
.key = tpk,
.get_secret_keys_called = 0,
};
rc = pgp_decrypt (&err, source, sink,
get_public_keys_cb, get_secret_keys_cb,
check_signatures_cb, &cookie);
if (rc)
error (1, 0, "pgp_decrypt: %s", pgp_error_to_string (err));
pgp_writer_free (sink);
pgp_reader_free (source);
pgp_tpk_free (tpk);
return 0;
}
|