Allow 'browse-url-emacs' to fetch URL in the selected window
[emacs.git] / src / gnutls.c
blob903393fed18c7cba5b1aee272ac95bdb95c8b625
1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2018 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 #include <config.h>
20 #include <errno.h>
21 #include <stdio.h>
23 #include "lisp.h"
24 #include "process.h"
25 #include "gnutls.h"
26 #include "coding.h"
27 #include "buffer.h"
29 #if GNUTLS_VERSION_NUMBER >= 0x030014
30 # define HAVE_GNUTLS_X509_SYSTEM_TRUST
31 #endif
33 /* Although AEAD support started in GnuTLS 3.4.0 and works in 3.5.14,
34 it was broken through at least GnuTLS 3.4.10; see:
35 https://lists.gnu.org/r/emacs-devel/2017-07/msg00992.html
36 The relevant fix seems to have been made in GnuTLS 3.5.1; see:
37 https://gitlab.com/gnutls/gnutls/commit/568935848dd6b82b9315d8b6c529d00e2605e03d
38 So, require 3.5.1. */
39 #if GNUTLS_VERSION_NUMBER >= 0x030501
40 # define HAVE_GNUTLS_AEAD
41 #endif
43 /* gnutls_mac_get_nonce_size was added in GnuTLS 3.2.0, but was
44 exported only since 3.3.0. */
45 #if GNUTLS_VERSION_NUMBER >= 0x030300
46 # define HAVE_GNUTLS_MAC_GET_NONCE_SIZE
47 #endif
49 #if GNUTLS_VERSION_NUMBER >= 0x030501
50 # define HAVE_GNUTLS_EXT_GET_NAME
51 #endif
53 #if GNUTLS_VERSION_NUMBER >= 0x030205
54 # define HAVE_GNUTLS_EXT__DUMBFW
55 #endif
57 #ifdef HAVE_GNUTLS
59 # ifdef WINDOWSNT
60 # include <windows.h>
61 # include "w32.h"
62 # endif
64 static bool emacs_gnutls_handle_error (gnutls_session_t, int);
66 static bool gnutls_global_initialized;
68 static void gnutls_log_function (int, const char *);
69 static void gnutls_log_function2 (int, const char *, const char *);
70 # ifdef HAVE_GNUTLS3
71 static void gnutls_audit_log_function (gnutls_session_t, const char *);
72 # endif
74 enum extra_peer_verification
76 CERTIFICATE_NOT_MATCHING = 2
80 # ifdef WINDOWSNT
82 DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
83 (gnutls_session_t));
84 DEF_DLL_FN (const char *, gnutls_alert_get_name,
85 (gnutls_alert_description_t));
86 DEF_DLL_FN (int, gnutls_anon_allocate_client_credentials,
87 (gnutls_anon_client_credentials_t *));
88 DEF_DLL_FN (void, gnutls_anon_free_client_credentials,
89 (gnutls_anon_client_credentials_t));
90 DEF_DLL_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
91 DEF_DLL_FN (int, gnutls_certificate_allocate_credentials,
92 (gnutls_certificate_credentials_t *));
93 DEF_DLL_FN (void, gnutls_certificate_free_credentials,
94 (gnutls_certificate_credentials_t));
95 DEF_DLL_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
96 (gnutls_session_t, unsigned int *));
97 DEF_DLL_FN (void, gnutls_certificate_set_verify_flags,
98 (gnutls_certificate_credentials_t, unsigned int));
99 DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
100 (gnutls_certificate_credentials_t, const char *,
101 gnutls_x509_crt_fmt_t));
102 DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
103 (gnutls_certificate_credentials_t, const char *, const char *,
104 gnutls_x509_crt_fmt_t));
105 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
106 DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
107 (gnutls_certificate_credentials_t));
108 # endif
109 DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
110 (gnutls_certificate_credentials_t, const char *,
111 gnutls_x509_crt_fmt_t));
112 DEF_DLL_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
113 (gnutls_session_t));
114 DEF_DLL_FN (int, gnutls_certificate_verify_peers2,
115 (gnutls_session_t, unsigned int *));
116 DEF_DLL_FN (int, gnutls_credentials_set,
117 (gnutls_session_t, gnutls_credentials_type_t, void *));
118 DEF_DLL_FN (void, gnutls_deinit, (gnutls_session_t));
119 DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
120 (gnutls_session_t, unsigned int));
121 DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
122 DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
123 DEF_DLL_FN (int, gnutls_global_init, (void));
124 DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
125 # ifdef HAVE_GNUTLS3
126 DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
127 # endif
128 DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
129 DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
130 DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
131 DEF_DLL_FN (int, gnutls_priority_set_direct,
132 (gnutls_session_t, const char *, const char **));
133 DEF_DLL_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
134 DEF_DLL_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
135 DEF_DLL_FN (ssize_t, gnutls_record_send,
136 (gnutls_session_t, const void *, size_t));
137 DEF_DLL_FN (const char *, gnutls_strerror, (int));
138 DEF_DLL_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
139 DEF_DLL_FN (void, gnutls_transport_set_ptr2,
140 (gnutls_session_t, gnutls_transport_ptr_t,
141 gnutls_transport_ptr_t));
142 DEF_DLL_FN (void, gnutls_transport_set_pull_function,
143 (gnutls_session_t, gnutls_pull_func));
144 DEF_DLL_FN (void, gnutls_transport_set_push_function,
145 (gnutls_session_t, gnutls_push_func));
146 DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
147 (gnutls_x509_crt_t, const char *));
148 DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
149 (gnutls_x509_crt_t, gnutls_x509_crt_t));
150 DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
151 DEF_DLL_FN (int, gnutls_x509_crt_import,
152 (gnutls_x509_crt_t, const gnutls_datum_t *,
153 gnutls_x509_crt_fmt_t));
154 DEF_DLL_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
155 DEF_DLL_FN (int, gnutls_x509_crt_get_fingerprint,
156 (gnutls_x509_crt_t,
157 gnutls_digest_algorithm_t, void *, size_t *));
158 DEF_DLL_FN (int, gnutls_x509_crt_get_version,
159 (gnutls_x509_crt_t));
160 DEF_DLL_FN (int, gnutls_x509_crt_get_serial,
161 (gnutls_x509_crt_t, void *, size_t *));
162 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_dn,
163 (gnutls_x509_crt_t, char *, size_t *));
164 DEF_DLL_FN (time_t, gnutls_x509_crt_get_activation_time,
165 (gnutls_x509_crt_t));
166 DEF_DLL_FN (time_t, gnutls_x509_crt_get_expiration_time,
167 (gnutls_x509_crt_t));
168 DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
169 (gnutls_x509_crt_t, char *, size_t *));
170 DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
171 (gnutls_x509_crt_t, unsigned int *));
172 DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name,
173 (gnutls_pk_algorithm_t));
174 DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
175 (gnutls_pk_algorithm_t, unsigned int));
176 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_unique_id,
177 (gnutls_x509_crt_t, char *, size_t *));
178 DEF_DLL_FN (int, gnutls_x509_crt_get_subject_unique_id,
179 (gnutls_x509_crt_t, char *, size_t *));
180 DEF_DLL_FN (int, gnutls_x509_crt_get_signature_algorithm,
181 (gnutls_x509_crt_t));
182 DEF_DLL_FN (int, gnutls_x509_crt_get_key_id,
183 (gnutls_x509_crt_t, unsigned int, unsigned char *, size_t *_size));
184 DEF_DLL_FN (const char *, gnutls_sec_param_get_name, (gnutls_sec_param_t));
185 DEF_DLL_FN (const char *, gnutls_sign_get_name, (gnutls_sign_algorithm_t));
186 DEF_DLL_FN (int, gnutls_server_name_set,
187 (gnutls_session_t, gnutls_server_name_type_t,
188 const void *, size_t));
189 DEF_DLL_FN (gnutls_kx_algorithm_t, gnutls_kx_get, (gnutls_session_t));
190 DEF_DLL_FN (const char *, gnutls_kx_get_name, (gnutls_kx_algorithm_t));
191 DEF_DLL_FN (gnutls_protocol_t, gnutls_protocol_get_version,
192 (gnutls_session_t));
193 DEF_DLL_FN (const char *, gnutls_protocol_get_name, (gnutls_protocol_t));
194 DEF_DLL_FN (gnutls_cipher_algorithm_t, gnutls_cipher_get,
195 (gnutls_session_t));
196 DEF_DLL_FN (const char *, gnutls_cipher_get_name,
197 (gnutls_cipher_algorithm_t));
198 DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
199 DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
201 # ifdef HAVE_GNUTLS3
202 DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t));
203 DEF_DLL_FN (const gnutls_mac_algorithm_t *, gnutls_mac_list, (void));
204 # ifdef HAVE_GNUTLS_MAC_GET_NONCE_SIZE
205 DEF_DLL_FN (size_t, gnutls_mac_get_nonce_size, (gnutls_mac_algorithm_t));
206 # endif
207 DEF_DLL_FN (size_t, gnutls_mac_get_key_size, (gnutls_mac_algorithm_t));
208 DEF_DLL_FN (const gnutls_digest_algorithm_t *, gnutls_digest_list, (void));
209 DEF_DLL_FN (const char *, gnutls_digest_get_name, (gnutls_digest_algorithm_t));
210 DEF_DLL_FN (gnutls_cipher_algorithm_t *, gnutls_cipher_list, (void));
211 DEF_DLL_FN (int, gnutls_cipher_get_iv_size, (gnutls_cipher_algorithm_t));
212 DEF_DLL_FN (size_t, gnutls_cipher_get_key_size, (gnutls_cipher_algorithm_t));
213 DEF_DLL_FN (int, gnutls_cipher_get_block_size, (gnutls_cipher_algorithm_t));
214 DEF_DLL_FN (int, gnutls_cipher_get_tag_size, (gnutls_cipher_algorithm_t));
215 DEF_DLL_FN (int, gnutls_cipher_init,
216 (gnutls_cipher_hd_t *, gnutls_cipher_algorithm_t,
217 const gnutls_datum_t *, const gnutls_datum_t *));
218 DEF_DLL_FN (void, gnutls_cipher_set_iv, (gnutls_cipher_hd_t, void *, size_t));
219 DEF_DLL_FN (int, gnutls_cipher_encrypt2,
220 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
221 DEF_DLL_FN (void, gnutls_cipher_deinit, (gnutls_cipher_hd_t));
222 DEF_DLL_FN (int, gnutls_cipher_decrypt2,
223 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
224 # ifdef HAVE_GNUTLS_AEAD
225 DEF_DLL_FN (int, gnutls_aead_cipher_init,
226 (gnutls_aead_cipher_hd_t *, gnutls_cipher_algorithm_t,
227 const gnutls_datum_t *));
228 DEF_DLL_FN (void, gnutls_aead_cipher_deinit, (gnutls_aead_cipher_hd_t));
229 DEF_DLL_FN (int, gnutls_aead_cipher_encrypt,
230 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
231 size_t, size_t, const void *, size_t, void *, size_t *));
232 DEF_DLL_FN (int, gnutls_aead_cipher_decrypt,
233 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
234 size_t, size_t, const void *, size_t, void *, size_t *));
235 # endif
236 DEF_DLL_FN (int, gnutls_hmac_init,
237 (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t));
238 DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t));
239 DEF_DLL_FN (int, gnutls_hmac, (gnutls_hmac_hd_t, const void *, size_t));
240 DEF_DLL_FN (void, gnutls_hmac_deinit, (gnutls_hmac_hd_t, void *));
241 DEF_DLL_FN (void, gnutls_hmac_output, (gnutls_hmac_hd_t, void *));
242 DEF_DLL_FN (int, gnutls_hash_init,
243 (gnutls_hash_hd_t *, gnutls_digest_algorithm_t));
244 DEF_DLL_FN (int, gnutls_hash_get_len, (gnutls_digest_algorithm_t));
245 DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
246 DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
247 DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
248 # ifdef HAVE_GNUTLS_EXT_GET_NAME
249 DEF_DLL_FN (const char *, gnutls_ext_get_name, (unsigned int));
250 # endif
251 # endif /* HAVE_GNUTLS3 */
254 static bool
255 init_gnutls_functions (void)
257 HMODULE library;
258 int max_log_level = 1;
260 if (!(library = w32_delayed_load (Qgnutls)))
262 GNUTLS_LOG (1, max_log_level, "GnuTLS library not found");
263 return 0;
266 LOAD_DLL_FN (library, gnutls_alert_get);
267 LOAD_DLL_FN (library, gnutls_alert_get_name);
268 LOAD_DLL_FN (library, gnutls_anon_allocate_client_credentials);
269 LOAD_DLL_FN (library, gnutls_anon_free_client_credentials);
270 LOAD_DLL_FN (library, gnutls_bye);
271 LOAD_DLL_FN (library, gnutls_certificate_allocate_credentials);
272 LOAD_DLL_FN (library, gnutls_certificate_free_credentials);
273 LOAD_DLL_FN (library, gnutls_certificate_get_peers);
274 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
275 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
276 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
277 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
278 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
279 # endif
280 LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
281 LOAD_DLL_FN (library, gnutls_certificate_type_get);
282 LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
283 LOAD_DLL_FN (library, gnutls_credentials_set);
284 LOAD_DLL_FN (library, gnutls_deinit);
285 LOAD_DLL_FN (library, gnutls_dh_set_prime_bits);
286 LOAD_DLL_FN (library, gnutls_dh_get_prime_bits);
287 LOAD_DLL_FN (library, gnutls_error_is_fatal);
288 LOAD_DLL_FN (library, gnutls_global_init);
289 LOAD_DLL_FN (library, gnutls_global_set_log_function);
290 # ifdef HAVE_GNUTLS3
291 LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
292 # endif
293 LOAD_DLL_FN (library, gnutls_global_set_log_level);
294 LOAD_DLL_FN (library, gnutls_handshake);
295 LOAD_DLL_FN (library, gnutls_init);
296 LOAD_DLL_FN (library, gnutls_priority_set_direct);
297 LOAD_DLL_FN (library, gnutls_record_check_pending);
298 LOAD_DLL_FN (library, gnutls_record_recv);
299 LOAD_DLL_FN (library, gnutls_record_send);
300 LOAD_DLL_FN (library, gnutls_strerror);
301 LOAD_DLL_FN (library, gnutls_transport_set_errno);
302 LOAD_DLL_FN (library, gnutls_transport_set_ptr2);
303 LOAD_DLL_FN (library, gnutls_transport_set_pull_function);
304 LOAD_DLL_FN (library, gnutls_transport_set_push_function);
305 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
306 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
307 LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
308 LOAD_DLL_FN (library, gnutls_x509_crt_import);
309 LOAD_DLL_FN (library, gnutls_x509_crt_init);
310 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
311 LOAD_DLL_FN (library, gnutls_x509_crt_get_version);
312 LOAD_DLL_FN (library, gnutls_x509_crt_get_serial);
313 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_dn);
314 LOAD_DLL_FN (library, gnutls_x509_crt_get_activation_time);
315 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
316 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
317 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
318 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
319 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
320 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
321 LOAD_DLL_FN (library, gnutls_x509_crt_get_subject_unique_id);
322 LOAD_DLL_FN (library, gnutls_x509_crt_get_signature_algorithm);
323 LOAD_DLL_FN (library, gnutls_x509_crt_get_key_id);
324 LOAD_DLL_FN (library, gnutls_sec_param_get_name);
325 LOAD_DLL_FN (library, gnutls_sign_get_name);
326 LOAD_DLL_FN (library, gnutls_server_name_set);
327 LOAD_DLL_FN (library, gnutls_kx_get);
328 LOAD_DLL_FN (library, gnutls_kx_get_name);
329 LOAD_DLL_FN (library, gnutls_protocol_get_version);
330 LOAD_DLL_FN (library, gnutls_protocol_get_name);
331 LOAD_DLL_FN (library, gnutls_cipher_get);
332 LOAD_DLL_FN (library, gnutls_cipher_get_name);
333 LOAD_DLL_FN (library, gnutls_mac_get);
334 LOAD_DLL_FN (library, gnutls_mac_get_name);
335 # ifdef HAVE_GNUTLS3
336 LOAD_DLL_FN (library, gnutls_rnd);
337 LOAD_DLL_FN (library, gnutls_mac_list);
338 # ifdef HAVE_GNUTLS_MAC_GET_NONCE_SIZE
339 LOAD_DLL_FN (library, gnutls_mac_get_nonce_size);
340 # endif
341 LOAD_DLL_FN (library, gnutls_mac_get_key_size);
342 LOAD_DLL_FN (library, gnutls_digest_list);
343 LOAD_DLL_FN (library, gnutls_digest_get_name);
344 LOAD_DLL_FN (library, gnutls_cipher_list);
345 LOAD_DLL_FN (library, gnutls_cipher_get_iv_size);
346 LOAD_DLL_FN (library, gnutls_cipher_get_key_size);
347 LOAD_DLL_FN (library, gnutls_cipher_get_block_size);
348 LOAD_DLL_FN (library, gnutls_cipher_get_tag_size);
349 LOAD_DLL_FN (library, gnutls_cipher_init);
350 LOAD_DLL_FN (library, gnutls_cipher_set_iv);
351 LOAD_DLL_FN (library, gnutls_cipher_encrypt2);
352 LOAD_DLL_FN (library, gnutls_cipher_deinit);
353 LOAD_DLL_FN (library, gnutls_cipher_decrypt2);
354 # ifdef HAVE_GNUTLS_AEAD
355 LOAD_DLL_FN (library, gnutls_aead_cipher_init);
356 LOAD_DLL_FN (library, gnutls_aead_cipher_deinit);
357 LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt);
358 LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt);
359 # endif
360 LOAD_DLL_FN (library, gnutls_hmac_init);
361 LOAD_DLL_FN (library, gnutls_hmac_get_len);
362 LOAD_DLL_FN (library, gnutls_hmac);
363 LOAD_DLL_FN (library, gnutls_hmac_deinit);
364 LOAD_DLL_FN (library, gnutls_hmac_output);
365 LOAD_DLL_FN (library, gnutls_hash_init);
366 LOAD_DLL_FN (library, gnutls_hash_get_len);
367 LOAD_DLL_FN (library, gnutls_hash);
368 LOAD_DLL_FN (library, gnutls_hash_deinit);
369 LOAD_DLL_FN (library, gnutls_hash_output);
370 # ifdef HAVE_GNUTLS_EXT_GET_NAME
371 LOAD_DLL_FN (library, gnutls_ext_get_name);
372 # endif
373 # endif /* HAVE_GNUTLS3 */
375 max_log_level = global_gnutls_log_level;
378 Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from));
379 GNUTLS_LOG2 (1, max_log_level, "GnuTLS library loaded:",
380 STRINGP (name) ? (const char *) SDATA (name) : "unknown");
383 return 1;
386 # define gnutls_alert_get fn_gnutls_alert_get
387 # define gnutls_alert_get_name fn_gnutls_alert_get_name
388 # define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
389 # define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
390 # define gnutls_bye fn_gnutls_bye
391 # define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
392 # define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
393 # define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
394 # define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
395 # define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
396 # define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
397 # define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
398 # define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
399 # define gnutls_certificate_type_get fn_gnutls_certificate_type_get
400 # define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
401 # define gnutls_cipher_get fn_gnutls_cipher_get
402 # define gnutls_cipher_get_name fn_gnutls_cipher_get_name
403 # define gnutls_credentials_set fn_gnutls_credentials_set
404 # define gnutls_deinit fn_gnutls_deinit
405 # define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
406 # define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
407 # define gnutls_error_is_fatal fn_gnutls_error_is_fatal
408 # define gnutls_global_init fn_gnutls_global_init
409 # define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
410 # define gnutls_global_set_log_function fn_gnutls_global_set_log_function
411 # define gnutls_global_set_log_level fn_gnutls_global_set_log_level
412 # define gnutls_handshake fn_gnutls_handshake
413 # define gnutls_init fn_gnutls_init
414 # define gnutls_kx_get fn_gnutls_kx_get
415 # define gnutls_kx_get_name fn_gnutls_kx_get_name
416 # define gnutls_mac_get fn_gnutls_mac_get
417 # define gnutls_mac_get_name fn_gnutls_mac_get_name
418 # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
419 # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
420 # define gnutls_priority_set_direct fn_gnutls_priority_set_direct
421 # define gnutls_protocol_get_name fn_gnutls_protocol_get_name
422 # define gnutls_protocol_get_version fn_gnutls_protocol_get_version
423 # define gnutls_record_check_pending fn_gnutls_record_check_pending
424 # define gnutls_record_recv fn_gnutls_record_recv
425 # define gnutls_record_send fn_gnutls_record_send
426 # define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
427 # define gnutls_server_name_set fn_gnutls_server_name_set
428 # define gnutls_sign_get_name fn_gnutls_sign_get_name
429 # define gnutls_strerror fn_gnutls_strerror
430 # define gnutls_transport_set_errno fn_gnutls_transport_set_errno
431 # define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
432 # define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
433 # define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
434 # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
435 # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
436 # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
437 # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
438 # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
439 # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
440 # define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
441 # define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
442 # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
443 # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
444 # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
445 # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
446 # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
447 # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
448 # define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
449 # define gnutls_x509_crt_import fn_gnutls_x509_crt_import
450 # define gnutls_x509_crt_init fn_gnutls_x509_crt_init
451 # ifdef HAVE_GNUTLS3
452 # define gnutls_rnd fn_gnutls_rnd
453 # define gnutls_mac_list fn_gnutls_mac_list
454 # ifdef HAVE_GNUTLS_MAC_GET_NONCE_SIZE
455 # define gnutls_mac_get_nonce_size fn_gnutls_mac_get_nonce_size
456 # endif
457 # define gnutls_mac_get_key_size fn_gnutls_mac_get_key_size
458 # define gnutls_digest_list fn_gnutls_digest_list
459 # define gnutls_digest_get_name fn_gnutls_digest_get_name
460 # define gnutls_cipher_list fn_gnutls_cipher_list
461 # define gnutls_cipher_get_iv_size fn_gnutls_cipher_get_iv_size
462 # define gnutls_cipher_get_key_size fn_gnutls_cipher_get_key_size
463 # define gnutls_cipher_get_block_size fn_gnutls_cipher_get_block_size
464 # define gnutls_cipher_get_tag_size fn_gnutls_cipher_get_tag_size
465 # define gnutls_cipher_init fn_gnutls_cipher_init
466 # define gnutls_cipher_set_iv fn_gnutls_cipher_set_iv
467 # define gnutls_cipher_encrypt2 fn_gnutls_cipher_encrypt2
468 # define gnutls_cipher_decrypt2 fn_gnutls_cipher_decrypt2
469 # define gnutls_cipher_deinit fn_gnutls_cipher_deinit
470 # ifdef HAVE_GNUTLS_AEAD
471 # define gnutls_aead_cipher_encrypt fn_gnutls_aead_cipher_encrypt
472 # define gnutls_aead_cipher_decrypt fn_gnutls_aead_cipher_decrypt
473 # define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
474 # define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
475 # endif
476 # define gnutls_hmac_init fn_gnutls_hmac_init
477 # define gnutls_hmac_get_len fn_gnutls_hmac_get_len
478 # define gnutls_hmac fn_gnutls_hmac
479 # define gnutls_hmac_deinit fn_gnutls_hmac_deinit
480 # define gnutls_hmac_output fn_gnutls_hmac_output
481 # define gnutls_hash_init fn_gnutls_hash_init
482 # define gnutls_hash_get_len fn_gnutls_hash_get_len
483 # define gnutls_hash fn_gnutls_hash
484 # define gnutls_hash_deinit fn_gnutls_hash_deinit
485 # define gnutls_hash_output fn_gnutls_hash_output
486 # ifdef HAVE_GNUTLS_EXT_GET_NAME
487 # define gnutls_ext_get_name fn_gnutls_ext_get_name
488 # endif
489 # endif /* HAVE_GNUTLS3 */
492 /* This wrapper is called from fns.c, which doesn't know about the
493 LOAD_DLL_FN stuff above. */
495 w32_gnutls_rnd (gnutls_rnd_level_t level, void *data, size_t len)
497 return gnutls_rnd (level, data, len);
500 # endif /* WINDOWSNT */
503 /* Report memory exhaustion if ERR is an out-of-memory indication. */
504 static void
505 check_memory_full (int err)
507 /* When GnuTLS exhausts memory, it doesn't say how much memory it
508 asked for, so tell the Emacs allocator that GnuTLS asked for no
509 bytes. This isn't accurate, but it's good enough. */
510 if (err == GNUTLS_E_MEMORY_ERROR)
511 memory_full (0);
514 # ifdef HAVE_GNUTLS3
515 /* Log a simple audit message. */
516 static void
517 gnutls_audit_log_function (gnutls_session_t session, const char *string)
519 if (global_gnutls_log_level >= 1)
521 message ("gnutls.c: [audit] %s", string);
524 # endif
526 /* Log a simple message. */
527 static void
528 gnutls_log_function (int level, const char *string)
530 message ("gnutls.c: [%d] %s", level, string);
533 /* Log a message and a string. */
534 static void
535 gnutls_log_function2 (int level, const char *string, const char *extra)
537 message ("gnutls.c: [%d] %s %s", level, string, extra);
541 gnutls_try_handshake (struct Lisp_Process *proc)
543 gnutls_session_t state = proc->gnutls_state;
544 int ret;
545 bool non_blocking = proc->is_non_blocking_client;
547 if (proc->gnutls_complete_negotiation_p)
548 non_blocking = false;
550 if (non_blocking)
551 proc->gnutls_p = true;
555 ret = gnutls_handshake (state);
556 emacs_gnutls_handle_error (state, ret);
557 maybe_quit ();
559 while (ret < 0
560 && gnutls_error_is_fatal (ret) == 0
561 && ! non_blocking);
563 proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
565 if (ret == GNUTLS_E_SUCCESS)
567 /* Here we're finally done. */
568 proc->gnutls_initstage = GNUTLS_STAGE_READY;
570 else
572 /* check_memory_full (gnutls_alert_send_appropriate (state, ret)); */
574 return ret;
577 # ifndef WINDOWSNT
578 static int
579 emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
581 int err = errno;
583 switch (err)
585 # ifdef _AIX
586 /* This is taken from the GnuTLS system_errno function circa 2016;
587 see <https://savannah.gnu.org/support/?107464>. */
588 case 0:
589 errno = EAGAIN;
590 /* Fall through. */
591 # endif
592 case EINPROGRESS:
593 case ENOTCONN:
594 return EAGAIN;
596 default:
597 return err;
600 # endif /* !WINDOWSNT */
602 static int
603 emacs_gnutls_handshake (struct Lisp_Process *proc)
605 gnutls_session_t state = proc->gnutls_state;
607 if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO)
608 return -1;
610 if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
612 # ifdef WINDOWSNT
613 /* On W32 we cannot transfer socket handles between different runtime
614 libraries, so we tell GnuTLS to use our special push/pull
615 functions. */
616 gnutls_transport_set_ptr2 (state,
617 (gnutls_transport_ptr_t) proc,
618 (gnutls_transport_ptr_t) proc);
619 gnutls_transport_set_push_function (state, &emacs_gnutls_push);
620 gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
621 # else
622 /* This is how GnuTLS takes sockets: as file descriptors passed
623 in. For an Emacs process socket, infd and outfd are the
624 same but we use this two-argument version for clarity. */
625 gnutls_transport_set_ptr2 (state,
626 (void *) (intptr_t) proc->infd,
627 (void *) (intptr_t) proc->outfd);
628 if (proc->is_non_blocking_client)
629 gnutls_transport_set_errno_function (state,
630 emacs_gnutls_nonblock_errno);
631 # endif
633 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
636 return gnutls_try_handshake (proc);
639 ptrdiff_t
640 emacs_gnutls_record_check_pending (gnutls_session_t state)
642 return gnutls_record_check_pending (state);
645 # ifdef WINDOWSNT
646 void
647 emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
649 gnutls_transport_set_errno (state, err);
651 # endif
653 ptrdiff_t
654 emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
656 ssize_t rtnval = 0;
657 ptrdiff_t bytes_written;
658 gnutls_session_t state = proc->gnutls_state;
660 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
662 errno = EAGAIN;
663 return 0;
666 bytes_written = 0;
668 while (nbyte > 0)
670 rtnval = gnutls_record_send (state, buf, nbyte);
672 if (rtnval < 0)
674 if (rtnval == GNUTLS_E_INTERRUPTED)
675 continue;
676 else
678 /* If we get GNUTLS_E_AGAIN, then set errno
679 appropriately so that send_process retries the
680 correct way instead of erroring out. */
681 if (rtnval == GNUTLS_E_AGAIN)
682 errno = EAGAIN;
683 break;
687 buf += rtnval;
688 nbyte -= rtnval;
689 bytes_written += rtnval;
692 emacs_gnutls_handle_error (state, rtnval);
693 return (bytes_written);
696 ptrdiff_t
697 emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
699 ssize_t rtnval;
700 gnutls_session_t state = proc->gnutls_state;
702 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
704 errno = EAGAIN;
705 return -1;
708 rtnval = gnutls_record_recv (state, buf, nbyte);
709 if (rtnval >= 0)
710 return rtnval;
711 else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
712 /* The peer closed the connection. */
713 return 0;
714 else if (emacs_gnutls_handle_error (state, rtnval))
715 /* non-fatal error */
716 return -1;
717 else {
718 /* a fatal error occurred */
719 return 0;
723 static char const *
724 emacs_gnutls_strerror (int err)
726 char const *str = gnutls_strerror (err);
727 return str ? str : "unknown";
730 /* Report a GnuTLS error to the user.
731 Return true if the error code was successfully handled. */
732 static bool
733 emacs_gnutls_handle_error (gnutls_session_t session, int err)
735 int max_log_level = 0;
737 bool ret;
739 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
740 if (err >= 0)
741 return 1;
743 check_memory_full (err);
745 max_log_level = global_gnutls_log_level;
747 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
749 char const *str = emacs_gnutls_strerror (err);
751 if (gnutls_error_is_fatal (err))
753 int level = 1;
754 /* Mostly ignore "The TLS connection was non-properly
755 terminated" message which just means that the peer closed the
756 connection. */
757 # ifdef HAVE_GNUTLS3
758 if (err == GNUTLS_E_PREMATURE_TERMINATION)
759 level = 3;
760 # endif
762 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
763 ret = false;
765 else
767 ret = true;
769 switch (err)
771 case GNUTLS_E_AGAIN:
772 GNUTLS_LOG2 (3,
773 max_log_level,
774 "retry:",
775 str);
776 FALLTHROUGH;
777 default:
778 GNUTLS_LOG2 (1,
779 max_log_level,
780 "non-fatal error:",
781 str);
785 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
786 || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
788 int alert = gnutls_alert_get (session);
789 int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
790 str = gnutls_alert_get_name (alert);
791 if (!str)
792 str = "unknown";
794 GNUTLS_LOG2 (level, max_log_level, "Received alert: ", str);
796 return ret;
799 /* convert an integer error to a Lisp_Object; it will be either a
800 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
801 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
802 to Qt. */
803 static Lisp_Object
804 gnutls_make_error (int err)
806 switch (err)
808 case GNUTLS_E_SUCCESS:
809 return Qt;
810 case GNUTLS_E_AGAIN:
811 return Qgnutls_e_again;
812 case GNUTLS_E_INTERRUPTED:
813 return Qgnutls_e_interrupted;
814 case GNUTLS_E_INVALID_SESSION:
815 return Qgnutls_e_invalid_session;
818 check_memory_full (err);
819 return make_number (err);
822 Lisp_Object
823 emacs_gnutls_deinit (Lisp_Object proc)
825 int log_level;
827 CHECK_PROCESS (proc);
829 if (! XPROCESS (proc)->gnutls_p)
830 return Qnil;
832 log_level = XPROCESS (proc)->gnutls_log_level;
834 if (XPROCESS (proc)->gnutls_x509_cred)
836 GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
837 gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
838 XPROCESS (proc)->gnutls_x509_cred = NULL;
841 if (XPROCESS (proc)->gnutls_anon_cred)
843 GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
844 gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
845 XPROCESS (proc)->gnutls_anon_cred = NULL;
848 if (XPROCESS (proc)->gnutls_state)
850 gnutls_deinit (XPROCESS (proc)->gnutls_state);
851 XPROCESS (proc)->gnutls_state = NULL;
852 if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
853 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
856 XPROCESS (proc)->gnutls_p = false;
857 return Qt;
860 DEFUN ("gnutls-asynchronous-parameters", Fgnutls_asynchronous_parameters,
861 Sgnutls_asynchronous_parameters, 2, 2, 0,
862 doc: /* Mark this process as being a pre-init GnuTLS process.
863 The second parameter is the list of parameters to feed to gnutls-boot
864 to finish setting up the connection. */)
865 (Lisp_Object proc, Lisp_Object params)
867 CHECK_PROCESS (proc);
869 XPROCESS (proc)->gnutls_boot_parameters = params;
870 return Qnil;
873 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0,
874 doc: /* Return the GnuTLS init stage of process PROC.
875 See also `gnutls-boot'. */)
876 (Lisp_Object proc)
878 CHECK_PROCESS (proc);
880 return make_number (GNUTLS_INITSTAGE (proc));
883 DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
884 doc: /* Return t if ERROR indicates a GnuTLS problem.
885 ERROR is an integer or a symbol with an integer `gnutls-code' property.
886 usage: (gnutls-errorp ERROR) */
887 attributes: const)
888 (Lisp_Object err)
890 if (EQ (err, Qt)
891 || EQ (err, Qgnutls_e_again))
892 return Qnil;
894 return Qt;
897 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
898 doc: /* Return non-nil if ERROR is fatal.
899 ERROR is an integer or a symbol with an integer `gnutls-code' property.
900 Usage: (gnutls-error-fatalp ERROR) */)
901 (Lisp_Object err)
903 Lisp_Object code;
905 if (EQ (err, Qt)) return Qnil;
907 if (SYMBOLP (err))
909 code = Fget (err, Qgnutls_code);
910 if (NUMBERP (code))
912 err = code;
914 else
916 error ("Symbol has no numeric gnutls-code property");
920 if (! TYPE_RANGED_INTEGERP (int, err))
921 error ("Not an error symbol or code");
923 if (0 == gnutls_error_is_fatal (XINT (err)))
924 return Qnil;
926 return Qt;
929 DEFUN ("gnutls-error-string", Fgnutls_error_string, Sgnutls_error_string, 1, 1, 0,
930 doc: /* Return a description of ERROR.
931 ERROR is an integer or a symbol with an integer `gnutls-code' property.
932 usage: (gnutls-error-string ERROR) */)
933 (Lisp_Object err)
935 Lisp_Object code;
937 if (EQ (err, Qt)) return build_string ("Not an error");
939 if (SYMBOLP (err))
941 code = Fget (err, Qgnutls_code);
942 if (NUMBERP (code))
944 err = code;
946 else
948 return build_string ("Symbol has no numeric gnutls-code property");
952 if (! TYPE_RANGED_INTEGERP (int, err))
953 return build_string ("Not an error symbol or code");
955 return build_string (emacs_gnutls_strerror (XINT (err)));
958 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
959 doc: /* Deallocate GnuTLS resources associated with process PROC.
960 See also `gnutls-init'. */)
961 (Lisp_Object proc)
963 return emacs_gnutls_deinit (proc);
966 static Lisp_Object
967 gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
969 ptrdiff_t prefix_length = strlen (prefix);
970 ptrdiff_t retlen;
971 if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
972 || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
973 string_overflow ();
974 Lisp_Object ret = make_uninit_string (retlen);
975 char *string = SSDATA (ret);
976 strcpy (string, prefix);
978 for (ptrdiff_t i = 0; i < buf_size; i++)
979 sprintf (string + i * 3 + prefix_length,
980 i == buf_size - 1 ? "%02x" : "%02x:",
981 buf[i]);
983 return ret;
986 static Lisp_Object
987 gnutls_certificate_details (gnutls_x509_crt_t cert)
989 Lisp_Object res = Qnil;
990 int err;
991 size_t buf_size;
993 /* Version. */
995 int version = gnutls_x509_crt_get_version (cert);
996 check_memory_full (version);
997 if (version >= GNUTLS_E_SUCCESS)
998 res = nconc2 (res, list2 (intern (":version"),
999 make_number (version)));
1002 /* Serial. */
1003 buf_size = 0;
1004 err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
1005 check_memory_full (err);
1006 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1008 void *serial = xmalloc (buf_size);
1009 err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
1010 check_memory_full (err);
1011 if (err >= GNUTLS_E_SUCCESS)
1012 res = nconc2 (res, list2 (intern (":serial-number"),
1013 gnutls_hex_string (serial, buf_size, "")));
1014 xfree (serial);
1017 /* Issuer. */
1018 buf_size = 0;
1019 err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
1020 check_memory_full (err);
1021 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1023 char *dn = xmalloc (buf_size);
1024 err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
1025 check_memory_full (err);
1026 if (err >= GNUTLS_E_SUCCESS)
1027 res = nconc2 (res, list2 (intern (":issuer"),
1028 make_string (dn, buf_size)));
1029 xfree (dn);
1032 /* Validity. */
1034 /* Add 1 to the buffer size, since 1900 is added to tm_year and
1035 that might add 1 to the year length. */
1036 char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
1037 struct tm t;
1038 time_t tim = gnutls_x509_crt_get_activation_time (cert);
1040 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1041 res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
1043 tim = gnutls_x509_crt_get_expiration_time (cert);
1044 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1045 res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
1048 /* Subject. */
1049 buf_size = 0;
1050 err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
1051 check_memory_full (err);
1052 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1054 char *dn = xmalloc (buf_size);
1055 err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
1056 check_memory_full (err);
1057 if (err >= GNUTLS_E_SUCCESS)
1058 res = nconc2 (res, list2 (intern (":subject"),
1059 make_string (dn, buf_size)));
1060 xfree (dn);
1063 /* SubjectPublicKeyInfo. */
1065 unsigned int bits;
1067 err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
1068 check_memory_full (err);
1069 if (err >= GNUTLS_E_SUCCESS)
1071 const char *name = gnutls_pk_algorithm_get_name (err);
1072 if (name)
1073 res = nconc2 (res, list2 (intern (":public-key-algorithm"),
1074 build_string (name)));
1076 name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
1077 (err, bits));
1078 res = nconc2 (res, list2 (intern (":certificate-security-level"),
1079 build_string (name)));
1083 /* Unique IDs. */
1084 buf_size = 0;
1085 err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
1086 check_memory_full (err);
1087 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1089 char *buf = xmalloc (buf_size);
1090 err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
1091 check_memory_full (err);
1092 if (err >= GNUTLS_E_SUCCESS)
1093 res = nconc2 (res, list2 (intern (":issuer-unique-id"),
1094 make_string (buf, buf_size)));
1095 xfree (buf);
1098 buf_size = 0;
1099 err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
1100 check_memory_full (err);
1101 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1103 char *buf = xmalloc (buf_size);
1104 err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
1105 check_memory_full (err);
1106 if (err >= GNUTLS_E_SUCCESS)
1107 res = nconc2 (res, list2 (intern (":subject-unique-id"),
1108 make_string (buf, buf_size)));
1109 xfree (buf);
1112 /* Signature. */
1113 err = gnutls_x509_crt_get_signature_algorithm (cert);
1114 check_memory_full (err);
1115 if (err >= GNUTLS_E_SUCCESS)
1117 const char *name = gnutls_sign_get_name (err);
1118 if (name)
1119 res = nconc2 (res, list2 (intern (":signature-algorithm"),
1120 build_string (name)));
1123 /* Public key ID. */
1124 buf_size = 0;
1125 err = gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size);
1126 check_memory_full (err);
1127 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1129 void *buf = xmalloc (buf_size);
1130 err = gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size);
1131 check_memory_full (err);
1132 if (err >= GNUTLS_E_SUCCESS)
1133 res = nconc2 (res, list2 (intern (":public-key-id"),
1134 gnutls_hex_string (buf, buf_size, "sha1:")));
1135 xfree (buf);
1138 /* Certificate fingerprint. */
1139 buf_size = 0;
1140 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1141 NULL, &buf_size);
1142 check_memory_full (err);
1143 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1145 void *buf = xmalloc (buf_size);
1146 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1147 buf, &buf_size);
1148 check_memory_full (err);
1149 if (err >= GNUTLS_E_SUCCESS)
1150 res = nconc2 (res, list2 (intern (":certificate-id"),
1151 gnutls_hex_string (buf, buf_size, "sha1:")));
1152 xfree (buf);
1155 return res;
1158 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
1159 doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
1160 (Lisp_Object status_symbol)
1162 CHECK_SYMBOL (status_symbol);
1164 if (EQ (status_symbol, intern (":invalid")))
1165 return build_string ("certificate could not be verified");
1167 if (EQ (status_symbol, intern (":revoked")))
1168 return build_string ("certificate was revoked (CRL)");
1170 if (EQ (status_symbol, intern (":self-signed")))
1171 return build_string ("certificate signer was not found (self-signed)");
1173 if (EQ (status_symbol, intern (":unknown-ca")))
1174 return build_string ("the certificate was signed by an unknown "
1175 "and therefore untrusted authority");
1177 if (EQ (status_symbol, intern (":not-ca")))
1178 return build_string ("certificate signer is not a CA");
1180 if (EQ (status_symbol, intern (":insecure")))
1181 return build_string ("certificate was signed with an insecure algorithm");
1183 if (EQ (status_symbol, intern (":not-activated")))
1184 return build_string ("certificate is not yet activated");
1186 if (EQ (status_symbol, intern (":expired")))
1187 return build_string ("certificate has expired");
1189 if (EQ (status_symbol, intern (":no-host-match")))
1190 return build_string ("certificate host does not match hostname");
1192 return Qnil;
1195 DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
1196 doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1197 The return value is a property list with top-level keys :warnings and
1198 :certificate. The :warnings entry is a list of symbols you can describe with
1199 `gnutls-peer-status-warning-describe'. */)
1200 (Lisp_Object proc)
1202 Lisp_Object warnings = Qnil, result = Qnil;
1203 unsigned int verification;
1204 gnutls_session_t state;
1206 CHECK_PROCESS (proc);
1208 if (GNUTLS_INITSTAGE (proc) != GNUTLS_STAGE_READY)
1209 return Qnil;
1211 /* Then collect any warnings already computed by the handshake. */
1212 verification = XPROCESS (proc)->gnutls_peer_verification;
1214 if (verification & GNUTLS_CERT_INVALID)
1215 warnings = Fcons (intern (":invalid"), warnings);
1217 if (verification & GNUTLS_CERT_REVOKED)
1218 warnings = Fcons (intern (":revoked"), warnings);
1220 if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
1221 warnings = Fcons (intern (":unknown-ca"), warnings);
1223 if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
1224 warnings = Fcons (intern (":not-ca"), warnings);
1226 if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
1227 warnings = Fcons (intern (":insecure"), warnings);
1229 if (verification & GNUTLS_CERT_NOT_ACTIVATED)
1230 warnings = Fcons (intern (":not-activated"), warnings);
1232 if (verification & GNUTLS_CERT_EXPIRED)
1233 warnings = Fcons (intern (":expired"), warnings);
1235 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1236 CERTIFICATE_NOT_MATCHING)
1237 warnings = Fcons (intern (":no-host-match"), warnings);
1239 /* This could get called in the INIT stage, when the certificate is
1240 not yet set. */
1241 if (XPROCESS (proc)->gnutls_certificate != NULL &&
1242 gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificate,
1243 XPROCESS (proc)->gnutls_certificate))
1244 warnings = Fcons (intern (":self-signed"), warnings);
1246 if (!NILP (warnings))
1247 result = list2 (intern (":warnings"), warnings);
1249 /* This could get called in the INIT stage, when the certificate is
1250 not yet set. */
1251 if (XPROCESS (proc)->gnutls_certificate != NULL)
1252 result = nconc2 (result, list2
1253 (intern (":certificate"),
1254 gnutls_certificate_details (XPROCESS (proc)->gnutls_certificate)));
1256 state = XPROCESS (proc)->gnutls_state;
1258 /* Diffie-Hellman prime bits. */
1260 int bits = gnutls_dh_get_prime_bits (state);
1261 check_memory_full (bits);
1262 if (bits > 0)
1263 result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
1264 make_number (bits)));
1267 /* Key exchange. */
1268 result = nconc2
1269 (result, list2 (intern (":key-exchange"),
1270 build_string (gnutls_kx_get_name
1271 (gnutls_kx_get (state)))));
1273 /* Protocol name. */
1274 result = nconc2
1275 (result, list2 (intern (":protocol"),
1276 build_string (gnutls_protocol_get_name
1277 (gnutls_protocol_get_version (state)))));
1279 /* Cipher name. */
1280 result = nconc2
1281 (result, list2 (intern (":cipher"),
1282 build_string (gnutls_cipher_get_name
1283 (gnutls_cipher_get (state)))));
1285 /* MAC name. */
1286 result = nconc2
1287 (result, list2 (intern (":mac"),
1288 build_string (gnutls_mac_get_name
1289 (gnutls_mac_get (state)))));
1292 return result;
1295 /* Initialize global GnuTLS state to defaults.
1296 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1297 Return zero on success. */
1298 Lisp_Object
1299 emacs_gnutls_global_init (void)
1301 int ret = GNUTLS_E_SUCCESS;
1303 if (!gnutls_global_initialized)
1305 ret = gnutls_global_init ();
1306 if (ret == GNUTLS_E_SUCCESS)
1307 gnutls_global_initialized = 1;
1310 return gnutls_make_error (ret);
1313 static bool
1314 gnutls_ip_address_p (char *string)
1316 char c;
1318 while ((c = *string++) != 0)
1319 if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
1320 return false;
1322 return true;
1325 # if 0
1326 /* Deinitialize global GnuTLS state.
1327 See also `gnutls-global-init'. */
1328 static Lisp_Object
1329 emacs_gnutls_global_deinit (void)
1331 if (gnutls_global_initialized)
1332 gnutls_global_deinit ();
1334 gnutls_global_initialized = 0;
1336 return gnutls_make_error (GNUTLS_E_SUCCESS);
1338 # endif
1340 static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
1341 boot_error (struct Lisp_Process *p, const char *m, ...)
1343 va_list ap;
1344 va_start (ap, m);
1345 if (p->is_non_blocking_client)
1346 pset_status (p, list2 (Qfailed, vformat_string (m, ap)));
1347 else
1348 verror (m, ap);
1349 va_end (ap);
1352 Lisp_Object
1353 gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1355 int ret;
1356 struct Lisp_Process *p = XPROCESS (proc);
1357 gnutls_session_t state = p->gnutls_state;
1358 unsigned int peer_verification;
1359 Lisp_Object warnings;
1360 int max_log_level = p->gnutls_log_level;
1361 Lisp_Object hostname, verify_error;
1362 bool verify_error_all = false;
1363 char *c_hostname;
1365 if (NILP (proplist))
1366 proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
1368 verify_error = Fplist_get (proplist, QCverify_error);
1369 hostname = Fplist_get (proplist, QChostname);
1371 if (EQ (verify_error, Qt))
1372 verify_error_all = true;
1373 else if (NILP (Flistp (verify_error)))
1375 boot_error (p,
1376 "gnutls-boot: invalid :verify_error parameter (not a list)");
1377 return Qnil;
1380 if (!STRINGP (hostname))
1382 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1383 return Qnil;
1385 c_hostname = SSDATA (hostname);
1387 /* Now verify the peer, following
1388 https://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1389 The peer should present at least one certificate in the chain; do a
1390 check of the certificate's hostname with
1391 gnutls_x509_crt_check_hostname against :hostname. */
1393 ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
1394 if (ret < GNUTLS_E_SUCCESS)
1395 return gnutls_make_error (ret);
1397 XPROCESS (proc)->gnutls_peer_verification = peer_verification;
1399 warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
1400 if (!NILP (warnings))
1402 for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
1404 Lisp_Object warning = XCAR (tail);
1405 Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
1406 if (!NILP (message))
1407 GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
1411 if (peer_verification != 0)
1413 if (verify_error_all
1414 || !NILP (Fmember (QCtrustfiles, verify_error)))
1416 emacs_gnutls_deinit (proc);
1417 boot_error (p,
1418 "Certificate validation failed %s, verification code %x",
1419 c_hostname, peer_verification);
1420 return Qnil;
1422 else
1424 GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
1425 c_hostname);
1429 /* Up to here the process is the same for X.509 certificates and
1430 OpenPGP keys. From now on X.509 certificates are assumed. This
1431 can be easily extended to work with openpgp keys as well. */
1432 if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
1434 gnutls_x509_crt_t gnutls_verify_cert;
1435 const gnutls_datum_t *gnutls_verify_cert_list;
1436 unsigned int gnutls_verify_cert_list_size;
1438 ret = gnutls_x509_crt_init (&gnutls_verify_cert);
1439 if (ret < GNUTLS_E_SUCCESS)
1440 return gnutls_make_error (ret);
1442 gnutls_verify_cert_list
1443 = gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
1445 if (gnutls_verify_cert_list == NULL)
1447 gnutls_x509_crt_deinit (gnutls_verify_cert);
1448 emacs_gnutls_deinit (proc);
1449 boot_error (p, "No x509 certificate was found\n");
1450 return Qnil;
1453 /* Check only the first certificate in the given chain. */
1454 ret = gnutls_x509_crt_import (gnutls_verify_cert,
1455 &gnutls_verify_cert_list[0],
1456 GNUTLS_X509_FMT_DER);
1458 if (ret < GNUTLS_E_SUCCESS)
1460 gnutls_x509_crt_deinit (gnutls_verify_cert);
1461 return gnutls_make_error (ret);
1464 XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert;
1466 int err = gnutls_x509_crt_check_hostname (gnutls_verify_cert,
1467 c_hostname);
1468 check_memory_full (err);
1469 if (!err)
1471 XPROCESS (proc)->gnutls_extra_peer_verification
1472 |= CERTIFICATE_NOT_MATCHING;
1473 if (verify_error_all
1474 || !NILP (Fmember (QChostname, verify_error)))
1476 gnutls_x509_crt_deinit (gnutls_verify_cert);
1477 emacs_gnutls_deinit (proc);
1478 boot_error (p, "The x509 certificate does not match \"%s\"",
1479 c_hostname);
1480 return Qnil;
1482 else
1483 GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
1484 c_hostname);
1488 /* Set this flag only if the whole initialization succeeded. */
1489 XPROCESS (proc)->gnutls_p = true;
1491 return gnutls_make_error (ret);
1494 DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1495 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1496 Currently only client mode is supported. Return a success/failure
1497 value you can check with `gnutls-errorp'.
1499 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1500 PROPLIST is a property list with the following keys:
1502 :hostname is a string naming the remote host.
1504 :priority is a GnuTLS priority string, defaults to "NORMAL".
1506 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1508 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1510 :keylist is an alist of PEM-encoded key files and PEM-encoded
1511 certificates for `gnutls-x509pki'.
1513 :callbacks is an alist of callback functions, see below.
1515 :loglevel is the debug level requested from GnuTLS, try 4.
1517 :verify-flags is a bitset as per GnuTLS'
1518 gnutls_certificate_set_verify_flags.
1520 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1521 instead.
1523 :verify-error is a list of symbols to express verification checks or
1524 t to do all checks. Currently it can contain `:trustfiles' and
1525 `:hostname' to verify the certificate or the hostname respectively.
1527 :min-prime-bits is the minimum accepted number of bits the client will
1528 accept in Diffie-Hellman key exchange.
1530 :complete-negotiation, if non-nil, will make negotiation complete
1531 before returning even on non-blocking sockets.
1533 The debug level will be set for this process AND globally for GnuTLS.
1534 So if you set it higher or lower at any point, it affects global
1535 debugging.
1537 Note that the priority is set on the client. The server does not use
1538 the protocols's priority except for disabling protocols that were not
1539 specified.
1541 Processes must be initialized with this function before other GnuTLS
1542 functions are used. This function allocates resources which can only
1543 be deallocated by calling `gnutls-deinit' or by calling it again.
1545 The callbacks alist can have a `verify' key, associated with a
1546 verification function (UNUSED).
1548 Each authentication type may need additional information in order to
1549 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1550 one trustfile (usually a CA bundle). */)
1551 (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist)
1553 int ret = GNUTLS_E_SUCCESS;
1554 int max_log_level = 0;
1556 gnutls_session_t state;
1557 gnutls_certificate_credentials_t x509_cred = NULL;
1558 gnutls_anon_client_credentials_t anon_cred = NULL;
1559 Lisp_Object global_init;
1560 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1561 char *c_hostname;
1563 /* Placeholders for the property list elements. */
1564 Lisp_Object priority_string;
1565 Lisp_Object trustfiles;
1566 Lisp_Object crlfiles;
1567 Lisp_Object keylist;
1568 /* Lisp_Object callbacks; */
1569 Lisp_Object loglevel;
1570 Lisp_Object hostname;
1571 Lisp_Object prime_bits;
1572 struct Lisp_Process *p = XPROCESS (proc);
1574 CHECK_PROCESS (proc);
1575 CHECK_SYMBOL (type);
1576 CHECK_LIST (proplist);
1578 if (NILP (Fgnutls_available_p ()))
1580 boot_error (p, "GnuTLS not available");
1581 return Qnil;
1584 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1586 boot_error (p, "Invalid GnuTLS credential type");
1587 return Qnil;
1590 hostname = Fplist_get (proplist, QChostname);
1591 priority_string = Fplist_get (proplist, QCpriority);
1592 trustfiles = Fplist_get (proplist, QCtrustfiles);
1593 keylist = Fplist_get (proplist, QCkeylist);
1594 crlfiles = Fplist_get (proplist, QCcrlfiles);
1595 loglevel = Fplist_get (proplist, QCloglevel);
1596 prime_bits = Fplist_get (proplist, QCmin_prime_bits);
1598 if (!STRINGP (hostname))
1600 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1601 return Qnil;
1603 c_hostname = SSDATA (hostname);
1605 state = XPROCESS (proc)->gnutls_state;
1607 if (TYPE_RANGED_INTEGERP (int, loglevel))
1609 gnutls_global_set_log_function (gnutls_log_function);
1610 # ifdef HAVE_GNUTLS3
1611 gnutls_global_set_audit_log_function (gnutls_audit_log_function);
1612 # endif
1613 gnutls_global_set_log_level (XINT (loglevel));
1614 max_log_level = XINT (loglevel);
1615 XPROCESS (proc)->gnutls_log_level = max_log_level;
1618 GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
1620 /* Always initialize globals. */
1621 global_init = emacs_gnutls_global_init ();
1622 if (! NILP (Fgnutls_errorp (global_init)))
1623 return global_init;
1625 /* Before allocating new credentials, deallocate any credentials
1626 that PROC might already have. */
1627 emacs_gnutls_deinit (proc);
1629 /* Mark PROC as a GnuTLS process. */
1630 XPROCESS (proc)->gnutls_state = NULL;
1631 XPROCESS (proc)->gnutls_x509_cred = NULL;
1632 XPROCESS (proc)->gnutls_anon_cred = NULL;
1633 pset_gnutls_cred_type (XPROCESS (proc), type);
1634 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY;
1636 GNUTLS_LOG (1, max_log_level, "allocating credentials");
1637 if (EQ (type, Qgnutls_x509pki))
1639 Lisp_Object verify_flags;
1640 unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1642 GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
1643 check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
1644 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1646 verify_flags = Fplist_get (proplist, QCverify_flags);
1647 if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
1649 gnutls_verify_flags = XFASTINT (verify_flags);
1650 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1652 else if (NILP (verify_flags))
1653 GNUTLS_LOG (2, max_log_level, "using default verification flags");
1654 else
1655 GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
1657 gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
1659 else /* Qgnutls_anon: */
1661 GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
1662 check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
1663 XPROCESS (proc)->gnutls_anon_cred = anon_cred;
1666 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC;
1668 if (EQ (type, Qgnutls_x509pki))
1670 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1671 int file_format = GNUTLS_X509_FMT_PEM;
1672 Lisp_Object tail;
1674 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
1675 ret = gnutls_certificate_set_x509_system_trust (x509_cred);
1676 if (ret < GNUTLS_E_SUCCESS)
1678 check_memory_full (ret);
1679 GNUTLS_LOG2i (4, max_log_level,
1680 "setting system trust failed with code ", ret);
1682 # endif
1684 for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
1686 Lisp_Object trustfile = XCAR (tail);
1687 if (STRINGP (trustfile))
1689 GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
1690 SSDATA (trustfile));
1691 trustfile = ENCODE_FILE (trustfile);
1692 # ifdef WINDOWSNT
1693 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1694 file names on Windows, we need to re-encode the file
1695 name using the current ANSI codepage. */
1696 trustfile = ansi_encode_filename (trustfile);
1697 # endif
1698 ret = gnutls_certificate_set_x509_trust_file
1699 (x509_cred,
1700 SSDATA (trustfile),
1701 file_format);
1703 if (ret < GNUTLS_E_SUCCESS)
1704 return gnutls_make_error (ret);
1706 else
1708 emacs_gnutls_deinit (proc);
1709 boot_error (p, "Invalid trustfile");
1710 return Qnil;
1714 for (tail = crlfiles; CONSP (tail); tail = XCDR (tail))
1716 Lisp_Object crlfile = XCAR (tail);
1717 if (STRINGP (crlfile))
1719 GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
1720 SSDATA (crlfile));
1721 crlfile = ENCODE_FILE (crlfile);
1722 # ifdef WINDOWSNT
1723 crlfile = ansi_encode_filename (crlfile);
1724 # endif
1725 ret = gnutls_certificate_set_x509_crl_file
1726 (x509_cred, SSDATA (crlfile), file_format);
1728 if (ret < GNUTLS_E_SUCCESS)
1729 return gnutls_make_error (ret);
1731 else
1733 emacs_gnutls_deinit (proc);
1734 boot_error (p, "Invalid CRL file");
1735 return Qnil;
1739 for (tail = keylist; CONSP (tail); tail = XCDR (tail))
1741 Lisp_Object keyfile = Fcar (XCAR (tail));
1742 Lisp_Object certfile = Fcar (Fcdr (XCAR (tail)));
1743 if (STRINGP (keyfile) && STRINGP (certfile))
1745 GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ",
1746 SSDATA (keyfile));
1747 GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
1748 SSDATA (certfile));
1749 keyfile = ENCODE_FILE (keyfile);
1750 certfile = ENCODE_FILE (certfile);
1751 # ifdef WINDOWSNT
1752 keyfile = ansi_encode_filename (keyfile);
1753 certfile = ansi_encode_filename (certfile);
1754 # endif
1755 ret = gnutls_certificate_set_x509_key_file
1756 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
1758 if (ret < GNUTLS_E_SUCCESS)
1759 return gnutls_make_error (ret);
1761 else
1763 emacs_gnutls_deinit (proc);
1764 boot_error (p, STRINGP (keyfile) ? "Invalid client cert file"
1765 : "Invalid client key file");
1766 return Qnil;
1771 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
1772 GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
1773 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
1775 /* Call gnutls_init here: */
1777 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1778 int gnutls_flags = GNUTLS_CLIENT;
1779 # ifdef GNUTLS_NONBLOCK
1780 if (XPROCESS (proc)->is_non_blocking_client)
1781 gnutls_flags |= GNUTLS_NONBLOCK;
1782 # endif
1783 ret = gnutls_init (&state, gnutls_flags);
1784 XPROCESS (proc)->gnutls_state = state;
1785 if (ret < GNUTLS_E_SUCCESS)
1786 return gnutls_make_error (ret);
1787 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT;
1789 if (STRINGP (priority_string))
1791 priority_string_ptr = SSDATA (priority_string);
1792 GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:",
1793 priority_string_ptr);
1795 else
1797 GNUTLS_LOG2 (1, max_log_level, "using default priority string:",
1798 priority_string_ptr);
1801 GNUTLS_LOG (1, max_log_level, "setting the priority string");
1802 ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
1803 if (ret < GNUTLS_E_SUCCESS)
1804 return gnutls_make_error (ret);
1806 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
1808 if (INTEGERP (prime_bits))
1809 gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
1811 ret = EQ (type, Qgnutls_x509pki)
1812 ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
1813 : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
1814 if (ret < GNUTLS_E_SUCCESS)
1815 return gnutls_make_error (ret);
1817 if (!gnutls_ip_address_p (c_hostname))
1819 ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
1820 strlen (c_hostname));
1821 if (ret < GNUTLS_E_SUCCESS)
1822 return gnutls_make_error (ret);
1825 XPROCESS (proc)->gnutls_complete_negotiation_p =
1826 !NILP (Fplist_get (proplist, QCcomplete_negotiation));
1827 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
1828 ret = emacs_gnutls_handshake (XPROCESS (proc));
1829 if (ret < GNUTLS_E_SUCCESS)
1830 return gnutls_make_error (ret);
1832 return gnutls_verify_boot (proc, proplist);
1835 DEFUN ("gnutls-bye", Fgnutls_bye,
1836 Sgnutls_bye, 2, 2, 0,
1837 doc: /* Terminate current GnuTLS connection for process PROC.
1838 The connection should have been initiated using `gnutls-handshake'.
1840 If CONT is not nil the TLS connection gets terminated and further
1841 receives and sends will be disallowed. If the return value is zero you
1842 may continue using the connection. If CONT is nil, GnuTLS actually
1843 sends an alert containing a close request and waits for the peer to
1844 reply with the same message. In order to reuse the connection you
1845 should wait for an EOF from the peer.
1847 This function may also return `gnutls-e-again', or
1848 `gnutls-e-interrupted'. */)
1849 (Lisp_Object proc, Lisp_Object cont)
1851 gnutls_session_t state;
1852 int ret;
1854 CHECK_PROCESS (proc);
1856 state = XPROCESS (proc)->gnutls_state;
1858 gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate);
1860 ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
1862 return gnutls_make_error (ret);
1865 #endif /* HAVE_GNUTLS */
1867 #ifdef HAVE_GNUTLS3
1869 DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
1870 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
1871 The alist key is the cipher name. */)
1872 (void)
1874 Lisp_Object ciphers = Qnil;
1876 const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
1877 for (ptrdiff_t pos = 0; gciphers[pos] != 0; pos++)
1879 gnutls_cipher_algorithm_t gca = gciphers[pos];
1880 if (gca == GNUTLS_CIPHER_NULL)
1881 continue;
1882 char const *cipher_name = gnutls_cipher_get_name (gca);
1883 if (!cipher_name)
1884 continue;
1886 /* A symbol representing the GnuTLS cipher. */
1887 Lisp_Object cipher_symbol = intern (cipher_name);
1889 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1891 Lisp_Object cp
1892 = listn (CONSTYPE_HEAP, 15, cipher_symbol,
1893 QCcipher_id, make_number (gca),
1894 QCtype, Qgnutls_type_cipher,
1895 QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
1896 QCcipher_tagsize, make_number (cipher_tag_size),
1898 QCcipher_blocksize,
1899 make_number (gnutls_cipher_get_block_size (gca)),
1901 QCcipher_keysize,
1902 make_number (gnutls_cipher_get_key_size (gca)),
1904 QCcipher_ivsize,
1905 make_number (gnutls_cipher_get_iv_size (gca)));
1907 ciphers = Fcons (cp, ciphers);
1910 return ciphers;
1913 static Lisp_Object
1914 gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1915 Lisp_Object cipher,
1916 const char *kdata, ptrdiff_t ksize,
1917 const char *vdata, ptrdiff_t vsize,
1918 const char *idata, ptrdiff_t isize,
1919 Lisp_Object aead_auth)
1921 # ifdef HAVE_GNUTLS_AEAD
1923 const char *desc = encrypting ? "encrypt" : "decrypt";
1924 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
1926 gnutls_aead_cipher_hd_t acipher;
1927 gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
1928 int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
1930 if (ret < GNUTLS_E_SUCCESS)
1931 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
1932 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1934 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1935 ptrdiff_t tagged_size;
1936 if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
1937 || SIZE_MAX < tagged_size)
1938 memory_full (SIZE_MAX);
1939 size_t storage_length = tagged_size;
1940 USE_SAFE_ALLOCA;
1941 char *storage = SAFE_ALLOCA (storage_length);
1943 const char *aead_auth_data = NULL;
1944 ptrdiff_t aead_auth_size = 0;
1946 if (!NILP (aead_auth))
1948 if (BUFFERP (aead_auth) || STRINGP (aead_auth))
1949 aead_auth = list1 (aead_auth);
1951 CHECK_CONS (aead_auth);
1953 ptrdiff_t astart_byte, aend_byte;
1954 const char *adata
1955 = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
1956 if (adata == NULL)
1957 error ("GnuTLS AEAD cipher auth extraction failed");
1959 aead_auth_data = adata;
1960 aead_auth_size = aend_byte - astart_byte;
1963 ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
1964 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
1966 if (isize < expected_remainder
1967 || (isize - expected_remainder) % cipher_block_size != 0)
1968 error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
1969 "is not %"pD"d greater than a multiple of the required %"pD"d"),
1970 gnutls_cipher_get_name (gca), desc,
1971 isize, expected_remainder, cipher_block_size);
1973 ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
1974 (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
1975 cipher_tag_size, idata, isize, storage, &storage_length));
1977 Lisp_Object output;
1978 if (GNUTLS_E_SUCCESS <= ret)
1979 output = make_unibyte_string (storage, storage_length);
1980 explicit_bzero (storage, storage_length);
1981 gnutls_aead_cipher_deinit (acipher);
1983 if (ret < GNUTLS_E_SUCCESS)
1984 error ((encrypting
1985 ? "GnuTLS AEAD cipher %s encryption failed: %s"
1986 : "GnuTLS AEAD cipher %s decryption failed: %s"),
1987 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
1989 SAFE_FREE ();
1990 return list2 (output, actual_iv);
1991 # else
1992 printmax_t print_gca = gca;
1993 error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
1994 # endif
1997 static Lisp_Object
1998 gnutls_symmetric (bool encrypting, Lisp_Object cipher,
1999 Lisp_Object key, Lisp_Object iv,
2000 Lisp_Object input, Lisp_Object aead_auth)
2002 if (BUFFERP (key) || STRINGP (key))
2003 key = list1 (key);
2005 CHECK_CONS (key);
2007 if (BUFFERP (input) || STRINGP (input))
2008 input = list1 (input);
2010 CHECK_CONS (input);
2012 if (BUFFERP (iv) || STRINGP (iv))
2013 iv = list1 (iv);
2015 CHECK_CONS (iv);
2018 const char *desc = encrypting ? "encrypt" : "decrypt";
2020 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
2022 Lisp_Object info = Qnil;
2023 if (STRINGP (cipher))
2024 cipher = intern (SSDATA (cipher));
2026 if (SYMBOLP (cipher))
2027 info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
2028 else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
2029 gca = XINT (cipher);
2030 else
2031 info = cipher;
2033 if (!NILP (info) && CONSP (info))
2035 Lisp_Object v = Fplist_get (info, QCcipher_id);
2036 if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
2037 gca = XINT (v);
2040 ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
2041 if (key_size == 0)
2042 error ("GnuTLS cipher is invalid or not found");
2044 ptrdiff_t kstart_byte, kend_byte;
2045 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2047 if (kdata == NULL)
2048 error ("GnuTLS cipher key extraction failed");
2050 if (kend_byte - kstart_byte != key_size)
2051 error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
2052 "the required %"pD"d"),
2053 gnutls_cipher_get_name (gca), desc,
2054 kend_byte - kstart_byte, key_size);
2056 ptrdiff_t vstart_byte, vend_byte;
2057 char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
2059 if (vdata == NULL)
2060 error ("GnuTLS cipher IV extraction failed");
2062 ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
2063 if (vend_byte - vstart_byte != iv_size)
2064 error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
2065 "the required %"pD"d"),
2066 gnutls_cipher_get_name (gca), desc,
2067 vend_byte - vstart_byte, iv_size);
2069 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
2071 ptrdiff_t istart_byte, iend_byte;
2072 const char *idata
2073 = extract_data_from_object (input, &istart_byte, &iend_byte);
2075 if (idata == NULL)
2076 error ("GnuTLS cipher input extraction failed");
2078 /* Is this an AEAD cipher? */
2079 if (gnutls_cipher_get_tag_size (gca) > 0)
2081 Lisp_Object aead_output =
2082 gnutls_symmetric_aead (encrypting, gca, cipher,
2083 kdata, kend_byte - kstart_byte,
2084 vdata, vend_byte - vstart_byte,
2085 idata, iend_byte - istart_byte,
2086 aead_auth);
2087 if (STRINGP (XCAR (key)))
2088 Fclear_string (XCAR (key));
2089 return aead_output;
2092 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2093 if ((iend_byte - istart_byte) % cipher_block_size != 0)
2094 error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
2095 "of the required %"pD"d"),
2096 gnutls_cipher_get_name (gca), desc,
2097 iend_byte - istart_byte, cipher_block_size);
2099 gnutls_cipher_hd_t hcipher;
2100 gnutls_datum_t key_datum
2101 = { (unsigned char *) kdata, kend_byte - kstart_byte };
2103 int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
2105 if (ret < GNUTLS_E_SUCCESS)
2106 error ("GnuTLS cipher %s/%s initialization failed: %s",
2107 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2109 /* Note that this will not support streaming block mode. */
2110 gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
2112 /* GnuTLS docs: "For the supported ciphers the encrypted data length
2113 will equal the plaintext size." */
2114 ptrdiff_t storage_length = iend_byte - istart_byte;
2115 Lisp_Object storage = make_uninit_string (storage_length);
2117 ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
2118 (hcipher, idata, iend_byte - istart_byte,
2119 SSDATA (storage), storage_length));
2121 if (STRINGP (XCAR (key)))
2122 Fclear_string (XCAR (key));
2124 if (ret < GNUTLS_E_SUCCESS)
2126 gnutls_cipher_deinit (hcipher);
2127 if (encrypting)
2128 error ("GnuTLS cipher %s encryption failed: %s",
2129 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2130 else
2131 error ("GnuTLS cipher %s decryption failed: %s",
2132 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2135 gnutls_cipher_deinit (hcipher);
2137 return list2 (storage, actual_iv);
2140 DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
2141 Sgnutls_symmetric_encrypt, 4, 5, 0,
2142 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2144 Return nil on error.
2146 The KEY can be specified as a buffer or string or in other ways (see
2147 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2148 will be wiped after use if it's a string.
2150 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2151 buffer or string or in other ways (see Info node `(elisp)Format of
2152 GnuTLS Cryptography Inputs').
2154 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2155 The CIPHER may be a string or symbol matching a key in that alist, or
2156 a plist with the :cipher-id numeric property, or the number itself.
2158 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2159 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2160 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2161 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2162 Lisp_Object input, Lisp_Object aead_auth)
2164 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
2167 DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
2168 Sgnutls_symmetric_decrypt, 4, 5, 0,
2169 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2171 Return nil on error.
2173 The KEY can be specified as a buffer or string or in other ways (see
2174 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2175 will be wiped after use if it's a string.
2177 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2178 buffer or string or in other ways (see Info node `(elisp)Format of
2179 GnuTLS Cryptography Inputs').
2181 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2182 The CIPHER may be a string or symbol matching a key in that alist, or
2183 a plist with the `:cipher-id' numeric property, or the number itself.
2185 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2186 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2187 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2188 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2189 Lisp_Object input, Lisp_Object aead_auth)
2191 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
2194 DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
2195 doc: /* Return alist of GnuTLS mac-algorithm method descriptions as plists.
2197 Use the value of the alist (extract it with `alist-get' for instance)
2198 with `gnutls-hash-mac'. The alist key is the mac-algorithm method
2199 name. */)
2200 (void)
2202 Lisp_Object mac_algorithms = Qnil;
2203 const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
2204 for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
2206 const gnutls_mac_algorithm_t gma = macs[pos];
2208 /* A symbol representing the GnuTLS MAC algorithm. */
2209 Lisp_Object gma_symbol = intern (gnutls_mac_get_name (gma));
2211 size_t nonce_size = 0;
2212 #ifdef HAVE_GNUTLS_MAC_GET_NONCE_SIZE
2213 nonce_size = gnutls_mac_get_nonce_size (gma);
2214 #endif
2215 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, gma_symbol,
2216 QCmac_algorithm_id, make_number (gma),
2217 QCtype, Qgnutls_type_mac_algorithm,
2219 QCmac_algorithm_length,
2220 make_number (gnutls_hmac_get_len (gma)),
2222 QCmac_algorithm_keysize,
2223 make_number (gnutls_mac_get_key_size (gma)),
2225 QCmac_algorithm_noncesize,
2226 make_number (nonce_size));
2227 mac_algorithms = Fcons (mp, mac_algorithms);
2230 return mac_algorithms;
2233 DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
2234 doc: /* Return alist of GnuTLS digest-algorithm method descriptions as plists.
2236 Use the value of the alist (extract it with `alist-get' for instance)
2237 with `gnutls-hash-digest'. The alist key is the digest-algorithm
2238 method name. */)
2239 (void)
2241 Lisp_Object digest_algorithms = Qnil;
2242 const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
2243 for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
2245 const gnutls_digest_algorithm_t gda = digests[pos];
2247 /* A symbol representing the GnuTLS digest algorithm. */
2248 Lisp_Object gda_symbol = intern (gnutls_digest_get_name (gda));
2250 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, gda_symbol,
2251 QCdigest_algorithm_id, make_number (gda),
2252 QCtype, Qgnutls_type_digest_algorithm,
2254 QCdigest_algorithm_length,
2255 make_number (gnutls_hash_get_len (gda)));
2257 digest_algorithms = Fcons (mp, digest_algorithms);
2260 return digest_algorithms;
2263 DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
2264 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
2266 Return nil on error.
2268 The KEY can be specified as a buffer or string or in other ways (see
2269 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2270 will be wiped after use if it's a string.
2272 The INPUT can be specified as a buffer or string or in other
2273 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2275 The alist of MAC algorithms can be obtained with `gnutls-macs`. The
2276 HASH-METHOD may be a string or symbol matching a key in that alist, or
2277 a plist with the `:mac-algorithm-id' numeric property, or the number
2278 itself. */)
2279 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
2281 if (BUFFERP (input) || STRINGP (input))
2282 input = list1 (input);
2284 CHECK_CONS (input);
2286 if (BUFFERP (key) || STRINGP (key))
2287 key = list1 (key);
2289 CHECK_CONS (key);
2291 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
2293 Lisp_Object info = Qnil;
2294 if (STRINGP (hash_method))
2295 hash_method = intern (SSDATA (hash_method));
2297 if (SYMBOLP (hash_method))
2298 info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
2299 else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
2300 gma = XINT (hash_method);
2301 else
2302 info = hash_method;
2304 if (!NILP (info) && CONSP (info))
2306 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
2307 if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
2308 gma = XINT (v);
2311 ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
2312 if (digest_length == 0)
2313 error ("GnuTLS MAC-method is invalid or not found");
2315 ptrdiff_t kstart_byte, kend_byte;
2316 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2317 if (kdata == NULL)
2318 error ("GnuTLS MAC key extraction failed");
2320 gnutls_hmac_hd_t hmac;
2321 int ret = gnutls_hmac_init (&hmac, gma,
2322 kdata + kstart_byte, kend_byte - kstart_byte);
2323 if (ret < GNUTLS_E_SUCCESS)
2324 error ("GnuTLS MAC %s initialization failed: %s",
2325 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2327 ptrdiff_t istart_byte, iend_byte;
2328 const char *idata
2329 = extract_data_from_object (input, &istart_byte, &iend_byte);
2330 if (idata == NULL)
2331 error ("GnuTLS MAC input extraction failed");
2333 Lisp_Object digest = make_uninit_string (digest_length);
2335 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
2337 if (STRINGP (XCAR (key)))
2338 Fclear_string (XCAR (key));
2340 if (ret < GNUTLS_E_SUCCESS)
2342 gnutls_hmac_deinit (hmac, NULL);
2343 error ("GnuTLS MAC %s application failed: %s",
2344 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2347 gnutls_hmac_output (hmac, SSDATA (digest));
2348 gnutls_hmac_deinit (hmac, NULL);
2350 return digest;
2353 DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
2354 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
2356 Return nil on error.
2358 The INPUT can be specified as a buffer or string or in other
2359 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2361 The alist of digest algorithms can be obtained with `gnutls-digests`.
2362 The DIGEST-METHOD may be a string or symbol matching a key in that
2363 alist, or a plist with the `:digest-algorithm-id' numeric property, or
2364 the number itself. */)
2365 (Lisp_Object digest_method, Lisp_Object input)
2367 if (BUFFERP (input) || STRINGP (input))
2368 input = list1 (input);
2370 CHECK_CONS (input);
2372 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
2374 Lisp_Object info = Qnil;
2375 if (STRINGP (digest_method))
2376 digest_method = intern (SSDATA (digest_method));
2378 if (SYMBOLP (digest_method))
2379 info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
2380 else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
2381 gda = XINT (digest_method);
2382 else
2383 info = digest_method;
2385 if (!NILP (info) && CONSP (info))
2387 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
2388 if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
2389 gda = XINT (v);
2392 ptrdiff_t digest_length = gnutls_hash_get_len (gda);
2393 if (digest_length == 0)
2394 error ("GnuTLS digest-method is invalid or not found");
2396 gnutls_hash_hd_t hash;
2397 int ret = gnutls_hash_init (&hash, gda);
2399 if (ret < GNUTLS_E_SUCCESS)
2400 error ("GnuTLS digest initialization failed: %s",
2401 emacs_gnutls_strerror (ret));
2403 Lisp_Object digest = make_uninit_string (digest_length);
2405 ptrdiff_t istart_byte, iend_byte;
2406 const char *idata
2407 = extract_data_from_object (input, &istart_byte, &iend_byte);
2408 if (idata == NULL)
2409 error ("GnuTLS digest input extraction failed");
2411 ret = gnutls_hash (hash, idata + istart_byte, iend_byte - istart_byte);
2413 if (ret < GNUTLS_E_SUCCESS)
2415 gnutls_hash_deinit (hash, NULL);
2416 error ("GnuTLS digest application failed: %s",
2417 emacs_gnutls_strerror (ret));
2420 gnutls_hash_output (hash, SSDATA (digest));
2421 gnutls_hash_deinit (hash, NULL);
2423 return digest;
2426 #endif /* HAVE_GNUTLS3 */
2428 DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
2429 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
2431 ...if supported : then...
2432 GnuTLS 3 or higher : the list will contain `gnutls3'.
2433 GnuTLS MACs : the list will contain `macs'.
2434 GnuTLS digests : the list will contain `digests'.
2435 GnuTLS symmetric ciphers: the list will contain `ciphers'.
2436 GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'.
2437 %DUMBFW : the list will contain `ClientHello\ Padding'.
2438 Any GnuTLS extension with ID up to 100
2439 : the list will contain its name. */)
2440 (void)
2442 Lisp_Object capabilities = Qnil;
2444 #ifdef HAVE_GNUTLS
2446 # ifdef WINDOWSNT
2447 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
2448 if (CONSP (found))
2449 return XCDR (found);
2451 /* Load the GnuTLS DLL and find exported functions. The external
2452 library cache is updated after the capabilities have been
2453 determined. */
2454 if (!init_gnutls_functions ())
2455 return Qnil;
2456 # endif /* WINDOWSNT */
2458 capabilities = Fcons (intern("gnutls"), capabilities);
2460 # ifdef HAVE_GNUTLS3
2461 capabilities = Fcons (intern("gnutls3"), capabilities);
2462 capabilities = Fcons (intern("digests"), capabilities);
2463 capabilities = Fcons (intern("ciphers"), capabilities);
2465 # ifdef HAVE_GNUTLS_AEAD
2466 capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
2467 # endif
2469 capabilities = Fcons (intern("macs"), capabilities);
2471 # ifdef HAVE_GNUTLS_EXT_GET_NAME
2472 for (unsigned int ext=0; ext < 100; ext++)
2474 const char* name = gnutls_ext_get_name(ext);
2475 if (name != NULL)
2477 capabilities = Fcons (intern(name), capabilities);
2480 # endif
2481 # endif /* HAVE_GNUTLS3 */
2483 # ifdef HAVE_GNUTLS_EXT__DUMBFW
2484 capabilities = Fcons (intern("ClientHello Padding"), capabilities);
2485 # endif
2487 # ifdef WINDOWSNT
2488 Vlibrary_cache = Fcons (Fcons (Qgnutls, capabilities), Vlibrary_cache);
2489 # endif /* WINDOWSNT */
2490 #endif /* HAVE_GNUTLS */
2492 return capabilities;
2495 void
2496 syms_of_gnutls (void)
2498 DEFSYM (Qlibgnutls_version, "libgnutls-version");
2499 Fset (Qlibgnutls_version,
2500 #ifdef HAVE_GNUTLS
2501 make_number (GNUTLS_VERSION_MAJOR * 10000
2502 + GNUTLS_VERSION_MINOR * 100
2503 + GNUTLS_VERSION_PATCH)
2504 #else
2505 make_number (-1)
2506 #endif
2508 #ifdef HAVE_GNUTLS
2509 gnutls_global_initialized = 0;
2511 DEFSYM (Qgnutls_code, "gnutls-code");
2512 DEFSYM (Qgnutls_anon, "gnutls-anon");
2513 DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
2515 /* The following are for the property list of 'gnutls-boot'. */
2516 DEFSYM (QChostname, ":hostname");
2517 DEFSYM (QCpriority, ":priority");
2518 DEFSYM (QCtrustfiles, ":trustfiles");
2519 DEFSYM (QCkeylist, ":keylist");
2520 DEFSYM (QCcrlfiles, ":crlfiles");
2521 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
2522 DEFSYM (QCloglevel, ":loglevel");
2523 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
2524 DEFSYM (QCverify_flags, ":verify-flags");
2525 DEFSYM (QCverify_error, ":verify-error");
2527 DEFSYM (QCcipher_id, ":cipher-id");
2528 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
2529 DEFSYM (QCcipher_blocksize, ":cipher-blocksize");
2530 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2531 DEFSYM (QCcipher_tagsize, ":cipher-tagsize");
2532 DEFSYM (QCcipher_ivsize, ":cipher-ivsize");
2534 DEFSYM (QCmac_algorithm_id, ":mac-algorithm-id");
2535 DEFSYM (QCmac_algorithm_noncesize, ":mac-algorithm-noncesize");
2536 DEFSYM (QCmac_algorithm_keysize, ":mac-algorithm-keysize");
2537 DEFSYM (QCmac_algorithm_length, ":mac-algorithm-length");
2539 DEFSYM (QCdigest_algorithm_id, ":digest-algorithm-id");
2540 DEFSYM (QCdigest_algorithm_length, ":digest-algorithm-length");
2542 DEFSYM (QCtype, ":type");
2543 DEFSYM (Qgnutls_type_cipher, "gnutls-symmetric-cipher");
2544 DEFSYM (Qgnutls_type_mac_algorithm, "gnutls-mac-algorithm");
2545 DEFSYM (Qgnutls_type_digest_algorithm, "gnutls-digest-algorithm");
2547 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
2548 Fput (Qgnutls_e_interrupted, Qgnutls_code,
2549 make_number (GNUTLS_E_INTERRUPTED));
2551 DEFSYM (Qgnutls_e_again, "gnutls-e-again");
2552 Fput (Qgnutls_e_again, Qgnutls_code,
2553 make_number (GNUTLS_E_AGAIN));
2555 DEFSYM (Qgnutls_e_invalid_session, "gnutls-e-invalid-session");
2556 Fput (Qgnutls_e_invalid_session, Qgnutls_code,
2557 make_number (GNUTLS_E_INVALID_SESSION));
2559 DEFSYM (Qgnutls_e_not_ready_for_handshake, "gnutls-e-not-ready-for-handshake");
2560 Fput (Qgnutls_e_not_ready_for_handshake, Qgnutls_code,
2561 make_number (GNUTLS_E_APPLICATION_ERROR_MIN));
2563 defsubr (&Sgnutls_get_initstage);
2564 defsubr (&Sgnutls_asynchronous_parameters);
2565 defsubr (&Sgnutls_errorp);
2566 defsubr (&Sgnutls_error_fatalp);
2567 defsubr (&Sgnutls_error_string);
2568 defsubr (&Sgnutls_boot);
2569 defsubr (&Sgnutls_deinit);
2570 defsubr (&Sgnutls_bye);
2571 defsubr (&Sgnutls_peer_status);
2572 defsubr (&Sgnutls_peer_status_warning_describe);
2574 #ifdef HAVE_GNUTLS3
2575 defsubr (&Sgnutls_ciphers);
2576 defsubr (&Sgnutls_macs);
2577 defsubr (&Sgnutls_digests);
2578 defsubr (&Sgnutls_hash_mac);
2579 defsubr (&Sgnutls_hash_digest);
2580 defsubr (&Sgnutls_symmetric_encrypt);
2581 defsubr (&Sgnutls_symmetric_decrypt);
2582 #endif
2584 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
2585 doc: /* Logging level used by the GnuTLS functions.
2586 Set this larger than 0 to get debug output in the *Messages* buffer.
2587 1 is for important messages, 2 is for debug data, and higher numbers
2588 are as per the GnuTLS logging conventions. */);
2589 global_gnutls_log_level = 0;
2591 #endif /* HAVE_GNUTLS */
2593 defsubr (&Sgnutls_available_p);