; doc/emacs/misc.texi (Network Security): Fix typo.
[emacs.git] / src / gnutls.c
bloba8034d0abbfd688ab3b46215d89fdc4234a1b43e
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 static void
823 gnutls_deinit_certificates (struct Lisp_Process *p)
825 if (! p->gnutls_certificates)
826 return;
828 for (int i = 0; i < p->gnutls_certificates_length; i++)
829 gnutls_x509_crt_deinit (p->gnutls_certificates[i]);
831 xfree (p->gnutls_certificates);
832 p->gnutls_certificates = NULL;
835 Lisp_Object
836 emacs_gnutls_deinit (Lisp_Object proc)
838 int log_level;
840 CHECK_PROCESS (proc);
842 if (! XPROCESS (proc)->gnutls_p)
843 return Qnil;
845 log_level = XPROCESS (proc)->gnutls_log_level;
847 if (XPROCESS (proc)->gnutls_x509_cred)
849 GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
850 gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
851 XPROCESS (proc)->gnutls_x509_cred = NULL;
854 if (XPROCESS (proc)->gnutls_anon_cred)
856 GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
857 gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
858 XPROCESS (proc)->gnutls_anon_cred = NULL;
861 if (XPROCESS (proc)->gnutls_state)
863 gnutls_deinit (XPROCESS (proc)->gnutls_state);
864 XPROCESS (proc)->gnutls_state = NULL;
865 if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
866 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
869 if (XPROCESS (proc)->gnutls_certificates)
870 gnutls_deinit_certificates (XPROCESS (proc));
872 XPROCESS (proc)->gnutls_p = false;
873 return Qt;
876 DEFUN ("gnutls-asynchronous-parameters", Fgnutls_asynchronous_parameters,
877 Sgnutls_asynchronous_parameters, 2, 2, 0,
878 doc: /* Mark this process as being a pre-init GnuTLS process.
879 The second parameter is the list of parameters to feed to gnutls-boot
880 to finish setting up the connection. */)
881 (Lisp_Object proc, Lisp_Object params)
883 CHECK_PROCESS (proc);
885 XPROCESS (proc)->gnutls_boot_parameters = params;
886 return Qnil;
889 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0,
890 doc: /* Return the GnuTLS init stage of process PROC.
891 See also `gnutls-boot'. */)
892 (Lisp_Object proc)
894 CHECK_PROCESS (proc);
896 return make_number (GNUTLS_INITSTAGE (proc));
899 DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
900 doc: /* Return t if ERROR indicates a GnuTLS problem.
901 ERROR is an integer or a symbol with an integer `gnutls-code' property.
902 usage: (gnutls-errorp ERROR) */
903 attributes: const)
904 (Lisp_Object err)
906 if (EQ (err, Qt)
907 || EQ (err, Qgnutls_e_again))
908 return Qnil;
910 return Qt;
913 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
914 doc: /* Return non-nil if ERROR is fatal.
915 ERROR is an integer or a symbol with an integer `gnutls-code' property.
916 Usage: (gnutls-error-fatalp ERROR) */)
917 (Lisp_Object err)
919 Lisp_Object code;
921 if (EQ (err, Qt)) return Qnil;
923 if (SYMBOLP (err))
925 code = Fget (err, Qgnutls_code);
926 if (NUMBERP (code))
928 err = code;
930 else
932 error ("Symbol has no numeric gnutls-code property");
936 if (! TYPE_RANGED_INTEGERP (int, err))
937 error ("Not an error symbol or code");
939 if (0 == gnutls_error_is_fatal (XINT (err)))
940 return Qnil;
942 return Qt;
945 DEFUN ("gnutls-error-string", Fgnutls_error_string, Sgnutls_error_string, 1, 1, 0,
946 doc: /* Return a description of ERROR.
947 ERROR is an integer or a symbol with an integer `gnutls-code' property.
948 usage: (gnutls-error-string ERROR) */)
949 (Lisp_Object err)
951 Lisp_Object code;
953 if (EQ (err, Qt)) return build_string ("Not an error");
955 if (SYMBOLP (err))
957 code = Fget (err, Qgnutls_code);
958 if (NUMBERP (code))
960 err = code;
962 else
964 return build_string ("Symbol has no numeric gnutls-code property");
968 if (! TYPE_RANGED_INTEGERP (int, err))
969 return build_string ("Not an error symbol or code");
971 return build_string (emacs_gnutls_strerror (XINT (err)));
974 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
975 doc: /* Deallocate GnuTLS resources associated with process PROC.
976 See also `gnutls-init'. */)
977 (Lisp_Object proc)
979 return emacs_gnutls_deinit (proc);
982 static Lisp_Object
983 gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
985 ptrdiff_t prefix_length = strlen (prefix);
986 ptrdiff_t retlen;
987 if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
988 || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
989 string_overflow ();
990 Lisp_Object ret = make_uninit_string (retlen);
991 char *string = SSDATA (ret);
992 strcpy (string, prefix);
994 for (ptrdiff_t i = 0; i < buf_size; i++)
995 sprintf (string + i * 3 + prefix_length,
996 i == buf_size - 1 ? "%02x" : "%02x:",
997 buf[i]);
999 return ret;
1002 static Lisp_Object
1003 gnutls_certificate_details (gnutls_x509_crt_t cert)
1005 Lisp_Object res = Qnil;
1006 int err;
1007 size_t buf_size;
1009 /* Version. */
1011 int version = gnutls_x509_crt_get_version (cert);
1012 check_memory_full (version);
1013 if (version >= GNUTLS_E_SUCCESS)
1014 res = nconc2 (res, list2 (intern (":version"),
1015 make_number (version)));
1018 /* Serial. */
1019 buf_size = 0;
1020 err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
1021 check_memory_full (err);
1022 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1024 void *serial = xmalloc (buf_size);
1025 err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
1026 check_memory_full (err);
1027 if (err >= GNUTLS_E_SUCCESS)
1028 res = nconc2 (res, list2 (intern (":serial-number"),
1029 gnutls_hex_string (serial, buf_size, "")));
1030 xfree (serial);
1033 /* Issuer. */
1034 buf_size = 0;
1035 err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
1036 check_memory_full (err);
1037 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1039 char *dn = xmalloc (buf_size);
1040 err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
1041 check_memory_full (err);
1042 if (err >= GNUTLS_E_SUCCESS)
1043 res = nconc2 (res, list2 (intern (":issuer"),
1044 make_string (dn, buf_size)));
1045 xfree (dn);
1048 /* Validity. */
1050 /* Add 1 to the buffer size, since 1900 is added to tm_year and
1051 that might add 1 to the year length. */
1052 char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
1053 struct tm t;
1054 time_t tim = gnutls_x509_crt_get_activation_time (cert);
1056 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1057 res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
1059 tim = gnutls_x509_crt_get_expiration_time (cert);
1060 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
1061 res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
1064 /* Subject. */
1065 buf_size = 0;
1066 err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
1067 check_memory_full (err);
1068 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1070 char *dn = xmalloc (buf_size);
1071 err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
1072 check_memory_full (err);
1073 if (err >= GNUTLS_E_SUCCESS)
1074 res = nconc2 (res, list2 (intern (":subject"),
1075 make_string (dn, buf_size)));
1076 xfree (dn);
1079 /* SubjectPublicKeyInfo. */
1081 unsigned int bits;
1083 err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
1084 check_memory_full (err);
1085 if (err >= GNUTLS_E_SUCCESS)
1087 const char *name = gnutls_pk_algorithm_get_name (err);
1088 if (name)
1089 res = nconc2 (res, list2 (intern (":public-key-algorithm"),
1090 build_string (name)));
1092 name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
1093 (err, bits));
1094 res = nconc2 (res, list2 (intern (":certificate-security-level"),
1095 build_string (name)));
1099 /* Unique IDs. */
1100 buf_size = 0;
1101 err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
1102 check_memory_full (err);
1103 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1105 char *buf = xmalloc (buf_size);
1106 err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
1107 check_memory_full (err);
1108 if (err >= GNUTLS_E_SUCCESS)
1109 res = nconc2 (res, list2 (intern (":issuer-unique-id"),
1110 make_string (buf, buf_size)));
1111 xfree (buf);
1114 buf_size = 0;
1115 err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
1116 check_memory_full (err);
1117 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1119 char *buf = xmalloc (buf_size);
1120 err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
1121 check_memory_full (err);
1122 if (err >= GNUTLS_E_SUCCESS)
1123 res = nconc2 (res, list2 (intern (":subject-unique-id"),
1124 make_string (buf, buf_size)));
1125 xfree (buf);
1128 /* Signature. */
1129 err = gnutls_x509_crt_get_signature_algorithm (cert);
1130 check_memory_full (err);
1131 if (err >= GNUTLS_E_SUCCESS)
1133 const char *name = gnutls_sign_get_name (err);
1134 if (name)
1135 res = nconc2 (res, list2 (intern (":signature-algorithm"),
1136 build_string (name)));
1139 /* Public key ID. */
1140 buf_size = 0;
1141 err = gnutls_x509_crt_get_key_id (cert, 0, 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_key_id (cert, 0, buf, &buf_size);
1147 check_memory_full (err);
1148 if (err >= GNUTLS_E_SUCCESS)
1149 res = nconc2 (res, list2 (intern (":public-key-id"),
1150 gnutls_hex_string (buf, buf_size, "sha1:")));
1151 xfree (buf);
1154 /* Certificate fingerprint. */
1155 buf_size = 0;
1156 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1157 NULL, &buf_size);
1158 check_memory_full (err);
1159 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1161 void *buf = xmalloc (buf_size);
1162 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1163 buf, &buf_size);
1164 check_memory_full (err);
1165 if (err >= GNUTLS_E_SUCCESS)
1166 res = nconc2 (res, list2 (intern (":certificate-id"),
1167 gnutls_hex_string (buf, buf_size, "sha1:")));
1168 xfree (buf);
1171 return res;
1174 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
1175 doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
1176 (Lisp_Object status_symbol)
1178 CHECK_SYMBOL (status_symbol);
1180 if (EQ (status_symbol, intern (":invalid")))
1181 return build_string ("certificate could not be verified");
1183 if (EQ (status_symbol, intern (":revoked")))
1184 return build_string ("certificate was revoked (CRL)");
1186 if (EQ (status_symbol, intern (":self-signed")))
1187 return build_string ("certificate signer was not found (self-signed)");
1189 if (EQ (status_symbol, intern (":unknown-ca")))
1190 return build_string ("the certificate was signed by an unknown "
1191 "and therefore untrusted authority");
1193 if (EQ (status_symbol, intern (":not-ca")))
1194 return build_string ("certificate signer is not a CA");
1196 if (EQ (status_symbol, intern (":insecure")))
1197 return build_string ("certificate was signed with an insecure algorithm");
1199 if (EQ (status_symbol, intern (":not-activated")))
1200 return build_string ("certificate is not yet activated");
1202 if (EQ (status_symbol, intern (":expired")))
1203 return build_string ("certificate has expired");
1205 if (EQ (status_symbol, intern (":no-host-match")))
1206 return build_string ("certificate host does not match hostname");
1208 return Qnil;
1211 DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
1212 doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1213 The return value is a property list with top-level keys :warnings and
1214 :certificate. The :warnings entry is a list of symbols you can describe with
1215 `gnutls-peer-status-warning-describe'. */)
1216 (Lisp_Object proc)
1218 Lisp_Object warnings = Qnil, result = Qnil;
1219 unsigned int verification;
1220 gnutls_session_t state;
1222 CHECK_PROCESS (proc);
1224 if (GNUTLS_INITSTAGE (proc) != GNUTLS_STAGE_READY)
1225 return Qnil;
1227 /* Then collect any warnings already computed by the handshake. */
1228 verification = XPROCESS (proc)->gnutls_peer_verification;
1230 if (verification & GNUTLS_CERT_INVALID)
1231 warnings = Fcons (intern (":invalid"), warnings);
1233 if (verification & GNUTLS_CERT_REVOKED)
1234 warnings = Fcons (intern (":revoked"), warnings);
1236 if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
1237 warnings = Fcons (intern (":unknown-ca"), warnings);
1239 if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
1240 warnings = Fcons (intern (":not-ca"), warnings);
1242 if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
1243 warnings = Fcons (intern (":insecure"), warnings);
1245 if (verification & GNUTLS_CERT_NOT_ACTIVATED)
1246 warnings = Fcons (intern (":not-activated"), warnings);
1248 if (verification & GNUTLS_CERT_EXPIRED)
1249 warnings = Fcons (intern (":expired"), warnings);
1251 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1252 CERTIFICATE_NOT_MATCHING)
1253 warnings = Fcons (intern (":no-host-match"), warnings);
1255 /* This could get called in the INIT stage, when the certificate is
1256 not yet set. */
1257 if (XPROCESS (proc)->gnutls_certificates != NULL &&
1258 gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificates[0],
1259 XPROCESS (proc)->gnutls_certificates[0]))
1260 warnings = Fcons (intern (":self-signed"), warnings);
1262 if (!NILP (warnings))
1263 result = list2 (intern (":warnings"), warnings);
1265 /* This could get called in the INIT stage, when the certificate is
1266 not yet set. */
1267 if (XPROCESS (proc)->gnutls_certificates != NULL)
1269 Lisp_Object certs = Qnil;
1271 /* Return all the certificates in a list. */
1272 for (int i = 0; i < XPROCESS (proc)->gnutls_certificates_length; i++)
1273 certs = nconc2 (certs, list1 (gnutls_certificate_details
1274 (XPROCESS (proc)->gnutls_certificates[i])));
1276 result = nconc2 (result, list2 (intern (":certificates"), certs));
1278 /* Return the host certificate in its own element for
1279 compatibility reasons. */
1280 result = nconc2 (result, list2 (intern (":certificate"), Fcar (certs)));
1283 state = XPROCESS (proc)->gnutls_state;
1285 /* Diffie-Hellman prime bits. */
1287 int bits = gnutls_dh_get_prime_bits (state);
1288 check_memory_full (bits);
1289 if (bits > 0)
1290 result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
1291 make_number (bits)));
1294 /* Key exchange. */
1295 result = nconc2
1296 (result, list2 (intern (":key-exchange"),
1297 build_string (gnutls_kx_get_name
1298 (gnutls_kx_get (state)))));
1300 /* Protocol name. */
1301 result = nconc2
1302 (result, list2 (intern (":protocol"),
1303 build_string (gnutls_protocol_get_name
1304 (gnutls_protocol_get_version (state)))));
1306 /* Cipher name. */
1307 result = nconc2
1308 (result, list2 (intern (":cipher"),
1309 build_string (gnutls_cipher_get_name
1310 (gnutls_cipher_get (state)))));
1312 /* MAC name. */
1313 result = nconc2
1314 (result, list2 (intern (":mac"),
1315 build_string (gnutls_mac_get_name
1316 (gnutls_mac_get (state)))));
1319 return result;
1322 /* Initialize global GnuTLS state to defaults.
1323 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1324 Return zero on success. */
1325 Lisp_Object
1326 emacs_gnutls_global_init (void)
1328 int ret = GNUTLS_E_SUCCESS;
1330 if (!gnutls_global_initialized)
1332 ret = gnutls_global_init ();
1333 if (ret == GNUTLS_E_SUCCESS)
1334 gnutls_global_initialized = 1;
1337 return gnutls_make_error (ret);
1340 static bool
1341 gnutls_ip_address_p (char *string)
1343 char c;
1345 while ((c = *string++) != 0)
1346 if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
1347 return false;
1349 return true;
1352 # if 0
1353 /* Deinitialize global GnuTLS state.
1354 See also `gnutls-global-init'. */
1355 static Lisp_Object
1356 emacs_gnutls_global_deinit (void)
1358 if (gnutls_global_initialized)
1359 gnutls_global_deinit ();
1361 gnutls_global_initialized = 0;
1363 return gnutls_make_error (GNUTLS_E_SUCCESS);
1365 # endif
1367 static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
1368 boot_error (struct Lisp_Process *p, const char *m, ...)
1370 va_list ap;
1371 va_start (ap, m);
1372 if (p->is_non_blocking_client)
1373 pset_status (p, list2 (Qfailed, vformat_string (m, ap)));
1374 else
1375 verror (m, ap);
1376 va_end (ap);
1379 Lisp_Object
1380 gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1382 int ret;
1383 struct Lisp_Process *p = XPROCESS (proc);
1384 gnutls_session_t state = p->gnutls_state;
1385 unsigned int peer_verification;
1386 Lisp_Object warnings;
1387 int max_log_level = p->gnutls_log_level;
1388 Lisp_Object hostname, verify_error;
1389 bool verify_error_all = false;
1390 char *c_hostname;
1392 if (NILP (proplist))
1393 proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
1395 verify_error = Fplist_get (proplist, QCverify_error);
1396 hostname = Fplist_get (proplist, QChostname);
1398 if (EQ (verify_error, Qt))
1399 verify_error_all = true;
1400 else if (NILP (Flistp (verify_error)))
1402 boot_error (p,
1403 "gnutls-boot: invalid :verify_error parameter (not a list)");
1404 return Qnil;
1407 if (!STRINGP (hostname))
1409 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1410 return Qnil;
1412 c_hostname = SSDATA (hostname);
1414 /* Now verify the peer, following
1415 https://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1416 The peer should present at least one certificate in the chain; do a
1417 check of the certificate's hostname with
1418 gnutls_x509_crt_check_hostname against :hostname. */
1420 ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
1421 if (ret < GNUTLS_E_SUCCESS)
1422 return gnutls_make_error (ret);
1424 p->gnutls_peer_verification = peer_verification;
1426 warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
1427 if (!NILP (warnings))
1429 for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
1431 Lisp_Object warning = XCAR (tail);
1432 Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
1433 if (!NILP (message))
1434 GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
1438 if (peer_verification != 0)
1440 if (verify_error_all
1441 || !NILP (Fmember (QCtrustfiles, verify_error)))
1443 emacs_gnutls_deinit (proc);
1444 boot_error (p,
1445 "Certificate validation failed %s, verification code %x",
1446 c_hostname, peer_verification);
1447 return Qnil;
1449 else
1451 GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
1452 c_hostname);
1456 /* Up to here the process is the same for X.509 certificates and
1457 OpenPGP keys. From now on X.509 certificates are assumed. This
1458 can be easily extended to work with openpgp keys as well. */
1459 if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
1461 const gnutls_datum_t *cert_list;
1462 unsigned int cert_list_length;
1463 int failed_import = 0;
1465 cert_list = gnutls_certificate_get_peers (state, &cert_list_length);
1467 if (cert_list == NULL)
1469 emacs_gnutls_deinit (proc);
1470 boot_error (p, "No x509 certificate was found\n");
1471 return Qnil;
1474 /* Check only the first certificate in the given chain, but
1475 store them all. */
1476 p->gnutls_certificates =
1477 xmalloc (cert_list_length * sizeof (gnutls_x509_crt_t));
1478 p->gnutls_certificates_length = cert_list_length;
1480 for (int i = cert_list_length - 1; i >= 0; i--)
1482 gnutls_x509_crt_t cert;
1484 gnutls_x509_crt_init (&cert);
1486 if (ret < GNUTLS_E_SUCCESS)
1487 failed_import = ret;
1488 else
1490 ret = gnutls_x509_crt_import (cert, &cert_list[i],
1491 GNUTLS_X509_FMT_DER);
1493 if (ret < GNUTLS_E_SUCCESS)
1494 failed_import = ret;
1497 p->gnutls_certificates[i] = cert;
1500 if (failed_import != 0)
1502 gnutls_deinit_certificates (p);
1503 p->gnutls_certificates = NULL;
1504 return gnutls_make_error (failed_import);
1507 int err = gnutls_x509_crt_check_hostname (p->gnutls_certificates[0],
1508 c_hostname);
1509 check_memory_full (err);
1510 if (!err)
1512 p->gnutls_extra_peer_verification |= CERTIFICATE_NOT_MATCHING;
1513 if (verify_error_all
1514 || !NILP (Fmember (QChostname, verify_error)))
1516 emacs_gnutls_deinit (proc);
1517 boot_error (p, "The x509 certificate does not match \"%s\"",
1518 c_hostname);
1519 return Qnil;
1521 else
1522 GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
1523 c_hostname);
1527 /* Set this flag only if the whole initialization succeeded. */
1528 p->gnutls_p = true;
1530 return gnutls_make_error (ret);
1533 DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1534 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1535 Currently only client mode is supported. Return a success/failure
1536 value you can check with `gnutls-errorp'.
1538 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1539 PROPLIST is a property list with the following keys:
1541 :hostname is a string naming the remote host.
1543 :priority is a GnuTLS priority string, defaults to "NORMAL".
1545 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1547 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1549 :keylist is an alist of PEM-encoded key files and PEM-encoded
1550 certificates for `gnutls-x509pki'.
1552 :callbacks is an alist of callback functions, see below.
1554 :loglevel is the debug level requested from GnuTLS, try 4.
1556 :verify-flags is a bitset as per GnuTLS'
1557 gnutls_certificate_set_verify_flags.
1559 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1560 instead.
1562 :verify-error is a list of symbols to express verification checks or
1563 t to do all checks. Currently it can contain `:trustfiles' and
1564 `:hostname' to verify the certificate or the hostname respectively.
1566 :min-prime-bits is the minimum accepted number of bits the client will
1567 accept in Diffie-Hellman key exchange.
1569 :complete-negotiation, if non-nil, will make negotiation complete
1570 before returning even on non-blocking sockets.
1572 The debug level will be set for this process AND globally for GnuTLS.
1573 So if you set it higher or lower at any point, it affects global
1574 debugging.
1576 Note that the priority is set on the client. The server does not use
1577 the protocols's priority except for disabling protocols that were not
1578 specified.
1580 Processes must be initialized with this function before other GnuTLS
1581 functions are used. This function allocates resources which can only
1582 be deallocated by calling `gnutls-deinit' or by calling it again.
1584 The callbacks alist can have a `verify' key, associated with a
1585 verification function (UNUSED).
1587 Each authentication type may need additional information in order to
1588 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1589 one trustfile (usually a CA bundle). */)
1590 (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist)
1592 int ret = GNUTLS_E_SUCCESS;
1593 int max_log_level = 0;
1595 gnutls_session_t state;
1596 gnutls_certificate_credentials_t x509_cred = NULL;
1597 gnutls_anon_client_credentials_t anon_cred = NULL;
1598 Lisp_Object global_init;
1599 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1600 char *c_hostname;
1602 /* Placeholders for the property list elements. */
1603 Lisp_Object priority_string;
1604 Lisp_Object trustfiles;
1605 Lisp_Object crlfiles;
1606 Lisp_Object keylist;
1607 /* Lisp_Object callbacks; */
1608 Lisp_Object loglevel;
1609 Lisp_Object hostname;
1610 Lisp_Object prime_bits;
1611 struct Lisp_Process *p = XPROCESS (proc);
1613 CHECK_PROCESS (proc);
1614 CHECK_SYMBOL (type);
1615 CHECK_LIST (proplist);
1617 if (NILP (Fgnutls_available_p ()))
1619 boot_error (p, "GnuTLS not available");
1620 return Qnil;
1623 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1625 boot_error (p, "Invalid GnuTLS credential type");
1626 return Qnil;
1629 hostname = Fplist_get (proplist, QChostname);
1630 priority_string = Fplist_get (proplist, QCpriority);
1631 trustfiles = Fplist_get (proplist, QCtrustfiles);
1632 keylist = Fplist_get (proplist, QCkeylist);
1633 crlfiles = Fplist_get (proplist, QCcrlfiles);
1634 loglevel = Fplist_get (proplist, QCloglevel);
1635 prime_bits = Fplist_get (proplist, QCmin_prime_bits);
1637 if (!STRINGP (hostname))
1639 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1640 return Qnil;
1642 c_hostname = SSDATA (hostname);
1644 state = XPROCESS (proc)->gnutls_state;
1646 if (TYPE_RANGED_INTEGERP (int, loglevel))
1648 gnutls_global_set_log_function (gnutls_log_function);
1649 # ifdef HAVE_GNUTLS3
1650 gnutls_global_set_audit_log_function (gnutls_audit_log_function);
1651 # endif
1652 gnutls_global_set_log_level (XINT (loglevel));
1653 max_log_level = XINT (loglevel);
1654 XPROCESS (proc)->gnutls_log_level = max_log_level;
1657 GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
1659 /* Always initialize globals. */
1660 global_init = emacs_gnutls_global_init ();
1661 if (! NILP (Fgnutls_errorp (global_init)))
1662 return global_init;
1664 /* Before allocating new credentials, deallocate any credentials
1665 that PROC might already have. */
1666 emacs_gnutls_deinit (proc);
1668 /* Mark PROC as a GnuTLS process. */
1669 XPROCESS (proc)->gnutls_state = NULL;
1670 XPROCESS (proc)->gnutls_x509_cred = NULL;
1671 XPROCESS (proc)->gnutls_anon_cred = NULL;
1672 pset_gnutls_cred_type (XPROCESS (proc), type);
1673 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY;
1675 GNUTLS_LOG (1, max_log_level, "allocating credentials");
1676 if (EQ (type, Qgnutls_x509pki))
1678 Lisp_Object verify_flags;
1679 unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1681 GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
1682 check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
1683 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1685 verify_flags = Fplist_get (proplist, QCverify_flags);
1686 if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
1688 gnutls_verify_flags = XFASTINT (verify_flags);
1689 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1691 else if (NILP (verify_flags))
1692 GNUTLS_LOG (2, max_log_level, "using default verification flags");
1693 else
1694 GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
1696 gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
1698 else /* Qgnutls_anon: */
1700 GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
1701 check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
1702 XPROCESS (proc)->gnutls_anon_cred = anon_cred;
1705 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC;
1707 if (EQ (type, Qgnutls_x509pki))
1709 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1710 int file_format = GNUTLS_X509_FMT_PEM;
1711 Lisp_Object tail;
1713 # ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
1714 ret = gnutls_certificate_set_x509_system_trust (x509_cred);
1715 if (ret < GNUTLS_E_SUCCESS)
1717 check_memory_full (ret);
1718 GNUTLS_LOG2i (4, max_log_level,
1719 "setting system trust failed with code ", ret);
1721 # endif
1723 for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
1725 Lisp_Object trustfile = XCAR (tail);
1726 if (STRINGP (trustfile))
1728 GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
1729 SSDATA (trustfile));
1730 trustfile = ENCODE_FILE (trustfile);
1731 # ifdef WINDOWSNT
1732 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1733 file names on Windows, we need to re-encode the file
1734 name using the current ANSI codepage. */
1735 trustfile = ansi_encode_filename (trustfile);
1736 # endif
1737 ret = gnutls_certificate_set_x509_trust_file
1738 (x509_cred,
1739 SSDATA (trustfile),
1740 file_format);
1742 if (ret < GNUTLS_E_SUCCESS)
1743 return gnutls_make_error (ret);
1745 else
1747 emacs_gnutls_deinit (proc);
1748 boot_error (p, "Invalid trustfile");
1749 return Qnil;
1753 for (tail = crlfiles; CONSP (tail); tail = XCDR (tail))
1755 Lisp_Object crlfile = XCAR (tail);
1756 if (STRINGP (crlfile))
1758 GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
1759 SSDATA (crlfile));
1760 crlfile = ENCODE_FILE (crlfile);
1761 # ifdef WINDOWSNT
1762 crlfile = ansi_encode_filename (crlfile);
1763 # endif
1764 ret = gnutls_certificate_set_x509_crl_file
1765 (x509_cred, SSDATA (crlfile), file_format);
1767 if (ret < GNUTLS_E_SUCCESS)
1768 return gnutls_make_error (ret);
1770 else
1772 emacs_gnutls_deinit (proc);
1773 boot_error (p, "Invalid CRL file");
1774 return Qnil;
1778 for (tail = keylist; CONSP (tail); tail = XCDR (tail))
1780 Lisp_Object keyfile = Fcar (XCAR (tail));
1781 Lisp_Object certfile = Fcar (Fcdr (XCAR (tail)));
1782 if (STRINGP (keyfile) && STRINGP (certfile))
1784 GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ",
1785 SSDATA (keyfile));
1786 GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
1787 SSDATA (certfile));
1788 keyfile = ENCODE_FILE (keyfile);
1789 certfile = ENCODE_FILE (certfile);
1790 # ifdef WINDOWSNT
1791 keyfile = ansi_encode_filename (keyfile);
1792 certfile = ansi_encode_filename (certfile);
1793 # endif
1794 ret = gnutls_certificate_set_x509_key_file
1795 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
1797 if (ret < GNUTLS_E_SUCCESS)
1798 return gnutls_make_error (ret);
1800 else
1802 emacs_gnutls_deinit (proc);
1803 boot_error (p, STRINGP (keyfile) ? "Invalid client cert file"
1804 : "Invalid client key file");
1805 return Qnil;
1810 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
1811 GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
1812 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
1814 /* Call gnutls_init here: */
1816 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1817 int gnutls_flags = GNUTLS_CLIENT;
1818 # ifdef GNUTLS_NONBLOCK
1819 if (XPROCESS (proc)->is_non_blocking_client)
1820 gnutls_flags |= GNUTLS_NONBLOCK;
1821 # endif
1822 ret = gnutls_init (&state, gnutls_flags);
1823 XPROCESS (proc)->gnutls_state = state;
1824 if (ret < GNUTLS_E_SUCCESS)
1825 return gnutls_make_error (ret);
1826 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT;
1828 if (STRINGP (priority_string))
1830 priority_string_ptr = SSDATA (priority_string);
1831 GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:",
1832 priority_string_ptr);
1834 else
1836 GNUTLS_LOG2 (1, max_log_level, "using default priority string:",
1837 priority_string_ptr);
1840 GNUTLS_LOG (1, max_log_level, "setting the priority string");
1841 ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
1842 if (ret < GNUTLS_E_SUCCESS)
1843 return gnutls_make_error (ret);
1845 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
1847 if (INTEGERP (prime_bits))
1848 gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
1850 ret = EQ (type, Qgnutls_x509pki)
1851 ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
1852 : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
1853 if (ret < GNUTLS_E_SUCCESS)
1854 return gnutls_make_error (ret);
1856 if (!gnutls_ip_address_p (c_hostname))
1858 ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
1859 strlen (c_hostname));
1860 if (ret < GNUTLS_E_SUCCESS)
1861 return gnutls_make_error (ret);
1864 XPROCESS (proc)->gnutls_complete_negotiation_p =
1865 !NILP (Fplist_get (proplist, QCcomplete_negotiation));
1866 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
1867 ret = emacs_gnutls_handshake (XPROCESS (proc));
1868 if (ret < GNUTLS_E_SUCCESS)
1869 return gnutls_make_error (ret);
1871 return gnutls_verify_boot (proc, proplist);
1874 DEFUN ("gnutls-bye", Fgnutls_bye,
1875 Sgnutls_bye, 2, 2, 0,
1876 doc: /* Terminate current GnuTLS connection for process PROC.
1877 The connection should have been initiated using `gnutls-handshake'.
1879 If CONT is not nil the TLS connection gets terminated and further
1880 receives and sends will be disallowed. If the return value is zero you
1881 may continue using the connection. If CONT is nil, GnuTLS actually
1882 sends an alert containing a close request and waits for the peer to
1883 reply with the same message. In order to reuse the connection you
1884 should wait for an EOF from the peer.
1886 This function may also return `gnutls-e-again', or
1887 `gnutls-e-interrupted'. */)
1888 (Lisp_Object proc, Lisp_Object cont)
1890 gnutls_session_t state;
1891 int ret;
1893 CHECK_PROCESS (proc);
1895 state = XPROCESS (proc)->gnutls_state;
1897 if (XPROCESS (proc)->gnutls_certificates)
1898 gnutls_deinit_certificates (XPROCESS (proc));
1900 ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
1902 return gnutls_make_error (ret);
1905 #endif /* HAVE_GNUTLS */
1907 #ifdef HAVE_GNUTLS3
1909 DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
1910 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
1911 The alist key is the cipher name. */)
1912 (void)
1914 Lisp_Object ciphers = Qnil;
1916 const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
1917 for (ptrdiff_t pos = 0; gciphers[pos] != 0; pos++)
1919 gnutls_cipher_algorithm_t gca = gciphers[pos];
1920 if (gca == GNUTLS_CIPHER_NULL)
1921 continue;
1922 char const *cipher_name = gnutls_cipher_get_name (gca);
1923 if (!cipher_name)
1924 continue;
1926 /* A symbol representing the GnuTLS cipher. */
1927 Lisp_Object cipher_symbol = intern (cipher_name);
1929 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1931 Lisp_Object cp
1932 = listn (CONSTYPE_HEAP, 15, cipher_symbol,
1933 QCcipher_id, make_number (gca),
1934 QCtype, Qgnutls_type_cipher,
1935 QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
1936 QCcipher_tagsize, make_number (cipher_tag_size),
1938 QCcipher_blocksize,
1939 make_number (gnutls_cipher_get_block_size (gca)),
1941 QCcipher_keysize,
1942 make_number (gnutls_cipher_get_key_size (gca)),
1944 QCcipher_ivsize,
1945 make_number (gnutls_cipher_get_iv_size (gca)));
1947 ciphers = Fcons (cp, ciphers);
1950 return ciphers;
1953 static Lisp_Object
1954 gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1955 Lisp_Object cipher,
1956 const char *kdata, ptrdiff_t ksize,
1957 const char *vdata, ptrdiff_t vsize,
1958 const char *idata, ptrdiff_t isize,
1959 Lisp_Object aead_auth)
1961 # ifdef HAVE_GNUTLS_AEAD
1963 const char *desc = encrypting ? "encrypt" : "decrypt";
1964 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
1966 gnutls_aead_cipher_hd_t acipher;
1967 gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
1968 int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
1970 if (ret < GNUTLS_E_SUCCESS)
1971 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
1972 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1974 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1975 ptrdiff_t tagged_size;
1976 if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
1977 || SIZE_MAX < tagged_size)
1978 memory_full (SIZE_MAX);
1979 size_t storage_length = tagged_size;
1980 USE_SAFE_ALLOCA;
1981 char *storage = SAFE_ALLOCA (storage_length);
1983 const char *aead_auth_data = NULL;
1984 ptrdiff_t aead_auth_size = 0;
1986 if (!NILP (aead_auth))
1988 if (BUFFERP (aead_auth) || STRINGP (aead_auth))
1989 aead_auth = list1 (aead_auth);
1991 CHECK_CONS (aead_auth);
1993 ptrdiff_t astart_byte, aend_byte;
1994 const char *adata
1995 = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
1996 if (adata == NULL)
1997 error ("GnuTLS AEAD cipher auth extraction failed");
1999 aead_auth_data = adata;
2000 aead_auth_size = aend_byte - astart_byte;
2003 ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
2004 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2006 if (isize < expected_remainder
2007 || (isize - expected_remainder) % cipher_block_size != 0)
2008 error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
2009 "is not %"pD"d greater than a multiple of the required %"pD"d"),
2010 gnutls_cipher_get_name (gca), desc,
2011 isize, expected_remainder, cipher_block_size);
2013 ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
2014 (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
2015 cipher_tag_size, idata, isize, storage, &storage_length));
2017 Lisp_Object output;
2018 if (GNUTLS_E_SUCCESS <= ret)
2019 output = make_unibyte_string (storage, storage_length);
2020 explicit_bzero (storage, storage_length);
2021 gnutls_aead_cipher_deinit (acipher);
2023 if (ret < GNUTLS_E_SUCCESS)
2024 error ((encrypting
2025 ? "GnuTLS AEAD cipher %s encryption failed: %s"
2026 : "GnuTLS AEAD cipher %s decryption failed: %s"),
2027 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2029 SAFE_FREE ();
2030 return list2 (output, actual_iv);
2031 # else
2032 printmax_t print_gca = gca;
2033 error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
2034 # endif
2037 static Lisp_Object
2038 gnutls_symmetric (bool encrypting, Lisp_Object cipher,
2039 Lisp_Object key, Lisp_Object iv,
2040 Lisp_Object input, Lisp_Object aead_auth)
2042 if (BUFFERP (key) || STRINGP (key))
2043 key = list1 (key);
2045 CHECK_CONS (key);
2047 if (BUFFERP (input) || STRINGP (input))
2048 input = list1 (input);
2050 CHECK_CONS (input);
2052 if (BUFFERP (iv) || STRINGP (iv))
2053 iv = list1 (iv);
2055 CHECK_CONS (iv);
2058 const char *desc = encrypting ? "encrypt" : "decrypt";
2060 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
2062 Lisp_Object info = Qnil;
2063 if (STRINGP (cipher))
2064 cipher = intern (SSDATA (cipher));
2066 if (SYMBOLP (cipher))
2067 info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
2068 else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
2069 gca = XINT (cipher);
2070 else
2071 info = cipher;
2073 if (!NILP (info) && CONSP (info))
2075 Lisp_Object v = Fplist_get (info, QCcipher_id);
2076 if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
2077 gca = XINT (v);
2080 ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
2081 if (key_size == 0)
2082 error ("GnuTLS cipher is invalid or not found");
2084 ptrdiff_t kstart_byte, kend_byte;
2085 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2087 if (kdata == NULL)
2088 error ("GnuTLS cipher key extraction failed");
2090 if (kend_byte - kstart_byte != key_size)
2091 error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
2092 "the required %"pD"d"),
2093 gnutls_cipher_get_name (gca), desc,
2094 kend_byte - kstart_byte, key_size);
2096 ptrdiff_t vstart_byte, vend_byte;
2097 char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
2099 if (vdata == NULL)
2100 error ("GnuTLS cipher IV extraction failed");
2102 ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
2103 if (vend_byte - vstart_byte != iv_size)
2104 error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
2105 "the required %"pD"d"),
2106 gnutls_cipher_get_name (gca), desc,
2107 vend_byte - vstart_byte, iv_size);
2109 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
2111 ptrdiff_t istart_byte, iend_byte;
2112 const char *idata
2113 = extract_data_from_object (input, &istart_byte, &iend_byte);
2115 if (idata == NULL)
2116 error ("GnuTLS cipher input extraction failed");
2118 /* Is this an AEAD cipher? */
2119 if (gnutls_cipher_get_tag_size (gca) > 0)
2121 Lisp_Object aead_output =
2122 gnutls_symmetric_aead (encrypting, gca, cipher,
2123 kdata, kend_byte - kstart_byte,
2124 vdata, vend_byte - vstart_byte,
2125 idata, iend_byte - istart_byte,
2126 aead_auth);
2127 if (STRINGP (XCAR (key)))
2128 Fclear_string (XCAR (key));
2129 return aead_output;
2132 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2133 if ((iend_byte - istart_byte) % cipher_block_size != 0)
2134 error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
2135 "of the required %"pD"d"),
2136 gnutls_cipher_get_name (gca), desc,
2137 iend_byte - istart_byte, cipher_block_size);
2139 gnutls_cipher_hd_t hcipher;
2140 gnutls_datum_t key_datum
2141 = { (unsigned char *) kdata, kend_byte - kstart_byte };
2143 int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
2145 if (ret < GNUTLS_E_SUCCESS)
2146 error ("GnuTLS cipher %s/%s initialization failed: %s",
2147 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2149 /* Note that this will not support streaming block mode. */
2150 gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
2152 /* GnuTLS docs: "For the supported ciphers the encrypted data length
2153 will equal the plaintext size." */
2154 ptrdiff_t storage_length = iend_byte - istart_byte;
2155 Lisp_Object storage = make_uninit_string (storage_length);
2157 ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
2158 (hcipher, idata, iend_byte - istart_byte,
2159 SSDATA (storage), storage_length));
2161 if (STRINGP (XCAR (key)))
2162 Fclear_string (XCAR (key));
2164 if (ret < GNUTLS_E_SUCCESS)
2166 gnutls_cipher_deinit (hcipher);
2167 if (encrypting)
2168 error ("GnuTLS cipher %s encryption failed: %s",
2169 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2170 else
2171 error ("GnuTLS cipher %s decryption failed: %s",
2172 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2175 gnutls_cipher_deinit (hcipher);
2177 return list2 (storage, actual_iv);
2180 DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
2181 Sgnutls_symmetric_encrypt, 4, 5, 0,
2182 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2184 Return nil on error.
2186 The KEY can be specified as a buffer or string or in other ways (see
2187 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2188 will be wiped after use if it's a string.
2190 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2191 buffer or string or in other ways (see Info node `(elisp)Format of
2192 GnuTLS Cryptography Inputs').
2194 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2195 The CIPHER may be a string or symbol matching a key in that alist, or
2196 a plist with the :cipher-id numeric property, or the number itself.
2198 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2199 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2200 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2201 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2202 Lisp_Object input, Lisp_Object aead_auth)
2204 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
2207 DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
2208 Sgnutls_symmetric_decrypt, 4, 5, 0,
2209 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2211 Return nil on error.
2213 The KEY can be specified as a buffer or string or in other ways (see
2214 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2215 will be wiped after use if it's a string.
2217 The IV and INPUT and the optional AEAD_AUTH can be specified as a
2218 buffer or string or in other ways (see Info node `(elisp)Format of
2219 GnuTLS Cryptography Inputs').
2221 The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2222 The CIPHER may be a string or symbol matching a key in that alist, or
2223 a plist with the `:cipher-id' numeric property, or the number itself.
2225 AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2226 :cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2227 these AEAD ciphers, but it may still be omitted (nil) as well. */)
2228 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2229 Lisp_Object input, Lisp_Object aead_auth)
2231 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
2234 DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
2235 doc: /* Return alist of GnuTLS mac-algorithm method descriptions as plists.
2237 Use the value of the alist (extract it with `alist-get' for instance)
2238 with `gnutls-hash-mac'. The alist key is the mac-algorithm method
2239 name. */)
2240 (void)
2242 Lisp_Object mac_algorithms = Qnil;
2243 const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
2244 for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
2246 const gnutls_mac_algorithm_t gma = macs[pos];
2248 /* A symbol representing the GnuTLS MAC algorithm. */
2249 Lisp_Object gma_symbol = intern (gnutls_mac_get_name (gma));
2251 size_t nonce_size = 0;
2252 #ifdef HAVE_GNUTLS_MAC_GET_NONCE_SIZE
2253 nonce_size = gnutls_mac_get_nonce_size (gma);
2254 #endif
2255 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, gma_symbol,
2256 QCmac_algorithm_id, make_number (gma),
2257 QCtype, Qgnutls_type_mac_algorithm,
2259 QCmac_algorithm_length,
2260 make_number (gnutls_hmac_get_len (gma)),
2262 QCmac_algorithm_keysize,
2263 make_number (gnutls_mac_get_key_size (gma)),
2265 QCmac_algorithm_noncesize,
2266 make_number (nonce_size));
2267 mac_algorithms = Fcons (mp, mac_algorithms);
2270 return mac_algorithms;
2273 DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
2274 doc: /* Return alist of GnuTLS digest-algorithm method descriptions as plists.
2276 Use the value of the alist (extract it with `alist-get' for instance)
2277 with `gnutls-hash-digest'. The alist key is the digest-algorithm
2278 method name. */)
2279 (void)
2281 Lisp_Object digest_algorithms = Qnil;
2282 const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
2283 for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
2285 const gnutls_digest_algorithm_t gda = digests[pos];
2287 /* A symbol representing the GnuTLS digest algorithm. */
2288 Lisp_Object gda_symbol = intern (gnutls_digest_get_name (gda));
2290 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, gda_symbol,
2291 QCdigest_algorithm_id, make_number (gda),
2292 QCtype, Qgnutls_type_digest_algorithm,
2294 QCdigest_algorithm_length,
2295 make_number (gnutls_hash_get_len (gda)));
2297 digest_algorithms = Fcons (mp, digest_algorithms);
2300 return digest_algorithms;
2303 DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
2304 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
2306 Return nil on error.
2308 The KEY can be specified as a buffer or string or in other ways (see
2309 Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2310 will be wiped after use if it's a string.
2312 The INPUT can be specified as a buffer or string or in other
2313 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2315 The alist of MAC algorithms can be obtained with `gnutls-macs`. The
2316 HASH-METHOD may be a string or symbol matching a key in that alist, or
2317 a plist with the `:mac-algorithm-id' numeric property, or the number
2318 itself. */)
2319 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
2321 if (BUFFERP (input) || STRINGP (input))
2322 input = list1 (input);
2324 CHECK_CONS (input);
2326 if (BUFFERP (key) || STRINGP (key))
2327 key = list1 (key);
2329 CHECK_CONS (key);
2331 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
2333 Lisp_Object info = Qnil;
2334 if (STRINGP (hash_method))
2335 hash_method = intern (SSDATA (hash_method));
2337 if (SYMBOLP (hash_method))
2338 info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
2339 else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
2340 gma = XINT (hash_method);
2341 else
2342 info = hash_method;
2344 if (!NILP (info) && CONSP (info))
2346 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
2347 if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
2348 gma = XINT (v);
2351 ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
2352 if (digest_length == 0)
2353 error ("GnuTLS MAC-method is invalid or not found");
2355 ptrdiff_t kstart_byte, kend_byte;
2356 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2357 if (kdata == NULL)
2358 error ("GnuTLS MAC key extraction failed");
2360 gnutls_hmac_hd_t hmac;
2361 int ret = gnutls_hmac_init (&hmac, gma,
2362 kdata + kstart_byte, kend_byte - kstart_byte);
2363 if (ret < GNUTLS_E_SUCCESS)
2364 error ("GnuTLS MAC %s initialization failed: %s",
2365 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2367 ptrdiff_t istart_byte, iend_byte;
2368 const char *idata
2369 = extract_data_from_object (input, &istart_byte, &iend_byte);
2370 if (idata == NULL)
2371 error ("GnuTLS MAC input extraction failed");
2373 Lisp_Object digest = make_uninit_string (digest_length);
2375 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
2377 if (STRINGP (XCAR (key)))
2378 Fclear_string (XCAR (key));
2380 if (ret < GNUTLS_E_SUCCESS)
2382 gnutls_hmac_deinit (hmac, NULL);
2383 error ("GnuTLS MAC %s application failed: %s",
2384 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2387 gnutls_hmac_output (hmac, SSDATA (digest));
2388 gnutls_hmac_deinit (hmac, NULL);
2390 return digest;
2393 DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
2394 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
2396 Return nil on error.
2398 The INPUT can be specified as a buffer or string or in other
2399 ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2401 The alist of digest algorithms can be obtained with `gnutls-digests`.
2402 The DIGEST-METHOD may be a string or symbol matching a key in that
2403 alist, or a plist with the `:digest-algorithm-id' numeric property, or
2404 the number itself. */)
2405 (Lisp_Object digest_method, Lisp_Object input)
2407 if (BUFFERP (input) || STRINGP (input))
2408 input = list1 (input);
2410 CHECK_CONS (input);
2412 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
2414 Lisp_Object info = Qnil;
2415 if (STRINGP (digest_method))
2416 digest_method = intern (SSDATA (digest_method));
2418 if (SYMBOLP (digest_method))
2419 info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
2420 else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
2421 gda = XINT (digest_method);
2422 else
2423 info = digest_method;
2425 if (!NILP (info) && CONSP (info))
2427 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
2428 if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
2429 gda = XINT (v);
2432 ptrdiff_t digest_length = gnutls_hash_get_len (gda);
2433 if (digest_length == 0)
2434 error ("GnuTLS digest-method is invalid or not found");
2436 gnutls_hash_hd_t hash;
2437 int ret = gnutls_hash_init (&hash, gda);
2439 if (ret < GNUTLS_E_SUCCESS)
2440 error ("GnuTLS digest initialization failed: %s",
2441 emacs_gnutls_strerror (ret));
2443 Lisp_Object digest = make_uninit_string (digest_length);
2445 ptrdiff_t istart_byte, iend_byte;
2446 const char *idata
2447 = extract_data_from_object (input, &istart_byte, &iend_byte);
2448 if (idata == NULL)
2449 error ("GnuTLS digest input extraction failed");
2451 ret = gnutls_hash (hash, idata + istart_byte, iend_byte - istart_byte);
2453 if (ret < GNUTLS_E_SUCCESS)
2455 gnutls_hash_deinit (hash, NULL);
2456 error ("GnuTLS digest application failed: %s",
2457 emacs_gnutls_strerror (ret));
2460 gnutls_hash_output (hash, SSDATA (digest));
2461 gnutls_hash_deinit (hash, NULL);
2463 return digest;
2466 #endif /* HAVE_GNUTLS3 */
2468 DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
2469 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
2471 ...if supported : then...
2472 GnuTLS 3 or higher : the list will contain `gnutls3'.
2473 GnuTLS MACs : the list will contain `macs'.
2474 GnuTLS digests : the list will contain `digests'.
2475 GnuTLS symmetric ciphers: the list will contain `ciphers'.
2476 GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'.
2477 %DUMBFW : the list will contain `ClientHello\ Padding'.
2478 Any GnuTLS extension with ID up to 100
2479 : the list will contain its name. */)
2480 (void)
2482 Lisp_Object capabilities = Qnil;
2484 #ifdef HAVE_GNUTLS
2486 # ifdef WINDOWSNT
2487 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
2488 if (CONSP (found))
2489 return XCDR (found);
2491 /* Load the GnuTLS DLL and find exported functions. The external
2492 library cache is updated after the capabilities have been
2493 determined. */
2494 if (!init_gnutls_functions ())
2495 return Qnil;
2496 # endif /* WINDOWSNT */
2498 capabilities = Fcons (intern("gnutls"), capabilities);
2500 # ifdef HAVE_GNUTLS3
2501 capabilities = Fcons (intern("gnutls3"), capabilities);
2502 capabilities = Fcons (intern("digests"), capabilities);
2503 capabilities = Fcons (intern("ciphers"), capabilities);
2505 # ifdef HAVE_GNUTLS_AEAD
2506 capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
2507 # endif
2509 capabilities = Fcons (intern("macs"), capabilities);
2511 # ifdef HAVE_GNUTLS_EXT_GET_NAME
2512 for (unsigned int ext=0; ext < 100; ext++)
2514 const char* name = gnutls_ext_get_name(ext);
2515 if (name != NULL)
2517 capabilities = Fcons (intern(name), capabilities);
2520 # endif
2521 # endif /* HAVE_GNUTLS3 */
2523 # ifdef HAVE_GNUTLS_EXT__DUMBFW
2524 capabilities = Fcons (intern("ClientHello Padding"), capabilities);
2525 # endif
2527 # ifdef WINDOWSNT
2528 Vlibrary_cache = Fcons (Fcons (Qgnutls, capabilities), Vlibrary_cache);
2529 # endif /* WINDOWSNT */
2530 #endif /* HAVE_GNUTLS */
2532 return capabilities;
2535 void
2536 syms_of_gnutls (void)
2538 DEFSYM (Qlibgnutls_version, "libgnutls-version");
2539 Fset (Qlibgnutls_version,
2540 #ifdef HAVE_GNUTLS
2541 make_number (GNUTLS_VERSION_MAJOR * 10000
2542 + GNUTLS_VERSION_MINOR * 100
2543 + GNUTLS_VERSION_PATCH)
2544 #else
2545 make_number (-1)
2546 #endif
2548 #ifdef HAVE_GNUTLS
2549 gnutls_global_initialized = 0;
2551 DEFSYM (Qgnutls_code, "gnutls-code");
2552 DEFSYM (Qgnutls_anon, "gnutls-anon");
2553 DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
2555 /* The following are for the property list of 'gnutls-boot'. */
2556 DEFSYM (QChostname, ":hostname");
2557 DEFSYM (QCpriority, ":priority");
2558 DEFSYM (QCtrustfiles, ":trustfiles");
2559 DEFSYM (QCkeylist, ":keylist");
2560 DEFSYM (QCcrlfiles, ":crlfiles");
2561 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
2562 DEFSYM (QCloglevel, ":loglevel");
2563 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
2564 DEFSYM (QCverify_flags, ":verify-flags");
2565 DEFSYM (QCverify_error, ":verify-error");
2567 DEFSYM (QCcipher_id, ":cipher-id");
2568 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
2569 DEFSYM (QCcipher_blocksize, ":cipher-blocksize");
2570 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2571 DEFSYM (QCcipher_tagsize, ":cipher-tagsize");
2572 DEFSYM (QCcipher_ivsize, ":cipher-ivsize");
2574 DEFSYM (QCmac_algorithm_id, ":mac-algorithm-id");
2575 DEFSYM (QCmac_algorithm_noncesize, ":mac-algorithm-noncesize");
2576 DEFSYM (QCmac_algorithm_keysize, ":mac-algorithm-keysize");
2577 DEFSYM (QCmac_algorithm_length, ":mac-algorithm-length");
2579 DEFSYM (QCdigest_algorithm_id, ":digest-algorithm-id");
2580 DEFSYM (QCdigest_algorithm_length, ":digest-algorithm-length");
2582 DEFSYM (QCtype, ":type");
2583 DEFSYM (Qgnutls_type_cipher, "gnutls-symmetric-cipher");
2584 DEFSYM (Qgnutls_type_mac_algorithm, "gnutls-mac-algorithm");
2585 DEFSYM (Qgnutls_type_digest_algorithm, "gnutls-digest-algorithm");
2587 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
2588 Fput (Qgnutls_e_interrupted, Qgnutls_code,
2589 make_number (GNUTLS_E_INTERRUPTED));
2591 DEFSYM (Qgnutls_e_again, "gnutls-e-again");
2592 Fput (Qgnutls_e_again, Qgnutls_code,
2593 make_number (GNUTLS_E_AGAIN));
2595 DEFSYM (Qgnutls_e_invalid_session, "gnutls-e-invalid-session");
2596 Fput (Qgnutls_e_invalid_session, Qgnutls_code,
2597 make_number (GNUTLS_E_INVALID_SESSION));
2599 DEFSYM (Qgnutls_e_not_ready_for_handshake, "gnutls-e-not-ready-for-handshake");
2600 Fput (Qgnutls_e_not_ready_for_handshake, Qgnutls_code,
2601 make_number (GNUTLS_E_APPLICATION_ERROR_MIN));
2603 defsubr (&Sgnutls_get_initstage);
2604 defsubr (&Sgnutls_asynchronous_parameters);
2605 defsubr (&Sgnutls_errorp);
2606 defsubr (&Sgnutls_error_fatalp);
2607 defsubr (&Sgnutls_error_string);
2608 defsubr (&Sgnutls_boot);
2609 defsubr (&Sgnutls_deinit);
2610 defsubr (&Sgnutls_bye);
2611 defsubr (&Sgnutls_peer_status);
2612 defsubr (&Sgnutls_peer_status_warning_describe);
2614 #ifdef HAVE_GNUTLS3
2615 defsubr (&Sgnutls_ciphers);
2616 defsubr (&Sgnutls_macs);
2617 defsubr (&Sgnutls_digests);
2618 defsubr (&Sgnutls_hash_mac);
2619 defsubr (&Sgnutls_hash_digest);
2620 defsubr (&Sgnutls_symmetric_encrypt);
2621 defsubr (&Sgnutls_symmetric_decrypt);
2622 #endif
2624 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
2625 doc: /* Logging level used by the GnuTLS functions.
2626 Set this larger than 0 to get debug output in the *Messages* buffer.
2627 1 is for important messages, 2 is for debug data, and higher numbers
2628 are as per the GnuTLS logging conventions. */);
2629 global_gnutls_log_level = 0;
2631 #endif /* HAVE_GNUTLS */
2633 defsubr (&Sgnutls_available_p);