Fix 'rename' on MS-Windows
[emacs.git] / src / gnutls.c
blob188f995979e52f57efa50b805ef48ac5a77fe6fc
1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2017 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 <http://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 0x030014 <= GNUTLS_VERSION_NUMBER
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/archive/html/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 0x030501 <= GNUTLS_VERSION_NUMBER
40 # define HAVE_GNUTLS_AEAD
41 #endif
43 #ifdef HAVE_GNUTLS
45 # ifdef WINDOWSNT
46 # include <windows.h>
47 # include "w32.h"
48 # endif
50 static bool emacs_gnutls_handle_error (gnutls_session_t, int);
52 static bool gnutls_global_initialized;
54 static void gnutls_log_function (int, const char *);
55 static void gnutls_log_function2 (int, const char *, const char *);
56 # ifdef HAVE_GNUTLS3
57 static void gnutls_audit_log_function (gnutls_session_t, const char *);
58 # endif
60 enum extra_peer_verification
62 CERTIFICATE_NOT_MATCHING = 2
66 # ifdef WINDOWSNT
68 DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
69 (gnutls_session_t));
70 DEF_DLL_FN (const char *, gnutls_alert_get_name,
71 (gnutls_alert_description_t));
72 DEF_DLL_FN (int, gnutls_anon_allocate_client_credentials,
73 (gnutls_anon_client_credentials_t *));
74 DEF_DLL_FN (void, gnutls_anon_free_client_credentials,
75 (gnutls_anon_client_credentials_t));
76 DEF_DLL_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
77 DEF_DLL_FN (int, gnutls_certificate_allocate_credentials,
78 (gnutls_certificate_credentials_t *));
79 DEF_DLL_FN (void, gnutls_certificate_free_credentials,
80 (gnutls_certificate_credentials_t));
81 DEF_DLL_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
82 (gnutls_session_t, unsigned int *));
83 DEF_DLL_FN (void, gnutls_certificate_set_verify_flags,
84 (gnutls_certificate_credentials_t, unsigned int));
85 DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
86 (gnutls_certificate_credentials_t, const char *,
87 gnutls_x509_crt_fmt_t));
88 DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
89 (gnutls_certificate_credentials_t, const char *, const char *,
90 gnutls_x509_crt_fmt_t));
91 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
92 DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
93 (gnutls_certificate_credentials_t));
94 # endif
95 DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
96 (gnutls_certificate_credentials_t, const char *,
97 gnutls_x509_crt_fmt_t));
98 DEF_DLL_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
99 (gnutls_session_t));
100 DEF_DLL_FN (int, gnutls_certificate_verify_peers2,
101 (gnutls_session_t, unsigned int *));
102 DEF_DLL_FN (int, gnutls_credentials_set,
103 (gnutls_session_t, gnutls_credentials_type_t, void *));
104 DEF_DLL_FN (void, gnutls_deinit, (gnutls_session_t));
105 DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
106 (gnutls_session_t, unsigned int));
107 DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
108 DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
109 DEF_DLL_FN (int, gnutls_global_init, (void));
110 DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
111 # ifdef HAVE_GNUTLS3
112 DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
113 # endif
114 DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
115 DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
116 DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
117 DEF_DLL_FN (int, gnutls_priority_set_direct,
118 (gnutls_session_t, const char *, const char **));
119 DEF_DLL_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
120 DEF_DLL_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
121 DEF_DLL_FN (ssize_t, gnutls_record_send,
122 (gnutls_session_t, const void *, size_t));
123 DEF_DLL_FN (const char *, gnutls_strerror, (int));
124 DEF_DLL_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
125 DEF_DLL_FN (void, gnutls_transport_set_ptr2,
126 (gnutls_session_t, gnutls_transport_ptr_t,
127 gnutls_transport_ptr_t));
128 DEF_DLL_FN (void, gnutls_transport_set_pull_function,
129 (gnutls_session_t, gnutls_pull_func));
130 DEF_DLL_FN (void, gnutls_transport_set_push_function,
131 (gnutls_session_t, gnutls_push_func));
132 DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
133 (gnutls_x509_crt_t, const char *));
134 DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
135 (gnutls_x509_crt_t, gnutls_x509_crt_t));
136 DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
137 DEF_DLL_FN (int, gnutls_x509_crt_import,
138 (gnutls_x509_crt_t, const gnutls_datum_t *,
139 gnutls_x509_crt_fmt_t));
140 DEF_DLL_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
141 DEF_DLL_FN (int, gnutls_x509_crt_get_fingerprint,
142 (gnutls_x509_crt_t,
143 gnutls_digest_algorithm_t, void *, size_t *));
144 DEF_DLL_FN (int, gnutls_x509_crt_get_version,
145 (gnutls_x509_crt_t));
146 DEF_DLL_FN (int, gnutls_x509_crt_get_serial,
147 (gnutls_x509_crt_t, void *, size_t *));
148 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_dn,
149 (gnutls_x509_crt_t, char *, size_t *));
150 DEF_DLL_FN (time_t, gnutls_x509_crt_get_activation_time,
151 (gnutls_x509_crt_t));
152 DEF_DLL_FN (time_t, gnutls_x509_crt_get_expiration_time,
153 (gnutls_x509_crt_t));
154 DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
155 (gnutls_x509_crt_t, char *, size_t *));
156 DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
157 (gnutls_x509_crt_t, unsigned int *));
158 DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name,
159 (gnutls_pk_algorithm_t));
160 DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
161 (gnutls_pk_algorithm_t, unsigned int));
162 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_unique_id,
163 (gnutls_x509_crt_t, char *, size_t *));
164 DEF_DLL_FN (int, gnutls_x509_crt_get_subject_unique_id,
165 (gnutls_x509_crt_t, char *, size_t *));
166 DEF_DLL_FN (int, gnutls_x509_crt_get_signature_algorithm,
167 (gnutls_x509_crt_t));
168 DEF_DLL_FN (int, gnutls_x509_crt_get_key_id,
169 (gnutls_x509_crt_t, unsigned int, unsigned char *, size_t *_size));
170 DEF_DLL_FN (const char *, gnutls_sec_param_get_name, (gnutls_sec_param_t));
171 DEF_DLL_FN (const char *, gnutls_sign_get_name, (gnutls_sign_algorithm_t));
172 DEF_DLL_FN (int, gnutls_server_name_set,
173 (gnutls_session_t, gnutls_server_name_type_t,
174 const void *, size_t));
175 DEF_DLL_FN (gnutls_kx_algorithm_t, gnutls_kx_get, (gnutls_session_t));
176 DEF_DLL_FN (const char *, gnutls_kx_get_name, (gnutls_kx_algorithm_t));
177 DEF_DLL_FN (gnutls_protocol_t, gnutls_protocol_get_version,
178 (gnutls_session_t));
179 DEF_DLL_FN (const char *, gnutls_protocol_get_name, (gnutls_protocol_t));
180 DEF_DLL_FN (gnutls_cipher_algorithm_t, gnutls_cipher_get,
181 (gnutls_session_t));
182 DEF_DLL_FN (const char *, gnutls_cipher_get_name,
183 (gnutls_cipher_algorithm_t));
184 DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
185 DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
187 # ifdef HAVE_GNUTLS3
188 DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t));
189 DEF_DLL_FN (const gnutls_mac_algorithm_t *, gnutls_mac_list, (void));
190 DEF_DLL_FN (size_t, gnutls_mac_get_nonce_size, (gnutls_mac_algorithm_t));
191 DEF_DLL_FN (size_t, gnutls_mac_get_key_size, (gnutls_mac_algorithm_t));
192 DEF_DLL_FN (const gnutls_digest_algorithm_t *, gnutls_digest_list, (void));
193 DEF_DLL_FN (const char *, gnutls_digest_get_name, (gnutls_digest_algorithm_t));
194 DEF_DLL_FN (gnutls_cipher_algorithm_t *, gnutls_cipher_list, (void));
195 DEF_DLL_FN (int, gnutls_cipher_get_iv_size, (gnutls_cipher_algorithm_t));
196 DEF_DLL_FN (size_t, gnutls_cipher_get_key_size, (gnutls_cipher_algorithm_t));
197 DEF_DLL_FN (int, gnutls_cipher_get_block_size, (gnutls_cipher_algorithm_t));
198 DEF_DLL_FN (int, gnutls_cipher_get_tag_size, (gnutls_cipher_algorithm_t));
199 DEF_DLL_FN (int, gnutls_cipher_init,
200 (gnutls_cipher_hd_t *, gnutls_cipher_algorithm_t,
201 const gnutls_datum_t *, const gnutls_datum_t *));
202 DEF_DLL_FN (void, gnutls_cipher_set_iv, (gnutls_cipher_hd_t, void *, size_t));
203 DEF_DLL_FN (int, gnutls_cipher_encrypt2,
204 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
205 DEF_DLL_FN (void, gnutls_cipher_deinit, (gnutls_cipher_hd_t));
206 DEF_DLL_FN (int, gnutls_cipher_decrypt2,
207 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
208 # ifdef HAVE_GNUTLS_AEAD
209 DEF_DLL_FN (int, gnutls_aead_cipher_init,
210 (gnutls_aead_cipher_hd_t *, gnutls_cipher_algorithm_t,
211 const gnutls_datum_t *));
212 DEF_DLL_FN (void, gnutls_aead_cipher_deinit, (gnutls_aead_cipher_hd_t));
213 DEF_DLL_FN (int, gnutls_aead_cipher_encrypt,
214 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
215 size_t, size_t, const void *, size_t, void *, size_t *));
216 DEF_DLL_FN (int, gnutls_aead_cipher_decrypt,
217 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
218 size_t, size_t, const void *, size_t, void *, size_t *));
219 # endif
220 DEF_DLL_FN (int, gnutls_hmac_init,
221 (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t));
222 DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t));
223 DEF_DLL_FN (int, gnutls_hmac, (gnutls_hmac_hd_t, const void *, size_t));
224 DEF_DLL_FN (void, gnutls_hmac_deinit, (gnutls_hmac_hd_t, void *));
225 DEF_DLL_FN (void, gnutls_hmac_output, (gnutls_hmac_hd_t, void *));
226 DEF_DLL_FN (int, gnutls_hash_init,
227 (gnutls_hash_hd_t *, gnutls_digest_algorithm_t));
228 DEF_DLL_FN (int, gnutls_hash_get_len, (gnutls_digest_algorithm_t));
229 DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
230 DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
231 DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
232 # endif /* HAVE_GNUTLS3 */
235 static bool
236 init_gnutls_functions (void)
238 HMODULE library;
239 int max_log_level = 1;
241 if (!(library = w32_delayed_load (Qgnutls)))
243 GNUTLS_LOG (1, max_log_level, "GnuTLS library not found");
244 return 0;
247 LOAD_DLL_FN (library, gnutls_alert_get);
248 LOAD_DLL_FN (library, gnutls_alert_get_name);
249 LOAD_DLL_FN (library, gnutls_anon_allocate_client_credentials);
250 LOAD_DLL_FN (library, gnutls_anon_free_client_credentials);
251 LOAD_DLL_FN (library, gnutls_bye);
252 LOAD_DLL_FN (library, gnutls_certificate_allocate_credentials);
253 LOAD_DLL_FN (library, gnutls_certificate_free_credentials);
254 LOAD_DLL_FN (library, gnutls_certificate_get_peers);
255 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
256 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
257 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
258 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
259 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
260 # endif
261 LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
262 LOAD_DLL_FN (library, gnutls_certificate_type_get);
263 LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
264 LOAD_DLL_FN (library, gnutls_credentials_set);
265 LOAD_DLL_FN (library, gnutls_deinit);
266 LOAD_DLL_FN (library, gnutls_dh_set_prime_bits);
267 LOAD_DLL_FN (library, gnutls_dh_get_prime_bits);
268 LOAD_DLL_FN (library, gnutls_error_is_fatal);
269 LOAD_DLL_FN (library, gnutls_global_init);
270 LOAD_DLL_FN (library, gnutls_global_set_log_function);
271 # ifdef HAVE_GNUTLS3
272 LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
273 # endif
274 LOAD_DLL_FN (library, gnutls_global_set_log_level);
275 LOAD_DLL_FN (library, gnutls_handshake);
276 LOAD_DLL_FN (library, gnutls_init);
277 LOAD_DLL_FN (library, gnutls_priority_set_direct);
278 LOAD_DLL_FN (library, gnutls_record_check_pending);
279 LOAD_DLL_FN (library, gnutls_record_recv);
280 LOAD_DLL_FN (library, gnutls_record_send);
281 LOAD_DLL_FN (library, gnutls_strerror);
282 LOAD_DLL_FN (library, gnutls_transport_set_errno);
283 LOAD_DLL_FN (library, gnutls_transport_set_ptr2);
284 LOAD_DLL_FN (library, gnutls_transport_set_pull_function);
285 LOAD_DLL_FN (library, gnutls_transport_set_push_function);
286 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
287 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
288 LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
289 LOAD_DLL_FN (library, gnutls_x509_crt_import);
290 LOAD_DLL_FN (library, gnutls_x509_crt_init);
291 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
292 LOAD_DLL_FN (library, gnutls_x509_crt_get_version);
293 LOAD_DLL_FN (library, gnutls_x509_crt_get_serial);
294 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_dn);
295 LOAD_DLL_FN (library, gnutls_x509_crt_get_activation_time);
296 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
297 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
298 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
299 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
300 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
301 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
302 LOAD_DLL_FN (library, gnutls_x509_crt_get_subject_unique_id);
303 LOAD_DLL_FN (library, gnutls_x509_crt_get_signature_algorithm);
304 LOAD_DLL_FN (library, gnutls_x509_crt_get_key_id);
305 LOAD_DLL_FN (library, gnutls_sec_param_get_name);
306 LOAD_DLL_FN (library, gnutls_sign_get_name);
307 LOAD_DLL_FN (library, gnutls_server_name_set);
308 LOAD_DLL_FN (library, gnutls_kx_get);
309 LOAD_DLL_FN (library, gnutls_kx_get_name);
310 LOAD_DLL_FN (library, gnutls_protocol_get_version);
311 LOAD_DLL_FN (library, gnutls_protocol_get_name);
312 LOAD_DLL_FN (library, gnutls_cipher_get);
313 LOAD_DLL_FN (library, gnutls_cipher_get_name);
314 LOAD_DLL_FN (library, gnutls_mac_get);
315 LOAD_DLL_FN (library, gnutls_mac_get_name);
316 # ifdef HAVE_GNUTLS3
317 LOAD_DLL_FN (library, gnutls_rnd);
318 LOAD_DLL_FN (library, gnutls_mac_list);
319 LOAD_DLL_FN (library, gnutls_mac_get_nonce_size);
320 LOAD_DLL_FN (library, gnutls_mac_get_key_size);
321 LOAD_DLL_FN (library, gnutls_digest_list);
322 LOAD_DLL_FN (library, gnutls_digest_get_name);
323 LOAD_DLL_FN (library, gnutls_cipher_list);
324 LOAD_DLL_FN (library, gnutls_cipher_get_iv_size);
325 LOAD_DLL_FN (library, gnutls_cipher_get_key_size);
326 LOAD_DLL_FN (library, gnutls_cipher_get_block_size);
327 LOAD_DLL_FN (library, gnutls_cipher_get_tag_size);
328 LOAD_DLL_FN (library, gnutls_cipher_init);
329 LOAD_DLL_FN (library, gnutls_cipher_set_iv);
330 LOAD_DLL_FN (library, gnutls_cipher_encrypt2);
331 LOAD_DLL_FN (library, gnutls_cipher_deinit);
332 LOAD_DLL_FN (library, gnutls_cipher_decrypt2);
333 # ifdef HAVE_GNUTLS_AEAD
334 LOAD_DLL_FN (library, gnutls_aead_cipher_init);
335 LOAD_DLL_FN (library, gnutls_aead_cipher_deinit);
336 LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt);
337 LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt);
338 # endif
339 LOAD_DLL_FN (library, gnutls_hmac_init);
340 LOAD_DLL_FN (library, gnutls_hmac_get_len);
341 LOAD_DLL_FN (library, gnutls_hmac);
342 LOAD_DLL_FN (library, gnutls_hmac_deinit);
343 LOAD_DLL_FN (library, gnutls_hmac_output);
344 LOAD_DLL_FN (library, gnutls_hash_init);
345 LOAD_DLL_FN (library, gnutls_hash_get_len);
346 LOAD_DLL_FN (library, gnutls_hash);
347 LOAD_DLL_FN (library, gnutls_hash_deinit);
348 LOAD_DLL_FN (library, gnutls_hash_output);
349 # endif /* HAVE_GNUTLS3 */
351 max_log_level = global_gnutls_log_level;
354 Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from));
355 GNUTLS_LOG2 (1, max_log_level, "GnuTLS library loaded:",
356 STRINGP (name) ? (const char *) SDATA (name) : "unknown");
359 return 1;
362 # define gnutls_alert_get fn_gnutls_alert_get
363 # define gnutls_alert_get_name fn_gnutls_alert_get_name
364 # define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
365 # define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
366 # define gnutls_bye fn_gnutls_bye
367 # define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
368 # define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
369 # define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
370 # define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
371 # define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
372 # define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
373 # define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
374 # define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
375 # define gnutls_certificate_type_get fn_gnutls_certificate_type_get
376 # define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
377 # define gnutls_cipher_get fn_gnutls_cipher_get
378 # define gnutls_cipher_get_name fn_gnutls_cipher_get_name
379 # define gnutls_credentials_set fn_gnutls_credentials_set
380 # define gnutls_deinit fn_gnutls_deinit
381 # define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
382 # define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
383 # define gnutls_error_is_fatal fn_gnutls_error_is_fatal
384 # define gnutls_global_init fn_gnutls_global_init
385 # define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
386 # define gnutls_global_set_log_function fn_gnutls_global_set_log_function
387 # define gnutls_global_set_log_level fn_gnutls_global_set_log_level
388 # define gnutls_handshake fn_gnutls_handshake
389 # define gnutls_init fn_gnutls_init
390 # define gnutls_kx_get fn_gnutls_kx_get
391 # define gnutls_kx_get_name fn_gnutls_kx_get_name
392 # define gnutls_mac_get fn_gnutls_mac_get
393 # define gnutls_mac_get_name fn_gnutls_mac_get_name
394 # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
395 # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
396 # define gnutls_priority_set_direct fn_gnutls_priority_set_direct
397 # define gnutls_protocol_get_name fn_gnutls_protocol_get_name
398 # define gnutls_protocol_get_version fn_gnutls_protocol_get_version
399 # define gnutls_record_check_pending fn_gnutls_record_check_pending
400 # define gnutls_record_recv fn_gnutls_record_recv
401 # define gnutls_record_send fn_gnutls_record_send
402 # define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
403 # define gnutls_server_name_set fn_gnutls_server_name_set
404 # define gnutls_sign_get_name fn_gnutls_sign_get_name
405 # define gnutls_strerror fn_gnutls_strerror
406 # define gnutls_transport_set_errno fn_gnutls_transport_set_errno
407 # define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
408 # define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
409 # define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
410 # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
411 # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
412 # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
413 # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
414 # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
415 # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
416 # define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
417 # define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
418 # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
419 # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
420 # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
421 # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
422 # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
423 # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
424 # define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
425 # define gnutls_x509_crt_import fn_gnutls_x509_crt_import
426 # define gnutls_x509_crt_init fn_gnutls_x509_crt_init
427 # ifdef HAVE_GNUTLS3
428 # define gnutls_rnd fn_gnutls_rnd
429 # define gnutls_mac_list fn_gnutls_mac_list
430 # define gnutls_mac_get_nonce_size fn_gnutls_mac_get_nonce_size
431 # define gnutls_mac_get_key_size fn_gnutls_mac_get_key_size
432 # define gnutls_digest_list fn_gnutls_digest_list
433 # define gnutls_digest_get_name fn_gnutls_digest_get_name
434 # define gnutls_cipher_list fn_gnutls_cipher_list
435 # define gnutls_cipher_get_iv_size fn_gnutls_cipher_get_iv_size
436 # define gnutls_cipher_get_key_size fn_gnutls_cipher_get_key_size
437 # define gnutls_cipher_get_block_size fn_gnutls_cipher_get_block_size
438 # define gnutls_cipher_get_tag_size fn_gnutls_cipher_get_tag_size
439 # define gnutls_cipher_init fn_gnutls_cipher_init
440 # define gnutls_cipher_set_iv fn_gnutls_cipher_set_iv
441 # define gnutls_cipher_encrypt2 fn_gnutls_cipher_encrypt2
442 # define gnutls_cipher_decrypt2 fn_gnutls_cipher_decrypt2
443 # define gnutls_cipher_deinit fn_gnutls_cipher_deinit
444 # ifdef HAVE_GNUTLS_AEAD
445 # define gnutls_aead_cipher_encrypt fn_gnutls_aead_cipher_encrypt
446 # define gnutls_aead_cipher_decrypt fn_gnutls_aead_cipher_decrypt
447 # define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
448 # define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
449 # endif
450 # define gnutls_hmac_init fn_gnutls_hmac_init
451 # define gnutls_hmac_get_len fn_gnutls_hmac_get_len
452 # define gnutls_hmac fn_gnutls_hmac
453 # define gnutls_hmac_deinit fn_gnutls_hmac_deinit
454 # define gnutls_hmac_output fn_gnutls_hmac_output
455 # define gnutls_hash_init fn_gnutls_hash_init
456 # define gnutls_hash_get_len fn_gnutls_hash_get_len
457 # define gnutls_hash fn_gnutls_hash
458 # define gnutls_hash_deinit fn_gnutls_hash_deinit
459 # define gnutls_hash_output fn_gnutls_hash_output
460 # endif /* HAVE_GNUTLS3 */
462 /* This wrapper is called from fns.c, which doesn't know about the
463 LOAD_DLL_FN stuff above. */
465 w32_gnutls_rnd (gnutls_rnd_level_t level, void *data, size_t len)
467 return gnutls_rnd (level, data, len);
470 # endif /* WINDOWSNT */
473 /* Report memory exhaustion if ERR is an out-of-memory indication. */
474 static void
475 check_memory_full (int err)
477 /* When GnuTLS exhausts memory, it doesn't say how much memory it
478 asked for, so tell the Emacs allocator that GnuTLS asked for no
479 bytes. This isn't accurate, but it's good enough. */
480 if (err == GNUTLS_E_MEMORY_ERROR)
481 memory_full (0);
484 # ifdef HAVE_GNUTLS3
485 /* Log a simple audit message. */
486 static void
487 gnutls_audit_log_function (gnutls_session_t session, const char *string)
489 if (global_gnutls_log_level >= 1)
491 message ("gnutls.c: [audit] %s", string);
494 # endif
496 /* Log a simple message. */
497 static void
498 gnutls_log_function (int level, const char *string)
500 message ("gnutls.c: [%d] %s", level, string);
503 /* Log a message and a string. */
504 static void
505 gnutls_log_function2 (int level, const char *string, const char *extra)
507 message ("gnutls.c: [%d] %s %s", level, string, extra);
511 gnutls_try_handshake (struct Lisp_Process *proc)
513 gnutls_session_t state = proc->gnutls_state;
514 int ret;
515 bool non_blocking = proc->is_non_blocking_client;
517 if (proc->gnutls_complete_negotiation_p)
518 non_blocking = false;
520 if (non_blocking)
521 proc->gnutls_p = true;
525 ret = gnutls_handshake (state);
526 emacs_gnutls_handle_error (state, ret);
527 maybe_quit ();
529 while (ret < 0
530 && gnutls_error_is_fatal (ret) == 0
531 && ! non_blocking);
533 proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
535 if (ret == GNUTLS_E_SUCCESS)
537 /* Here we're finally done. */
538 proc->gnutls_initstage = GNUTLS_STAGE_READY;
540 else
542 /* check_memory_full (gnutls_alert_send_appropriate (state, ret)); */
544 return ret;
547 # ifndef WINDOWSNT
548 static int
549 emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
551 int err = errno;
553 switch (err)
555 # ifdef _AIX
556 /* This is taken from the GnuTLS system_errno function circa 2016;
557 see <http://savannah.gnu.org/support/?107464>. */
558 case 0:
559 errno = EAGAIN;
560 /* Fall through. */
561 # endif
562 case EINPROGRESS:
563 case ENOTCONN:
564 return EAGAIN;
566 default:
567 return err;
570 # endif /* !WINDOWSNT */
572 static int
573 emacs_gnutls_handshake (struct Lisp_Process *proc)
575 gnutls_session_t state = proc->gnutls_state;
577 if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO)
578 return -1;
580 if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
582 # ifdef WINDOWSNT
583 /* On W32 we cannot transfer socket handles between different runtime
584 libraries, so we tell GnuTLS to use our special push/pull
585 functions. */
586 gnutls_transport_set_ptr2 (state,
587 (gnutls_transport_ptr_t) proc,
588 (gnutls_transport_ptr_t) proc);
589 gnutls_transport_set_push_function (state, &emacs_gnutls_push);
590 gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
591 # else
592 /* This is how GnuTLS takes sockets: as file descriptors passed
593 in. For an Emacs process socket, infd and outfd are the
594 same but we use this two-argument version for clarity. */
595 gnutls_transport_set_ptr2 (state,
596 (void *) (intptr_t) proc->infd,
597 (void *) (intptr_t) proc->outfd);
598 if (proc->is_non_blocking_client)
599 gnutls_transport_set_errno_function (state,
600 emacs_gnutls_nonblock_errno);
601 # endif
603 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
606 return gnutls_try_handshake (proc);
609 ptrdiff_t
610 emacs_gnutls_record_check_pending (gnutls_session_t state)
612 return gnutls_record_check_pending (state);
615 # ifdef WINDOWSNT
616 void
617 emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
619 gnutls_transport_set_errno (state, err);
621 # endif
623 ptrdiff_t
624 emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
626 ssize_t rtnval = 0;
627 ptrdiff_t bytes_written;
628 gnutls_session_t state = proc->gnutls_state;
630 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
632 errno = EAGAIN;
633 return 0;
636 bytes_written = 0;
638 while (nbyte > 0)
640 rtnval = gnutls_record_send (state, buf, nbyte);
642 if (rtnval < 0)
644 if (rtnval == GNUTLS_E_INTERRUPTED)
645 continue;
646 else
648 /* If we get GNUTLS_E_AGAIN, then set errno
649 appropriately so that send_process retries the
650 correct way instead of erroring out. */
651 if (rtnval == GNUTLS_E_AGAIN)
652 errno = EAGAIN;
653 break;
657 buf += rtnval;
658 nbyte -= rtnval;
659 bytes_written += rtnval;
662 emacs_gnutls_handle_error (state, rtnval);
663 return (bytes_written);
666 ptrdiff_t
667 emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
669 ssize_t rtnval;
670 gnutls_session_t state = proc->gnutls_state;
672 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
674 errno = EAGAIN;
675 return -1;
678 rtnval = gnutls_record_recv (state, buf, nbyte);
679 if (rtnval >= 0)
680 return rtnval;
681 else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
682 /* The peer closed the connection. */
683 return 0;
684 else if (emacs_gnutls_handle_error (state, rtnval))
685 /* non-fatal error */
686 return -1;
687 else {
688 /* a fatal error occurred */
689 return 0;
693 static char const *
694 emacs_gnutls_strerror (int err)
696 char const *str = gnutls_strerror (err);
697 return str ? str : "unknown";
700 /* Report a GnuTLS error to the user.
701 Return true if the error code was successfully handled. */
702 static bool
703 emacs_gnutls_handle_error (gnutls_session_t session, int err)
705 int max_log_level = 0;
707 bool ret;
709 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
710 if (err >= 0)
711 return 1;
713 check_memory_full (err);
715 max_log_level = global_gnutls_log_level;
717 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
719 char const *str = emacs_gnutls_strerror (err);
721 if (gnutls_error_is_fatal (err))
723 int level = 1;
724 /* Mostly ignore "The TLS connection was non-properly
725 terminated" message which just means that the peer closed the
726 connection. */
727 # ifdef HAVE_GNUTLS3
728 if (err == GNUTLS_E_PREMATURE_TERMINATION)
729 level = 3;
730 # endif
732 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
733 ret = false;
735 else
737 ret = true;
739 switch (err)
741 case GNUTLS_E_AGAIN:
742 GNUTLS_LOG2 (3,
743 max_log_level,
744 "retry:",
745 str);
746 FALLTHROUGH;
747 default:
748 GNUTLS_LOG2 (1,
749 max_log_level,
750 "non-fatal error:",
751 str);
755 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
756 || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
758 int alert = gnutls_alert_get (session);
759 int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
760 str = gnutls_alert_get_name (alert);
761 if (!str)
762 str = "unknown";
764 GNUTLS_LOG2 (level, max_log_level, "Received alert: ", str);
766 return ret;
769 /* convert an integer error to a Lisp_Object; it will be either a
770 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
771 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
772 to Qt. */
773 static Lisp_Object
774 gnutls_make_error (int err)
776 switch (err)
778 case GNUTLS_E_SUCCESS:
779 return Qt;
780 case GNUTLS_E_AGAIN:
781 return Qgnutls_e_again;
782 case GNUTLS_E_INTERRUPTED:
783 return Qgnutls_e_interrupted;
784 case GNUTLS_E_INVALID_SESSION:
785 return Qgnutls_e_invalid_session;
788 check_memory_full (err);
789 return make_number (err);
792 Lisp_Object
793 emacs_gnutls_deinit (Lisp_Object proc)
795 int log_level;
797 CHECK_PROCESS (proc);
799 if (! XPROCESS (proc)->gnutls_p)
800 return Qnil;
802 log_level = XPROCESS (proc)->gnutls_log_level;
804 if (XPROCESS (proc)->gnutls_x509_cred)
806 GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
807 gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
808 XPROCESS (proc)->gnutls_x509_cred = NULL;
811 if (XPROCESS (proc)->gnutls_anon_cred)
813 GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
814 gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
815 XPROCESS (proc)->gnutls_anon_cred = NULL;
818 if (XPROCESS (proc)->gnutls_state)
820 gnutls_deinit (XPROCESS (proc)->gnutls_state);
821 XPROCESS (proc)->gnutls_state = NULL;
822 if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
823 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
826 XPROCESS (proc)->gnutls_p = false;
827 return Qt;
830 DEFUN ("gnutls-asynchronous-parameters", Fgnutls_asynchronous_parameters,
831 Sgnutls_asynchronous_parameters, 2, 2, 0,
832 doc: /* Mark this process as being a pre-init GnuTLS process.
833 The second parameter is the list of parameters to feed to gnutls-boot
834 to finish setting up the connection. */)
835 (Lisp_Object proc, Lisp_Object params)
837 CHECK_PROCESS (proc);
839 XPROCESS (proc)->gnutls_boot_parameters = params;
840 return Qnil;
843 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0,
844 doc: /* Return the GnuTLS init stage of process PROC.
845 See also `gnutls-boot'. */)
846 (Lisp_Object proc)
848 CHECK_PROCESS (proc);
850 return make_number (GNUTLS_INITSTAGE (proc));
853 DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
854 doc: /* Return t if ERROR indicates a GnuTLS problem.
855 ERROR is an integer or a symbol with an integer `gnutls-code' property.
856 usage: (gnutls-errorp ERROR) */
857 attributes: const)
858 (Lisp_Object err)
860 if (EQ (err, Qt)
861 || EQ (err, Qgnutls_e_again))
862 return Qnil;
864 return Qt;
867 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
868 doc: /* Return non-nil if ERROR is fatal.
869 ERROR is an integer or a symbol with an integer `gnutls-code' property.
870 Usage: (gnutls-error-fatalp ERROR) */)
871 (Lisp_Object err)
873 Lisp_Object code;
875 if (EQ (err, Qt)) return Qnil;
877 if (SYMBOLP (err))
879 code = Fget (err, Qgnutls_code);
880 if (NUMBERP (code))
882 err = code;
884 else
886 error ("Symbol has no numeric gnutls-code property");
890 if (! TYPE_RANGED_INTEGERP (int, err))
891 error ("Not an error symbol or code");
893 if (0 == gnutls_error_is_fatal (XINT (err)))
894 return Qnil;
896 return Qt;
899 DEFUN ("gnutls-error-string", Fgnutls_error_string, Sgnutls_error_string, 1, 1, 0,
900 doc: /* Return a description of ERROR.
901 ERROR is an integer or a symbol with an integer `gnutls-code' property.
902 usage: (gnutls-error-string ERROR) */)
903 (Lisp_Object err)
905 Lisp_Object code;
907 if (EQ (err, Qt)) return build_string ("Not an error");
909 if (SYMBOLP (err))
911 code = Fget (err, Qgnutls_code);
912 if (NUMBERP (code))
914 err = code;
916 else
918 return build_string ("Symbol has no numeric gnutls-code property");
922 if (! TYPE_RANGED_INTEGERP (int, err))
923 return build_string ("Not an error symbol or code");
925 return build_string (emacs_gnutls_strerror (XINT (err)));
928 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
929 doc: /* Deallocate GnuTLS resources associated with process PROC.
930 See also `gnutls-init'. */)
931 (Lisp_Object proc)
933 return emacs_gnutls_deinit (proc);
936 static Lisp_Object
937 gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
939 ptrdiff_t prefix_length = strlen (prefix);
940 ptrdiff_t retlen;
941 if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
942 || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
943 string_overflow ();
944 Lisp_Object ret = make_uninit_string (retlen);
945 char *string = SSDATA (ret);
946 strcpy (string, prefix);
948 for (ptrdiff_t i = 0; i < buf_size; i++)
949 sprintf (string + i * 3 + prefix_length,
950 i == buf_size - 1 ? "%02x" : "%02x:",
951 buf[i]);
953 return ret;
956 static Lisp_Object
957 gnutls_certificate_details (gnutls_x509_crt_t cert)
959 Lisp_Object res = Qnil;
960 int err;
961 size_t buf_size;
963 /* Version. */
965 int version = gnutls_x509_crt_get_version (cert);
966 check_memory_full (version);
967 if (version >= GNUTLS_E_SUCCESS)
968 res = nconc2 (res, list2 (intern (":version"),
969 make_number (version)));
972 /* Serial. */
973 buf_size = 0;
974 err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
975 check_memory_full (err);
976 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
978 void *serial = xmalloc (buf_size);
979 err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
980 check_memory_full (err);
981 if (err >= GNUTLS_E_SUCCESS)
982 res = nconc2 (res, list2 (intern (":serial-number"),
983 gnutls_hex_string (serial, buf_size, "")));
984 xfree (serial);
987 /* Issuer. */
988 buf_size = 0;
989 err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
990 check_memory_full (err);
991 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
993 char *dn = xmalloc (buf_size);
994 err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
995 check_memory_full (err);
996 if (err >= GNUTLS_E_SUCCESS)
997 res = nconc2 (res, list2 (intern (":issuer"),
998 make_string (dn, buf_size)));
999 xfree (dn);
1002 /* Validity. */
1004 /* Add 1 to the buffer size, since 1900 is added to tm_year and
1005 that might add 1 to the year length. */
1006 char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
1007 struct tm t;
1008 time_t tim = gnutls_x509_crt_get_activation_time (cert);
1010 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1011 res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
1013 tim = gnutls_x509_crt_get_expiration_time (cert);
1014 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1015 res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
1018 /* Subject. */
1019 buf_size = 0;
1020 err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
1021 check_memory_full (err);
1022 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1024 char *dn = xmalloc (buf_size);
1025 err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
1026 check_memory_full (err);
1027 if (err >= GNUTLS_E_SUCCESS)
1028 res = nconc2 (res, list2 (intern (":subject"),
1029 make_string (dn, buf_size)));
1030 xfree (dn);
1033 /* SubjectPublicKeyInfo. */
1035 unsigned int bits;
1037 err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
1038 check_memory_full (err);
1039 if (err >= GNUTLS_E_SUCCESS)
1041 const char *name = gnutls_pk_algorithm_get_name (err);
1042 if (name)
1043 res = nconc2 (res, list2 (intern (":public-key-algorithm"),
1044 build_string (name)));
1046 name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
1047 (err, bits));
1048 res = nconc2 (res, list2 (intern (":certificate-security-level"),
1049 build_string (name)));
1053 /* Unique IDs. */
1054 buf_size = 0;
1055 err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
1056 check_memory_full (err);
1057 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1059 char *buf = xmalloc (buf_size);
1060 err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
1061 check_memory_full (err);
1062 if (err >= GNUTLS_E_SUCCESS)
1063 res = nconc2 (res, list2 (intern (":issuer-unique-id"),
1064 make_string (buf, buf_size)));
1065 xfree (buf);
1068 buf_size = 0;
1069 err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
1070 check_memory_full (err);
1071 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1073 char *buf = xmalloc (buf_size);
1074 err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
1075 check_memory_full (err);
1076 if (err >= GNUTLS_E_SUCCESS)
1077 res = nconc2 (res, list2 (intern (":subject-unique-id"),
1078 make_string (buf, buf_size)));
1079 xfree (buf);
1082 /* Signature. */
1083 err = gnutls_x509_crt_get_signature_algorithm (cert);
1084 check_memory_full (err);
1085 if (err >= GNUTLS_E_SUCCESS)
1087 const char *name = gnutls_sign_get_name (err);
1088 if (name)
1089 res = nconc2 (res, list2 (intern (":signature-algorithm"),
1090 build_string (name)));
1093 /* Public key ID. */
1094 buf_size = 0;
1095 err = gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size);
1096 check_memory_full (err);
1097 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1099 void *buf = xmalloc (buf_size);
1100 err = gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size);
1101 check_memory_full (err);
1102 if (err >= GNUTLS_E_SUCCESS)
1103 res = nconc2 (res, list2 (intern (":public-key-id"),
1104 gnutls_hex_string (buf, buf_size, "sha1:")));
1105 xfree (buf);
1108 /* Certificate fingerprint. */
1109 buf_size = 0;
1110 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1111 NULL, &buf_size);
1112 check_memory_full (err);
1113 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1115 void *buf = xmalloc (buf_size);
1116 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1117 buf, &buf_size);
1118 check_memory_full (err);
1119 if (err >= GNUTLS_E_SUCCESS)
1120 res = nconc2 (res, list2 (intern (":certificate-id"),
1121 gnutls_hex_string (buf, buf_size, "sha1:")));
1122 xfree (buf);
1125 return res;
1128 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
1129 doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
1130 (Lisp_Object status_symbol)
1132 CHECK_SYMBOL (status_symbol);
1134 if (EQ (status_symbol, intern (":invalid")))
1135 return build_string ("certificate could not be verified");
1137 if (EQ (status_symbol, intern (":revoked")))
1138 return build_string ("certificate was revoked (CRL)");
1140 if (EQ (status_symbol, intern (":self-signed")))
1141 return build_string ("certificate signer was not found (self-signed)");
1143 if (EQ (status_symbol, intern (":unknown-ca")))
1144 return build_string ("the certificate was signed by an unknown "
1145 "and therefore untrusted authority");
1147 if (EQ (status_symbol, intern (":not-ca")))
1148 return build_string ("certificate signer is not a CA");
1150 if (EQ (status_symbol, intern (":insecure")))
1151 return build_string ("certificate was signed with an insecure algorithm");
1153 if (EQ (status_symbol, intern (":not-activated")))
1154 return build_string ("certificate is not yet activated");
1156 if (EQ (status_symbol, intern (":expired")))
1157 return build_string ("certificate has expired");
1159 if (EQ (status_symbol, intern (":no-host-match")))
1160 return build_string ("certificate host does not match hostname");
1162 return Qnil;
1165 DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
1166 doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1167 The return value is a property list with top-level keys :warnings and
1168 :certificate. The :warnings entry is a list of symbols you can describe with
1169 `gnutls-peer-status-warning-describe'. */)
1170 (Lisp_Object proc)
1172 Lisp_Object warnings = Qnil, result = Qnil;
1173 unsigned int verification;
1174 gnutls_session_t state;
1176 CHECK_PROCESS (proc);
1178 if (GNUTLS_INITSTAGE (proc) != GNUTLS_STAGE_READY)
1179 return Qnil;
1181 /* Then collect any warnings already computed by the handshake. */
1182 verification = XPROCESS (proc)->gnutls_peer_verification;
1184 if (verification & GNUTLS_CERT_INVALID)
1185 warnings = Fcons (intern (":invalid"), warnings);
1187 if (verification & GNUTLS_CERT_REVOKED)
1188 warnings = Fcons (intern (":revoked"), warnings);
1190 if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
1191 warnings = Fcons (intern (":unknown-ca"), warnings);
1193 if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
1194 warnings = Fcons (intern (":not-ca"), warnings);
1196 if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
1197 warnings = Fcons (intern (":insecure"), warnings);
1199 if (verification & GNUTLS_CERT_NOT_ACTIVATED)
1200 warnings = Fcons (intern (":not-activated"), warnings);
1202 if (verification & GNUTLS_CERT_EXPIRED)
1203 warnings = Fcons (intern (":expired"), warnings);
1205 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1206 CERTIFICATE_NOT_MATCHING)
1207 warnings = Fcons (intern (":no-host-match"), warnings);
1209 /* This could get called in the INIT stage, when the certificate is
1210 not yet set. */
1211 if (XPROCESS (proc)->gnutls_certificate != NULL &&
1212 gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificate,
1213 XPROCESS (proc)->gnutls_certificate))
1214 warnings = Fcons (intern (":self-signed"), warnings);
1216 if (!NILP (warnings))
1217 result = list2 (intern (":warnings"), warnings);
1219 /* This could get called in the INIT stage, when the certificate is
1220 not yet set. */
1221 if (XPROCESS (proc)->gnutls_certificate != NULL)
1222 result = nconc2 (result, list2
1223 (intern (":certificate"),
1224 gnutls_certificate_details (XPROCESS (proc)->gnutls_certificate)));
1226 state = XPROCESS (proc)->gnutls_state;
1228 /* Diffie-Hellman prime bits. */
1230 int bits = gnutls_dh_get_prime_bits (state);
1231 check_memory_full (bits);
1232 if (bits > 0)
1233 result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
1234 make_number (bits)));
1237 /* Key exchange. */
1238 result = nconc2
1239 (result, list2 (intern (":key-exchange"),
1240 build_string (gnutls_kx_get_name
1241 (gnutls_kx_get (state)))));
1243 /* Protocol name. */
1244 result = nconc2
1245 (result, list2 (intern (":protocol"),
1246 build_string (gnutls_protocol_get_name
1247 (gnutls_protocol_get_version (state)))));
1249 /* Cipher name. */
1250 result = nconc2
1251 (result, list2 (intern (":cipher"),
1252 build_string (gnutls_cipher_get_name
1253 (gnutls_cipher_get (state)))));
1255 /* MAC name. */
1256 result = nconc2
1257 (result, list2 (intern (":mac"),
1258 build_string (gnutls_mac_get_name
1259 (gnutls_mac_get (state)))));
1262 return result;
1265 /* Initialize global GnuTLS state to defaults.
1266 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1267 Return zero on success. */
1268 Lisp_Object
1269 emacs_gnutls_global_init (void)
1271 int ret = GNUTLS_E_SUCCESS;
1273 if (!gnutls_global_initialized)
1275 ret = gnutls_global_init ();
1276 if (ret == GNUTLS_E_SUCCESS)
1277 gnutls_global_initialized = 1;
1280 return gnutls_make_error (ret);
1283 static bool
1284 gnutls_ip_address_p (char *string)
1286 char c;
1288 while ((c = *string++) != 0)
1289 if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
1290 return false;
1292 return true;
1295 # if 0
1296 /* Deinitialize global GnuTLS state.
1297 See also `gnutls-global-init'. */
1298 static Lisp_Object
1299 emacs_gnutls_global_deinit (void)
1301 if (gnutls_global_initialized)
1302 gnutls_global_deinit ();
1304 gnutls_global_initialized = 0;
1306 return gnutls_make_error (GNUTLS_E_SUCCESS);
1308 # endif
1310 static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
1311 boot_error (struct Lisp_Process *p, const char *m, ...)
1313 va_list ap;
1314 va_start (ap, m);
1315 if (p->is_non_blocking_client)
1316 pset_status (p, list2 (Qfailed, vformat_string (m, ap)));
1317 else
1318 verror (m, ap);
1319 va_end (ap);
1322 Lisp_Object
1323 gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1325 int ret;
1326 struct Lisp_Process *p = XPROCESS (proc);
1327 gnutls_session_t state = p->gnutls_state;
1328 unsigned int peer_verification;
1329 Lisp_Object warnings;
1330 int max_log_level = p->gnutls_log_level;
1331 Lisp_Object hostname, verify_error;
1332 bool verify_error_all = false;
1333 char *c_hostname;
1335 if (NILP (proplist))
1336 proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
1338 verify_error = Fplist_get (proplist, QCverify_error);
1339 hostname = Fplist_get (proplist, QChostname);
1341 if (EQ (verify_error, Qt))
1342 verify_error_all = true;
1343 else if (NILP (Flistp (verify_error)))
1345 boot_error (p,
1346 "gnutls-boot: invalid :verify_error parameter (not a list)");
1347 return Qnil;
1350 if (!STRINGP (hostname))
1352 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1353 return Qnil;
1355 c_hostname = SSDATA (hostname);
1357 /* Now verify the peer, following
1358 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1359 The peer should present at least one certificate in the chain; do a
1360 check of the certificate's hostname with
1361 gnutls_x509_crt_check_hostname against :hostname. */
1363 ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
1364 if (ret < GNUTLS_E_SUCCESS)
1365 return gnutls_make_error (ret);
1367 XPROCESS (proc)->gnutls_peer_verification = peer_verification;
1369 warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
1370 if (!NILP (warnings))
1372 for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
1374 Lisp_Object warning = XCAR (tail);
1375 Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
1376 if (!NILP (message))
1377 GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
1381 if (peer_verification != 0)
1383 if (verify_error_all
1384 || !NILP (Fmember (QCtrustfiles, verify_error)))
1386 emacs_gnutls_deinit (proc);
1387 boot_error (p,
1388 "Certificate validation failed %s, verification code %x",
1389 c_hostname, peer_verification);
1390 return Qnil;
1392 else
1394 GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
1395 c_hostname);
1399 /* Up to here the process is the same for X.509 certificates and
1400 OpenPGP keys. From now on X.509 certificates are assumed. This
1401 can be easily extended to work with openpgp keys as well. */
1402 if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
1404 gnutls_x509_crt_t gnutls_verify_cert;
1405 const gnutls_datum_t *gnutls_verify_cert_list;
1406 unsigned int gnutls_verify_cert_list_size;
1408 ret = gnutls_x509_crt_init (&gnutls_verify_cert);
1409 if (ret < GNUTLS_E_SUCCESS)
1410 return gnutls_make_error (ret);
1412 gnutls_verify_cert_list
1413 = gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
1415 if (gnutls_verify_cert_list == NULL)
1417 gnutls_x509_crt_deinit (gnutls_verify_cert);
1418 emacs_gnutls_deinit (proc);
1419 boot_error (p, "No x509 certificate was found\n");
1420 return Qnil;
1423 /* Check only the first certificate in the given chain. */
1424 ret = gnutls_x509_crt_import (gnutls_verify_cert,
1425 &gnutls_verify_cert_list[0],
1426 GNUTLS_X509_FMT_DER);
1428 if (ret < GNUTLS_E_SUCCESS)
1430 gnutls_x509_crt_deinit (gnutls_verify_cert);
1431 return gnutls_make_error (ret);
1434 XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert;
1436 int err = gnutls_x509_crt_check_hostname (gnutls_verify_cert,
1437 c_hostname);
1438 check_memory_full (err);
1439 if (!err)
1441 XPROCESS (proc)->gnutls_extra_peer_verification
1442 |= CERTIFICATE_NOT_MATCHING;
1443 if (verify_error_all
1444 || !NILP (Fmember (QChostname, verify_error)))
1446 gnutls_x509_crt_deinit (gnutls_verify_cert);
1447 emacs_gnutls_deinit (proc);
1448 boot_error (p, "The x509 certificate does not match \"%s\"",
1449 c_hostname);
1450 return Qnil;
1452 else
1453 GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
1454 c_hostname);
1458 /* Set this flag only if the whole initialization succeeded. */
1459 XPROCESS (proc)->gnutls_p = true;
1461 return gnutls_make_error (ret);
1464 DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1465 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1466 Currently only client mode is supported. Return a success/failure
1467 value you can check with `gnutls-errorp'.
1469 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1470 PROPLIST is a property list with the following keys:
1472 :hostname is a string naming the remote host.
1474 :priority is a GnuTLS priority string, defaults to "NORMAL".
1476 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1478 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1480 :keylist is an alist of PEM-encoded key files and PEM-encoded
1481 certificates for `gnutls-x509pki'.
1483 :callbacks is an alist of callback functions, see below.
1485 :loglevel is the debug level requested from GnuTLS, try 4.
1487 :verify-flags is a bitset as per GnuTLS'
1488 gnutls_certificate_set_verify_flags.
1490 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1491 instead.
1493 :verify-error is a list of symbols to express verification checks or
1494 t to do all checks. Currently it can contain `:trustfiles' and
1495 `:hostname' to verify the certificate or the hostname respectively.
1497 :min-prime-bits is the minimum accepted number of bits the client will
1498 accept in Diffie-Hellman key exchange.
1500 :complete-negotiation, if non-nil, will make negotiation complete
1501 before returning even on non-blocking sockets.
1503 The debug level will be set for this process AND globally for GnuTLS.
1504 So if you set it higher or lower at any point, it affects global
1505 debugging.
1507 Note that the priority is set on the client. The server does not use
1508 the protocols's priority except for disabling protocols that were not
1509 specified.
1511 Processes must be initialized with this function before other GnuTLS
1512 functions are used. This function allocates resources which can only
1513 be deallocated by calling `gnutls-deinit' or by calling it again.
1515 The callbacks alist can have a `verify' key, associated with a
1516 verification function (UNUSED).
1518 Each authentication type may need additional information in order to
1519 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1520 one trustfile (usually a CA bundle). */)
1521 (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist)
1523 int ret = GNUTLS_E_SUCCESS;
1524 int max_log_level = 0;
1526 gnutls_session_t state;
1527 gnutls_certificate_credentials_t x509_cred = NULL;
1528 gnutls_anon_client_credentials_t anon_cred = NULL;
1529 Lisp_Object global_init;
1530 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1531 char *c_hostname;
1533 /* Placeholders for the property list elements. */
1534 Lisp_Object priority_string;
1535 Lisp_Object trustfiles;
1536 Lisp_Object crlfiles;
1537 Lisp_Object keylist;
1538 /* Lisp_Object callbacks; */
1539 Lisp_Object loglevel;
1540 Lisp_Object hostname;
1541 Lisp_Object prime_bits;
1542 struct Lisp_Process *p = XPROCESS (proc);
1544 CHECK_PROCESS (proc);
1545 CHECK_SYMBOL (type);
1546 CHECK_LIST (proplist);
1548 if (NILP (Fgnutls_available_p ()))
1550 boot_error (p, "GnuTLS not available");
1551 return Qnil;
1554 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1556 boot_error (p, "Invalid GnuTLS credential type");
1557 return Qnil;
1560 hostname = Fplist_get (proplist, QChostname);
1561 priority_string = Fplist_get (proplist, QCpriority);
1562 trustfiles = Fplist_get (proplist, QCtrustfiles);
1563 keylist = Fplist_get (proplist, QCkeylist);
1564 crlfiles = Fplist_get (proplist, QCcrlfiles);
1565 loglevel = Fplist_get (proplist, QCloglevel);
1566 prime_bits = Fplist_get (proplist, QCmin_prime_bits);
1568 if (!STRINGP (hostname))
1570 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1571 return Qnil;
1573 c_hostname = SSDATA (hostname);
1575 state = XPROCESS (proc)->gnutls_state;
1577 if (TYPE_RANGED_INTEGERP (int, loglevel))
1579 gnutls_global_set_log_function (gnutls_log_function);
1580 # ifdef HAVE_GNUTLS3
1581 gnutls_global_set_audit_log_function (gnutls_audit_log_function);
1582 # endif
1583 gnutls_global_set_log_level (XINT (loglevel));
1584 max_log_level = XINT (loglevel);
1585 XPROCESS (proc)->gnutls_log_level = max_log_level;
1588 GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
1590 /* Always initialize globals. */
1591 global_init = emacs_gnutls_global_init ();
1592 if (! NILP (Fgnutls_errorp (global_init)))
1593 return global_init;
1595 /* Before allocating new credentials, deallocate any credentials
1596 that PROC might already have. */
1597 emacs_gnutls_deinit (proc);
1599 /* Mark PROC as a GnuTLS process. */
1600 XPROCESS (proc)->gnutls_state = NULL;
1601 XPROCESS (proc)->gnutls_x509_cred = NULL;
1602 XPROCESS (proc)->gnutls_anon_cred = NULL;
1603 pset_gnutls_cred_type (XPROCESS (proc), type);
1604 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY;
1606 GNUTLS_LOG (1, max_log_level, "allocating credentials");
1607 if (EQ (type, Qgnutls_x509pki))
1609 Lisp_Object verify_flags;
1610 unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1612 GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
1613 check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
1614 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1616 verify_flags = Fplist_get (proplist, QCverify_flags);
1617 if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
1619 gnutls_verify_flags = XFASTINT (verify_flags);
1620 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1622 else if (NILP (verify_flags))
1623 GNUTLS_LOG (2, max_log_level, "using default verification flags");
1624 else
1625 GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
1627 gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
1629 else /* Qgnutls_anon: */
1631 GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
1632 check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
1633 XPROCESS (proc)->gnutls_anon_cred = anon_cred;
1636 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC;
1638 if (EQ (type, Qgnutls_x509pki))
1640 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1641 int file_format = GNUTLS_X509_FMT_PEM;
1642 Lisp_Object tail;
1644 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
1645 ret = gnutls_certificate_set_x509_system_trust (x509_cred);
1646 if (ret < GNUTLS_E_SUCCESS)
1648 check_memory_full (ret);
1649 GNUTLS_LOG2i (4, max_log_level,
1650 "setting system trust failed with code ", ret);
1652 # endif
1654 for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
1656 Lisp_Object trustfile = XCAR (tail);
1657 if (STRINGP (trustfile))
1659 GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
1660 SSDATA (trustfile));
1661 trustfile = ENCODE_FILE (trustfile);
1662 # ifdef WINDOWSNT
1663 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1664 file names on Windows, we need to re-encode the file
1665 name using the current ANSI codepage. */
1666 trustfile = ansi_encode_filename (trustfile);
1667 # endif
1668 ret = gnutls_certificate_set_x509_trust_file
1669 (x509_cred,
1670 SSDATA (trustfile),
1671 file_format);
1673 if (ret < GNUTLS_E_SUCCESS)
1674 return gnutls_make_error (ret);
1676 else
1678 emacs_gnutls_deinit (proc);
1679 boot_error (p, "Invalid trustfile");
1680 return Qnil;
1684 for (tail = crlfiles; CONSP (tail); tail = XCDR (tail))
1686 Lisp_Object crlfile = XCAR (tail);
1687 if (STRINGP (crlfile))
1689 GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
1690 SSDATA (crlfile));
1691 crlfile = ENCODE_FILE (crlfile);
1692 # ifdef WINDOWSNT
1693 crlfile = ansi_encode_filename (crlfile);
1694 # endif
1695 ret = gnutls_certificate_set_x509_crl_file
1696 (x509_cred, SSDATA (crlfile), file_format);
1698 if (ret < GNUTLS_E_SUCCESS)
1699 return gnutls_make_error (ret);
1701 else
1703 emacs_gnutls_deinit (proc);
1704 boot_error (p, "Invalid CRL file");
1705 return Qnil;
1709 for (tail = keylist; CONSP (tail); tail = XCDR (tail))
1711 Lisp_Object keyfile = Fcar (XCAR (tail));
1712 Lisp_Object certfile = Fcar (Fcdr (XCAR (tail)));
1713 if (STRINGP (keyfile) && STRINGP (certfile))
1715 GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ",
1716 SSDATA (keyfile));
1717 GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
1718 SSDATA (certfile));
1719 keyfile = ENCODE_FILE (keyfile);
1720 certfile = ENCODE_FILE (certfile);
1721 # ifdef WINDOWSNT
1722 keyfile = ansi_encode_filename (keyfile);
1723 certfile = ansi_encode_filename (certfile);
1724 # endif
1725 ret = gnutls_certificate_set_x509_key_file
1726 (x509_cred, SSDATA (certfile), SSDATA (keyfile), 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, STRINGP (keyfile) ? "Invalid client cert file"
1735 : "Invalid client key file");
1736 return Qnil;
1741 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
1742 GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
1743 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
1745 /* Call gnutls_init here: */
1747 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1748 int gnutls_flags = GNUTLS_CLIENT;
1749 # ifdef GNUTLS_NONBLOCK
1750 if (XPROCESS (proc)->is_non_blocking_client)
1751 gnutls_flags |= GNUTLS_NONBLOCK;
1752 # endif
1753 ret = gnutls_init (&state, gnutls_flags);
1754 XPROCESS (proc)->gnutls_state = state;
1755 if (ret < GNUTLS_E_SUCCESS)
1756 return gnutls_make_error (ret);
1757 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT;
1759 if (STRINGP (priority_string))
1761 priority_string_ptr = SSDATA (priority_string);
1762 GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:",
1763 priority_string_ptr);
1765 else
1767 GNUTLS_LOG2 (1, max_log_level, "using default priority string:",
1768 priority_string_ptr);
1771 GNUTLS_LOG (1, max_log_level, "setting the priority string");
1772 ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
1773 if (ret < GNUTLS_E_SUCCESS)
1774 return gnutls_make_error (ret);
1776 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
1778 if (INTEGERP (prime_bits))
1779 gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
1781 ret = EQ (type, Qgnutls_x509pki)
1782 ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
1783 : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
1784 if (ret < GNUTLS_E_SUCCESS)
1785 return gnutls_make_error (ret);
1787 if (!gnutls_ip_address_p (c_hostname))
1789 ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
1790 strlen (c_hostname));
1791 if (ret < GNUTLS_E_SUCCESS)
1792 return gnutls_make_error (ret);
1795 XPROCESS (proc)->gnutls_complete_negotiation_p =
1796 !NILP (Fplist_get (proplist, QCcomplete_negotiation));
1797 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
1798 ret = emacs_gnutls_handshake (XPROCESS (proc));
1799 if (ret < GNUTLS_E_SUCCESS)
1800 return gnutls_make_error (ret);
1802 return gnutls_verify_boot (proc, proplist);
1805 DEFUN ("gnutls-bye", Fgnutls_bye,
1806 Sgnutls_bye, 2, 2, 0,
1807 doc: /* Terminate current GnuTLS connection for process PROC.
1808 The connection should have been initiated using `gnutls-handshake'.
1810 If CONT is not nil the TLS connection gets terminated and further
1811 receives and sends will be disallowed. If the return value is zero you
1812 may continue using the connection. If CONT is nil, GnuTLS actually
1813 sends an alert containing a close request and waits for the peer to
1814 reply with the same message. In order to reuse the connection you
1815 should wait for an EOF from the peer.
1817 This function may also return `gnutls-e-again', or
1818 `gnutls-e-interrupted'. */)
1819 (Lisp_Object proc, Lisp_Object cont)
1821 gnutls_session_t state;
1822 int ret;
1824 CHECK_PROCESS (proc);
1826 state = XPROCESS (proc)->gnutls_state;
1828 gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate);
1830 ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
1832 return gnutls_make_error (ret);
1835 #endif /* HAVE_GNUTLS */
1837 #ifdef HAVE_GNUTLS3
1839 DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
1840 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
1841 The alist key is the cipher name. */)
1842 (void)
1844 Lisp_Object ciphers = Qnil;
1846 const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
1847 for (ptrdiff_t pos = 0; gciphers[pos] != 0; pos++)
1849 gnutls_cipher_algorithm_t gca = gciphers[pos];
1850 if (gca == GNUTLS_CIPHER_NULL)
1851 continue;
1852 char const *cipher_name = gnutls_cipher_get_name (gca);
1853 if (!cipher_name)
1854 continue;
1856 /* A symbol representing the GnuTLS cipher. */
1857 Lisp_Object cipher_symbol = intern (cipher_name);
1859 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1861 Lisp_Object cp
1862 = listn (CONSTYPE_HEAP, 15, cipher_symbol,
1863 QCcipher_id, make_number (gca),
1864 QCtype, Qgnutls_type_cipher,
1865 QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
1866 QCcipher_tagsize, make_number (cipher_tag_size),
1868 QCcipher_blocksize,
1869 make_number (gnutls_cipher_get_block_size (gca)),
1871 QCcipher_keysize,
1872 make_number (gnutls_cipher_get_key_size (gca)),
1874 QCcipher_ivsize,
1875 make_number (gnutls_cipher_get_iv_size (gca)));
1877 ciphers = Fcons (cp, ciphers);
1880 return ciphers;
1883 static Lisp_Object
1884 gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1885 Lisp_Object cipher,
1886 const char *kdata, ptrdiff_t ksize,
1887 const char *vdata, ptrdiff_t vsize,
1888 const char *idata, ptrdiff_t isize,
1889 Lisp_Object aead_auth)
1891 # ifdef HAVE_GNUTLS_AEAD
1893 const char *desc = encrypting ? "encrypt" : "decrypt";
1894 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
1896 gnutls_aead_cipher_hd_t acipher;
1897 gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
1898 int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
1900 if (ret < GNUTLS_E_SUCCESS)
1901 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
1902 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1904 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1905 ptrdiff_t tagged_size;
1906 if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
1907 || SIZE_MAX < tagged_size)
1908 memory_full (SIZE_MAX);
1909 size_t storage_length = tagged_size;
1910 USE_SAFE_ALLOCA;
1911 char *storage = SAFE_ALLOCA (storage_length);
1913 const char *aead_auth_data = NULL;
1914 ptrdiff_t aead_auth_size = 0;
1916 if (!NILP (aead_auth))
1918 if (BUFFERP (aead_auth) || STRINGP (aead_auth))
1919 aead_auth = list1 (aead_auth);
1921 CHECK_CONS (aead_auth);
1923 ptrdiff_t astart_byte, aend_byte;
1924 const char *adata
1925 = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
1926 if (adata == NULL)
1927 error ("GnuTLS AEAD cipher auth extraction failed");
1929 aead_auth_data = adata;
1930 aead_auth_size = aend_byte - astart_byte;
1933 ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
1934 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
1936 if (isize < expected_remainder
1937 || (isize - expected_remainder) % cipher_block_size != 0)
1938 error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
1939 "is not %"pD"d greater than a multiple of the required %"pD"d"),
1940 gnutls_cipher_get_name (gca), desc,
1941 isize, expected_remainder, cipher_block_size);
1943 ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
1944 (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
1945 cipher_tag_size, idata, isize, storage, &storage_length));
1947 Lisp_Object output;
1948 if (GNUTLS_E_SUCCESS <= ret)
1949 output = make_unibyte_string (storage, storage_length);
1950 explicit_bzero (storage, storage_length);
1951 gnutls_aead_cipher_deinit (acipher);
1953 if (ret < GNUTLS_E_SUCCESS)
1954 error ((encrypting
1955 ? "GnuTLS AEAD cipher %s encryption failed: %s"
1956 : "GnuTLS AEAD cipher %s decryption failed: %s"),
1957 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
1959 SAFE_FREE ();
1960 return list2 (output, actual_iv);
1961 # else
1962 printmax_t print_gca = gca;
1963 error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
1964 # endif
1967 static Lisp_Object
1968 gnutls_symmetric (bool encrypting, Lisp_Object cipher,
1969 Lisp_Object key, Lisp_Object iv,
1970 Lisp_Object input, Lisp_Object aead_auth)
1972 if (BUFFERP (key) || STRINGP (key))
1973 key = list1 (key);
1975 CHECK_CONS (key);
1977 if (BUFFERP (input) || STRINGP (input))
1978 input = list1 (input);
1980 CHECK_CONS (input);
1982 if (BUFFERP (iv) || STRINGP (iv))
1983 iv = list1 (iv);
1985 CHECK_CONS (iv);
1988 const char *desc = encrypting ? "encrypt" : "decrypt";
1990 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
1992 Lisp_Object info = Qnil;
1993 if (STRINGP (cipher))
1994 cipher = intern (SSDATA (cipher));
1996 if (SYMBOLP (cipher))
1997 info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
1998 else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
1999 gca = XINT (cipher);
2000 else
2001 info = cipher;
2003 if (!NILP (info) && CONSP (info))
2005 Lisp_Object v = Fplist_get (info, QCcipher_id);
2006 if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
2007 gca = XINT (v);
2010 ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
2011 if (key_size == 0)
2012 error ("GnuTLS cipher is invalid or not found");
2014 ptrdiff_t kstart_byte, kend_byte;
2015 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2017 if (kdata == NULL)
2018 error ("GnuTLS cipher key extraction failed");
2020 if (kend_byte - kstart_byte != key_size)
2021 error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
2022 "the required %"pD"d"),
2023 gnutls_cipher_get_name (gca), desc,
2024 kend_byte - kstart_byte, key_size);
2026 ptrdiff_t vstart_byte, vend_byte;
2027 char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
2029 if (vdata == NULL)
2030 error ("GnuTLS cipher IV extraction failed");
2032 ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
2033 if (vend_byte - vstart_byte != iv_size)
2034 error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
2035 "the required %"pD"d"),
2036 gnutls_cipher_get_name (gca), desc,
2037 vend_byte - vstart_byte, iv_size);
2039 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
2041 ptrdiff_t istart_byte, iend_byte;
2042 const char *idata
2043 = extract_data_from_object (input, &istart_byte, &iend_byte);
2045 if (idata == NULL)
2046 error ("GnuTLS cipher input extraction failed");
2048 /* Is this an AEAD cipher? */
2049 if (gnutls_cipher_get_tag_size (gca) > 0)
2051 Lisp_Object aead_output =
2052 gnutls_symmetric_aead (encrypting, gca, cipher,
2053 kdata, kend_byte - kstart_byte,
2054 vdata, vend_byte - vstart_byte,
2055 idata, iend_byte - istart_byte,
2056 aead_auth);
2057 if (STRINGP (XCAR (key)))
2058 Fclear_string (XCAR (key));
2059 return aead_output;
2062 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2063 if ((iend_byte - istart_byte) % cipher_block_size != 0)
2064 error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
2065 "of the required %"pD"d"),
2066 gnutls_cipher_get_name (gca), desc,
2067 iend_byte - istart_byte, cipher_block_size);
2069 gnutls_cipher_hd_t hcipher;
2070 gnutls_datum_t key_datum
2071 = { (unsigned char *) kdata, kend_byte - kstart_byte };
2073 int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
2075 if (ret < GNUTLS_E_SUCCESS)
2076 error ("GnuTLS cipher %s/%s initialization failed: %s",
2077 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2079 /* Note that this will not support streaming block mode. */
2080 gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
2082 /* GnuTLS docs: "For the supported ciphers the encrypted data length
2083 will equal the plaintext size." */
2084 ptrdiff_t storage_length = iend_byte - istart_byte;
2085 Lisp_Object storage = make_uninit_string (storage_length);
2087 ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
2088 (hcipher, idata, iend_byte - istart_byte,
2089 SSDATA (storage), storage_length));
2091 if (STRINGP (XCAR (key)))
2092 Fclear_string (XCAR (key));
2094 if (ret < GNUTLS_E_SUCCESS)
2096 gnutls_cipher_deinit (hcipher);
2097 if (encrypting)
2098 error ("GnuTLS cipher %s encryption failed: %s",
2099 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2100 else
2101 error ("GnuTLS cipher %s decryption failed: %s",
2102 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2105 gnutls_cipher_deinit (hcipher);
2107 return list2 (storage, actual_iv);
2110 DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
2111 Sgnutls_symmetric_encrypt, 4, 5, 0,
2112 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2114 Return nil on error.
2116 The KEY can be specified as a buffer or string or in other ways (see
2117 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2118 will be wiped after use if it's a string.
2120 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2121 buffer or string or in other ways (see Info node `(elisp)Format of
2122 GnuTLS Cryptography Inputs').
2124 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2125 The CIPHER may be a string or symbol matching a key in that alist, or
2126 a plist with the :cipher-id numeric property, or the number itself.
2128 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2129 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2130 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2131 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2132 Lisp_Object input, Lisp_Object aead_auth)
2134 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
2137 DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
2138 Sgnutls_symmetric_decrypt, 4, 5, 0,
2139 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2141 Return nil on error.
2143 The KEY can be specified as a buffer or string or in other ways (see
2144 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2145 will be wiped after use if it's a string.
2147 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2148 buffer or string or in other ways (see Info node `(elisp)Format of
2149 GnuTLS Cryptography Inputs').
2151 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2152 The CIPHER may be a string or symbol matching a key in that alist, or
2153 a plist with the `:cipher-id' numeric property, or the number itself.
2155 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2156 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2157 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2158 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2159 Lisp_Object input, Lisp_Object aead_auth)
2161 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
2164 DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
2165 doc: /* Return alist of GnuTLS mac-algorithm method descriptions as plists.
2167 Use the value of the alist (extract it with `alist-get' for instance)
2168 with `gnutls-hash-mac'. The alist key is the mac-algorithm method
2169 name. */)
2170 (void)
2172 Lisp_Object mac_algorithms = Qnil;
2173 const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
2174 for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
2176 const gnutls_mac_algorithm_t gma = macs[pos];
2178 /* A symbol representing the GnuTLS MAC algorithm. */
2179 Lisp_Object gma_symbol = intern (gnutls_mac_get_name (gma));
2181 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, gma_symbol,
2182 QCmac_algorithm_id, make_number (gma),
2183 QCtype, Qgnutls_type_mac_algorithm,
2185 QCmac_algorithm_length,
2186 make_number (gnutls_hmac_get_len (gma)),
2188 QCmac_algorithm_keysize,
2189 make_number (gnutls_mac_get_key_size (gma)),
2191 QCmac_algorithm_noncesize,
2192 make_number (gnutls_mac_get_nonce_size (gma)));
2193 mac_algorithms = Fcons (mp, mac_algorithms);
2196 return mac_algorithms;
2199 DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
2200 doc: /* Return alist of GnuTLS digest-algorithm method descriptions as plists.
2202 Use the value of the alist (extract it with `alist-get' for instance)
2203 with `gnutls-hash-digest'. The alist key is the digest-algorithm
2204 method name. */)
2205 (void)
2207 Lisp_Object digest_algorithms = Qnil;
2208 const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
2209 for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
2211 const gnutls_digest_algorithm_t gda = digests[pos];
2213 /* A symbol representing the GnuTLS digest algorithm. */
2214 Lisp_Object gda_symbol = intern (gnutls_digest_get_name (gda));
2216 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, gda_symbol,
2217 QCdigest_algorithm_id, make_number (gda),
2218 QCtype, Qgnutls_type_digest_algorithm,
2220 QCdigest_algorithm_length,
2221 make_number (gnutls_hash_get_len (gda)));
2223 digest_algorithms = Fcons (mp, digest_algorithms);
2226 return digest_algorithms;
2229 DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
2230 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
2232 Return nil on error.
2234 The KEY can be specified as a buffer or string or in other ways (see
2235 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2236 will be wiped after use if it's a string.
2238 The INPUT can be specified as a buffer or string or in other
2239 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2241 The alist of MAC algorithms can be obtained with `gnutls-macs`. The
2242 HASH-METHOD may be a string or symbol matching a key in that alist, or
2243 a plist with the `:mac-algorithm-id' numeric property, or the number
2244 itself. */)
2245 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
2247 if (BUFFERP (input) || STRINGP (input))
2248 input = list1 (input);
2250 CHECK_CONS (input);
2252 if (BUFFERP (key) || STRINGP (key))
2253 key = list1 (key);
2255 CHECK_CONS (key);
2257 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
2259 Lisp_Object info = Qnil;
2260 if (STRINGP (hash_method))
2261 hash_method = intern (SSDATA (hash_method));
2263 if (SYMBOLP (hash_method))
2264 info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
2265 else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
2266 gma = XINT (hash_method);
2267 else
2268 info = hash_method;
2270 if (!NILP (info) && CONSP (info))
2272 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
2273 if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
2274 gma = XINT (v);
2277 ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
2278 if (digest_length == 0)
2279 error ("GnuTLS MAC-method is invalid or not found");
2281 ptrdiff_t kstart_byte, kend_byte;
2282 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2283 if (kdata == NULL)
2284 error ("GnuTLS MAC key extraction failed");
2286 gnutls_hmac_hd_t hmac;
2287 int ret = gnutls_hmac_init (&hmac, gma,
2288 kdata + kstart_byte, kend_byte - kstart_byte);
2289 if (ret < GNUTLS_E_SUCCESS)
2290 error ("GnuTLS MAC %s initialization failed: %s",
2291 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2293 ptrdiff_t istart_byte, iend_byte;
2294 const char *idata
2295 = extract_data_from_object (input, &istart_byte, &iend_byte);
2296 if (idata == NULL)
2297 error ("GnuTLS MAC input extraction failed");
2299 Lisp_Object digest = make_uninit_string (digest_length);
2301 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
2303 if (STRINGP (XCAR (key)))
2304 Fclear_string (XCAR (key));
2306 if (ret < GNUTLS_E_SUCCESS)
2308 gnutls_hmac_deinit (hmac, NULL);
2309 error ("GnuTLS MAC %s application failed: %s",
2310 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2313 gnutls_hmac_output (hmac, SSDATA (digest));
2314 gnutls_hmac_deinit (hmac, NULL);
2316 return digest;
2319 DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
2320 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
2322 Return nil on error.
2324 The INPUT can be specified as a buffer or string or in other
2325 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2327 The alist of digest algorithms can be obtained with `gnutls-digests`.
2328 The DIGEST-METHOD may be a string or symbol matching a key in that
2329 alist, or a plist with the `:digest-algorithm-id' numeric property, or
2330 the number itself. */)
2331 (Lisp_Object digest_method, Lisp_Object input)
2333 if (BUFFERP (input) || STRINGP (input))
2334 input = list1 (input);
2336 CHECK_CONS (input);
2338 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
2340 Lisp_Object info = Qnil;
2341 if (STRINGP (digest_method))
2342 digest_method = intern (SSDATA (digest_method));
2344 if (SYMBOLP (digest_method))
2345 info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
2346 else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
2347 gda = XINT (digest_method);
2348 else
2349 info = digest_method;
2351 if (!NILP (info) && CONSP (info))
2353 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
2354 if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
2355 gda = XINT (v);
2358 ptrdiff_t digest_length = gnutls_hash_get_len (gda);
2359 if (digest_length == 0)
2360 error ("GnuTLS digest-method is invalid or not found");
2362 gnutls_hash_hd_t hash;
2363 int ret = gnutls_hash_init (&hash, gda);
2365 if (ret < GNUTLS_E_SUCCESS)
2366 error ("GnuTLS digest initialization failed: %s",
2367 emacs_gnutls_strerror (ret));
2369 Lisp_Object digest = make_uninit_string (digest_length);
2371 ptrdiff_t istart_byte, iend_byte;
2372 const char *idata
2373 = extract_data_from_object (input, &istart_byte, &iend_byte);
2374 if (idata == NULL)
2375 error ("GnuTLS digest input extraction failed");
2377 ret = gnutls_hash (hash, idata + istart_byte, iend_byte - istart_byte);
2379 if (ret < GNUTLS_E_SUCCESS)
2381 gnutls_hash_deinit (hash, NULL);
2382 error ("GnuTLS digest application failed: %s",
2383 emacs_gnutls_strerror (ret));
2386 gnutls_hash_output (hash, SSDATA (digest));
2387 gnutls_hash_deinit (hash, NULL);
2389 return digest;
2392 #endif /* HAVE_GNUTLS3 */
2394 DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
2395 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
2397 ...if supported : then...
2398 GnuTLS 3 or higher : the list will contain `gnutls3'.
2399 GnuTLS MACs : the list will contain `macs'.
2400 GnuTLS digests : the list will contain `digests'.
2401 GnuTLS symmetric ciphers: the list will contain `ciphers'.
2402 GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
2403 (void)
2405 Lisp_Object capabilities = Qnil;
2407 #ifdef HAVE_GNUTLS
2409 # ifdef HAVE_GNUTLS3
2410 capabilities = Fcons (intern("gnutls3"), capabilities);
2411 capabilities = Fcons (intern("digests"), capabilities);
2412 capabilities = Fcons (intern("ciphers"), capabilities);
2414 # ifdef HAVE_GNUTLS_AEAD
2415 capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
2416 # endif
2418 capabilities = Fcons (intern("macs"), capabilities);
2419 # endif /* HAVE_GNUTLS3 */
2421 # ifdef WINDOWSNT
2422 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
2423 if (CONSP (found))
2424 return XCDR (found);
2425 else
2427 Lisp_Object status;
2428 status = init_gnutls_functions () ? capabilities : Qnil;
2429 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
2430 return status;
2432 # endif /* WINDOWSNT */
2433 #endif /* HAVE_GNUTLS */
2435 return capabilities;
2438 void
2439 syms_of_gnutls (void)
2441 DEFSYM (Qlibgnutls_version, "libgnutls-version");
2442 Fset (Qlibgnutls_version,
2443 #ifdef HAVE_GNUTLS
2444 make_number (GNUTLS_VERSION_MAJOR * 10000
2445 + GNUTLS_VERSION_MINOR * 100
2446 + GNUTLS_VERSION_PATCH)
2447 #else
2448 make_number (-1)
2449 #endif
2451 #ifdef HAVE_GNUTLS
2452 gnutls_global_initialized = 0;
2454 DEFSYM (Qgnutls_code, "gnutls-code");
2455 DEFSYM (Qgnutls_anon, "gnutls-anon");
2456 DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
2458 /* The following are for the property list of 'gnutls-boot'. */
2459 DEFSYM (QChostname, ":hostname");
2460 DEFSYM (QCpriority, ":priority");
2461 DEFSYM (QCtrustfiles, ":trustfiles");
2462 DEFSYM (QCkeylist, ":keylist");
2463 DEFSYM (QCcrlfiles, ":crlfiles");
2464 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
2465 DEFSYM (QCloglevel, ":loglevel");
2466 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
2467 DEFSYM (QCverify_flags, ":verify-flags");
2468 DEFSYM (QCverify_error, ":verify-error");
2470 DEFSYM (QCcipher_id, ":cipher-id");
2471 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
2472 DEFSYM (QCcipher_blocksize, ":cipher-blocksize");
2473 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2474 DEFSYM (QCcipher_tagsize, ":cipher-tagsize");
2475 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2476 DEFSYM (QCcipher_ivsize, ":cipher-ivsize");
2478 DEFSYM (QCmac_algorithm_id, ":mac-algorithm-id");
2479 DEFSYM (QCmac_algorithm_noncesize, ":mac-algorithm-noncesize");
2480 DEFSYM (QCmac_algorithm_keysize, ":mac-algorithm-keysize");
2481 DEFSYM (QCmac_algorithm_length, ":mac-algorithm-length");
2483 DEFSYM (QCdigest_algorithm_id, ":digest-algorithm-id");
2484 DEFSYM (QCdigest_algorithm_length, ":digest-algorithm-length");
2486 DEFSYM (QCtype, ":type");
2487 DEFSYM (Qgnutls_type_cipher, "gnutls-symmetric-cipher");
2488 DEFSYM (Qgnutls_type_mac_algorithm, "gnutls-mac-algorithm");
2489 DEFSYM (Qgnutls_type_digest_algorithm, "gnutls-digest-algorithm");
2491 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
2492 Fput (Qgnutls_e_interrupted, Qgnutls_code,
2493 make_number (GNUTLS_E_INTERRUPTED));
2495 DEFSYM (Qgnutls_e_again, "gnutls-e-again");
2496 Fput (Qgnutls_e_again, Qgnutls_code,
2497 make_number (GNUTLS_E_AGAIN));
2499 DEFSYM (Qgnutls_e_invalid_session, "gnutls-e-invalid-session");
2500 Fput (Qgnutls_e_invalid_session, Qgnutls_code,
2501 make_number (GNUTLS_E_INVALID_SESSION));
2503 DEFSYM (Qgnutls_e_not_ready_for_handshake, "gnutls-e-not-ready-for-handshake");
2504 Fput (Qgnutls_e_not_ready_for_handshake, Qgnutls_code,
2505 make_number (GNUTLS_E_APPLICATION_ERROR_MIN));
2507 defsubr (&Sgnutls_get_initstage);
2508 defsubr (&Sgnutls_asynchronous_parameters);
2509 defsubr (&Sgnutls_errorp);
2510 defsubr (&Sgnutls_error_fatalp);
2511 defsubr (&Sgnutls_error_string);
2512 defsubr (&Sgnutls_boot);
2513 defsubr (&Sgnutls_deinit);
2514 defsubr (&Sgnutls_bye);
2515 defsubr (&Sgnutls_peer_status);
2516 defsubr (&Sgnutls_peer_status_warning_describe);
2518 #ifdef HAVE_GNUTLS3
2519 defsubr (&Sgnutls_ciphers);
2520 defsubr (&Sgnutls_macs);
2521 defsubr (&Sgnutls_digests);
2522 defsubr (&Sgnutls_hash_mac);
2523 defsubr (&Sgnutls_hash_digest);
2524 defsubr (&Sgnutls_symmetric_encrypt);
2525 defsubr (&Sgnutls_symmetric_decrypt);
2526 #endif
2528 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
2529 doc: /* Logging level used by the GnuTLS functions.
2530 Set this larger than 0 to get debug output in the *Messages* buffer.
2531 1 is for important messages, 2 is for debug data, and higher numbers
2532 are as per the GnuTLS logging conventions. */);
2533 global_gnutls_log_level = 0;
2535 #endif /* HAVE_GNUTLS */
2537 defsubr (&Sgnutls_available_p);