diff options
author | lv-426 <oxcafebaby@yahoo.com> | 2008-06-22 18:20:35 +0000 |
---|---|---|
committer | lv-426 <oxcafebaby@yahoo.com> | 2008-06-22 18:20:35 +0000 |
commit | a0339d2458867dbe9485499265641ff205063445 (patch) | |
tree | 055b38828b3696520408a32edf81df5bb37400f0 /src/daemon/https/openpgp | |
parent | 97c026da05495b83f1511906c2ca027e12ef6cf7 (diff) | |
download | libmicrohttpd-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.am | 27 | ||||
-rw-r--r-- | src/daemon/https/openpgp/compat.c | 252 | ||||
-rw-r--r-- | src/daemon/https/openpgp/extras.c | 165 | ||||
-rw-r--r-- | src/daemon/https/openpgp/gnutls_extra.c | 110 | ||||
-rw-r--r-- | src/daemon/https/openpgp/gnutls_extra.h | 50 | ||||
-rw-r--r-- | src/daemon/https/openpgp/gnutls_ia.c | 905 | ||||
-rw-r--r-- | src/daemon/https/openpgp/gnutls_openpgp.c | 973 | ||||
-rw-r--r-- | src/daemon/https/openpgp/gnutls_openpgp.h | 98 | ||||
-rw-r--r-- | src/daemon/https/openpgp/openpgp.h | 182 | ||||
-rw-r--r-- | src/daemon/https/openpgp/pgp.c | 534 | ||||
-rw-r--r-- | src/daemon/https/openpgp/pgp_privkey.c | 134 | ||||
-rw-r--r-- | src/daemon/https/openpgp/pgp_verify.c | 144 |
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 @@ | |||
1 | SUBDIRS = . | ||
2 | |||
3 | AM_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 | |||
12 | noinst_LTLIBRARIES = libopenpgp.la | ||
13 | |||
14 | # libopenpgp_la_LDFLAGS = -l$(top_srcdir)/src/daemon/https/libextra/.lib/libextra.la | ||
15 | |||
16 | libopenpgp_la_SOURCES = \ | ||
17 | pgp_privkey.c \ | ||
18 | compat.c \ | ||
19 | pgp_verify.c \ | ||
20 | extras.c \ | ||
21 | pgp.c | ||
22 | |||
23 | # x libextra source list | ||
24 | libopenpgp_la_SOURCES += \ | ||
25 | gnutls_openpgp.c \ | ||
26 | gnutls_ia.c \ | ||
27 | gnutls_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 | -*/ | ||
44 | int | ||
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 | |||
137 | leave: | ||
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 | -*/ | ||
152 | int | ||
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 | -*/ | ||
190 | time_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 | -*/ | ||
226 | time_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 | **/ | ||
44 | int 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 | **/ | ||
60 | void 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 | **/ | ||
93 | int 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 | **/ | ||
126 | int 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 | */ | ||
33 | extern int _gnutls_comp_algorithms_size; | ||
34 | |||
35 | /* Functions in gnutls that have not been initialized. | ||
36 | */ | ||
37 | |||
38 | static 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 | **/ | ||
51 | int | ||
52 | gnutls_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 | **/ | ||
103 | const char * | ||
104 | gnutls_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 | |||
27 | typedef int (*OPENPGP_VERIFY_KEY_FUNC) (const | ||
28 | gnutls_certificate_credentials_t, | ||
29 | const gnutls_datum_t *, int, | ||
30 | unsigned int *); | ||
31 | |||
32 | typedef time_t (*OPENPGP_KEY_CREATION_TIME_FUNC) (const gnutls_datum_t *); | ||
33 | typedef time_t (*OPENPGP_KEY_EXPIRATION_TIME_FUNC) (const gnutls_datum_t *); | ||
34 | typedef int (*OPENPGP_KEY_REQUEST) (gnutls_session_t, gnutls_datum_t *, | ||
35 | const gnutls_certificate_credentials_t, | ||
36 | opaque *, int); | ||
37 | |||
38 | typedef int (*OPENPGP_FINGERPRINT) (const gnutls_datum_t *, | ||
39 | unsigned char *, size_t *); | ||
40 | |||
41 | typedef int (*OPENPGP_RAW_KEY_TO_GCERT) (gnutls_cert *, | ||
42 | const gnutls_datum_t *); | ||
43 | typedef int (*OPENPGP_RAW_PRIVKEY_TO_GKEY) (gnutls_privkey *, | ||
44 | const gnutls_datum_t *); | ||
45 | |||
46 | typedef int (*OPENPGP_KEY_TO_GCERT) (gnutls_cert *, gnutls_openpgp_crt_t); | ||
47 | typedef int (*OPENPGP_PRIVKEY_TO_GKEY) (gnutls_privkey *, | ||
48 | gnutls_openpgp_privkey_t); | ||
49 | typedef void (*OPENPGP_KEY_DEINIT) (gnutls_openpgp_crt_t); | ||
50 | typedef 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 | |||
30 | struct gnutls_ia_client_credentials_st | ||
31 | { | ||
32 | gnutls_ia_avp_func avp_func; | ||
33 | void *avp_ptr; | ||
34 | }; | ||
35 | |||
36 | struct gnutls_ia_server_credentials_st | ||
37 | { | ||
38 | gnutls_ia_avp_func avp_func; | ||
39 | void *avp_ptr; | ||
40 | }; | ||
41 | |||
42 | static const char server_finished_label[] = "server phase finished"; | ||
43 | static const char client_finished_label[] = "client phase finished"; | ||
44 | static const char inner_permutation_label[] = "inner secret permutation"; | ||
45 | static 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. */ | ||
73 | static 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. */ | ||
108 | static 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. */ | ||
161 | static 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 | **/ | ||
207 | int | ||
208 | gnutls_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 | **/ | ||
232 | int | ||
233 | gnutls_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 | **/ | ||
257 | void | ||
258 | gnutls_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 | **/ | ||
278 | int | ||
279 | gnutls_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 | **/ | ||
332 | int | ||
333 | gnutls_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 | **/ | ||
395 | ssize_t | ||
396 | gnutls_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 | **/ | ||
435 | ssize_t | ||
436 | gnutls_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 | |||
455 | int | ||
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 | |||
524 | int | ||
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 | **/ | ||
605 | int | ||
606 | gnutls_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 | **/ | ||
636 | int | ||
637 | gnutls_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 | **/ | ||
663 | int | ||
664 | gnutls_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 | **/ | ||
682 | void | ||
683 | gnutls_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 | **/ | ||
722 | void | ||
723 | gnutls_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 | **/ | ||
738 | void | ||
739 | gnutls_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 | **/ | ||
752 | void * | ||
753 | gnutls_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 | **/ | ||
772 | int | ||
773 | gnutls_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 | **/ | ||
791 | void | ||
792 | gnutls_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 | **/ | ||
838 | void | ||
839 | gnutls_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 | **/ | ||
854 | void | ||
855 | gnutls_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 | **/ | ||
868 | void * | ||
869 | gnutls_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 | **/ | ||
899 | void | ||
900 | gnutls_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 | |||
43 | static void | ||
44 | release_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. */ | ||
59 | int | ||
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 | |||
85 | static unsigned long | ||
86 | buftou32 (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 | |||
96 | static int | ||
97 | openpgp_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 | -*/ | ||
166 | int | ||
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 | |||
254 | leave: | ||
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 | -*/ | ||
268 | int | ||
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 | **/ | ||
315 | int | ||
316 | gnutls_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 | -*/ | ||
393 | int | ||
394 | gnutls_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 | |||
448 | leave: | ||
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. */ | ||
456 | static int | ||
457 | stream_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 | **/ | ||
494 | int | ||
495 | gnutls_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 | **/ | ||
556 | int | ||
557 | gnutls_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 | |||
611 | int | ||
612 | gnutls_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 | **/ | ||
657 | int | ||
658 | gnutls_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 | **/ | ||
701 | int | ||
702 | gnutls_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 | -*/ | ||
767 | int | ||
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 | |||
828 | error: | ||
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 | **/ | ||
845 | void | ||
846 | gnutls_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. */ | ||
854 | int | ||
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 | |||
878 | cleanup: | ||
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 | */ | ||
886 | int | ||
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 | **/ | ||
951 | int | ||
952 | gnutls_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 | |||
11 | typedef struct | ||
12 | { | ||
13 | int type; | ||
14 | size_t size; | ||
15 | uint8_t *data; | ||
16 | }keybox_blob; | ||
17 | |||
18 | typedef enum | ||
19 | { | ||
20 | KBX_BLOB_FILE = 0x00, | ||
21 | KBX_BLOB_DATA = 0x01 | ||
22 | }keyring_blob_types; | ||
23 | |||
24 | /* OpenCDK compatible */ | ||
25 | typedef 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 | |||
33 | int | ||
34 | gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t | ||
35 | res, const char *CERTFILE, | ||
36 | const char *KEYFILE, gnutls_openpgp_crt_fmt_t); | ||
37 | |||
38 | int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert); | ||
39 | |||
40 | int gnutls_certificate_set_openpgp_keyring_file | ||
41 | (gnutls_certificate_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t); | ||
42 | |||
43 | int | ||
44 | gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t | ||
45 | c, const opaque * data, | ||
46 | size_t dlen, gnutls_openpgp_crt_fmt_t); | ||
47 | |||
48 | int gnutls_openpgp_get_key (gnutls_datum_t * key, | ||
49 | gnutls_openpgp_keyring_t keyring, | ||
50 | key_attr_t by, opaque * pattern); | ||
51 | |||
52 | int gnutls_openpgp_recv_key (const char *host, | ||
53 | short port, uint32_t keyid, | ||
54 | gnutls_datum_t * key); | ||
55 | |||
56 | /* internal */ | ||
57 | int _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert, | ||
58 | const gnutls_datum_t * raw); | ||
59 | |||
60 | extern 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 | |||
65 | int | ||
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 | |||
71 | int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t, | ||
72 | const gnutls_datum_t * cert_list, | ||
73 | int cert_list_length, unsigned int *status); | ||
74 | int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, | ||
75 | unsigned char *fpr, size_t * fprlen); | ||
76 | time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * | ||
77 | cert); | ||
78 | time_t _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * | ||
79 | cert); | ||
80 | |||
81 | int | ||
82 | gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); | ||
83 | |||
84 | int | ||
85 | gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); | ||
86 | |||
87 | void | ||
88 | gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key); | ||
89 | |||
90 | int | ||
91 | gnutls_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 | ||
9 | extern "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. */ | ||
18 | typedef 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. */ | ||
24 | typedef struct gnutls_openpgp_privkey_int | ||
25 | { | ||
26 | gnutls_privkey pkey; | ||
27 | } gnutls_openpgp_privkey_int; | ||
28 | |||
29 | typedef struct gnutls_openpgp_keyring_int | ||
30 | { | ||
31 | cdk_keydb_hd_t db; | ||
32 | cdk_stream_t db_stream; | ||
33 | } gnutls_openpgp_keyring_int; | ||
34 | |||
35 | typedef 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 */ | ||
39 | int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key); | ||
40 | /* frees all memory */ | ||
41 | void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key); | ||
42 | |||
43 | int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key, | ||
44 | const gnutls_datum_t * data, | ||
45 | gnutls_openpgp_crt_fmt_t format); | ||
46 | int 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 | */ | ||
54 | int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t cert, | ||
55 | unsigned int *key_usage); | ||
56 | int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key, | ||
57 | void *fpr, | ||
58 | size_t * fprlen); | ||
59 | |||
60 | int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key, | ||
61 | int idx, | ||
62 | char *buf, | ||
63 | size_t * sizeof_buf); | ||
64 | |||
65 | gnutls_pk_algorithm_t | ||
66 | gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key, | ||
67 | unsigned int *bits); | ||
68 | |||
69 | int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key); | ||
70 | |||
71 | time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key); | ||
72 | time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key); | ||
73 | |||
74 | int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key, | ||
75 | unsigned char keyid[8]); | ||
76 | |||
77 | int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key, | ||
78 | const char *hostname); | ||
79 | |||
80 | /* privkey stuff. */ | ||
81 | int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey_t * key); | ||
82 | void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key); | ||
83 | gnutls_pk_algorithm_t | ||
84 | gnutls_openpgp_privkey_get_pk_algorithm(gnutls_openpgp_privkey_t key, | ||
85 | unsigned int *bits); | ||
86 | int 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); | ||
91 | int 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 | |||
97 | int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring); | ||
98 | void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring); | ||
99 | |||
100 | int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring, | ||
101 | const gnutls_datum_t * data, | ||
102 | gnutls_openpgp_crt_fmt_t format); | ||
103 | |||
104 | int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring, | ||
105 | const unsigned char keyid[8], | ||
106 | unsigned int flags); | ||
107 | |||
108 | int 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 | |||
114 | int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key, | ||
115 | unsigned int flags, | ||
116 | unsigned int *verify); | ||
117 | |||
118 | /* certificate authentication stuff. | ||
119 | */ | ||
120 | int 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 | |||
129 | int _gnutls_map_cdk_rc(int rc); | ||
130 | int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key, | ||
131 | int idx, | ||
132 | char *buf, | ||
133 | size_t * sizeof_buf); | ||
134 | int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key, | ||
135 | void *fpr, | ||
136 | size_t * fprlen); | ||
137 | gnutls_pk_algorithm_t | ||
138 | gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key, | ||
139 | unsigned int *bits); | ||
140 | int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key); | ||
141 | time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key); | ||
142 | time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key); | ||
143 | int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key, | ||
144 | unsigned char keyid[8]); | ||
145 | |||
146 | int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key); | ||
147 | void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key); | ||
148 | int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key, | ||
149 | const gnutls_datum_t * data, | ||
150 | gnutls_openpgp_crt_fmt_t format); | ||
151 | int 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 | |||
156 | void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring); | ||
157 | int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring); | ||
158 | int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring, | ||
159 | const gnutls_datum_t * data, | ||
160 | gnutls_openpgp_crt_fmt_t format); | ||
161 | int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring, | ||
162 | const unsigned char keyid[8], | ||
163 | unsigned int flags); | ||
164 | |||
165 | int 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 | |||
170 | int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key, | ||
171 | unsigned int flags, | ||
172 | unsigned int *verify); | ||
173 | |||
174 | int _gnutls_openpgp_crt_to_gcert(gnutls_cert * gcert, | ||
175 | gnutls_openpgp_crt_t cert); | ||
176 | int _gnutls_openpgp_privkey_to_gkey(gnutls_privkey * dest, | ||
177 | gnutls_openpgp_privkey_t src); | ||
178 | |||
179 | void 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 | **/ | ||
42 | int 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 | **/ | ||
57 | void 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 | **/ | ||
82 | int 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 | **/ | ||
130 | int 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 | **/ | ||
189 | int 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 | |||
219 | int _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 | **/ | ||
257 | int 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 | **/ | ||
329 | gnutls_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 | **/ | ||
360 | int 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 | **/ | ||
383 | time_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 | **/ | ||
407 | time_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 | **/ | ||
431 | int 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 | **/ | ||
472 | int 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 | */ | ||
506 | int 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 | **/ | ||
44 | int | ||
45 | gnutls_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 | **/ | ||
61 | void | ||
62 | gnutls_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 | **/ | ||
85 | int | ||
86 | 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, 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 | **/ | ||
120 | gnutls_pk_algorithm_t | ||
121 | gnutls_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 | **/ | ||
56 | int | ||
57 | gnutls_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 | **/ | ||
130 | int | ||
131 | gnutls_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 | } | ||