aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/openpgp
diff options
context:
space:
mode:
authorlv-426 <oxcafebaby@yahoo.com>2008-06-22 18:20:35 +0000
committerlv-426 <oxcafebaby@yahoo.com>2008-06-22 18:20:35 +0000
commita0339d2458867dbe9485499265641ff205063445 (patch)
tree055b38828b3696520408a32edf81df5bb37400f0 /src/daemon/https/openpgp
parent97c026da05495b83f1511906c2ca027e12ef6cf7 (diff)
downloadlibmicrohttpd-a0339d2458867dbe9485499265641ff205063445.tar.gz
libmicrohttpd-a0339d2458867dbe9485499265641ff205063445.zip
initial GNU TLS import - this should reduce in size considerable
Diffstat (limited to 'src/daemon/https/openpgp')
-rw-r--r--src/daemon/https/openpgp/Makefile.am27
-rw-r--r--src/daemon/https/openpgp/compat.c252
-rw-r--r--src/daemon/https/openpgp/extras.c165
-rw-r--r--src/daemon/https/openpgp/gnutls_extra.c110
-rw-r--r--src/daemon/https/openpgp/gnutls_extra.h50
-rw-r--r--src/daemon/https/openpgp/gnutls_ia.c905
-rw-r--r--src/daemon/https/openpgp/gnutls_openpgp.c973
-rw-r--r--src/daemon/https/openpgp/gnutls_openpgp.h98
-rw-r--r--src/daemon/https/openpgp/openpgp.h182
-rw-r--r--src/daemon/https/openpgp/pgp.c534
-rw-r--r--src/daemon/https/openpgp/pgp_privkey.c134
-rw-r--r--src/daemon/https/openpgp/pgp_verify.c144
12 files changed, 3574 insertions, 0 deletions
diff --git a/src/daemon/https/openpgp/Makefile.am b/src/daemon/https/openpgp/Makefile.am
new file mode 100644
index 00000000..94c27ac1
--- /dev/null
+++ b/src/daemon/https/openpgp/Makefile.am
@@ -0,0 +1,27 @@
1SUBDIRS = .
2
3AM_CPPFLAGS = -I./includes \
4-I$(top_srcdir)/src/daemon/https/includes \
5-I$(top_srcdir)/src/daemon/https/lgl \
6-I$(top_srcdir)/src/daemon/https/x509 \
7-I$(top_srcdir)/src/daemon/https/tls \
8-I$(top_srcdir)/src/daemon/https/openpgp \
9-I$(top_srcdir)/src/daemon/https/opencdk \
10-I$(top_srcdir)/src/daemon/https/minitasn1
11
12noinst_LTLIBRARIES = libopenpgp.la
13
14# libopenpgp_la_LDFLAGS = -l$(top_srcdir)/src/daemon/https/libextra/.lib/libextra.la
15
16libopenpgp_la_SOURCES = \
17pgp_privkey.c \
18compat.c \
19pgp_verify.c \
20extras.c \
21pgp.c
22
23# x libextra source list
24libopenpgp_la_SOURCES += \
25gnutls_openpgp.c \
26gnutls_ia.c \
27gnutls_extra.c
diff --git a/src/daemon/https/openpgp/compat.c b/src/daemon/https/openpgp/compat.c
new file mode 100644
index 00000000..1ba7177a
--- /dev/null
+++ b/src/daemon/https/openpgp/compat.c
@@ -0,0 +1,252 @@
1/*
2 * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
3 *
4 * Author: Timo Schulz, Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/* Compatibility functions on OpenPGP key parsing.
23 */
24
25#include <gnutls_int.h>
26#include <gnutls_errors.h>
27#include <gnutls_openpgp.h>
28#include "openpgp.h"
29
30/*-
31 * gnutls_openpgp_verify_key - Verify all signatures on the key
32 * @cert_list: the structure that holds the certificates.
33 * @cert_list_lenght: the items in the cert_list.
34 * @status: the output of the verification function
35 *
36 * Verify all signatures in the certificate list. When the key
37 * is not available, the signature is skipped.
38 *
39 * The return value is one of the CertificateStatus entries.
40 *
41 * NOTE: this function does not verify using any "web of trust". You
42 * may use GnuPG for that purpose, or any other external PGP application.
43 -*/
44int
45_gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred,
46 const gnutls_datum_t * cert_list,
47 int cert_list_length, unsigned int *status)
48{
49 int ret = 0;
50 gnutls_openpgp_crt_t key = NULL;
51 unsigned int verify = 0, verify_self = 0;
52
53 if (!cert_list || cert_list_length != 1)
54 {
55 gnutls_assert ();
56 return GNUTLS_E_NO_CERTIFICATE_FOUND;
57 }
58
59 ret = gnutls_openpgp_crt_init (&key);
60 if (ret < 0)
61 {
62 gnutls_assert ();
63 return ret;
64 }
65
66 ret =
67 gnutls_openpgp_crt_import (key, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
68 if (ret < 0)
69 {
70 gnutls_assert ();
71 goto leave;
72 }
73
74#ifndef KEYRING_HACK
75 if (cred->keyring != NULL)
76 {
77 ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify);
78 if (ret < 0)
79 {
80 gnutls_assert ();
81 goto leave;
82 }
83 }
84#else
85 {
86 gnutls_openpgp_keyring_t kring;
87
88 ret = gnutls_openpgp_keyring_init (&kring);
89 if (ret < 0)
90 {
91 gnutls_assert ();
92 return ret;
93 }
94
95 ret =
96 gnutls_openpgp_keyring_import (kring, &cred->keyring,
97 cred->keyring_format);
98 if (ret < 0)
99 {
100 gnutls_assert ();
101 gnutls_openpgp_keyring_deinit (kring);
102 return ret;
103 }
104
105 ret = gnutls_openpgp_crt_verify_ring (key, kring, 0, &verify);
106 if (ret < 0)
107 {
108 gnutls_assert ();
109 gnutls_openpgp_keyring_deinit (kring);
110 return ret;
111 }
112 gnutls_openpgp_keyring_deinit (kring);
113 }
114#endif
115
116 /* Now try the self signature. */
117 ret = gnutls_openpgp_crt_verify_self (key, 0, &verify_self);
118 if (ret < 0)
119 {
120 gnutls_assert ();
121 goto leave;
122 }
123
124 *status = verify_self | verify;
125
126#ifndef KEYRING_HACK
127 /* If we only checked the self signature. */
128 if (!cred->keyring)
129#else
130 if (!cred->keyring.data || !cred->keyring.size)
131#endif
132 *status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
133
134
135 ret = 0;
136
137leave:
138 gnutls_openpgp_crt_deinit (key);
139
140 return ret;
141}
142
143/*-
144 * gnutls_openpgp_fingerprint - Gets the fingerprint
145 * @cert: the raw data that contains the OpenPGP public key.
146 * @fpr: the buffer to save the fingerprint.
147 * @fprlen: the integer to save the length of the fingerprint.
148 *
149 * Returns the fingerprint of the OpenPGP key. Depence on the algorithm,
150 * the fingerprint can be 16 or 20 bytes.
151 -*/
152int
153_gnutls_openpgp_fingerprint (const gnutls_datum_t * cert,
154 unsigned char *fpr, size_t * fprlen)
155{
156 gnutls_openpgp_crt_t key;
157 int ret;
158
159 ret = gnutls_openpgp_crt_init (&key);
160 if (ret < 0)
161 {
162 gnutls_assert ();
163 return ret;
164 }
165
166 ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
167 if (ret < 0)
168 {
169 gnutls_assert ();
170 return ret;
171 }
172
173 ret = gnutls_openpgp_crt_get_fingerprint (key, fpr, fprlen);
174 gnutls_openpgp_crt_deinit (key);
175 if (ret < 0)
176 {
177 gnutls_assert ();
178 return ret;
179 }
180
181 return 0;
182}
183
184/*-
185 * gnutls_openpgp_get_raw_key_creation_time - Extract the timestamp
186 * @cert: the raw data that contains the OpenPGP public key.
187 *
188 * Returns the timestamp when the OpenPGP key was created.
189 -*/
190time_t
191_gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * cert)
192{
193 gnutls_openpgp_crt_t key;
194 int ret;
195 time_t tim;
196
197 ret = gnutls_openpgp_crt_init (&key);
198 if (ret < 0)
199 {
200 gnutls_assert ();
201 return ret;
202 }
203
204 ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
205 if (ret < 0)
206 {
207 gnutls_assert ();
208 return ret;
209 }
210
211 tim = gnutls_openpgp_crt_get_creation_time (key);
212
213 gnutls_openpgp_crt_deinit (key);
214
215 return tim;
216}
217
218
219/*-
220 * gnutls_openpgp_get_raw_key_expiration_time - Extract the expire date
221 * @cert: the raw data that contains the OpenPGP public key.
222 *
223 * Returns the time when the OpenPGP key expires. A value of '0' means
224 * that the key doesn't expire at all.
225 -*/
226time_t
227_gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert)
228{
229 gnutls_openpgp_crt_t key;
230 int ret;
231 time_t tim;
232
233 ret = gnutls_openpgp_crt_init (&key);
234 if (ret < 0)
235 {
236 gnutls_assert ();
237 return ret;
238 }
239
240 ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
241 if (ret < 0)
242 {
243 gnutls_assert ();
244 return ret;
245 }
246
247 tim = gnutls_openpgp_crt_get_expiration_time (key);
248
249 gnutls_openpgp_crt_deinit (key);
250
251 return tim;
252}
diff --git a/src/daemon/https/openpgp/extras.c b/src/daemon/https/openpgp/extras.c
new file mode 100644
index 00000000..d3c755d4
--- /dev/null
+++ b/src/daemon/https/openpgp/extras.c
@@ -0,0 +1,165 @@
1/*
2 * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos, Timo Schulz
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/* Functions on OpenPGP keyring parsing
23 */
24
25#include <gnutls_int.h>
26#include <gnutls_datum.h>
27#include <gnutls_global.h>
28#include <gnutls_errors.h>
29#include <gnutls_openpgp.h>
30#include <gnutls_num.h>
31#include "openpgp.h"
32
33/* Keyring stuff. */
34
35/**
36 * gnutls_openpgp_keyring_init - This function initializes a gnutls_openpgp_keyring_t structure
37 * @keyring: The structure to be initialized
38 *-
39 * This function will initialize an OpenPGP keyring structure.
40 *
41 * Returns 0 on success.
42 *
43 **/
44int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring)
45{
46 *keyring = gnutls_calloc(1, sizeof(gnutls_openpgp_keyring_int));
47
48 if (*keyring)
49 return 0; /* success */
50 return GNUTLS_E_MEMORY_ERROR;
51}
52
53/**
54 * gnutls_openpgp_keyring_deinit - This function deinitializes memory used by a gnutls_openpgp_keyring_t structure
55 * @keyring: The structure to be initialized
56 *
57 * This function will deinitialize a keyring structure.
58 *
59 **/
60void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring)
61{
62 if (!keyring)
63 return;
64
65 if (keyring->db)
66 {
67 cdk_keydb_free(keyring->db);
68 keyring->db = NULL;
69 }
70
71 /* In some cases the stream is also stored outside the keydb context
72 and we need to close it here then. */
73 if (keyring->db_stream)
74 {
75 cdk_stream_close(keyring->db_stream);
76 keyring->db_stream = NULL;
77 }
78
79 gnutls_free(keyring);
80}
81
82/**
83 * gnutls_openpgp_keyring_check_id - Check if a key id exists in the keyring
84 * @ring: holds the keyring to check against
85 * @keyid: will hold the keyid to check for.
86 * @flags: unused (should be 0)
87 *
88 * Check if a given key ID exists in the keyring.
89 *
90 * Returns 0 on success (if keyid exists) and a negative error code
91 * on failure.
92 **/
93int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring,
94 const unsigned char keyid[8],
95 unsigned int flags)
96{
97 cdk_pkt_pubkey_t pk;
98 uint32_t id[2];
99
100 id[0] = _gnutls_read_uint32(keyid);
101 id[1] = _gnutls_read_uint32(&keyid[4]);
102
103 if (!cdk_keydb_get_pk(ring->db, id, &pk))
104 {
105 cdk_pk_release(pk);
106 return 0;
107 }
108
109 _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long) id[1]);
110 return GNUTLS_E_NO_CERTIFICATE_FOUND;
111}
112
113/**
114 * gnutls_openpgp_keyring_import - Import a raw- or Base64-encoded OpenPGP keyring
115 * @keyring: The structure to store the parsed key.
116 * @data: The RAW or BASE64 encoded keyring.
117 * @format: One of #gnutls_openpgp_keyring_fmt elements.
118 *
119 * This function will convert the given RAW or Base64 encoded keyring to the
120 * native #gnutls_openpgp_keyring_t format. The output will be stored in
121 * 'keyring'.
122 *
123 * Returns 0 on success.
124 *
125 **/
126int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring,
127 const gnutls_datum_t * data,
128 gnutls_openpgp_crt_fmt_t format)
129{
130 cdk_error_t err;
131 cdk_stream_t input;
132
133 _gnutls_debug_log ("PGP: keyring import format '%s'\n",
134 format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");
135
136 if (format == GNUTLS_OPENPGP_FMT_RAW)
137 {
138 err
139 = cdk_keydb_new(&keyring->db, CDK_DBTYPE_DATA, data->data, data->size);
140 if (err)
141 gnutls_assert ();
142 return _gnutls_map_cdk_rc (err);
143 }
144
145 /* Create a new stream from the given data, which means to
146 allocate a new stream and to write the data in the stream.
147 Then push the armor filter to decode the data and to store
148 it in the raw format. */
149 err = cdk_stream_tmp_from_mem(data->data, data->size, &input);
150 if (!err)
151 err = cdk_stream_set_armor_flag(input, 0);
152 if (!err)
153 err = cdk_keydb_new_from_stream(&keyring->db, 0, input);
154 if (err)
155 {
156 cdk_stream_close(input);
157 gnutls_assert ();
158 }
159 else
160 /* The keydb function will not close the stream itself, so we need to
161 store it separately to close it later. */
162 keyring->db_stream = input;
163
164 return _gnutls_map_cdk_rc (err);
165}
diff --git a/src/daemon/https/openpgp/gnutls_extra.c b/src/daemon/https/openpgp/gnutls_extra.c
new file mode 100644
index 00000000..7c47e3f1
--- /dev/null
+++ b/src/daemon/https/openpgp/gnutls_extra.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2001, 2004, 2005, 2007 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <gnutls_int.h>
23#include <gnutls_errors.h>
24#include <gnutls_extensions.h>
25#include <gnutls_openpgp.h>
26#include <gnutls_extra.h>
27#include <gnutls_extra_hooks.h>
28#include <gnutls_algorithms.h>
29
30/* the number of the compression algorithms available in the compression
31 * structure.
32 */
33extern int _gnutls_comp_algorithms_size;
34
35/* Functions in gnutls that have not been initialized.
36 */
37
38static int _gnutls_init_extra = 0;
39
40/**
41 * gnutls_global_init_extra - This function initializes the global state of gnutls-extra
42 *
43 * This function initializes the global state of gnutls-extra library
44 * to defaults. Returns zero on success.
45 *
46 * Note that gnutls_global_init() has to be called before this
47 * function. If this function is not called then the gnutls-extra
48 * library will not be usable.
49 *
50 **/
51int
52gnutls_global_init_extra (void)
53{
54 int ret;
55
56 /* If the version of libgnutls != version of
57 * libextra, then do not initialize the library.
58 * This is because it may break things.
59 */
60 if (strcmp (gnutls_check_version (NULL), VERSION) != 0)
61 {
62 return GNUTLS_E_LIBRARY_VERSION_MISMATCH;
63 }
64
65 _gnutls_init_extra++;
66
67 if (_gnutls_init_extra != 1)
68 {
69 return 0;
70 }
71
72 /* Register the openpgp functions. This is because some
73 * of them are defined to be NULL in the main library.
74 */
75 _gnutls_add_openpgp_functions (_gnutls_openpgp_verify_key,
76 _gnutls_openpgp_get_raw_key_creation_time,
77 _gnutls_openpgp_get_raw_key_expiration_time,
78 _gnutls_openpgp_fingerprint,
79 _gnutls_openpgp_request_key,
80 _gnutls_openpgp_raw_key_to_gcert,
81 _gnutls_openpgp_raw_privkey_to_gkey,
82 _gnutls_openpgp_crt_to_gcert,
83 _gnutls_openpgp_privkey_to_gkey,
84 gnutls_openpgp_crt_deinit,
85 gnutls_openpgp_keyring_deinit,
86 gnutls_openpgp_privkey_deinit);
87
88 return 0;
89}
90
91#include <strverscmp.h>
92
93/**
94 * gnutls_extra_check_version - This function checks the library's version
95 * @req_version: the version to check
96 *
97 * Check that the version of the gnutls-extra library is at minimum
98 * the requested one and return the version string; return NULL if the
99 * condition is not satisfied. If a NULL is passed to this function,
100 * no check is done, but the version string is simply returned.
101 *
102 **/
103const char *
104gnutls_extra_check_version (const char *req_version)
105{
106 if (!req_version || strverscmp (req_version, VERSION) <= 0)
107 return VERSION;
108
109 return NULL;
110}
diff --git a/src/daemon/https/openpgp/gnutls_extra.h b/src/daemon/https/openpgp/gnutls_extra.h
new file mode 100644
index 00000000..de7fc889
--- /dev/null
+++ b/src/daemon/https/openpgp/gnutls_extra.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 3 of the
11 * License, or (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNUTLS-EXTRA; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 *
23 */
24
25#include <auth_cert.h>
26
27typedef int (*OPENPGP_VERIFY_KEY_FUNC) (const
28 gnutls_certificate_credentials_t,
29 const gnutls_datum_t *, int,
30 unsigned int *);
31
32typedef time_t (*OPENPGP_KEY_CREATION_TIME_FUNC) (const gnutls_datum_t *);
33typedef time_t (*OPENPGP_KEY_EXPIRATION_TIME_FUNC) (const gnutls_datum_t *);
34typedef int (*OPENPGP_KEY_REQUEST) (gnutls_session_t, gnutls_datum_t *,
35 const gnutls_certificate_credentials_t,
36 opaque *, int);
37
38typedef int (*OPENPGP_FINGERPRINT) (const gnutls_datum_t *,
39 unsigned char *, size_t *);
40
41typedef int (*OPENPGP_RAW_KEY_TO_GCERT) (gnutls_cert *,
42 const gnutls_datum_t *);
43typedef int (*OPENPGP_RAW_PRIVKEY_TO_GKEY) (gnutls_privkey *,
44 const gnutls_datum_t *);
45
46typedef int (*OPENPGP_KEY_TO_GCERT) (gnutls_cert *, gnutls_openpgp_crt_t);
47typedef int (*OPENPGP_PRIVKEY_TO_GKEY) (gnutls_privkey *,
48 gnutls_openpgp_privkey_t);
49typedef void (*OPENPGP_KEY_DEINIT) (gnutls_openpgp_crt_t);
50typedef void (*OPENPGP_PRIVKEY_DEINIT) (gnutls_openpgp_privkey_t);
diff --git a/src/daemon/https/openpgp/gnutls_ia.c b/src/daemon/https/openpgp/gnutls_ia.c
new file mode 100644
index 00000000..55b22e9c
--- /dev/null
+++ b/src/daemon/https/openpgp/gnutls_ia.c
@@ -0,0 +1,905 @@
1/*
2 * Copyright (C) 2005, 2006 Free Software Foundation
3 *
4 * Author: Simon Josefsson
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "gnutls_int.h"
23#include "gnutls_record.h"
24#include "gnutls_errors.h"
25#include "gnutls_num.h"
26#include "gnutls_state.h"
27
28#define CHECKSUM_SIZE 12
29
30struct gnutls_ia_client_credentials_st
31{
32 gnutls_ia_avp_func avp_func;
33 void *avp_ptr;
34};
35
36struct gnutls_ia_server_credentials_st
37{
38 gnutls_ia_avp_func avp_func;
39 void *avp_ptr;
40};
41
42static const char server_finished_label[] = "server phase finished";
43static const char client_finished_label[] = "client phase finished";
44static const char inner_permutation_label[] = "inner secret permutation";
45static const char challenge_label[] = "inner application challenge";
46
47/*
48 * The TLS/IA packet is the InnerApplication token, described as
49 * follows in draft-funk-tls-inner-application-extension-01.txt:
50 *
51 * enum {
52 * application_payload(0), intermediate_phase_finished(1),
53 * final_phase_finished(2), (255)
54 * } InnerApplicationType;
55 *
56 * struct {
57 * InnerApplicationType msg_type;
58 * uint24 length;
59 * select (InnerApplicationType) {
60 * case application_payload: ApplicationPayload;
61 * case intermediate_phase_finished: IntermediatePhaseFinished;
62 * case final_phase_finished: FinalPhaseFinished;
63 * } body;
64 * } InnerApplication;
65 *
66 */
67
68/* Send TLS/IA data. If data==NULL && sizeofdata==NULL, then the last
69 send was interrupted for some reason, and then we try to send it
70 again. Returns the number of bytes sent, or an error code. If
71 this return E_AGAIN and E_INTERRUPTED, call this function again
72 with data==NULL&&sizeofdata=0NULL until it returns successfully. */
73static ssize_t
74_gnutls_send_inner_application (gnutls_session_t session,
75 gnutls_ia_apptype_t msg_type,
76 const char *data, size_t sizeofdata)
77{
78 opaque *p = NULL;
79 size_t plen = 0;
80 ssize_t len;
81
82 if (data != NULL)
83 {
84 plen = sizeofdata + 4;
85 p = gnutls_malloc (plen);
86 if (!p)
87 {
88 gnutls_assert ();
89 return GNUTLS_E_MEMORY_ERROR;
90 }
91
92 *(unsigned char *) p = (unsigned char) (msg_type & 0xFF);
93 _gnutls_write_uint24 (sizeofdata, p + 1);
94 memcpy (p + 4, data, sizeofdata);
95 }
96
97 len = _gnutls_send_int (session, GNUTLS_INNER_APPLICATION, -1, p, plen);
98
99 if (p)
100 gnutls_free (p);
101
102 return len;
103}
104
105/* Receive TLS/IA data. Store received TLS/IA message type in
106 *MSG_TYPE, and the data in DATA of max SIZEOFDATA size. Return the
107 number of bytes read, or an error code. */
108static ssize_t
109_gnutls_recv_inner_application (gnutls_session_t session,
110 gnutls_ia_apptype_t * msg_type,
111 opaque * data, size_t sizeofdata)
112{
113 ssize_t len;
114 opaque pkt[4];
115
116 len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, pkt, 4);
117 if (len != 4)
118 {
119 gnutls_assert ();
120 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
121 }
122
123 *msg_type = pkt[0];
124 len = _gnutls_read_uint24 (&pkt[1]);
125
126 if (*msg_type != GNUTLS_IA_APPLICATION_PAYLOAD && len != CHECKSUM_SIZE)
127 {
128 gnutls_assert ();
129 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
130 }
131
132 if (sizeofdata < len)
133 {
134 /* XXX push back pkt to IA buffer? */
135 gnutls_assert ();
136 return GNUTLS_E_SHORT_MEMORY_BUFFER;
137 }
138
139 if (len > 0)
140 {
141 int tmplen = len;
142
143 len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1,
144 data, tmplen);
145 if (len != tmplen)
146 {
147 gnutls_assert ();
148 /* XXX Correct? */
149 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
150 }
151 }
152
153 return len;
154}
155
156/* Apply the TLS PRF using the TLS/IA inner secret as keying material,
157 where the seed is the client random concatenated with the server
158 random concatenated EXTRA of EXTRA_SIZE length (which can be NULL/0
159 respectively). LABEL and LABEL_SIZE is used as the label. The
160 result is placed in pre-allocated OUT of OUTSIZE length. */
161static int
162_gnutls_ia_prf (gnutls_session_t session,
163 size_t label_size,
164 const char *label,
165 size_t extra_size,
166 const char *extra, size_t outsize, opaque * out)
167{
168 int ret;
169 opaque *seed;
170 size_t seedsize = 2 * TLS_RANDOM_SIZE + extra_size;
171
172 seed = gnutls_malloc (seedsize);
173 if (!seed)
174 {
175 gnutls_assert ();
176 return GNUTLS_E_MEMORY_ERROR;
177 }
178
179 memcpy (seed, session->security_parameters.server_random, TLS_RANDOM_SIZE);
180 memcpy (seed + TLS_RANDOM_SIZE, session->security_parameters.client_random,
181 TLS_RANDOM_SIZE);
182 memcpy (seed + 2 * TLS_RANDOM_SIZE, extra, extra_size);
183
184 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
185 TLS_MASTER_SIZE,
186 label, label_size, seed, seedsize, outsize, out);
187
188 gnutls_free (seed);
189
190 return ret;
191}
192
193/**
194 * gnutls_ia_permute_inner_secret:
195 * @session: is a #gnutls_session_t structure.
196 * @session_keys_size: Size of generated session keys (0 if none).
197 * @session_keys: Generated session keys, used to permute inner secret
198 * (NULL if none).
199 *
200 * Permute the inner secret using the generated session keys.
201 *
202 * This can be called in the TLS/IA AVP callback to mix any generated
203 * session keys with the TLS/IA inner secret.
204 *
205 * Return value: Return zero on success, or a negative error code.
206 **/
207int
208gnutls_ia_permute_inner_secret (gnutls_session_t session,
209 size_t session_keys_size,
210 const char *session_keys)
211{
212 return _gnutls_ia_prf (session,
213 sizeof (inner_permutation_label) - 1,
214 inner_permutation_label,
215 session_keys_size,
216 session_keys,
217 TLS_RANDOM_SIZE,
218 session->security_parameters.inner_secret);
219}
220
221/**
222 * gnutls_ia_generate_challenge:
223 * @session: is a #gnutls_session_t structure.
224 * @buffer_size: size of output buffer.
225 * @buffer: pre-allocated buffer to contain @buffer_size bytes of output.
226 *
227 * Generate an application challenge that the client cannot control or
228 * predict, based on the TLS/IA inner secret.
229 *
230 * Return value: Returns 0 on success, or an negative error code.
231 **/
232int
233gnutls_ia_generate_challenge (gnutls_session_t session,
234 size_t buffer_size, char *buffer)
235{
236 return _gnutls_ia_prf (session,
237 sizeof (challenge_label) - 1,
238 challenge_label, 0, NULL, buffer_size, buffer);
239}
240
241/**
242 * gnutls_ia_extract_inner_secret:
243 * @session: is a #gnutls_session_t structure.
244 * @buffer: pre-allocated buffer to hold 48 bytes of inner secret.
245 *
246 * Copy the 48 bytes large inner secret into the specified buffer
247 *
248 * This function is typically used after the TLS/IA handshake has
249 * concluded. The TLS/IA inner secret can be used as input to a PRF
250 * to derive session keys. Do not use the inner secret directly as a
251 * session key, because for a resumed session that does not include an
252 * application phase, the inner secret will be identical to the inner
253 * secret in the original session. It is important to include, for
254 * example, the client and server randomness when deriving a sesssion
255 * key from the inner secret.
256 **/
257void
258gnutls_ia_extract_inner_secret (gnutls_session_t session, char *buffer)
259{
260 memcpy (buffer, session->security_parameters.inner_secret, TLS_MASTER_SIZE);
261}
262
263/**
264 * gnutls_ia_endphase_send:
265 * @session: is a #gnutls_session_t structure.
266 * @final_p: Set iff this should signal the final phase.
267 *
268 * Send a TLS/IA end phase message.
269 *
270 * In the client, this should only be used to acknowledge an end phase
271 * message sent by the server.
272 *
273 * In the server, this can be called instead of gnutls_ia_send() if
274 * the server wishes to end an application phase.
275 *
276 * Return value: Return 0 on success, or an error code.
277 **/
278int
279gnutls_ia_endphase_send (gnutls_session_t session, int final_p)
280{
281 opaque local_checksum[CHECKSUM_SIZE];
282 int client = session->security_parameters.entity == GNUTLS_CLIENT;
283 const char *label = client ? client_finished_label : server_finished_label;
284 int size_of_label = client ? sizeof (client_finished_label) :
285 sizeof (server_finished_label);
286 ssize_t len;
287 int ret;
288
289 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
290 TLS_MASTER_SIZE, label, size_of_label - 1,
291 /* XXX specification unclear on seed. */
292 "", 0, CHECKSUM_SIZE, local_checksum);
293 if (ret < 0)
294 return ret;
295
296 len = _gnutls_send_inner_application
297 (session,
298 final_p ? GNUTLS_IA_FINAL_PHASE_FINISHED :
299 GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED, local_checksum, CHECKSUM_SIZE);
300
301 /* XXX Instead of calling this function over and over...?
302 * while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED)
303 * len = _gnutls_io_write_flush(session);
304 */
305
306 if (len < 0)
307 {
308 gnutls_assert ();
309 return len;
310 }
311
312 return 0;
313}
314
315/**
316 * gnutls_ia_verify_endphase:
317 * @session: is a #gnutls_session_t structure.
318 * @checksum: 12-byte checksum data, received from gnutls_ia_recv().
319 *
320 * Verify TLS/IA end phase checksum data. If verification fails, the
321 * %GNUTLS_A_INNER_APPLICATION_VERIFICATION alert is sent to the other
322 * sie.
323 *
324 * This function is called when gnutls_ia_recv() return
325 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
326 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED.
327 *
328 * Return value: Return 0 on successful verification, or an error
329 * code. If the checksum verification of the end phase message fails,
330 * %GNUTLS_E_IA_VERIFY_FAILED is returned.
331 **/
332int
333gnutls_ia_verify_endphase (gnutls_session_t session, const char *checksum)
334{
335 char local_checksum[CHECKSUM_SIZE];
336 int client = session->security_parameters.entity == GNUTLS_CLIENT;
337 const char *label = client ? server_finished_label : client_finished_label;
338 int size_of_label = client ? sizeof (server_finished_label) :
339 sizeof (client_finished_label);
340 int ret;
341
342 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
343 TLS_MASTER_SIZE,
344 label, size_of_label - 1,
345 "", 0, CHECKSUM_SIZE, local_checksum);
346 if (ret < 0)
347 {
348 gnutls_assert ();
349 return ret;
350 }
351
352 if (memcmp (local_checksum, checksum, CHECKSUM_SIZE) != 0)
353 {
354 ret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
355 GNUTLS_A_INNER_APPLICATION_VERIFICATION);
356 if (ret < 0)
357 {
358 gnutls_assert ();
359 return ret;
360 }
361
362 return GNUTLS_E_IA_VERIFY_FAILED;
363 }
364
365 return 0;
366}
367
368/**
369 * gnutls_ia_send: Send peer the specified TLS/IA data.
370 * @session: is a #gnutls_session_t structure.
371 * @data: contains the data to send
372 * @sizeofdata: is the length of the data
373 *
374 * Send TLS/IA application payload data. This function has the
375 * similar semantics with send(). The only difference is that is
376 * accepts a GNUTLS session, and uses different error codes.
377 *
378 * The TLS/IA protocol is synchronous, so you cannot send more than
379 * one packet at a time. The client always send the first packet.
380 *
381 * To finish an application phase in the server, use
382 * gnutls_ia_endphase_send(). The client cannot end an application
383 * phase unilaterally; rather, a client is required to respond with an
384 * endphase of its own if gnutls_ia_recv indicates that the server has
385 * sent one.
386 *
387 * If the EINTR is returned by the internal push function (the default
388 * is send()} then %GNUTLS_E_INTERRUPTED will be returned. If
389 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must call
390 * this function again, with the same parameters; alternatively you
391 * could provide a %NULL pointer for data, and 0 for size.
392 *
393 * Returns the number of bytes sent, or a negative error code.
394 **/
395ssize_t
396gnutls_ia_send (gnutls_session_t session, const char *data, size_t sizeofdata)
397{
398 ssize_t len;
399
400 len = _gnutls_send_inner_application (session,
401 GNUTLS_IA_APPLICATION_PAYLOAD,
402 data, sizeofdata);
403
404 return len;
405}
406
407/**
408 * gnutls_ia_recv - read data from the TLS/IA protocol
409 * @session: is a #gnutls_session_t structure.
410 * @data: the buffer that the data will be read into, must hold >= 12 bytes.
411 * @sizeofdata: the number of requested bytes, must be >= 12.
412 *
413 * Receive TLS/IA data. This function has the similar semantics with
414 * recv(). The only difference is that is accepts a GNUTLS session,
415 * and uses different error codes.
416 *
417 * If the server attempt to finish an application phase, this function
418 * will return %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
419 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. The caller should then invoke
420 * gnutls_ia_verify_endphase(), and if it runs the client side, also
421 * send an endphase message of its own using gnutls_ia_endphase_send.
422 *
423 * If EINTR is returned by the internal push function (the default is
424 * @code{recv()}) then GNUTLS_E_INTERRUPTED will be returned. If
425 * GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call
426 * this function again, with the same parameters; alternatively you
427 * could provide a NULL pointer for data, and 0 for size.
428 *
429 * Returns the number of bytes received. A negative error code is
430 * returned in case of an error. The
431 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED and
432 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED errors are returned when an
433 * application phase finished message has been sent by the server.
434 **/
435ssize_t
436gnutls_ia_recv (gnutls_session_t session, char *data, size_t sizeofdata)
437{
438 gnutls_ia_apptype_t msg_type;
439 ssize_t len;
440
441 len = _gnutls_recv_inner_application (session, &msg_type, data, sizeofdata);
442
443 if (msg_type == GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED)
444 return GNUTLS_E_WARNING_IA_IPHF_RECEIVED;
445 else if (msg_type == GNUTLS_IA_FINAL_PHASE_FINISHED)
446 return GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
447
448 return len;
449}
450
451/* XXX rewrite the following two functions as state machines, to
452 handle EAGAIN/EINTERRUPTED? just add more problems to callers,
453 though. */
454
455int
456_gnutls_ia_client_handshake (gnutls_session_t session)
457{
458 char *buf = NULL;
459 size_t buflen = 0;
460 char tmp[1024]; /* XXX */
461 ssize_t len;
462 int ret;
463 const struct gnutls_ia_client_credentials_st *cred =
464 _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
465
466 if (cred == NULL)
467 return GNUTLS_E_INTERNAL_ERROR;
468
469 while (1)
470 {
471 char *avp;
472 size_t avplen;
473
474 ret = cred->avp_func (session, cred->avp_ptr,
475 buf, buflen, &avp, &avplen);
476 if (ret)
477 {
478 int tmpret;
479 tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
480 GNUTLS_A_INNER_APPLICATION_FAILURE);
481 if (tmpret < 0)
482 gnutls_assert ();
483 return ret;
484 }
485
486 len = gnutls_ia_send (session, avp, avplen);
487 gnutls_free (avp);
488 if (len < 0)
489 return len;
490
491 len = gnutls_ia_recv (session, tmp, sizeof (tmp));
492 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
493 len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
494 {
495 ret = gnutls_ia_verify_endphase (session, tmp);
496 if (ret < 0)
497 return ret;
498
499 ret = gnutls_ia_endphase_send
500 (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED);
501 if (ret < 0)
502 return ret;
503 }
504
505 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
506 {
507 buf = NULL;
508 buflen = 0;
509 continue;
510 }
511 else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
512 break;
513
514 if (len < 0)
515 return len;
516
517 buflen = len;
518 buf = tmp;
519 }
520
521 return 0;
522}
523
524int
525_gnutls_ia_server_handshake (gnutls_session_t session)
526{
527 gnutls_ia_apptype_t msg_type;
528 ssize_t len;
529 char buf[1024];
530 int ret;
531 const struct gnutls_ia_server_credentials_st *cred =
532 _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
533
534 if (cred == NULL)
535 return GNUTLS_E_INTERNAL_ERROR;
536
537 do
538 {
539 char *avp;
540 size_t avplen;
541
542 len = gnutls_ia_recv (session, buf, sizeof (buf));
543 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
544 len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
545 {
546 ret = gnutls_ia_verify_endphase (session, buf);
547 if (ret < 0)
548 return ret;
549 }
550
551 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
552 continue;
553 else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
554 break;
555
556 if (len < 0)
557 return len;
558
559 avp = NULL;
560 avplen = 0;
561
562 ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen);
563 if (ret < 0)
564 {
565 int tmpret;
566 tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
567 GNUTLS_A_INNER_APPLICATION_FAILURE);
568 if (tmpret < 0)
569 gnutls_assert ();
570 return ret;
571 }
572
573 msg_type = ret;
574
575 if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD)
576 {
577 ret = gnutls_ia_endphase_send (session, msg_type ==
578 GNUTLS_IA_FINAL_PHASE_FINISHED);
579 if (ret < 0)
580 return ret;
581 }
582 else
583 {
584 len = gnutls_ia_send (session, avp, avplen);
585 gnutls_free (avp);
586 if (len < 0)
587 return len;
588 }
589 }
590 while (1);
591
592 return 0;
593}
594
595/**
596 * gnutls_ia_handshake_p:
597 * @session: is a #gnutls_session_t structure.
598 *
599 * Predicate to be used after gnutls_handshake() to decide whether to
600 * invoke gnutls_ia_handshake(). Usable by both clients and servers.
601 *
602 * Return value: non-zero if TLS/IA handshake is expected, zero
603 * otherwise.
604 **/
605int
606gnutls_ia_handshake_p (gnutls_session_t session)
607{
608 tls_ext_st *ext = &session->security_parameters.extensions;
609
610 /* Either local side or peer doesn't do TLS/IA: don't do IA */
611
612 if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable)
613 return 0;
614
615 /* Not resuming or we don't allow skipping on resumption locally: do IA */
616
617 if (!ext->gnutls_ia_allowskip || !gnutls_session_is_resumed (session))
618 return 1;
619
620 /* If we're resuming and we and the peer both allow skipping on resumption:
621 * don't do IA */
622
623 return !ext->gnutls_ia_peer_allowskip;
624}
625
626
627/**
628 * gnutls_ia_handshake:
629 * @session: is a #gnutls_session_t structure.
630 *
631 * Perform a TLS/IA handshake. This should be called after
632 * gnutls_handshake() iff gnutls_ia_handshake_p().
633 *
634 * Return 0 on success, or an error code.
635 **/
636int
637gnutls_ia_handshake (gnutls_session_t session)
638{
639 int ret;
640
641 if (session->security_parameters.entity == GNUTLS_CLIENT)
642 ret = _gnutls_ia_client_handshake (session);
643 else
644 ret = _gnutls_ia_server_handshake (session);
645
646 return ret;
647}
648
649/**
650 * gnutls_ia_allocate_client_credentials - Used to allocate an gnutls_ia_server_credentials_t structure
651 * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure.
652 *
653 * This structure is complex enough to manipulate directly thus this
654 * helper function is provided in order to allocate it.
655 *
656 * Adding this credential to a session will enable TLS/IA, and will
657 * require an Application Phase after the TLS handshake (if the server
658 * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the
659 * TLS/IA mode.
660 *
661 * Returns 0 on success.
662 **/
663int
664gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t * sc)
665{
666 *sc = gnutls_calloc (1, sizeof (**sc));
667
668 if (*sc == NULL)
669 return GNUTLS_E_MEMORY_ERROR;
670
671 return 0;
672}
673
674/**
675 * gnutls_ia_free_client_credentials - Used to free an allocated #gnutls_ia_client_credentials_t structure
676 * @sc: is an #gnutls_ia_client_credentials_t structure.
677 *
678 * This structure is complex enough to manipulate directly thus this
679 * helper function is provided in order to free (deallocate) it.
680 *
681 **/
682void
683gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc)
684{
685 gnutls_free (sc);
686}
687
688/**
689 * gnutls_ia_set_client_avp_function - Used to set a AVP callback
690 * @cred: is a #gnutls_ia_client_credentials_t structure.
691 * @avp_func: is the callback function
692 *
693 * Set the TLS/IA AVP callback handler used for the session.
694 *
695 * The AVP callback is called to process AVPs received from the
696 * server, and to get a new AVP to send to the server.
697 *
698 * The callback's function form is:
699 * int (*avp_func) (gnutls_session_t session, void *ptr,
700 * const char *last, size_t lastlen,
701 * char **next, size_t *nextlen);
702 *
703 * The @session parameter is the #gnutls_session_t structure
704 * corresponding to the current session. The @ptr parameter is the
705 * application hook pointer, set through
706 * gnutls_ia_set_client_avp_ptr(). The AVP received from the server
707 * is present in @last of @lastlen size, which will be %NULL on the
708 * first invocation. The newly allocated output AVP to send to the
709 * server should be placed in *@next of *@nextlen size.
710 *
711 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
712 * generated session keys with the TLS/IA inner secret.
713 *
714 * Return 0 (%GNUTLS_IA_APPLICATION_PAYLOAD) on success, or a negative
715 * error code to abort the TLS/IA handshake.
716 *
717 * Note that the callback must use allocate the @next parameter using
718 * gnutls_malloc(), because it is released via gnutls_free() by the
719 * TLS/IA handshake function.
720 *
721 **/
722void
723gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred,
724 gnutls_ia_avp_func avp_func)
725{
726 cred->avp_func = avp_func;
727}
728
729/**
730 * gnutls_ia_set_client_avp_ptr - Sets a pointer to be sent to TLS/IA callback
731 * @cred: is a #gnutls_ia_client_credentials_t structure.
732 * @ptr: is the pointer
733 *
734 * Sets the pointer that will be provided to the TLS/IA callback
735 * function as the first argument.
736 *
737 **/
738void
739gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, void *ptr)
740{
741 cred->avp_ptr = ptr;
742}
743
744/**
745 * gnutls_ia_get_client_avp_ptr - Returns the pointer which is sent to TLS/IA callback
746 * @cred: is a #gnutls_ia_client_credentials_t structure.
747 *
748 * Returns the pointer that will be provided to the TLS/IA callback
749 * function as the first argument.
750 *
751 **/
752void *
753gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred)
754{
755 return cred->avp_ptr;
756}
757
758/**
759 * gnutls_ia_allocate_server_credentials - Used to allocate an gnutls_ia_server_credentials_t structure
760 * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure.
761 *
762 * This structure is complex enough to manipulate directly thus this
763 * helper function is provided in order to allocate it.
764 *
765 * Adding this credential to a session will enable TLS/IA, and will
766 * require an Application Phase after the TLS handshake (if the client
767 * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the
768 * TLS/IA mode.
769 *
770 * Returns 0 on success.
771 **/
772int
773gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t * sc)
774{
775 *sc = gnutls_calloc (1, sizeof (**sc));
776
777 if (*sc == NULL)
778 return GNUTLS_E_MEMORY_ERROR;
779
780 return 0;
781}
782
783/**
784 * gnutls_ia_free_server_credentials - Used to free an allocated #gnutls_ia_server_credentials_t structure
785 * @sc: is an #gnutls_ia_server_credentials_t structure.
786 *
787 * This structure is complex enough to manipulate directly thus this
788 * helper function is provided in order to free (deallocate) it.
789 *
790 **/
791void
792gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc)
793{
794 gnutls_free (sc);
795}
796
797/**
798 * gnutls_ia_set_server_credentials_function - Used to set a AVP callback
799 * @cred: is a #gnutls_ia_server_credentials_t structure.
800 * @func: is the callback function
801 *
802 * Set the TLS/IA AVP callback handler used for the session.
803 *
804 * The callback's function form is:
805 * int (*avp_func) (gnutls_session_t session, void *ptr,
806 * const char *last, size_t lastlen,
807 * char **next, size_t *nextlen);
808 *
809 * The @session parameter is the #gnutls_session_t structure
810 * corresponding to the current session. The @ptr parameter is the
811 * application hook pointer, set through
812 * gnutls_ia_set_server_avp_ptr(). The AVP received from the client
813 * is present in @last of @lastlen size. The newly allocated output
814 * AVP to send to the client should be placed in *@next of *@nextlen
815 * size.
816 *
817 * The AVP callback is called to process incoming AVPs from the
818 * client, and to get a new AVP to send to the client. It can also be
819 * used to instruct the TLS/IA handshake to do go into the
820 * Intermediate or Final phases. It return a negative error code, or
821 * an #gnutls_ia_apptype_t message type.
822 *
823 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
824 * generated session keys with the TLS/IA inner secret.
825 *
826 * Specifically, return %GNUTLS_IA_APPLICATION_PAYLOAD (0) to send
827 * another AVP to the client, return
828 * %GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED (1) to indicate that an
829 * IntermediatePhaseFinished message should be sent, and return
830 * %GNUTLS_IA_FINAL_PHASE_FINISHED (2) to indicate that an
831 * FinalPhaseFinished message should be sent. In the last two cases,
832 * the contents of the @next and @nextlen parameter is not used.
833 *
834 * Note that the callback must use allocate the @next parameter using
835 * gnutls_malloc(), because it is released via gnutls_free() by the
836 * TLS/IA handshake function.
837 **/
838void
839gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred,
840 gnutls_ia_avp_func avp_func)
841{
842 cred->avp_func = avp_func;
843}
844
845/**
846 * gnutls_ia_set_server_avp_ptr - Sets a pointer to be sent to TLS/IA callback
847 * @cred: is a #gnutls_ia_client_credentials_t structure.
848 * @ptr: is the pointer
849 *
850 * Sets the pointer that will be provided to the TLS/IA callback
851 * function as the first argument.
852 *
853 **/
854void
855gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, void *ptr)
856{
857 cred->avp_ptr = ptr;
858}
859
860/**
861 * gnutls_ia_get_server_avp_ptr - Returns the pointer which is sent to TLS/IA callback
862 * @cred: is a #gnutls_ia_client_credentials_t structure.
863 *
864 * Returns the pointer that will be provided to the TLS/IA callback
865 * function as the first argument.
866 *
867 **/
868void *
869gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred)
870{
871 return cred->avp_ptr;
872}
873
874/**
875 * gnutls_ia_enable - Indicate willingness for TLS/IA application phases
876 * @session: is a #gnutls_session_t structure.
877 * @allow_skip_on_resume: non-zero if local party allows to skip the
878 * TLS/IA application phases for a resumed session.
879 *
880 * Specify whether we must advertise support for the TLS/IA extension
881 * during the handshake.
882 *
883 * At the client side, we always advertise TLS/IA if gnutls_ia_enable
884 * was called before the handshake; at the server side, we also
885 * require that the client has advertised that it wants to run TLS/IA
886 * before including the advertisement, as required by the protocol.
887 *
888 * Similarly, at the client side we always advertise that we allow
889 * TLS/IA to be skipped for resumed sessions if @allow_skip_on_resume
890 * is non-zero; at the server side, we also require that the session
891 * is indeed resumable and that the client has also advertised that it
892 * allows TLS/IA to be skipped for resumed sessions.
893 *
894 * After the TLS handshake, call gnutls_ia_handshake_p() to find out
895 * whether both parties agreed to do a TLS/IA handshake, before
896 * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_*
897 * functions.
898 **/
899void
900gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
901{
902 session->security_parameters.extensions.gnutls_ia_enable = 1;
903 session->security_parameters.extensions.gnutls_ia_allowskip =
904 allow_skip_on_resume;
905}
diff --git a/src/daemon/https/openpgp/gnutls_openpgp.c b/src/daemon/https/openpgp/gnutls_openpgp.c
new file mode 100644
index 00000000..02469463
--- /dev/null
+++ b/src/daemon/https/openpgp/gnutls_openpgp.c
@@ -0,0 +1,973 @@
1/*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
3 *
4 * Author: Timo Schulz
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "gnutls_int.h"
23#include "gnutls_errors.h"
24#include "gnutls_mpi.h"
25#include "gnutls_cert.h"
26#include "gnutls_datum.h"
27#include "gnutls_global.h"
28#include "gnutls_openpgp.h"
29#include "read-file.h"
30#include <gnutls_str.h>
31#include <gnutls_sig.h>
32#include <stdio.h>
33#include <gcrypt.h>
34#include <time.h>
35#include <sys/stat.h>
36
37#define OPENPGP_NAME_SIZE 256
38
39#define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc)
40
41
42
43static void
44release_mpi_array (mpi_t * arr, size_t n)
45{
46 mpi_t x;
47
48 while (arr && n--)
49 {
50 x = *arr;
51 _gnutls_mpi_release (&x);
52 *arr = NULL;
53 arr++;
54 }
55}
56
57
58/* Map an OpenCDK error type to a GnuTLS error type. */
59int
60_gnutls_map_cdk_rc (int rc)
61{
62 switch (rc)
63 {
64 case CDK_Success:
65 return 0;
66 case CDK_Too_Short:
67 return GNUTLS_E_SHORT_MEMORY_BUFFER;
68 case CDK_General_Error:
69 return GNUTLS_E_INTERNAL_ERROR;
70 case CDK_File_Error:
71 return GNUTLS_E_FILE_ERROR;
72 case CDK_MPI_Error:
73 return GNUTLS_E_MPI_SCAN_FAILED;
74 case CDK_Error_No_Key:
75 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
76 case CDK_Armor_Error:
77 return GNUTLS_E_BASE64_DECODING_ERROR;
78 case CDK_Inv_Value:
79 return GNUTLS_E_INVALID_REQUEST;
80 default:
81 return GNUTLS_E_INTERNAL_ERROR;
82 }
83}
84
85static unsigned long
86buftou32 (const uint8_t * buf)
87{
88 unsigned a;
89 a = buf[0] << 24;
90 a |= buf[1] << 16;
91 a |= buf[2] << 8;
92 a |= buf[3];
93 return a;
94}
95
96static int
97openpgp_pk_to_gnutls_cert (gnutls_cert * cert, cdk_pkt_pubkey_t pk)
98{
99 uint8_t buf[512 + 2];
100 size_t nbytes;
101 int algo, i;
102 int rc = 0;
103
104 if (!cert || !pk)
105 {
106 gnutls_assert ();
107 return GNUTLS_E_INVALID_REQUEST;
108 }
109
110 /* GnuTLS OpenPGP does not support ELG keys */
111 if (is_ELG (pk->pubkey_algo))
112 {
113 gnutls_assert ();
114 return GNUTLS_E_UNWANTED_ALGORITHM;
115 }
116
117 algo = GNUTLS_PK_RSA;
118 cert->subject_pk_algorithm = algo;
119 cert->version = pk->version;
120 cert->cert_type = GNUTLS_CRT_OPENPGP;
121
122 cert->key_usage = 0;
123 if (pk->pubkey_usage & CDK_KEY_USG_SIGN)
124 cert->key_usage = KEY_DIGITAL_SIGNATURE;
125 if (pk->pubkey_usage & CDK_KEY_USG_ENCR)
126 cert->key_usage = KEY_KEY_ENCIPHERMENT;
127 if (!cert->key_usage) /* Fallback code. */
128 {
129 if (pk->pubkey_algo == GCRY_PK_DSA || pk->pubkey_algo == GCRY_PK_RSA_S)
130 cert->key_usage = KEY_DIGITAL_SIGNATURE;
131 else if (pk->pubkey_algo == GCRY_PK_RSA_E)
132 cert->key_usage = KEY_KEY_ENCIPHERMENT;
133 else if (pk->pubkey_algo == GCRY_PK_RSA)
134 cert->key_usage = KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
135 }
136
137 cert->params_size = cdk_pk_get_npkey (pk->pubkey_algo);
138 for (i = 0; i < cert->params_size; i++)
139 {
140 nbytes = sizeof (buf) / sizeof (buf[0]);
141 cdk_pk_get_mpi (pk, i, buf, nbytes, &nbytes, NULL);
142 rc = _gnutls_mpi_scan_pgp (&cert->params[i], buf, &nbytes);
143 if (rc)
144 {
145 rc = GNUTLS_E_MPI_SCAN_FAILED;
146 break;
147 }
148 }
149
150 if (rc)
151 release_mpi_array (cert->params, i - 1);
152 return rc;
153}
154
155/*-
156 * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS
157 * @pkey: the GnuTLS private key context to store the key.
158 * @raw_key: the raw data which contains the whole key packets.
159 * @format: the format of the key packets.
160 *
161 * The RFC2440 (OpenPGP Message Format) data is converted into the
162 * GnuTLS specific data which is need to perform secret key operations.
163 *
164 * This function can read both BASE64 and RAW keys.
165 -*/
166int
167_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey,
168 const gnutls_datum_t * raw_key,
169 gnutls_openpgp_crt_fmt_t format)
170{
171 cdk_kbnode_t snode = NULL;
172 cdk_packet_t pkt;
173 cdk_stream_t out;
174 cdk_pkt_seckey_t sk = NULL;
175 int pke_algo, i, j;
176 size_t nbytes = 0;
177 uint8_t buf[512];
178 int rc = 0;
179
180 if (!pkey || raw_key->size <= 0)
181 {
182 gnutls_assert ();
183 return GNUTLS_E_CERTIFICATE_ERROR;
184 }
185
186 rc = cdk_stream_tmp_new (&out);
187 if (rc)
188 return GNUTLS_E_CERTIFICATE_ERROR;
189
190 if (format == GNUTLS_OPENPGP_FMT_BASE64)
191 {
192 rc = cdk_stream_set_armor_flag (out, 0);
193 if (rc)
194 {
195 cdk_stream_close (out);
196 rc = _gnutls_map_cdk_rc (rc);
197 gnutls_assert ();
198 goto leave;
199 }
200 }
201
202 cdk_stream_write (out, raw_key->data, raw_key->size);
203 cdk_stream_seek (out, 0);
204
205 rc = cdk_keydb_get_keyblock (out, &snode);
206 cdk_stream_close (out);
207 if (rc)
208 {
209 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
210 goto leave;
211 }
212
213 pkt = cdk_kbnode_find_packet (snode, CDK_PKT_SECRET_KEY);
214 if (!pkt)
215 {
216 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
217 goto leave;
218 }
219 sk = pkt->pkt.secret_key;
220 pke_algo = sk->pk->pubkey_algo;
221 pkey->params_size = cdk_pk_get_npkey (pke_algo);
222 for (i = 0; i < pkey->params_size; i++)
223 {
224 nbytes = sizeof (buf) / sizeof (buf[0]);
225 cdk_pk_get_mpi (sk->pk, i, buf, nbytes, &nbytes, NULL);
226 rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
227 if (rc)
228 {
229 rc = GNUTLS_E_MPI_SCAN_FAILED;
230 release_mpi_array (pkey->params, i - 1);
231 goto leave;
232 }
233 }
234
235 pkey->params_size += cdk_pk_get_nskey (pke_algo);
236 for (j = 0; j < cdk_pk_get_nskey (pke_algo); j++, i++)
237 {
238 nbytes = sizeof (buf) / sizeof (buf[0]);
239 cdk_sk_get_mpi (sk, j, buf, nbytes, &nbytes, NULL);
240 rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
241 if (rc)
242 {
243 rc = GNUTLS_E_MPI_SCAN_FAILED;
244 release_mpi_array (pkey->params, i - 1);
245 goto leave;
246 }
247 }
248
249 if (is_ELG (pke_algo))
250 return GNUTLS_E_UNWANTED_ALGORITHM;
251 else if (is_RSA (pke_algo))
252 pkey->pk_algorithm = GNUTLS_PK_RSA;
253
254leave:
255 cdk_kbnode_release (snode);
256 return rc;
257}
258
259
260/*-
261 * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs
262 * @cert: the certificate to store the data.
263 * @raw: the buffer which contains the whole OpenPGP key packets.
264 *
265 * The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS
266 * specific certificate.
267 -*/
268int
269_gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert,
270 const gnutls_datum_t * raw)
271{
272 cdk_kbnode_t knode = NULL;
273 cdk_packet_t pkt = NULL;
274 int rc;
275
276 if (!cert)
277 {
278 gnutls_assert ();
279 return GNUTLS_E_INVALID_REQUEST;
280 }
281
282 memset (cert, 0, sizeof *cert);
283
284 rc = cdk_kbnode_read_from_mem (&knode, raw->data, raw->size);
285 if (!(rc = _gnutls_map_cdk_rc (rc)))
286 {
287 pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY);
288 }
289 if (!pkt)
290 {
291 gnutls_assert ();
292 rc = _gnutls_map_cdk_rc (rc);
293 }
294 if (!rc)
295 rc = _gnutls_set_datum (&cert->raw, raw->data, raw->size);
296 if (!rc)
297 rc = openpgp_pk_to_gnutls_cert (cert, pkt->pkt.public_key);
298
299 cdk_kbnode_release (knode);
300 return rc;
301}
302
303/**
304 * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials_t structure
305 * @res: is an #gnutls_certificate_credentials_t structure.
306 * @key: contains an openpgp public key
307 * @pkey: is an openpgp private key
308 *
309 * This function sets a certificate/private key pair in the
310 * gnutls_certificate_credentials_t structure. This function may be called
311 * more than once (in case multiple keys/certificates exist for the
312 * server).
313 *
314 **/
315int
316gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
317 res, gnutls_openpgp_crt_t crt,
318 gnutls_openpgp_privkey_t pkey)
319{
320 int ret;
321
322 /* this should be first */
323
324 res->pkey = gnutls_realloc_fast (res->pkey,
325 (res->ncerts + 1) *
326 sizeof (gnutls_privkey));
327 if (res->pkey == NULL)
328 {
329 gnutls_assert ();
330 return GNUTLS_E_MEMORY_ERROR;
331 }
332
333 ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey);
334 if (ret < 0)
335 {
336 gnutls_assert ();
337 return ret;
338 }
339
340 res->cert_list = gnutls_realloc_fast (res->cert_list,
341 (1 +
342 res->ncerts) *
343 sizeof (gnutls_cert *));
344 if (res->cert_list == NULL)
345 {
346 gnutls_assert ();
347 return GNUTLS_E_MEMORY_ERROR;
348 }
349
350 res->cert_list_length = gnutls_realloc_fast (res->cert_list_length,
351 (1 +
352 res->ncerts) * sizeof (int));
353 if (res->cert_list_length == NULL)
354 {
355 gnutls_assert ();
356 return GNUTLS_E_MEMORY_ERROR;
357 }
358
359 res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert));
360 if (res->cert_list[res->ncerts] == NULL)
361 {
362 gnutls_assert ();
363 return GNUTLS_E_MEMORY_ERROR;
364 }
365
366 res->cert_list_length[res->ncerts] = 1;
367
368 ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt);
369 if (ret < 0)
370 {
371 gnutls_assert ();
372 return ret;
373 }
374
375 res->ncerts++;
376
377 /* FIXME: Check if the keys match. */
378
379 return 0;
380}
381
382
383/*-
384 * gnutls_openpgp_get_key - Retrieve a key from the keyring.
385 * @key: the destination context to save the key.
386 * @keyring: the datum struct that contains all keyring information.
387 * @attr: The attribute (keyid, fingerprint, ...).
388 * @by: What attribute is used.
389 *
390 * This function can be used to retrieve keys by different pattern
391 * from a binary or a file keyring.
392 -*/
393int
394gnutls_openpgp_get_key (gnutls_datum_t * key,
395 gnutls_openpgp_keyring_t keyring, key_attr_t by,
396 opaque * pattern)
397{
398 cdk_kbnode_t knode = NULL;
399 unsigned long keyid[2];
400 unsigned char *buf;
401 void *desc;
402 size_t len;
403 int rc = 0;
404
405 if (!key || !keyring || by == KEY_ATTR_NONE)
406 {
407 gnutls_assert ();
408 return GNUTLS_E_INVALID_REQUEST;
409 }
410
411 memset (key, 0, sizeof *key);
412
413 if (by == KEY_ATTR_SHORT_KEYID)
414 {
415 keyid[0] = buftou32 (pattern);
416 desc = keyid;
417 }
418 else if (by == KEY_ATTR_KEYID)
419 {
420 keyid[0] = buftou32 (pattern);
421 keyid[1] = buftou32 (pattern + 4);
422 desc = keyid;
423 }
424 else
425 desc = pattern;
426 rc = cdk_keydb_search_start (keyring->db, by, desc);
427 if (!rc)
428 rc = cdk_keydb_search (keyring->db, &knode);
429 if (rc)
430 {
431 rc = _gnutls_map_cdk_rc (rc);
432 goto leave;
433 }
434
435 if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY))
436 {
437 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
438 goto leave;
439 }
440
441 /* We let the function allocate the buffer to avoid
442 to call the function twice. */
443 rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len);
444 if (!rc)
445 datum_append (key, buf, len);
446 cdk_free (buf);
447
448leave:
449 cdk_kbnode_release (knode);
450 return rc;
451}
452
453
454/* Convert the stream to a datum. In this case we use the mmap
455 function to map the entire stream to a buffer. */
456static int
457stream_to_datum (cdk_stream_t inp, gnutls_datum_t * raw)
458{
459 uint8_t *buf;
460 size_t buflen;
461
462 if (!inp || !raw)
463 {
464 gnutls_assert ();
465 return GNUTLS_E_INVALID_REQUEST;
466 }
467
468 cdk_stream_mmap (inp, &buf, &buflen);
469 datum_append (raw, buf, buflen);
470 cdk_free (buf);
471
472 if (!buflen)
473 {
474 gnutls_assert ();
475 return GNUTLS_E_INTERNAL_ERROR;
476 }
477
478 return 0;
479}
480
481
482
483/**
484 * gnutls_certificate_set_openpgp_key_mem - Used to set OpenPGP keys
485 * @res: the destination context to save the data.
486 * @cert: the datum that contains the public key.
487 * @key: the datum that contains the secret key.
488 *
489 * This funtion is used to load OpenPGP keys into the GnuTLS credential
490 * structure.
491 * It doesn't matter whether the keys are armored or not, but the files
492 * should only contain one key which should not be encrypted.
493 **/
494int
495gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t
496 res, const gnutls_datum_t * icert,
497 const gnutls_datum_t * ikey,
498 gnutls_openpgp_crt_fmt_t format)
499{
500 gnutls_openpgp_privkey_t key;
501 gnutls_openpgp_crt_t cert;
502 int ret;
503
504 ret = gnutls_openpgp_privkey_init (&key);
505 if (ret < 0)
506 {
507 gnutls_assert ();
508 return ret;
509 }
510
511 ret = gnutls_openpgp_privkey_import (key, ikey, format, NULL, 0);
512 if (ret < 0)
513 {
514 gnutls_assert ();
515 gnutls_openpgp_privkey_deinit (key);
516 return ret;
517 }
518
519 ret = gnutls_openpgp_crt_init (&cert);
520 if (ret < 0)
521 {
522 gnutls_assert ();
523 gnutls_openpgp_privkey_deinit (key);
524 return ret;
525 }
526
527 ret = gnutls_openpgp_crt_import (cert, icert, format);
528 if (ret < 0)
529 {
530 gnutls_assert ();
531 gnutls_openpgp_privkey_deinit (key);
532 gnutls_openpgp_crt_deinit (cert);
533 return ret;
534 }
535
536
537 ret = gnutls_certificate_set_openpgp_key (res, cert, key);
538
539 gnutls_openpgp_privkey_deinit (key);
540 gnutls_openpgp_crt_deinit (cert);
541
542 return ret;
543}
544
545
546/**
547 * gnutls_certificate_set_openpgp_key_file - Used to set OpenPGP keys
548 * @res: the destination context to save the data.
549 * @certfile: the file that contains the public key.
550 * @keyfile: the file that contains the secret key.
551 *
552 * This funtion is used to load OpenPGP keys into the GnuTLS credentials structure.
553 * It doesn't matter whether the keys are armored or not, but the files
554 * should only contain one key which should not be encrypted.
555 **/
556int
557gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t
558 res, const char *certfile,
559 const char *keyfile,
560 gnutls_openpgp_crt_fmt_t format)
561{
562 struct stat statbuf;
563 gnutls_datum_t key, cert;
564 int rc;
565 size_t size;
566
567 if (!res || !keyfile || !certfile)
568 {
569 gnutls_assert ();
570 return GNUTLS_E_INVALID_REQUEST;
571 }
572
573 if (stat (certfile, &statbuf) || stat (keyfile, &statbuf))
574 {
575 gnutls_assert ();
576 return GNUTLS_E_FILE_ERROR;
577 }
578
579 cert.data = read_binary_file (certfile, &size);
580 cert.size = (unsigned int) size;
581 if (cert.data == NULL)
582 {
583 gnutls_assert ();
584 return GNUTLS_E_FILE_ERROR;
585 }
586
587 key.data = read_binary_file (keyfile, &size);
588 key.size = (unsigned int) size;
589 if (key.data == NULL)
590 {
591 gnutls_assert ();
592 free (cert.data);
593 return GNUTLS_E_FILE_ERROR;
594 }
595
596 rc = gnutls_certificate_set_openpgp_key_mem (res, &cert, &key, format);
597
598 free (cert.data);
599 free (key.data);
600
601 if (rc < 0)
602 {
603 gnutls_assert ();
604 return rc;
605 }
606
607 return 0;
608}
609
610
611int
612gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
613{
614 cdk_kbnode_t knode, p, ctx;
615 cdk_packet_t pkt;
616 int nuids;
617
618 if (cert == NULL)
619 {
620 gnutls_assert ();
621 return 0;
622 }
623
624 if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size))
625 {
626 gnutls_assert ();
627 return 0;
628 }
629
630 ctx = NULL;
631 for (nuids = 0;;)
632 {
633 p = cdk_kbnode_walk (knode, &ctx, 0);
634 if (!p)
635 break;
636 pkt = cdk_kbnode_get_packet (p);
637 if (pkt->pkttype == CDK_PKT_USER_ID)
638 nuids++;
639 }
640
641 cdk_kbnode_release (knode);
642 return nuids;
643}
644
645
646/**
647 * gnutls_certificate_set_openpgp_keyring_file - Sets a keyring file for OpenPGP
648 * @c: A certificate credentials structure
649 * @file: filename of the keyring.
650 *
651 * The function is used to set keyrings that will be used internally
652 * by various OpenPGP functions. For example to find a key when it
653 * is needed for an operations. The keyring will also be used at the
654 * verification functions.
655 *
656 **/
657int
658gnutls_certificate_set_openpgp_keyring_file (gnutls_certificate_credentials_t
659 c, const char *file,
660 gnutls_openpgp_crt_fmt_t format)
661{
662 gnutls_datum_t ring;
663 size_t size;
664 int rc;
665
666 if (!c || !file)
667 {
668 gnutls_assert ();
669 return GNUTLS_E_INVALID_REQUEST;
670 }
671
672 ring.data = read_binary_file (file, &size);
673 ring.size = (unsigned int) size;
674 if (ring.data == NULL)
675 {
676 gnutls_assert ();
677 return GNUTLS_E_FILE_ERROR;
678 }
679
680 rc =
681 gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size,
682 format);
683
684 free (ring.data);
685
686 return rc;
687}
688
689/**
690 * gnutls_certificate_set_openpgp_keyring_mem - Add keyring data for OpenPGP
691 * @c: A certificate credentials structure
692 * @data: buffer with keyring data.
693 * @dlen: length of data buffer.
694 *
695 * The function is used to set keyrings that will be used internally
696 * by various OpenPGP functions. For example to find a key when it
697 * is needed for an operations. The keyring will also be used at the
698 * verification functions.
699 *
700 **/
701int
702gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
703 c, const opaque * data,
704 size_t dlen,
705 gnutls_openpgp_crt_fmt_t format)
706{
707#ifndef KEYRING_HACK
708 cdk_stream_t inp;
709 size_t count;
710 uint8_t *buf;
711 gnutls_datum ddata;
712 int rc;
713
714 ddata.data = (void *) data;
715 ddata.size = dlen;
716
717 if (!c || !data || !dlen)
718 {
719 gnutls_assert ();
720 return GNUTLS_E_INVALID_REQUEST;
721 }
722
723 rc = gnutls_openpgp_keyring_init (&c->keyring);
724 if (rc < 0)
725 {
726 gnutls_assert ();
727 return rc;
728 }
729
730 rc = gnutls_openpgp_keyring_import (c->keyring, &ddata, format);
731 if (rc < 0)
732 {
733 gnutls_assert ();
734 gnutls_openpgp_keyring_deinit (c->keyring);
735 return rc;
736 }
737
738 return 0;
739#else
740
741 c->keyring_format = format;
742
743 c->keyring.data = gnutls_malloc (dlen + 1);
744 if (c->keyring.data == NULL)
745 {
746 gnutls_assert ();
747 return GNUTLS_E_MEMORY_ERROR;
748 }
749 memcpy (c->keyring.data, data, dlen);
750 c->keyring.data[dlen] = 0;
751 c->keyring.size = dlen;
752
753#endif
754}
755
756/*-
757 * _gnutls_openpgp_request_key - Receives a key from a database, key server etc
758 * @ret - a pointer to gnutls_datum_t structure.
759 * @cred - a gnutls_certificate_credentials_t structure.
760 * @key_fingerprint - The keyFingerprint
761 * @key_fingerprint_size - the size of the fingerprint
762 *
763 * Retrieves a key from a local database, keyring, or a key server. The
764 * return value is locally allocated.
765 *
766 -*/
767int
768_gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
769 const gnutls_certificate_credentials_t cred,
770 opaque * key_fpr, int key_fpr_size)
771{
772 int rc = 0;
773#ifdef KEYRING_HACK
774 gnutls_openpgp_keyring_t kring;
775#endif
776
777 if (!ret || !cred || !key_fpr)
778 {
779 gnutls_assert ();
780 return GNUTLS_E_INVALID_REQUEST;
781 }
782
783 if (key_fpr_size != 16 && key_fpr_size != 20)
784 return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
785
786#ifndef KEYRING_HACK
787 rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr);
788#else
789 rc = gnutls_openpgp_keyring_init (&kring);
790 if (rc < 0)
791 {
792 gnutls_assert ();
793 return rc;
794 }
795
796 rc =
797 gnutls_openpgp_keyring_import (kring, &cred->keyring,
798 cred->keyring_format);
799 if (rc < 0)
800 {
801 gnutls_assert ();
802 gnutls_openpgp_keyring_deinit (kring);
803 return rc;
804 }
805#endif
806 if (rc >= 0) /* key was found */
807 {
808 rc = 0;
809 goto error;
810 }
811 else
812 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
813
814 /* If the callback function was set, then try this one. */
815 if (session->internals.openpgp_recv_key_func != NULL)
816 {
817 rc = session->internals.openpgp_recv_key_func (session,
818 key_fpr,
819 key_fpr_size, ret);
820 if (rc < 0)
821 {
822 gnutls_assert ();
823 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
824 goto error;
825 }
826 }
827
828error:
829#ifdef KEYRING_HACK
830 gnutls_openpgp_keyring_deinit (kring);
831#endif
832 return rc;
833}
834
835/**
836 * gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys
837 * @session: a TLS session
838 * @func: the callback
839 *
840 * This funtion will set a key retrieval function for OpenPGP keys. This
841 * callback is only useful in server side, and will be used if the peer
842 * sent a key fingerprint instead of a full key.
843 *
844 **/
845void
846gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
847 gnutls_openpgp_recv_key_func func)
848{
849 session->internals.openpgp_recv_key_func = func;
850}
851
852
853/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */
854int
855_gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
856 gnutls_openpgp_privkey_t src)
857{
858 int i, ret;
859
860 memset (dest, 0, sizeof (gnutls_privkey));
861
862 for (i = 0; i < src->pkey.params_size; i++)
863 {
864 dest->params[i] = _gnutls_mpi_copy (src->pkey.params[i]);
865 if (dest->params[i] == NULL)
866 {
867 gnutls_assert ();
868 ret = GNUTLS_E_MEMORY_ERROR;
869 goto cleanup;
870 }
871 }
872
873 dest->pk_algorithm = src->pkey.pk_algorithm;
874 dest->params_size = src->pkey.params_size;
875
876 return 0;
877
878cleanup:
879 for (i = 0; i < src->pkey.params_size; i++)
880 _gnutls_mpi_release (&dest->params[i]);
881 return ret;
882}
883
884/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure.
885 */
886int
887_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
888{
889 opaque *der;
890 size_t der_size = 0;
891 gnutls_datum_t raw;
892 int ret;
893
894 memset (gcert, 0, sizeof (gnutls_cert));
895 gcert->cert_type = GNUTLS_CRT_OPENPGP;
896
897
898 ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW,
899 NULL, &der_size);
900 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
901 {
902 gnutls_assert ();
903 return ret;
904 }
905
906 der = gnutls_malloc (der_size);
907 if (der == NULL)
908 {
909 gnutls_assert ();
910 return GNUTLS_E_MEMORY_ERROR;
911 }
912
913 ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW,
914 der, &der_size);
915 if (ret < 0)
916 {
917 gnutls_assert ();
918 gnutls_free (der);
919 return ret;
920 }
921
922 raw.data = der;
923 raw.size = der_size;
924
925 ret = _gnutls_openpgp_raw_key_to_gcert (gcert, &raw);
926 if (ret < 0)
927 {
928 gnutls_assert ();
929 gnutls_free (der);
930 return ret;
931 }
932
933 gnutls_free (der);
934
935 return 0;
936
937}
938
939
940/**
941 * gnutls_openpgp_privkey_sign_hash - This function will sign the given data using the private key params
942 * @key: Holds the key
943 * @hash: holds the data to be signed
944 * @signature: will contain newly allocated signature
945 *
946 * This function will sign the given hash using the private key.
947 *
948 * Return value: In case of failure a negative value will be returned,
949 * and 0 on success.
950 **/
951int
952gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
953 const gnutls_datum_t * hash,
954 gnutls_datum_t * signature)
955{
956 int result;
957
958 if (key == NULL)
959 {
960 gnutls_assert ();
961 return GNUTLS_E_INVALID_REQUEST;
962 }
963
964 result = _gnutls_sign (key->pkey.pk_algorithm, key->pkey.params,
965 key->pkey.params_size, hash, signature);
966 if (result < 0)
967 {
968 gnutls_assert ();
969 return result;
970 }
971
972 return 0;
973}
diff --git a/src/daemon/https/openpgp/gnutls_openpgp.h b/src/daemon/https/openpgp/gnutls_openpgp.h
new file mode 100644
index 00000000..82e22eee
--- /dev/null
+++ b/src/daemon/https/openpgp/gnutls_openpgp.h
@@ -0,0 +1,98 @@
1#include <config.h>
2
3#ifdef ENABLE_OPENPGP
4
5#ifndef GNUTLS_OPENPGP_H
6#define GNUTLS_OPENPGP_H
7
8#include <auth_cert.h>
9#include <opencdk.h>
10
11typedef struct
12 {
13 int type;
14 size_t size;
15 uint8_t *data;
16 }keybox_blob;
17
18typedef enum
19 {
20 KBX_BLOB_FILE = 0x00,
21 KBX_BLOB_DATA = 0x01
22 }keyring_blob_types;
23
24/* OpenCDK compatible */
25typedef enum
26 {
27 KEY_ATTR_NONE = 0,
28 KEY_ATTR_SHORT_KEYID = 3,
29 KEY_ATTR_KEYID = 4,
30 KEY_ATTR_FPR = 5
31 }key_attr_t;
32
33int
34gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t
35 res, const char *CERTFILE,
36 const char *KEYFILE, gnutls_openpgp_crt_fmt_t);
37
38int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert);
39
40int gnutls_certificate_set_openpgp_keyring_file
41(gnutls_certificate_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t);
42
43int
44gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
45 c, const opaque * data,
46 size_t dlen, gnutls_openpgp_crt_fmt_t);
47
48int gnutls_openpgp_get_key (gnutls_datum_t * key,
49 gnutls_openpgp_keyring_t keyring,
50 key_attr_t by, opaque * pattern);
51
52int gnutls_openpgp_recv_key (const char *host,
53 short port, uint32_t keyid,
54 gnutls_datum_t * key);
55
56/* internal */
57int _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert,
58 const gnutls_datum_t * raw);
59
60extern int
61_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey,
62 const gnutls_datum_t * raw_key,
63 gnutls_openpgp_crt_fmt_t format);
64
65int
66_gnutls_openpgp_request_key (gnutls_session_t,
67 gnutls_datum_t * ret,
68 const gnutls_certificate_credentials_t cred,
69 opaque * key_fpr, int key_fpr_size);
70
71int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t,
72 const gnutls_datum_t * cert_list,
73 int cert_list_length, unsigned int *status);
74int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert,
75 unsigned char *fpr, size_t * fprlen);
76time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t *
77 cert);
78time_t _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t *
79 cert);
80
81int
82gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key);
83
84int
85gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key);
86
87void
88gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key);
89
90int
91gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key,
92 const gnutls_datum_t * data,
93 gnutls_openpgp_crt_fmt_t format,
94 const char *pass, unsigned int flags);
95
96#endif /*GNUTLS_OPENPGP_H */
97
98#endif /*ENABLE_OPENPGP */
diff --git a/src/daemon/https/openpgp/openpgp.h b/src/daemon/https/openpgp/openpgp.h
new file mode 100644
index 00000000..e4ea952b
--- /dev/null
+++ b/src/daemon/https/openpgp/openpgp.h
@@ -0,0 +1,182 @@
1#ifndef OPENPGP_H
2#define OPENPGP_H
3
4#include "config.h"
5
6#ifdef ENABLE_OPENPGP
7
8#ifdef __cplusplus
9extern "C"
10 {
11#endif
12
13#include <gnutls.h>
14#include <gnutls_cert.h>
15#include "opencdk.h"
16
17/* Internal context to store the OpenPGP key. */
18typedef struct gnutls_openpgp_crt_int
19 {
20 cdk_kbnode_t knode;
21 } gnutls_openpgp_crt_int;
22
23/* Internal context to store the private OpenPGP key. */
24typedef struct gnutls_openpgp_privkey_int
25 {
26 gnutls_privkey pkey;
27 } gnutls_openpgp_privkey_int;
28
29typedef struct gnutls_openpgp_keyring_int
30 {
31 cdk_keydb_hd_t db;
32 cdk_stream_t db_stream;
33 } gnutls_openpgp_keyring_int;
34
35typedef struct gnutls_openpgp_keyring_int * gnutls_openpgp_keyring_t;
36/* gnutls_openpgp_cert_t should be defined in gnutls.h */
37
38/* initializes the memory for gnutls_openpgp_crt_t struct */
39int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key);
40/* frees all memory */
41void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key);
42
43int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
44 const gnutls_datum_t * data,
45 gnutls_openpgp_crt_fmt_t format);
46int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key,
47 gnutls_openpgp_crt_fmt_t format,
48 void *output_data,
49 size_t * output_data_size);
50
51/* The key_usage flags are defined in gnutls.h. They are
52 * the GNUTLS_KEY_* definitions.
53 */
54int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t cert,
55 unsigned int *key_usage);
56int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
57 void *fpr,
58 size_t * fprlen);
59
60int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
61 int idx,
62 char *buf,
63 size_t * sizeof_buf);
64
65gnutls_pk_algorithm_t
66 gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key,
67 unsigned int *bits);
68
69int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key);
70
71time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key);
72time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key);
73
74int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
75 unsigned char keyid[8]);
76
77int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
78 const char *hostname);
79
80/* privkey stuff. */
81int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey_t * key);
82void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key);
83gnutls_pk_algorithm_t
84 gnutls_openpgp_privkey_get_pk_algorithm(gnutls_openpgp_privkey_t key,
85 unsigned int *bits);
86int gnutls_openpgp_privkey_import(gnutls_openpgp_privkey_t key,
87 const gnutls_datum_t * data,
88 gnutls_openpgp_crt_fmt_t format,
89 const char *pass,
90 unsigned int flags);
91int gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key,
92 const gnutls_datum_t * hash,
93 gnutls_datum_t * signature);
94
95/* Keyring stuff. */
96
97int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring);
98void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring);
99
100int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring,
101 const gnutls_datum_t * data,
102 gnutls_openpgp_crt_fmt_t format);
103
104int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring,
105 const unsigned char keyid[8],
106 unsigned int flags);
107
108int gnutls_openpgp_crt_verify_ring(gnutls_openpgp_crt_t key,
109 gnutls_openpgp_keyring_t keyring,
110 unsigned int flags,
111 unsigned int *verify
112/* the output of the verification */);
113
114int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key,
115 unsigned int flags,
116 unsigned int *verify);
117
118/* certificate authentication stuff.
119 */
120int gnutls_certificate_set_openpgp_key(gnutls_certificate_credentials_t
121 res,
122 gnutls_openpgp_crt_t key,
123 gnutls_openpgp_privkey_t pkey);
124
125#ifdef __cplusplus
126}
127#endif
128
129int _gnutls_map_cdk_rc(int rc);
130int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
131 int idx,
132 char *buf,
133 size_t * sizeof_buf);
134int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
135 void *fpr,
136 size_t * fprlen);
137gnutls_pk_algorithm_t
138 gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key,
139 unsigned int *bits);
140int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key);
141time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key);
142time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key);
143int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
144 unsigned char keyid[8]);
145
146int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key);
147void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key);
148int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
149 const gnutls_datum_t * data,
150 gnutls_openpgp_crt_fmt_t format);
151int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key,
152 gnutls_openpgp_crt_fmt_t format,
153 void *output_data,
154 size_t * output_data_size);
155
156void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring);
157int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring);
158int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring,
159 const gnutls_datum_t * data,
160 gnutls_openpgp_crt_fmt_t format);
161int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring,
162 const unsigned char keyid[8],
163 unsigned int flags);
164
165int gnutls_openpgp_crt_verify_ring(gnutls_openpgp_crt_t key,
166 gnutls_openpgp_keyring_t keyring,
167 unsigned int flags,
168 unsigned int *verify);
169
170int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key,
171 unsigned int flags,
172 unsigned int *verify);
173
174int _gnutls_openpgp_crt_to_gcert(gnutls_cert * gcert,
175 gnutls_openpgp_crt_t cert);
176int _gnutls_openpgp_privkey_to_gkey(gnutls_privkey * dest,
177 gnutls_openpgp_privkey_t src);
178
179void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key);
180
181#endif /* ENABLE_OPENPGP */
182#endif /* OPENPGP_H */
diff --git a/src/daemon/https/openpgp/pgp.c b/src/daemon/https/openpgp/pgp.c
new file mode 100644
index 00000000..fca307f5
--- /dev/null
+++ b/src/daemon/https/openpgp/pgp.c
@@ -0,0 +1,534 @@
1/*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation
3 *
4 * Author: Timo Schulz, Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/* Functions on OpenPGP key parsing
23 */
24
25#include <gnutls_int.h>
26#include <gnutls_datum.h>
27#include <gnutls_global.h>
28#include <gnutls_errors.h>
29#include "openpgp.h"
30/* x509 */
31#include <rfc2818.h>
32
33/**
34 * gnutls_openpgp_crt_init - This function initializes a gnutls_openpgp_crt_t structure
35 * @key: The structure to be initialized
36 *
37 * This function will initialize an OpenPGP key structure.
38 *
39 * Returns 0 on success.
40 *
41 **/
42int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key)
43{
44 *key = gnutls_calloc(1, sizeof(gnutls_openpgp_crt_int));
45
46 if (*key)
47 return 0; /* success */
48 return GNUTLS_E_MEMORY_ERROR;
49}
50
51/**
52 * gnutls_openpgp_crt_deinit - This function deinitializes memory used by a gnutls_openpgp_crt_t structure
53 * @key: The structure to be initialized
54 *
55 * This function will deinitialize a key structure.
56 **/
57void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key)
58{
59 if (!key)
60 return;
61
62 if (key->knode)
63 {
64 cdk_kbnode_release(key->knode);
65 key->knode = NULL;
66 }
67
68 gnutls_free(key);
69}
70
71/**
72 * gnutls_openpgp_crt_import - This function will import a RAW or BASE64 encoded key
73 * @key: The structure to store the parsed key.
74 * @data: The RAW or BASE64 encoded key.
75 * @format: One of gnutls_openpgp_crt_fmt_t elements.
76 *
77 * This function will convert the given RAW or Base64 encoded key
78 * to the native gnutls_openpgp_crt_t format. The output will be stored in 'key'.
79 *
80 * Returns 0 on success.
81 **/
82int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
83 const gnutls_datum_t * data,
84 gnutls_openpgp_crt_fmt_t format)
85{
86 cdk_stream_t inp;
87 int rc;
88
89 if (format == GNUTLS_OPENPGP_FMT_RAW)
90 rc = cdk_kbnode_read_from_mem(&key->knode, data->data, data->size);
91 else
92 {
93 rc = cdk_stream_tmp_from_mem(data->data, data->size, &inp);
94 if (rc)
95 {
96 rc = _gnutls_map_cdk_rc(rc);
97 gnutls_assert ();
98 return rc;
99 }
100 if (cdk_armor_filter_use(inp))
101 rc = cdk_stream_set_armor_flag(inp, 0);
102 if (!rc)
103 rc = cdk_keydb_get_keyblock(inp, &key->knode);
104 cdk_stream_close(inp);
105 if (rc)
106 {
107 rc = _gnutls_map_cdk_rc(rc);
108 gnutls_assert ();
109 return rc;
110 }
111 }
112
113 return 0;
114}
115
116/**
117 * gnutls_openpgp_crt_export - This function will export a RAW or BASE64 encoded key
118 * @key: Holds the key.
119 * @format: One of gnutls_openpgp_crt_fmt_t elements.
120 * @output_data: will contain the key base64 encoded or raw
121 * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters)
122 *
123 * This function will convert the given key to RAW or Base64 format.
124 * If the buffer provided is not long enough to hold the output, then
125 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
126 *
127 * Returns 0 on success.
128 *
129 **/
130int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key,
131 gnutls_openpgp_crt_fmt_t format,
132 void *output_data,
133 size_t * output_data_size)
134{
135 size_t input_data_size = *output_data_size;
136 size_t calc_size;
137 int rc;
138
139 rc = cdk_kbnode_write_to_mem(key->knode, output_data, output_data_size);
140 if (rc)
141 {
142 rc = _gnutls_map_cdk_rc(rc);
143 gnutls_assert ();
144 return rc;
145 }
146
147 /* FIXME: The first call of this function is with output_data == NULL
148 to figure out the size and the caller expects this error here. */
149 if (!output_data)
150 return GNUTLS_E_SHORT_MEMORY_BUFFER;
151
152 if (format == GNUTLS_OPENPGP_FMT_BASE64)
153 {
154 unsigned char *in = cdk_calloc(1, *output_data_size);
155 memcpy(in, output_data, *output_data_size);
156
157 /* Calculate the size of the encoded data and check if the provided
158 buffer is large enough. */
159 rc = cdk_armor_encode_buffer(in, input_data_size,
160 NULL, 0, &calc_size, CDK_ARMOR_PUBKEY);
161 if (rc || calc_size > input_data_size)
162 {
163 cdk_free(in);
164 *output_data_size = calc_size;
165 rc = _gnutls_map_cdk_rc(CDK_Too_Short);
166 gnutls_assert ();
167 return rc;
168 }
169
170 rc = cdk_armor_encode_buffer(in, input_data_size, output_data,
171 input_data_size, &calc_size,
172 CDK_ARMOR_PUBKEY);
173 cdk_free(in);
174 *output_data_size = calc_size;
175 }
176
177 return 0;
178}
179
180/**
181 * gnutls_openpgp_crt_get_fingerprint - Gets the fingerprint
182 * @key: the raw data that contains the OpenPGP public key.
183 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
184 * @fprlen: the integer to save the length of the fingerprint.
185 *
186 * Returns the fingerprint of the OpenPGP key. Depends on the algorithm,
187 * the fingerprint can be 16 or 20 bytes.
188 **/
189int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
190 void *fpr,
191 size_t * fprlen)
192{
193 cdk_packet_t pkt;
194 cdk_pkt_pubkey_t pk= NULL;
195
196 if (!fpr || !fprlen)
197 {
198 gnutls_assert ();
199 return GNUTLS_E_INVALID_REQUEST;
200 }
201
202 *fprlen = 0;
203
204 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
205 if (!pkt)
206 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
207
208 pk = pkt->pkt.public_key;
209 *fprlen = 20;
210
211 /* FIXME: Check if the draft allows old PGP keys. */
212 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
213 *fprlen = 16;
214 cdk_pk_get_fingerprint(pk, fpr);
215
216 return 0;
217}
218
219int _gnutls_openpgp_count_key_names(gnutls_openpgp_crt_t key)
220{
221 cdk_kbnode_t p, ctx;
222 cdk_packet_t pkt;
223 int nuids;
224
225 if (key == NULL)
226 {
227 gnutls_assert ();
228 return 0;
229 }
230
231 ctx = NULL;
232 nuids = 0;
233 while ((p = cdk_kbnode_walk(key->knode, &ctx, 0)))
234 {
235 pkt = cdk_kbnode_get_packet(p);
236 if (pkt->pkttype == CDK_PKT_USER_ID)
237 nuids++;
238 }
239
240 return nuids;
241}
242
243/**
244 * gnutls_openpgp_crt_get_name - Extracts the userID
245 * @key: the structure that contains the OpenPGP public key.
246 * @idx: the index of the ID to extract
247 * @buf: a pointer to a structure to hold the name
248 * @sizeof_buf: holds the maximum size of @buf, on return hold the
249 * actual/required size of @buf.
250 *
251 * Extracts the userID from the parsed OpenPGP key.
252 *
253 * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
254 * if the index of the ID does not exist.
255 *
256 **/
257int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
258 int idx,
259 char *buf,
260 size_t * sizeof_buf)
261{
262 cdk_kbnode_t ctx= NULL, p;
263 cdk_packet_t pkt= NULL;
264 cdk_pkt_userid_t uid= NULL;
265 int pos = 0;
266
267 if (!key || !buf)
268 {
269 gnutls_assert ();
270 return GNUTLS_E_INVALID_REQUEST;
271 }
272
273 if (idx < 0 || idx > _gnutls_openpgp_count_key_names(key))
274 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
275
276 if (!idx)
277 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_USER_ID);
278 else
279 {
280 pos = 0;
281 while ((p = cdk_kbnode_walk(key->knode, &ctx, 0)))
282 {
283 pkt = cdk_kbnode_get_packet(p);
284 if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx)
285 break;
286 }
287 }
288
289 if (!pkt)
290 {
291 gnutls_assert ();
292 return GNUTLS_E_INTERNAL_ERROR;
293 }
294
295 uid = pkt->pkt.user_id;
296 if (uid->len >= *sizeof_buf)
297 {
298 gnutls_assert ();
299 *sizeof_buf = uid->len + 1;
300 return GNUTLS_E_SHORT_MEMORY_BUFFER;
301 }
302
303 memcpy(buf, uid->name, uid->len);
304 buf[uid->len] = '\0'; /* make sure it's a string */
305 *sizeof_buf = uid->len + 1;
306
307 if (uid->is_revoked)
308 return GNUTLS_E_OPENPGP_UID_REVOKED;
309
310 return 0;
311}
312
313/**
314 * gnutls_openpgp_crt_get_pk_algorithm - This function returns the key's PublicKey algorithm
315 * @key: is an OpenPGP key
316 * @bits: if bits is non null it will hold the size of the parameters' in bits
317 *
318 * This function will return the public key algorithm of an OpenPGP
319 * certificate.
320 *
321 * If bits is non null, it should have enough size to hold the parameters
322 * size in bits. For RSA the bits returned is the modulus.
323 * For DSA the bits returned are of the public exponent.
324 *
325 * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
326 * or a negative value on error.
327 *
328 **/
329gnutls_pk_algorithm_t gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key,
330 unsigned int *bits)
331{
332 cdk_packet_t pkt;
333 int algo;
334
335 if (!key)
336 return GNUTLS_PK_UNKNOWN;
337
338 algo = 0;
339 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
340 if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
341 {
342 if (bits)
343 *bits = cdk_pk_get_nbits(pkt->pkt.public_key);
344 algo = pkt->pkt.public_key->pubkey_algo;
345 if (is_RSA (algo))
346 algo = GNUTLS_PK_RSA;
347 else
348 algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
349 }
350
351 return algo;
352}
353
354/**
355 * gnutls_openpgp_crt_get_version - Extracts the version of the key.
356 * @key: the structure that contains the OpenPGP public key.
357 *
358 * Extract the version of the OpenPGP key.
359 **/
360int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key)
361{
362 cdk_packet_t pkt;
363 int version;
364
365 if (!key)
366 return -1;
367
368 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
369 if (pkt)
370 version = pkt->pkt.public_key->version;
371 else
372 version = 0;
373
374 return version;
375}
376
377/**
378 * gnutls_openpgp_crt_get_creation_time - Extract the timestamp
379 * @key: the structure that contains the OpenPGP public key.
380 *
381 * Returns the timestamp when the OpenPGP key was created.
382 **/
383time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key)
384{
385 cdk_packet_t pkt;
386 time_t timestamp;
387
388 if (!key)
389 return (time_t) - 1;
390
391 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
392 if (pkt)
393 timestamp = pkt->pkt.public_key->timestamp;
394 else
395 timestamp = 0;
396
397 return timestamp;
398}
399
400/**
401 * gnutls_openpgp_crt_get_expiration_time - Extract the expire date
402 * @key: the structure that contains the OpenPGP public key.
403 *
404 * Returns the time when the OpenPGP key expires. A value of '0' means
405 * that the key doesn't expire at all.
406 **/
407time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key)
408{
409 cdk_packet_t pkt;
410 time_t expiredate;
411
412 if (!key)
413 return (time_t) - 1;
414
415 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
416 if (pkt)
417 expiredate = pkt->pkt.public_key->expiredate;
418 else
419 expiredate = 0;
420
421 return expiredate;
422}
423
424/**
425 * gnutls_openpgp_crt_get_id - Gets the keyID
426 * @key: the structure that contains the OpenPGP public key.
427 * @keyid: the buffer to save the keyid.
428 *
429 * Returns the 64-bit keyID of the OpenPGP key.
430 **/
431int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
432 unsigned char keyid[8])
433{
434 cdk_packet_t pkt;
435 uint32_t kid[2];
436
437 if (!key || !keyid)
438 {
439 gnutls_assert ();
440 return GNUTLS_E_INVALID_REQUEST;
441 }
442
443 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
444 if (!pkt)
445 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
446
447 cdk_pk_get_keyid(pkt->pkt.public_key, kid);
448 keyid[0] = kid[0] >> 24;
449 keyid[1] = kid[0] >> 16;
450 keyid[2] = kid[0] >> 8;
451 keyid[3] = kid[0];
452 keyid[4] = kid[1] >> 24;
453 keyid[5] = kid[1] >> 16;
454 keyid[6] = kid[1] >> 8;
455 keyid[7] = kid[1];
456
457 return 0;
458}
459
460/**
461 * gnutls_openpgp_crt_check_hostname - This function compares the given hostname with the hostname in the key
462 * @key: should contain an gnutls_openpgp_crt_t structure
463 * @hostname: A null terminated string that contains a DNS name
464 *
465 * This function will check if the given key's owner matches
466 * the given hostname. This is a basic implementation of the matching
467 * described in RFC2818 (HTTPS), which takes into account wildcards.
468 *
469 * Returns non zero on success, and zero on failure.
470 *
471 **/
472int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
473 const char *hostname)
474{
475 char dnsname[MAX_CN];
476 size_t dnsnamesize;
477 int ret;
478 int i;
479
480 /* Check through all included names. */
481 for (i = 0; !(ret < 0); i++)
482 {
483 dnsnamesize = sizeof (dnsname);
484 ret = gnutls_openpgp_crt_get_name(key, i, dnsname, &dnsnamesize);
485 /* FIXME: ret is not used */
486 if (_gnutls_hostname_compare(dnsname, hostname))
487 return 1;
488 }
489
490 /* not found a matching name */
491 return 0;
492}
493
494/**
495 * gnutls_openpgp_crt_get_key_usage - This function returns the key's usage
496 * @key: should contain a gnutls_openpgp_crt_t structure
497 * @key_usage: where the key usage bits will be stored
498 *
499 * This function will return certificate's key usage, by checking the
500 * key algorithm. The key usage value will ORed values of the:
501 * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT.
502 *
503 * A negative value may be returned in case of parsing error.
504 *
505 */
506int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t key,
507 unsigned int *key_usage)
508{
509 cdk_packet_t pkt;
510 int algo = 0;
511
512 if (!key)
513 return GNUTLS_E_INVALID_REQUEST;
514
515 *key_usage = 0;
516
517 pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
518 if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
519 {
520 algo = pkt->pkt.public_key->pubkey_algo;
521
522 /* FIXME: We need to take a look at the key flags because
523 RSA-E and RSA-S are obsolete. Only RSA is used
524 and the flags are used to set the capabilities. */
525 if (is_DSA (algo) || algo == GCRY_PK_RSA_S)
526 *key_usage |= KEY_DIGITAL_SIGNATURE;
527 else if (algo == GCRY_PK_RSA_E)
528 *key_usage |= KEY_KEY_ENCIPHERMENT;
529 else if (algo == GCRY_PK_RSA)
530 *key_usage |= KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
531 }
532
533 return 0;
534}
diff --git a/src/daemon/https/openpgp/pgp_privkey.c b/src/daemon/https/openpgp/pgp_privkey.c
new file mode 100644
index 00000000..e09697eb
--- /dev/null
+++ b/src/daemon/https/openpgp/pgp_privkey.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/* Functions on OpenPGP privkey parsing
23 */
24
25#include <gnutls_int.h>
26#include <gnutls_datum.h>
27#include <gnutls_global.h>
28#include <gnutls_errors.h>
29#include "openpgp.h"
30#include <gnutls_openpgp.h>
31#include <gnutls_cert.h>
32/* x509 */
33#include <rfc2818.h>
34
35/**
36 * gnutls_openpgp_privkey_init - This function initializes a gnutls_openpgp_privkey_t structure
37 * @key: The structure to be initialized
38 *
39 * This function will initialize an OpenPGP key structure.
40 *
41 * Returns 0 on success.
42 *
43 **/
44int
45gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key)
46{
47 *key = gnutls_calloc (1, sizeof (gnutls_openpgp_privkey_int));
48
49 if (*key)
50 return 0; /* success */
51 return GNUTLS_E_MEMORY_ERROR;
52}
53
54/**
55 * gnutls_openpgp_privkey_deinit - This function deinitializes memory used by a gnutls_openpgp_privkey_t structure
56 * @key: The structure to be initialized
57 *
58 * This function will deinitialize a key structure.
59 *
60 **/
61void
62gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key)
63{
64 if (!key)
65 return;
66
67 _gnutls_gkey_deinit (&key->pkey);
68 gnutls_free (key);
69}
70
71/**
72 * gnutls_openpgp_privkey_import - This function will import a RAW or BASE64 encoded key
73 * @key: The structure to store the parsed key.
74 * @data: The RAW or BASE64 encoded key.
75 * @format: One of gnutls_openpgp_crt_fmt_t elements.
76 * @pass: Unused for now
77 * @flags: should be zero
78 *
79 * This function will convert the given RAW or Base64 encoded key
80 * to the native gnutls_openpgp_privkey_t format. The output will be stored in 'key'.
81 *
82 * Returns 0 on success.
83 *
84 **/
85int
86gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key,
87 const gnutls_datum_t * data,
88 gnutls_openpgp_crt_fmt_t format,
89 const char *pass, unsigned int flags)
90{
91 int rc;
92
93 rc = _gnutls_openpgp_raw_privkey_to_gkey (&key->pkey, data, format);
94 if (rc)
95 {
96 gnutls_assert ();
97 return rc;
98 }
99
100 return 0;
101}
102
103
104/**
105 * gnutls_openpgp_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm
106 * @key: is an OpenPGP key
107 * @bits: if bits is non null it will hold the size of the parameters' in bits
108 *
109 * This function will return the public key algorithm of an OpenPGP
110 * certificate.
111 *
112 * If bits is non null, it should have enough size to hold the parameters
113 * size in bits. For RSA the bits returned is the modulus.
114 * For DSA the bits returned are of the public exponent.
115 *
116 * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
117 * or a negative value on error.
118 *
119 **/
120gnutls_pk_algorithm_t
121gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key,
122 unsigned int *bits)
123{
124 int pk = key->pkey.pk_algorithm;
125
126 if (bits)
127 {
128 *bits = 0;
129 if (pk == GNUTLS_PK_RSA)
130 *bits = _gnutls_mpi_get_nbits (key->pkey.params[0]);
131 }
132
133 return pk;
134}
diff --git a/src/daemon/https/openpgp/pgp_verify.c b/src/daemon/https/openpgp/pgp_verify.c
new file mode 100644
index 00000000..cfa29b69
--- /dev/null
+++ b/src/daemon/https/openpgp/pgp_verify.c
@@ -0,0 +1,144 @@
1/*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
3 *
4 * Author: Timo Schulz, Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS-EXTRA.
7 *
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/* Functions on OpenPGP key parsing
23 */
24
25#include <gnutls_int.h>
26#include <gnutls_errors.h>
27#include <gnutls_openpgp.h>
28#include <gnutls_num.h>
29#include "openpgp.h"
30/* x509 */
31#include <verify.h> /* lib/x509/verify.h */
32
33
34/**
35 * gnutls_openpgp_crt_verify_ring - Verify all signatures in the key
36 * @key: the structure that holds the key.
37 * @keyring: holds the keyring to check against
38 * @flags: unused (should be 0)
39 * @verify: will hold the certificate verification output.
40 *
41 * Verify all signatures in the key, using the given set of keys (keyring).
42 *
43 * The key verification output will be put in @verify and will be
44 * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd.
45 *
46 * GNUTLS_CERT_INVALID: A signature on the key is invalid.
47 *
48 * GNUTLS_CERT_REVOKED: The key has been revoked.
49 *
50 * Note that this function does not verify using any "web of
51 * trust". You may use GnuPG for that purpose, or any other external
52 * PGP application.
53 *
54 * Returns 0 on success.
55 **/
56int
57gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key,
58 gnutls_openpgp_keyring_t keyring,
59 unsigned int flags, unsigned int *verify)
60{
61 opaque id[8];
62 cdk_error_t rc;
63 int status;
64
65 if (!key || !keyring)
66 {
67 gnutls_assert ();
68 return GNUTLS_E_NO_CERTIFICATE_FOUND;
69 }
70
71 *verify = 0;
72
73 rc = cdk_pk_check_sigs (key->knode, keyring->db, &status);
74 if (rc == CDK_Error_No_Key)
75 {
76 rc = GNUTLS_E_NO_CERTIFICATE_FOUND;
77 gnutls_assert ();
78 return rc;
79 }
80 else if (rc != CDK_Success)
81 {
82 _gnutls_x509_log ("cdk_pk_check_sigs: error %d\n", rc);
83 rc = _gnutls_map_cdk_rc (rc);
84 gnutls_assert ();
85 return rc;
86 }
87 _gnutls_x509_log ("status: %x\n", status);
88
89 if (status & CDK_KEY_INVALID)
90 *verify |= GNUTLS_CERT_INVALID;
91 if (status & CDK_KEY_REVOKED)
92 *verify |= GNUTLS_CERT_REVOKED;
93 if (status & CDK_KEY_NOSIGNER)
94 *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND;
95
96 /* Check if the key is included in the ring. */
97 if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME))
98 {
99 rc = gnutls_openpgp_crt_get_id (key, id);
100 if (rc < 0)
101 {
102 gnutls_assert ();
103 return rc;
104 }
105
106 rc = gnutls_openpgp_keyring_check_id (keyring, id, 0);
107 /* If it exists in the keyring don't treat it as unknown. */
108 if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
109 *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
110 }
111
112 return 0;
113}
114
115
116/**
117 * gnutls_openpgp_crt_verify_self - Verify the self signature on the key
118 * @key: the structure that holds the key.
119 * @flags: unused (should be 0)
120 * @verify: will hold the key verification output.
121 *
122 * Verifies the self signature in the key.
123 * The key verification output will be put in @verify and will be
124 * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd.
125 *
126 * GNUTLS_CERT_INVALID: The self signature on the key is invalid.
127 *
128 * Returns 0 on success.
129 **/
130int
131gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key,
132 unsigned int flags, unsigned int *verify)
133{
134 int status;
135 cdk_error_t rc;
136
137 rc = cdk_pk_check_self_sig (key->knode, &status);
138 if (rc || status != CDK_KEY_VALID)
139 *verify |= GNUTLS_CERT_INVALID;
140 else
141 *verify = 0;
142
143 return 0;
144}