1 /* GnuTLS --- Guile bindings for GnuTLS.
2 Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 GnuTLS is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 GnuTLS is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with GnuTLS; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 /* Written by Ludovic Courtès <ludo@gnu.org>. */
27 #include <gnutls/gnutls.h>
39 /* SMOB and enums type definitions. */
40 #include "enum-map.i.c"
41 #include "smob-types.i.c"
43 const char scm_gnutls_array_error_message[] =
44 "cannot handle non-contiguous array: ~A";
47 /* Data that are attached to `gnutls_session_t' objects.
49 We need to keep several pieces of information along with each session:
51 - A boolean indicating whether its underlying transport is a file
52 descriptor or Scheme port. This is used to decide whether to leave
53 "Guile mode" when invoking `gnutls_record_recv ()'.
55 - The record port attached to the session (returned by
56 `session-record-port'). This is so that several calls to
57 `session-record-port' return the same port.
59 Currently, this information is maintained into a pair. The whole pair is
60 marked by the session mark procedure. */
62 #define SCM_GNUTLS_MAKE_SESSION_DATA() \
63 scm_cons (SCM_BOOL_F, SCM_BOOL_F)
64 #define SCM_GNUTLS_SET_SESSION_DATA(c_session, data) \
65 gnutls_session_set_ptr (c_session, (void *) SCM_UNPACK (data))
66 #define SCM_GNUTLS_SESSION_DATA(c_session) \
67 SCM_PACK ((scm_t_bits) gnutls_session_get_ptr (c_session))
69 #define SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD(c_session, c_is_fd) \
70 SCM_SETCAR (SCM_GNUTLS_SESSION_DATA (c_session), \
71 scm_from_bool (c_is_fd))
72 #define SCM_GNUTLS_SET_SESSION_RECORD_PORT(c_session, port) \
73 SCM_SETCDR (SCM_GNUTLS_SESSION_DATA (c_session), port)
75 #define SCM_GNUTLS_SESSION_TRANSPORT_IS_FD(c_session) \
76 scm_to_bool (SCM_CAR (SCM_GNUTLS_SESSION_DATA (c_session)))
77 #define SCM_GNUTLS_SESSION_RECORD_PORT(c_session) \
78 SCM_CDR (SCM_GNUTLS_SESSION_DATA (c_session))
84 /* Mark the data associated with SESSION. */
85 SCM_SMOB_MARK (scm_tc16_gnutls_session, mark_session, session)
87 gnutls_session_t c_session;
89 c_session = scm_to_gnutls_session (session, 1, "mark_session");
91 return (SCM_GNUTLS_SESSION_DATA (c_session));
94 SCM_DEFINE (scm_gnutls_version, "gnutls-version", 0, 0, 0,
96 "Return a string denoting the version number of the underlying "
97 "GnuTLS library, e.g., @code{\"1.7.2\"}.")
98 #define FUNC_NAME s_scm_gnutls_version
100 return (scm_from_locale_string (gnutls_check_version (NULL)));
105 SCM_DEFINE (scm_gnutls_make_session, "make-session", 1, 0, 0,
107 "Return a new session for connection end @var{end}, either "
108 "@code{connection-end/server} or @code{connection-end/client}.")
109 #define FUNC_NAME s_scm_gnutls_make_session
112 gnutls_session_t c_session;
113 gnutls_connection_end_t c_end;
116 c_end = scm_to_gnutls_connection_end (end, 1, FUNC_NAME);
118 session_data = SCM_GNUTLS_MAKE_SESSION_DATA ();
119 err = gnutls_init (&c_session, c_end);
121 if (EXPECT_FALSE (err))
122 scm_gnutls_error (err, FUNC_NAME);
124 SCM_GNUTLS_SET_SESSION_DATA (c_session, session_data);
126 return (scm_from_gnutls_session (c_session));
131 SCM_DEFINE (scm_gnutls_bye, "bye", 2, 0, 0,
132 (SCM session, SCM how),
133 "Close @var{session} according to @var{how}.")
134 #define FUNC_NAME s_scm_gnutls_bye
137 gnutls_session_t c_session;
138 gnutls_close_request_t c_how;
140 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
141 c_how = scm_to_gnutls_close_request (how, 2, FUNC_NAME);
143 err = gnutls_bye (c_session, c_how);
144 if (EXPECT_FALSE (err))
145 scm_gnutls_error (err, FUNC_NAME);
147 return SCM_UNSPECIFIED;
152 SCM_DEFINE (scm_gnutls_handshake, "handshake", 1, 0, 0,
153 (SCM session), "Perform a handshake for @var{session}.")
154 #define FUNC_NAME s_scm_gnutls_handshake
157 gnutls_session_t c_session;
159 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
161 err = gnutls_handshake (c_session);
162 if (EXPECT_FALSE (err))
163 scm_gnutls_error (err, FUNC_NAME);
165 return SCM_UNSPECIFIED;
170 SCM_DEFINE (scm_gnutls_rehandshake, "rehandshake", 1, 0, 0,
171 (SCM session), "Perform a re-handshaking for @var{session}.")
172 #define FUNC_NAME s_scm_gnutls_rehandshake
175 gnutls_session_t c_session;
177 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
179 err = gnutls_rehandshake (c_session);
180 if (EXPECT_FALSE (err))
181 scm_gnutls_error (err, FUNC_NAME);
183 return SCM_UNSPECIFIED;
188 SCM_DEFINE (scm_gnutls_alert_get, "alert-get", 1, 0, 0,
189 (SCM session), "Get an aleter from @var{session}.")
190 #define FUNC_NAME s_scm_gnutls_alert_get
192 gnutls_session_t c_session;
193 gnutls_alert_description_t c_alert;
195 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
197 c_alert = gnutls_alert_get (c_session);
199 return (scm_from_gnutls_alert_description (c_alert));
204 SCM_DEFINE (scm_gnutls_alert_send, "alert-send", 3, 0, 0,
205 (SCM session, SCM level, SCM alert),
206 "Send @var{alert} via @var{session}.")
207 #define FUNC_NAME s_scm_gnutls_alert_send
210 gnutls_session_t c_session;
211 gnutls_alert_level_t c_level;
212 gnutls_alert_description_t c_alert;
214 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
215 c_level = scm_to_gnutls_alert_level (level, 2, FUNC_NAME);
216 c_alert = scm_to_gnutls_alert_description (alert, 3, FUNC_NAME);
218 err = gnutls_alert_send (c_session, c_level, c_alert);
219 if (EXPECT_FALSE (err))
220 scm_gnutls_error (err, FUNC_NAME);
222 return SCM_UNSPECIFIED;
227 /* FIXME: Omitting `alert-send-appropriate'. */
230 /* Session accessors. */
232 SCM_DEFINE (scm_gnutls_session_cipher, "session-cipher", 1, 0, 0,
233 (SCM session), "Return @var{session}'s cipher.")
234 #define FUNC_NAME s_scm_gnutls_session_cipher
236 gnutls_session_t c_session;
237 gnutls_cipher_algorithm_t c_cipher;
239 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
241 c_cipher = gnutls_cipher_get (c_session);
243 return (scm_from_gnutls_cipher (c_cipher));
248 SCM_DEFINE (scm_gnutls_session_kx, "session-kx", 1, 0, 0,
249 (SCM session), "Return @var{session}'s kx.")
250 #define FUNC_NAME s_scm_gnutls_session_kx
252 gnutls_session_t c_session;
253 gnutls_kx_algorithm_t c_kx;
255 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
257 c_kx = gnutls_kx_get (c_session);
259 return (scm_from_gnutls_kx (c_kx));
264 SCM_DEFINE (scm_gnutls_session_mac, "session-mac", 1, 0, 0,
265 (SCM session), "Return @var{session}'s MAC.")
266 #define FUNC_NAME s_scm_gnutls_session_mac
268 gnutls_session_t c_session;
269 gnutls_mac_algorithm_t c_mac;
271 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
273 c_mac = gnutls_mac_get (c_session);
275 return (scm_from_gnutls_mac (c_mac));
280 SCM_DEFINE (scm_gnutls_session_compression_method,
281 "session-compression-method", 1, 0, 0,
282 (SCM session), "Return @var{session}'s compression method.")
283 #define FUNC_NAME s_scm_gnutls_session_compression_method
285 gnutls_session_t c_session;
286 gnutls_compression_method_t c_comp;
288 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
290 c_comp = gnutls_compression_get (c_session);
292 return (scm_from_gnutls_compression_method (c_comp));
297 SCM_DEFINE (scm_gnutls_session_certificate_type,
298 "session-certificate-type", 1, 0, 0,
299 (SCM session), "Return @var{session}'s certificate type.")
300 #define FUNC_NAME s_scm_gnutls_session_certificate_type
302 gnutls_session_t c_session;
303 gnutls_certificate_type_t c_cert;
305 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
307 c_cert = gnutls_certificate_type_get (c_session);
309 return (scm_from_gnutls_certificate_type (c_cert));
314 SCM_DEFINE (scm_gnutls_session_protocol, "session-protocol", 1, 0, 0,
315 (SCM session), "Return the protocol used by @var{session}.")
316 #define FUNC_NAME s_scm_gnutls_session_protocol
318 gnutls_session_t c_session;
319 gnutls_protocol_t c_protocol;
321 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
323 c_protocol = gnutls_protocol_get_version (c_session);
325 return (scm_from_gnutls_protocol (c_protocol));
330 SCM_DEFINE (scm_gnutls_session_authentication_type,
331 "session-authentication-type",
334 "Return the authentication type (a @code{credential-type} value) "
335 "used by @var{session}.")
336 #define FUNC_NAME s_scm_gnutls_session_authentication_type
338 gnutls_session_t c_session;
339 gnutls_credentials_type_t c_auth;
341 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
343 c_auth = gnutls_auth_get_type (c_session);
345 return (scm_from_gnutls_credentials (c_auth));
350 SCM_DEFINE (scm_gnutls_session_server_authentication_type,
351 "session-server-authentication-type",
354 "Return the server authentication type (a "
355 "@code{credential-type} value) used in @var{session}.")
356 #define FUNC_NAME s_scm_gnutls_session_server_authentication_type
358 gnutls_session_t c_session;
359 gnutls_credentials_type_t c_auth;
361 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
363 c_auth = gnutls_auth_server_get_type (c_session);
365 return (scm_from_gnutls_credentials (c_auth));
370 SCM_DEFINE (scm_gnutls_session_client_authentication_type,
371 "session-client-authentication-type",
374 "Return the client authentication type (a "
375 "@code{credential-type} value) used in @var{session}.")
376 #define FUNC_NAME s_scm_gnutls_session_client_authentication_type
378 gnutls_session_t c_session;
379 gnutls_credentials_type_t c_auth;
381 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
383 c_auth = gnutls_auth_client_get_type (c_session);
385 return (scm_from_gnutls_credentials (c_auth));
390 SCM_DEFINE (scm_gnutls_session_peer_certificate_chain,
391 "session-peer-certificate-chain",
394 "Return the a list of certificates in raw format (u8vectors) "
395 "where the first one is the peer's certificate. In the case "
396 "of OpenPGP, there is always exactly one certificate. In the "
397 "case of X.509, subsequent certificates indicate form a "
398 "certificate chain. Return the empty list if no certificate "
400 #define FUNC_NAME s_scm_gnutls_session_peer_certificate_chain
403 gnutls_session_t c_session;
404 const gnutls_datum_t *c_cert;
405 unsigned int c_list_size;
407 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
409 c_cert = gnutls_certificate_get_peers (c_session, &c_list_size);
411 if (EXPECT_FALSE (c_cert == NULL))
418 result = scm_make_list (scm_from_uint (c_list_size), SCM_UNSPECIFIED);
420 for (i = 0, pair = result; i < c_list_size; i++, pair = SCM_CDR (pair))
422 unsigned char *c_cert_copy;
424 c_cert_copy = (unsigned char *) malloc (c_cert[i].size);
425 if (EXPECT_FALSE (c_cert_copy == NULL))
426 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR, FUNC_NAME);
428 memcpy (c_cert_copy, c_cert[i].data, c_cert[i].size);
430 SCM_SETCAR (pair, scm_take_u8vector (c_cert_copy, c_cert[i].size));
439 SCM_DEFINE (scm_gnutls_session_our_certificate_chain,
440 "session-our-certificate-chain",
443 "Return our certificate chain for @var{session} (as sent to "
444 "the peer) in raw format (a u8vector). In the case of OpenPGP "
445 "there is exactly one certificate. Return the empty list "
446 "if no certificate was used.")
447 #define FUNC_NAME s_scm_gnutls_session_our_certificate_chain
450 gnutls_session_t c_session;
451 const gnutls_datum_t *c_cert;
452 unsigned char *c_cert_copy;
454 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
456 /* XXX: Currently, the C function actually returns only one certificate.
457 Future versions of the API may provide the full certificate chain, as
458 for `gnutls_certificate_get_peers ()'. */
459 c_cert = gnutls_certificate_get_ours (c_session);
461 if (EXPECT_FALSE (c_cert == NULL))
465 c_cert_copy = (unsigned char *) malloc (c_cert->size);
466 if (EXPECT_FALSE (c_cert_copy == NULL))
467 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR, FUNC_NAME);
469 memcpy (c_cert_copy, c_cert->data, c_cert->size);
471 result = scm_list_1 (scm_take_u8vector (c_cert_copy, c_cert->size));
479 SCM_DEFINE (scm_gnutls_set_server_session_certificate_request_x,
480 "set-server-session-certificate-request!",
482 (SCM session, SCM request),
483 "Tell how @var{session}, a server-side session, should deal "
484 "with certificate requests. @var{request} should be either "
485 "@code{certificate-request/request} or "
486 "@code{certificate-request/require}.")
487 #define FUNC_NAME s_scm_gnutls_set_server_session_certificate_request_x
489 gnutls_session_t c_session;
490 gnutls_certificate_status_t c_request;
492 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
493 c_request = scm_to_gnutls_certificate_request (request, 2, FUNC_NAME);
495 gnutls_certificate_server_set_request (c_session, c_request);
497 return SCM_UNSPECIFIED;
503 /* Choice of a protocol and cipher suite. */
505 #include "priorities.i.c"
507 SCM_DEFINE (scm_gnutls_set_default_priority_x,
508 "set-session-default-priority!", 1, 0, 0,
509 (SCM session), "Have @var{session} use the default priorities.")
510 #define FUNC_NAME s_scm_gnutls_set_default_priority_x
512 gnutls_session_t c_session;
514 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
515 gnutls_set_default_priority (c_session);
517 return SCM_UNSPECIFIED;
522 SCM_DEFINE (scm_gnutls_set_default_export_priority_x,
523 "set-session-default-export-priority!", 1, 0, 0,
525 "Have @var{session} use the default export priorities.")
526 #define FUNC_NAME s_scm_gnutls_set_default_export_priority_x
528 gnutls_session_t c_session;
530 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
531 gnutls_set_default_export_priority (c_session);
533 return SCM_UNSPECIFIED;
538 SCM_DEFINE (scm_gnutls_cipher_suite_to_string, "cipher-suite->string",
540 (SCM kx, SCM cipher, SCM mac),
541 "Return the name of the given cipher suite.")
542 #define FUNC_NAME s_scm_gnutls_cipher_suite_to_string
544 gnutls_kx_algorithm_t c_kx;
545 gnutls_cipher_algorithm_t c_cipher;
546 gnutls_mac_algorithm_t c_mac;
549 c_kx = scm_to_gnutls_kx (kx, 1, FUNC_NAME);
550 c_cipher = scm_to_gnutls_cipher (cipher, 2, FUNC_NAME);
551 c_mac = scm_to_gnutls_mac (mac, 3, FUNC_NAME);
553 c_name = gnutls_cipher_suite_get_name (c_kx, c_cipher, c_mac);
555 return (scm_from_locale_string (c_name));
560 SCM_DEFINE (scm_gnutls_set_session_credentials_x, "set-session-credentials!",
562 (SCM session, SCM cred),
563 "Use @var{cred} as @var{session}'s credentials.")
564 #define FUNC_NAME s_scm_gnutls_set_session_credentials_x
567 gnutls_session_t c_session;
569 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
571 if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_certificate_credentials, cred))
573 gnutls_certificate_credentials_t c_cred;
575 c_cred = scm_to_gnutls_certificate_credentials (cred, 2, FUNC_NAME);
577 gnutls_credentials_set (c_session, GNUTLS_CRD_CERTIFICATE, c_cred);
580 if (SCM_SMOB_PREDICATE
581 (scm_tc16_gnutls_anonymous_client_credentials, cred))
583 gnutls_anon_client_credentials_t c_cred;
585 c_cred = scm_to_gnutls_anonymous_client_credentials (cred, 2,
587 err = gnutls_credentials_set (c_session, GNUTLS_CRD_ANON, c_cred);
589 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_anonymous_server_credentials,
592 gnutls_anon_server_credentials_t c_cred;
594 c_cred = scm_to_gnutls_anonymous_server_credentials (cred, 2,
596 err = gnutls_credentials_set (c_session, GNUTLS_CRD_ANON, c_cred);
599 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_client_credentials, cred))
601 gnutls_srp_client_credentials_t c_cred;
603 c_cred = scm_to_gnutls_srp_client_credentials (cred, 2, FUNC_NAME);
604 err = gnutls_credentials_set (c_session, GNUTLS_CRD_SRP, c_cred);
606 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_server_credentials, cred))
608 gnutls_srp_server_credentials_t c_cred;
610 c_cred = scm_to_gnutls_srp_server_credentials (cred, 2, FUNC_NAME);
611 err = gnutls_credentials_set (c_session, GNUTLS_CRD_SRP, c_cred);
614 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_client_credentials, cred))
616 gnutls_psk_client_credentials_t c_cred;
618 c_cred = scm_to_gnutls_psk_client_credentials (cred, 2, FUNC_NAME);
619 err = gnutls_credentials_set (c_session, GNUTLS_CRD_PSK, c_cred);
621 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_server_credentials, cred))
623 gnutls_psk_server_credentials_t c_cred;
625 c_cred = scm_to_gnutls_psk_server_credentials (cred, 2, FUNC_NAME);
626 err = gnutls_credentials_set (c_session, GNUTLS_CRD_PSK, c_cred);
629 scm_wrong_type_arg (FUNC_NAME, 2, cred);
631 if (EXPECT_FALSE (err))
632 scm_gnutls_error (err, FUNC_NAME);
634 return SCM_UNSPECIFIED;
642 SCM_DEFINE (scm_gnutls_record_send, "record-send", 2, 0, 0,
643 (SCM session, SCM array),
644 "Send the record constituted by @var{array} through "
646 #define FUNC_NAME s_scm_gnutls_record_send
650 gnutls_session_t c_session;
651 scm_t_array_handle c_handle;
655 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
656 SCM_VALIDATE_ARRAY (2, array);
658 c_array = scm_gnutls_get_array (array, &c_handle, &c_len, FUNC_NAME);
660 c_result = gnutls_record_send (c_session, c_array, c_len);
662 scm_gnutls_release_array (&c_handle);
664 if (EXPECT_TRUE (c_result >= 0))
665 result = scm_from_ssize_t (c_result);
667 scm_gnutls_error (c_result, FUNC_NAME);
674 SCM_DEFINE (scm_gnutls_record_receive_x, "record-receive!", 2, 0, 0,
675 (SCM session, SCM array),
676 "Receive data from @var{session} into @var{array}, a uniform "
677 "homogeneous array. Return the number of bytes actually "
679 #define FUNC_NAME s_scm_gnutls_record_receive_x
683 gnutls_session_t c_session;
684 scm_t_array_handle c_handle;
688 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
689 SCM_VALIDATE_ARRAY (2, array);
691 c_array = scm_gnutls_get_writable_array (array, &c_handle, &c_len,
694 c_result = gnutls_record_recv (c_session, c_array, c_len);
696 scm_gnutls_release_array (&c_handle);
698 if (EXPECT_TRUE (c_result >= 0))
699 result = scm_from_ssize_t (c_result);
701 scm_gnutls_error (c_result, FUNC_NAME);
709 /* The session record port type. */
710 static scm_t_bits session_record_port_type;
712 /* Return the session associated with PORT. */
713 #define SCM_GNUTLS_SESSION_RECORD_PORT_SESSION(_port) \
714 (SCM_PACK (SCM_STREAM (_port)))
716 /* Size of a session port's input buffer. */
717 #define SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE 4096
719 /* Hint for the `scm_gc_' functions. */
720 static const char session_record_port_gc_hint[] =
721 "gnutls-session-record-port";
724 #if SCM_MAJOR_VERSION == 1 && SCM_MINOR_VERSION <= 8
726 /* Mark the session associated with PORT. */
728 mark_session_record_port (SCM port)
730 return (SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port));
734 free_session_record_port (SCM port)
735 #define FUNC_NAME "free_session_record_port"
740 session = SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port);
742 /* SESSION _can_ be invalid at this point: it can be freed in the same GC
743 cycle as PORT, just before PORT. Thus, we need to check whether SESSION
744 still points to a session SMOB. */
745 if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_session, session))
747 /* SESSION is still valid. Disassociate PORT from SESSION. */
748 gnutls_session_t c_session;
750 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
751 SCM_GNUTLS_SET_SESSION_RECORD_PORT (c_session, SCM_BOOL_F);
754 /* Free the input buffer of PORT. */
755 c_port = SCM_PTAB_ENTRY (port);
756 scm_gc_free (c_port->read_buf, c_port->read_buf_size,
757 session_record_port_gc_hint);
764 #endif /* SCM_MAJOR_VERSION == 1 && SCM_MINOR_VERSION <= 8 */
767 /* Data passed to `do_fill_port ()'. */
771 gnutls_session_t c_session;
774 /* Actually fill a session record port (see below). */
776 do_fill_port (void *data)
781 const fill_port_data_t *args = (fill_port_data_t *) data;
783 c_port = args->c_port;
784 result = gnutls_record_recv (args->c_session,
785 c_port->read_buf, c_port->read_buf_size);
786 if (EXPECT_TRUE (result > 0))
788 c_port->read_pos = c_port->read_buf;
789 c_port->read_end = c_port->read_buf + result;
790 chr = (int) *c_port->read_buf;
792 else if (result == 0)
795 scm_gnutls_error (result, "fill_session_record_port_input");
797 return ((void *) (uintptr_t) chr);
800 /* Fill in the input buffer of PORT. */
802 fill_session_record_port_input (SCM port)
803 #define FUNC_NAME "fill_session_record_port_input"
806 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
808 if (c_port->read_pos >= c_port->read_end)
811 fill_port_data_t c_args;
812 gnutls_session_t c_session;
814 session = SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port);
815 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
817 c_args.c_session = c_session;
818 c_args.c_port = c_port;
820 if (SCM_GNUTLS_SESSION_TRANSPORT_IS_FD (c_session))
821 /* SESSION's underlying transport is a raw file descriptor, so we
822 must leave "Guile mode" to allow the GC to run. */
823 chr = (intptr_t) scm_without_guile (do_fill_port, &c_args);
825 /* SESSION's underlying transport is a port, so don't leave "Guile
827 chr = (intptr_t) do_fill_port (&c_args);
830 chr = (int) *c_port->read_pos;
837 /* Write SIZE octets from DATA to PORT. */
839 write_to_session_record_port (SCM port, const void *data, size_t size)
840 #define FUNC_NAME "write_to_session_record_port"
843 gnutls_session_t c_session;
847 session = SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port);
848 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
850 while (c_sent < size)
852 c_result = gnutls_record_send (c_session, (char *) data + c_sent,
854 if (EXPECT_FALSE (c_result < 0))
855 scm_gnutls_error (c_result, FUNC_NAME);
863 /* Return a new session port for SESSION. */
865 make_session_record_port (SCM session)
869 unsigned char *c_port_buf;
870 const unsigned long mode_bits = SCM_OPN | SCM_RDNG | SCM_WRTNG;
872 c_port_buf = (unsigned char *)
873 #ifdef HAVE_SCM_GC_MALLOC_POINTERLESS
874 scm_gc_malloc_pointerless
878 (SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE, session_record_port_gc_hint);
880 /* Create a new port. */
881 port = scm_new_port_table_entry (session_record_port_type);
882 c_port = SCM_PTAB_ENTRY (port);
884 /* Mark PORT as open, readable and writable (hmm, how elegant...). */
885 SCM_SET_CELL_TYPE (port, session_record_port_type | mode_bits);
887 /* Associate it with SESSION. */
888 SCM_SETSTREAM (port, SCM_UNPACK (session));
890 c_port->read_pos = c_port->read_end = c_port->read_buf = c_port_buf;
891 c_port->read_buf_size = SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE;
893 c_port->write_buf = c_port->write_pos = &c_port->shortbuf;
894 c_port->write_buf_size = 1;
899 SCM_DEFINE (scm_gnutls_session_record_port, "session-record-port", 1, 0, 0,
901 "Return a read-write port that may be used to communicate over "
902 "@var{session}. All invocations of @code{session-port} on a "
903 "given session return the same object (in the sense of "
905 #define FUNC_NAME s_scm_gnutls_session_record_port
908 gnutls_session_t c_session;
910 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
911 port = SCM_GNUTLS_SESSION_RECORD_PORT (c_session);
913 if (!SCM_PORTP (port))
915 /* Lazily create a new session port. */
916 port = make_session_record_port (session);
917 SCM_GNUTLS_SET_SESSION_RECORD_PORT (c_session, port);
925 /* Create the session port type. */
927 scm_init_gnutls_session_record_port_type (void)
929 session_record_port_type =
930 scm_make_port_type ("gnutls-session-port",
931 fill_session_record_port_input,
932 write_to_session_record_port);
934 /* Guile >= 1.9.3 doesn't need a custom mark procedure, and doesn't need a
935 finalizer (since memory associated with the port is automatically
937 #if SCM_MAJOR_VERSION == 1 && SCM_MINOR_VERSION <= 8
938 scm_set_port_mark (session_record_port_type, mark_session_record_port);
939 scm_set_port_free (session_record_port_type, free_session_record_port);
946 SCM_DEFINE (scm_gnutls_set_session_transport_fd_x,
947 "set-session-transport-fd!", 2, 0, 0, (SCM session, SCM fd),
948 "Use file descriptor @var{fd} as the underlying transport for "
950 #define FUNC_NAME s_scm_gnutls_set_session_transport_fd_x
952 gnutls_session_t c_session;
955 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
956 c_fd = (int) scm_to_uint (fd);
958 gnutls_transport_set_ptr (c_session,
959 (gnutls_transport_ptr_t) (intptr_t) c_fd);
961 SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD (c_session, 1);
963 return SCM_UNSPECIFIED;
968 /* Pull SIZE octets from TRANSPORT (a Scheme port) into DATA. */
970 pull_from_port (gnutls_transport_ptr_t transport, void *data, size_t size)
975 port = SCM_PACK ((scm_t_bits) transport);
977 result = scm_c_read (port, data, size);
979 return ((ssize_t) result);
982 /* Write SIZE octets from DATA to TRANSPORT (a Scheme port). */
984 push_to_port (gnutls_transport_ptr_t transport, const void *data, size_t size)
988 port = SCM_PACK ((scm_t_bits) transport);
990 scm_c_write (port, data, size);
992 /* All we can do is assume that all SIZE octets were written. */
996 SCM_DEFINE (scm_gnutls_set_session_transport_port_x,
997 "set-session-transport-port!",
999 (SCM session, SCM port),
1000 "Use @var{port} as the input/output port for @var{session}.")
1001 #define FUNC_NAME s_scm_gnutls_set_session_transport_port_x
1003 gnutls_session_t c_session;
1005 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
1006 SCM_VALIDATE_PORT (2, port);
1008 /* Note: We do not attempt to optimize the case where PORT is a file port
1009 (i.e., over a file descriptor), because of port buffering issues. Users
1010 are expected to explicitly use `set-session-transport-fd!' and `fileno'
1011 when they wish to do it. */
1013 gnutls_transport_set_ptr (c_session,
1014 (gnutls_transport_ptr_t) SCM_UNPACK (port));
1015 gnutls_transport_set_push_function (c_session, push_to_port);
1016 gnutls_transport_set_pull_function (c_session, pull_from_port);
1018 SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD (c_session, 0);
1020 return SCM_UNSPECIFIED;
1026 /* Diffie-Hellman. */
1028 typedef int (*pkcs_export_function_t) (void *, gnutls_x509_crt_fmt_t,
1029 unsigned char *, size_t *);
1031 /* Hint for the `scm_gc' functions. */
1032 static const char pkcs_export_gc_hint[] = "gnutls-pkcs-export";
1035 /* Export DH/RSA parameters PARAMS through EXPORT, using format FORMAT.
1036 Return a `u8vector'. */
1038 pkcs_export_parameters (pkcs_export_function_t export,
1039 void *params, gnutls_x509_crt_fmt_t format,
1040 const char *func_name)
1041 #define FUNC_NAME func_name
1044 unsigned char *output;
1045 size_t output_len, output_total_len = 4096;
1047 output = (unsigned char *) scm_gc_malloc (output_total_len,
1048 pkcs_export_gc_hint);
1051 output_len = output_total_len;
1052 err = export (params, format, output, &output_len);
1054 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1056 output = scm_gc_realloc (output, output_total_len,
1057 output_total_len * 2, pkcs_export_gc_hint);
1058 output_total_len *= 2;
1061 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER);
1063 if (EXPECT_FALSE (err))
1065 scm_gc_free (output, output_total_len, pkcs_export_gc_hint);
1066 scm_gnutls_error (err, FUNC_NAME);
1069 if (output_len != output_total_len)
1070 /* Shrink the output buffer. */
1071 output = scm_gc_realloc (output, output_total_len,
1072 output_len, pkcs_export_gc_hint);
1074 return (scm_take_u8vector (output, output_len));
1080 SCM_DEFINE (scm_gnutls_make_dh_parameters, "make-dh-parameters", 1, 0, 0,
1081 (SCM bits), "Return new Diffie-Hellman parameters.")
1082 #define FUNC_NAME s_scm_gnutls_make_dh_parameters
1086 gnutls_dh_params_t c_dh_params;
1088 c_bits = scm_to_uint (bits);
1090 err = gnutls_dh_params_init (&c_dh_params);
1091 if (EXPECT_FALSE (err))
1092 scm_gnutls_error (err, FUNC_NAME);
1094 err = gnutls_dh_params_generate2 (c_dh_params, c_bits);
1095 if (EXPECT_FALSE (err))
1097 gnutls_dh_params_deinit (c_dh_params);
1098 scm_gnutls_error (err, FUNC_NAME);
1101 return (scm_from_gnutls_dh_parameters (c_dh_params));
1106 SCM_DEFINE (scm_gnutls_pkcs3_import_dh_parameters,
1107 "pkcs3-import-dh-parameters",
1109 (SCM array, SCM format),
1110 "Import Diffie-Hellman parameters in PKCS3 format (further "
1111 "specified by @var{format}, an @code{x509-certificate-format} "
1112 "value) from @var{array} (a homogeneous array) and return a "
1113 "new @code{dh-params} object.")
1114 #define FUNC_NAME s_scm_gnutls_pkcs3_import_dh_parameters
1117 gnutls_x509_crt_fmt_t c_format;
1118 gnutls_dh_params_t c_dh_params;
1119 scm_t_array_handle c_handle;
1120 const char *c_array;
1122 gnutls_datum_t c_datum;
1124 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
1126 c_array = scm_gnutls_get_array (array, &c_handle, &c_len, FUNC_NAME);
1127 c_datum.data = (unsigned char *) c_array;
1128 c_datum.size = c_len;
1130 err = gnutls_dh_params_init (&c_dh_params);
1131 if (EXPECT_FALSE (err))
1133 scm_gnutls_release_array (&c_handle);
1134 scm_gnutls_error (err, FUNC_NAME);
1137 err = gnutls_dh_params_import_pkcs3 (c_dh_params, &c_datum, c_format);
1138 scm_gnutls_release_array (&c_handle);
1140 if (EXPECT_FALSE (err))
1142 gnutls_dh_params_deinit (c_dh_params);
1143 scm_gnutls_error (err, FUNC_NAME);
1146 return (scm_from_gnutls_dh_parameters (c_dh_params));
1151 SCM_DEFINE (scm_gnutls_pkcs3_export_dh_parameters,
1152 "pkcs3-export-dh-parameters",
1154 (SCM dh_params, SCM format),
1155 "Export Diffie-Hellman parameters @var{dh_params} in PKCS3 "
1156 "format according for @var{format} (an "
1157 "@code{x509-certificate-format} value). Return a "
1158 "@code{u8vector} containing the result.")
1159 #define FUNC_NAME s_scm_gnutls_pkcs3_export_dh_parameters
1162 gnutls_dh_params_t c_dh_params;
1163 gnutls_x509_crt_fmt_t c_format;
1165 c_dh_params = scm_to_gnutls_dh_parameters (dh_params, 1, FUNC_NAME);
1166 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
1168 result = pkcs_export_parameters ((pkcs_export_function_t)
1169 gnutls_dh_params_export_pkcs3,
1170 (void *) c_dh_params, c_format, FUNC_NAME);
1177 SCM_DEFINE (scm_gnutls_set_session_dh_prime_bits_x,
1178 "set-session-dh-prime-bits!", 2, 0, 0,
1179 (SCM session, SCM bits),
1180 "Use @var{bits} DH prime bits for @var{session}.")
1181 #define FUNC_NAME s_scm_gnutls_set_session_dh_prime_bits_x
1183 unsigned int c_bits;
1184 gnutls_session_t c_session;
1186 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
1187 c_bits = scm_to_uint (bits);
1189 gnutls_dh_set_prime_bits (c_session, c_bits);
1191 return SCM_UNSPECIFIED;
1197 /* Anonymous credentials. */
1199 SCM_DEFINE (scm_gnutls_make_anon_server_credentials,
1200 "make-anonymous-server-credentials",
1201 0, 0, 0, (void), "Return anonymous server credentials.")
1202 #define FUNC_NAME s_scm_gnutls_make_anon_server_credentials
1205 gnutls_anon_server_credentials_t c_cred;
1207 err = gnutls_anon_allocate_server_credentials (&c_cred);
1209 if (EXPECT_FALSE (err))
1210 scm_gnutls_error (err, FUNC_NAME);
1212 return (scm_from_gnutls_anonymous_server_credentials (c_cred));
1217 SCM_DEFINE (scm_gnutls_make_anon_client_credentials,
1218 "make-anonymous-client-credentials",
1219 0, 0, 0, (void), "Return anonymous client credentials.")
1220 #define FUNC_NAME s_scm_gnutls_make_anon_client_credentials
1223 gnutls_anon_client_credentials_t c_cred;
1225 err = gnutls_anon_allocate_client_credentials (&c_cred);
1227 if (EXPECT_FALSE (err))
1228 scm_gnutls_error (err, FUNC_NAME);
1230 return (scm_from_gnutls_anonymous_client_credentials (c_cred));
1235 SCM_DEFINE (scm_gnutls_set_anonymous_server_dh_parameters_x,
1236 "set-anonymous-server-dh-parameters!", 2, 0, 0,
1237 (SCM cred, SCM dh_params),
1238 "Set the Diffie-Hellman parameters of anonymous server "
1239 "credentials @var{cred}.")
1240 #define FUNC_NAME s_scm_gnutls_set_anonymous_server_dh_parameters_x
1242 gnutls_dh_params_t c_dh_params;
1243 gnutls_anon_server_credentials_t c_cred;
1245 c_cred = scm_to_gnutls_anonymous_server_credentials (cred, 1, FUNC_NAME);
1246 c_dh_params = scm_to_gnutls_dh_parameters (dh_params, 2, FUNC_NAME);
1248 gnutls_anon_set_server_dh_params (c_cred, c_dh_params);
1250 return SCM_UNSPECIFIED;
1256 /* RSA parameters. */
1258 SCM_DEFINE (scm_gnutls_make_rsa_parameters, "make-rsa-parameters", 1, 0, 0,
1259 (SCM bits), "Return new RSA parameters.")
1260 #define FUNC_NAME s_scm_gnutls_make_rsa_parameters
1264 gnutls_rsa_params_t c_rsa_params;
1266 c_bits = scm_to_uint (bits);
1268 err = gnutls_rsa_params_init (&c_rsa_params);
1269 if (EXPECT_FALSE (err))
1270 scm_gnutls_error (err, FUNC_NAME);
1272 err = gnutls_rsa_params_generate2 (c_rsa_params, c_bits);
1273 if (EXPECT_FALSE (err))
1275 gnutls_rsa_params_deinit (c_rsa_params);
1276 scm_gnutls_error (err, FUNC_NAME);
1279 return (scm_from_gnutls_rsa_parameters (c_rsa_params));
1284 SCM_DEFINE (scm_gnutls_pkcs1_import_rsa_parameters,
1285 "pkcs1-import-rsa-parameters",
1287 (SCM array, SCM format),
1288 "Import Diffie-Hellman parameters in PKCS1 format (further "
1289 "specified by @var{format}, an @code{x509-certificate-format} "
1290 "value) from @var{array} (a homogeneous array) and return a "
1291 "new @code{rsa-params} object.")
1292 #define FUNC_NAME s_scm_gnutls_pkcs1_import_rsa_parameters
1295 gnutls_x509_crt_fmt_t c_format;
1296 gnutls_rsa_params_t c_rsa_params;
1297 scm_t_array_handle c_handle;
1298 const char *c_array;
1300 gnutls_datum_t c_datum;
1302 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
1304 c_array = scm_gnutls_get_array (array, &c_handle, &c_len, FUNC_NAME);
1305 c_datum.data = (unsigned char *) c_array;
1306 c_datum.size = c_len;
1308 err = gnutls_rsa_params_init (&c_rsa_params);
1309 if (EXPECT_FALSE (err))
1311 scm_gnutls_release_array (&c_handle);
1312 scm_gnutls_error (err, FUNC_NAME);
1315 err = gnutls_rsa_params_import_pkcs1 (c_rsa_params, &c_datum, c_format);
1316 scm_gnutls_release_array (&c_handle);
1318 if (EXPECT_FALSE (err))
1320 gnutls_rsa_params_deinit (c_rsa_params);
1321 scm_gnutls_error (err, FUNC_NAME);
1324 return (scm_from_gnutls_rsa_parameters (c_rsa_params));
1329 SCM_DEFINE (scm_gnutls_pkcs1_export_rsa_parameters,
1330 "pkcs1-export-rsa-parameters",
1332 (SCM rsa_params, SCM format),
1333 "Export Diffie-Hellman parameters @var{rsa_params} in PKCS1 "
1334 "format according for @var{format} (an "
1335 "@code{x509-certificate-format} value). Return a "
1336 "@code{u8vector} containing the result.")
1337 #define FUNC_NAME s_scm_gnutls_pkcs1_export_rsa_parameters
1340 gnutls_rsa_params_t c_rsa_params;
1341 gnutls_x509_crt_fmt_t c_format;
1343 c_rsa_params = scm_to_gnutls_rsa_parameters (rsa_params, 1, FUNC_NAME);
1344 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
1346 result = pkcs_export_parameters ((pkcs_export_function_t)
1347 gnutls_rsa_params_export_pkcs1,
1348 (void *) c_rsa_params,
1349 c_format, FUNC_NAME);
1357 /* Certificate credentials. */
1360 int (*certificate_set_file_function_t) (gnutls_certificate_credentials_t,
1362 gnutls_x509_crt_fmt_t);
1365 int (*certificate_set_data_function_t) (gnutls_certificate_credentials_t,
1366 const gnutls_datum_t *,
1367 gnutls_x509_crt_fmt_t);
1369 /* Helper function to implement the `set-file!' functions. */
1371 set_certificate_file (certificate_set_file_function_t set_file,
1372 SCM cred, SCM file, SCM format, const char *func_name)
1373 #define FUNC_NAME func_name
1379 gnutls_certificate_credentials_t c_cred;
1380 gnutls_x509_crt_fmt_t c_format;
1382 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1383 SCM_VALIDATE_STRING (2, file);
1384 c_format = scm_to_gnutls_x509_certificate_format (format, 3, FUNC_NAME);
1386 c_file_len = scm_c_string_length (file);
1387 c_file = (char *) alloca (c_file_len + 1);
1389 (void) scm_to_locale_stringbuf (file, c_file, c_file_len + 1);
1390 c_file[c_file_len] = '\0';
1392 err = set_file (c_cred, c_file, c_format);
1393 if (EXPECT_FALSE (err < 0))
1394 scm_gnutls_error (err, FUNC_NAME);
1396 /* Return the number of certificates processed. */
1397 return ((unsigned int) err);
1402 /* Helper function implementing the `set-data!' functions. */
1403 static inline unsigned int
1404 set_certificate_data (certificate_set_data_function_t set_data,
1405 SCM cred, SCM data, SCM format, const char *func_name)
1406 #define FUNC_NAME func_name
1409 gnutls_certificate_credentials_t c_cred;
1410 gnutls_x509_crt_fmt_t c_format;
1411 gnutls_datum_t c_datum;
1412 scm_t_array_handle c_handle;
1416 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1417 SCM_VALIDATE_ARRAY (2, data);
1418 c_format = scm_to_gnutls_x509_certificate_format (format, 3, FUNC_NAME);
1420 c_data = scm_gnutls_get_array (data, &c_handle, &c_len, FUNC_NAME);
1421 c_datum.data = (unsigned char *) c_data;
1422 c_datum.size = c_len;
1424 err = set_data (c_cred, &c_datum, c_format);
1425 scm_gnutls_release_array (&c_handle);
1427 if (EXPECT_FALSE (err < 0))
1428 scm_gnutls_error (err, FUNC_NAME);
1430 /* Return the number of certificates processed. */
1431 return ((unsigned int) err);
1437 SCM_DEFINE (scm_gnutls_make_certificate_credentials,
1438 "make-certificate-credentials",
1441 "Return new certificate credentials (i.e., for use with "
1442 "either X.509 or OpenPGP certificates.")
1443 #define FUNC_NAME s_scm_gnutls_make_certificate_credentials
1446 gnutls_certificate_credentials_t c_cred;
1448 err = gnutls_certificate_allocate_credentials (&c_cred);
1450 scm_gnutls_error (err, FUNC_NAME);
1452 return (scm_from_gnutls_certificate_credentials (c_cred));
1457 SCM_DEFINE (scm_gnutls_set_certificate_credentials_dh_params_x,
1458 "set-certificate-credentials-dh-parameters!",
1460 (SCM cred, SCM dh_params),
1461 "Use Diffie-Hellman parameters @var{dh_params} for "
1462 "certificate credentials @var{cred}.")
1463 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_dh_params_x
1465 gnutls_dh_params_t c_dh_params;
1466 gnutls_certificate_credentials_t c_cred;
1468 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1469 c_dh_params = scm_to_gnutls_dh_parameters (dh_params, 2, FUNC_NAME);
1471 gnutls_certificate_set_dh_params (c_cred, c_dh_params);
1473 return SCM_UNSPECIFIED;
1478 SCM_DEFINE (scm_gnutls_set_certificate_credentials_rsa_export_params_x,
1479 "set-certificate-credentials-rsa-export-parameters!",
1481 (SCM cred, SCM rsa_params),
1482 "Use RSA parameters @var{rsa_params} for certificate "
1483 "credentials @var{cred}.")
1484 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_rsa_export_params_x
1486 gnutls_rsa_params_t c_rsa_params;
1487 gnutls_certificate_credentials_t c_cred;
1489 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1490 c_rsa_params = scm_to_gnutls_rsa_parameters (rsa_params, 2, FUNC_NAME);
1492 gnutls_certificate_set_rsa_export_params (c_cred, c_rsa_params);
1494 return SCM_UNSPECIFIED;
1499 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_files_x,
1500 "set-certificate-credentials-x509-key-files!",
1502 (SCM cred, SCM cert_file, SCM key_file, SCM format),
1503 "Use @var{file} as the password file for PSK server "
1504 "credentials @var{cred}.")
1505 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_key_files_x
1508 gnutls_certificate_credentials_t c_cred;
1509 gnutls_x509_crt_fmt_t c_format;
1510 char *c_cert_file, *c_key_file;
1511 size_t c_cert_file_len, c_key_file_len;
1513 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1514 SCM_VALIDATE_STRING (2, cert_file);
1515 SCM_VALIDATE_STRING (3, key_file);
1516 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
1518 c_cert_file_len = scm_c_string_length (cert_file);
1519 c_cert_file = (char *) alloca (c_cert_file_len + 1);
1521 c_key_file_len = scm_c_string_length (key_file);
1522 c_key_file = (char *) alloca (c_key_file_len + 1);
1524 (void) scm_to_locale_stringbuf (cert_file, c_cert_file,
1525 c_cert_file_len + 1);
1526 c_cert_file[c_cert_file_len] = '\0';
1527 (void) scm_to_locale_stringbuf (key_file, c_key_file, c_key_file_len + 1);
1528 c_key_file[c_key_file_len] = '\0';
1530 err = gnutls_certificate_set_x509_key_file (c_cred, c_cert_file, c_key_file,
1532 if (EXPECT_FALSE (err))
1533 scm_gnutls_error (err, FUNC_NAME);
1535 return SCM_UNSPECIFIED;
1540 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_file_x,
1541 "set-certificate-credentials-x509-trust-file!",
1543 (SCM cred, SCM file, SCM format),
1544 "Use @var{file} as the X.509 trust file for certificate "
1545 "credentials @var{cred}. On success, return the number of "
1546 "certificates processed.")
1547 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_trust_file_x
1551 count = set_certificate_file (gnutls_certificate_set_x509_trust_file,
1552 cred, file, format, FUNC_NAME);
1554 return scm_from_uint (count);
1559 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_file_x,
1560 "set-certificate-credentials-x509-crl-file!",
1562 (SCM cred, SCM file, SCM format),
1563 "Use @var{file} as the X.509 CRL (certificate revocation list) "
1564 "file for certificate credentials @var{cred}. On success, "
1565 "return the number of CRLs processed.")
1566 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_crl_file_x
1570 count = set_certificate_file (gnutls_certificate_set_x509_crl_file,
1571 cred, file, format, FUNC_NAME);
1573 return scm_from_uint (count);
1578 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_data_x,
1579 "set-certificate-credentials-x509-trust-data!",
1581 (SCM cred, SCM data, SCM format),
1582 "Use @var{data} (a uniform array) as the X.509 trust "
1583 "database for @var{cred}. On success, return the number "
1584 "of certificates processed.")
1585 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_trust_data_x
1589 count = set_certificate_data (gnutls_certificate_set_x509_trust_mem,
1590 cred, data, format, FUNC_NAME);
1592 return scm_from_uint (count);
1597 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_data_x,
1598 "set-certificate-credentials-x509-crl-data!",
1600 (SCM cred, SCM data, SCM format),
1601 "Use @var{data} (a uniform array) as the X.509 CRL "
1602 "(certificate revocation list) database for @var{cred}. "
1603 "On success, return the number of CRLs processed.")
1604 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_crl_data_x
1608 count = set_certificate_data (gnutls_certificate_set_x509_crl_mem,
1609 cred, data, format, FUNC_NAME);
1611 return scm_from_uint (count);
1616 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_data_x,
1617 "set-certificate-credentials-x509-key-data!",
1619 (SCM cred, SCM cert, SCM key, SCM format),
1620 "Use X.509 certificate @var{cert} and private key @var{key}, "
1621 "both uniform arrays containing the X.509 certificate and key "
1622 "in format @var{format}, for certificate credentials "
1624 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_key_data_x
1627 gnutls_x509_crt_fmt_t c_format;
1628 gnutls_certificate_credentials_t c_cred;
1629 gnutls_datum_t c_cert_d, c_key_d;
1630 scm_t_array_handle c_cert_handle, c_key_handle;
1631 const char *c_cert, *c_key;
1632 size_t c_cert_len, c_key_len;
1634 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1635 c_format = scm_to_gnutls_x509_certificate_format (format, 4, FUNC_NAME);
1636 SCM_VALIDATE_ARRAY (2, cert);
1637 SCM_VALIDATE_ARRAY (3, key);
1639 /* FIXME: If the second call fails, an exception is raised and
1640 C_CERT_HANDLE is not released. */
1641 c_cert = scm_gnutls_get_array (cert, &c_cert_handle, &c_cert_len,
1643 c_key = scm_gnutls_get_array (key, &c_key_handle, &c_key_len, FUNC_NAME);
1645 c_cert_d.data = (unsigned char *) c_cert;
1646 c_cert_d.size = c_cert_len;
1647 c_key_d.data = (unsigned char *) c_key;
1648 c_key_d.size = c_key_len;
1650 err = gnutls_certificate_set_x509_key_mem (c_cred, &c_cert_d, &c_key_d,
1652 scm_gnutls_release_array (&c_cert_handle);
1653 scm_gnutls_release_array (&c_key_handle);
1655 if (EXPECT_FALSE (err))
1656 scm_gnutls_error (err, FUNC_NAME);
1658 return SCM_UNSPECIFIED;
1663 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_keys_x,
1664 "set-certificate-credentials-x509-keys!",
1666 (SCM cred, SCM certs, SCM privkey),
1667 "Have certificate credentials @var{cred} use the X.509 "
1668 "certificates listed in @var{certs} and X.509 private key "
1670 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_keys_x
1673 gnutls_x509_crt_t *c_certs;
1674 gnutls_x509_privkey_t c_key;
1675 gnutls_certificate_credentials_t c_cred;
1676 long int c_cert_count, i;
1678 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1679 SCM_VALIDATE_LIST_COPYLEN (2, certs, c_cert_count);
1680 c_key = scm_to_gnutls_x509_private_key (privkey, 3, FUNC_NAME);
1682 c_certs = (gnutls_x509_crt_t *) alloca (c_cert_count * sizeof (*c_certs));
1683 for (i = 0; scm_is_pair (certs); certs = SCM_CDR (certs), i++)
1685 c_certs[i] = scm_to_gnutls_x509_certificate (SCM_CAR (certs),
1689 err = gnutls_certificate_set_x509_key (c_cred, c_certs, c_cert_count,
1691 if (EXPECT_FALSE (err))
1692 scm_gnutls_error (err, FUNC_NAME);
1694 return SCM_UNSPECIFIED;
1699 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_limits_x,
1700 "set-certificate-credentials-verify-limits!",
1702 (SCM cred, SCM max_bits, SCM max_depth),
1703 "Set the verification limits of @code{peer-certificate-status} "
1704 "for certificate credentials @var{cred} to @var{max_bits} "
1705 "bits for an acceptable certificate and @var{max_depth} "
1706 "as the maximum depth of a certificate chain.")
1707 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_verify_limits_x
1709 gnutls_certificate_credentials_t c_cred;
1710 unsigned int c_max_bits, c_max_depth;
1712 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1713 c_max_bits = scm_to_uint (max_bits);
1714 c_max_depth = scm_to_uint (max_depth);
1716 gnutls_certificate_set_verify_limits (c_cred, c_max_bits, c_max_depth);
1718 return SCM_UNSPECIFIED;
1723 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_flags_x,
1724 "set-certificate-credentials-verify-flags!",
1726 (SCM cred, SCM flags),
1727 "Set the certificate verification flags to @var{flags}, a "
1728 "series of @code{certificate-verify} values.")
1729 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_verify_flags_x
1731 unsigned int c_flags, c_pos;
1732 gnutls_certificate_credentials_t c_cred;
1734 c_cred = scm_to_gnutls_certificate_credentials (cred, 1, FUNC_NAME);
1736 for (c_flags = 0, c_pos = 2;
1737 !scm_is_null (flags); flags = SCM_CDR (flags), c_pos++)
1739 c_flags |= (unsigned int)
1740 scm_to_gnutls_certificate_verify (SCM_CAR (flags), c_pos, FUNC_NAME);
1743 gnutls_certificate_set_verify_flags (c_cred, c_flags);
1745 return SCM_UNSPECIFIED;
1750 SCM_DEFINE (scm_gnutls_peer_certificate_status, "peer-certificate-status",
1753 "Verify the peer certificate for @var{session} and return "
1754 "a list of @code{certificate-status} values (such as "
1755 "@code{certificate-status/revoked}), or the empty list if "
1756 "the certificate is valid.")
1757 #define FUNC_NAME s_scm_gnutls_peer_certificate_status
1760 unsigned int c_status;
1761 gnutls_session_t c_session;
1762 SCM result = SCM_EOL;
1764 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
1766 err = gnutls_certificate_verify_peers2 (c_session, &c_status);
1767 if (EXPECT_FALSE (err))
1768 scm_gnutls_error (err, FUNC_NAME);
1770 #define MATCH_STATUS(_value) \
1771 if (c_status & (_value)) \
1773 result = scm_cons (scm_from_gnutls_certificate_status (_value), \
1775 c_status &= ~(_value); \
1778 MATCH_STATUS (GNUTLS_CERT_INVALID);
1779 MATCH_STATUS (GNUTLS_CERT_REVOKED);
1780 MATCH_STATUS (GNUTLS_CERT_SIGNER_NOT_FOUND);
1781 MATCH_STATUS (GNUTLS_CERT_SIGNER_NOT_CA);
1782 MATCH_STATUS (GNUTLS_CERT_INSECURE_ALGORITHM);
1784 if (EXPECT_FALSE (c_status != 0))
1785 /* XXX: We failed to interpret one of the status flags. */
1786 scm_gnutls_error (GNUTLS_E_UNIMPLEMENTED_FEATURE, FUNC_NAME);
1796 /* SRP credentials. */
1799 SCM_DEFINE (scm_gnutls_make_srp_server_credentials,
1800 "make-srp-server-credentials",
1801 0, 0, 0, (void), "Return new SRP server credentials.")
1802 #define FUNC_NAME s_scm_gnutls_make_srp_server_credentials
1805 gnutls_srp_server_credentials_t c_cred;
1807 err = gnutls_srp_allocate_server_credentials (&c_cred);
1808 if (EXPECT_FALSE (err))
1809 scm_gnutls_error (err, FUNC_NAME);
1811 return (scm_from_gnutls_srp_server_credentials (c_cred));
1816 SCM_DEFINE (scm_gnutls_set_srp_server_credentials_files_x,
1817 "set-srp-server-credentials-files!",
1819 (SCM cred, SCM password_file, SCM password_conf_file),
1820 "Set the credentials files for @var{cred}, an SRP server "
1821 "credentials object.")
1822 #define FUNC_NAME s_scm_gnutls_set_srp_server_credentials_files_x
1825 gnutls_srp_server_credentials_t c_cred;
1826 char *c_password_file, *c_password_conf_file;
1827 size_t c_password_file_len, c_password_conf_file_len;
1829 c_cred = scm_to_gnutls_srp_server_credentials (cred, 1, FUNC_NAME);
1830 SCM_VALIDATE_STRING (2, password_file);
1831 SCM_VALIDATE_STRING (3, password_conf_file);
1833 c_password_file_len = scm_c_string_length (password_file);
1834 c_password_conf_file_len = scm_c_string_length (password_conf_file);
1836 c_password_file = (char *) alloca (c_password_file_len + 1);
1837 c_password_conf_file = (char *) alloca (c_password_conf_file_len + 1);
1839 (void) scm_to_locale_stringbuf (password_file, c_password_file,
1840 c_password_file_len + 1);
1841 c_password_file[c_password_file_len] = '\0';
1842 (void) scm_to_locale_stringbuf (password_conf_file, c_password_conf_file,
1843 c_password_conf_file_len + 1);
1844 c_password_conf_file[c_password_conf_file_len] = '\0';
1846 err = gnutls_srp_set_server_credentials_file (c_cred, c_password_file,
1847 c_password_conf_file);
1848 if (EXPECT_FALSE (err))
1849 scm_gnutls_error (err, FUNC_NAME);
1851 return SCM_UNSPECIFIED;
1856 SCM_DEFINE (scm_gnutls_make_srp_client_credentials,
1857 "make-srp-client-credentials",
1858 0, 0, 0, (void), "Return new SRP client credentials.")
1859 #define FUNC_NAME s_scm_gnutls_make_srp_client_credentials
1862 gnutls_srp_client_credentials_t c_cred;
1864 err = gnutls_srp_allocate_client_credentials (&c_cred);
1865 if (EXPECT_FALSE (err))
1866 scm_gnutls_error (err, FUNC_NAME);
1868 return (scm_from_gnutls_srp_client_credentials (c_cred));
1874 SCM_DEFINE (scm_gnutls_set_srp_client_credentials_x,
1875 "set-srp-client-credentials!",
1877 (SCM cred, SCM username, SCM password),
1878 "Use @var{username} and @var{password} as the credentials "
1879 "for @var{cred}, a client-side SRP credentials object.")
1880 #define FUNC_NAME s_scm_gnutls_make_srp_client_credentials
1883 gnutls_srp_client_credentials_t c_cred;
1884 char *c_username, *c_password;
1885 size_t c_username_len, c_password_len;
1887 c_cred = scm_to_gnutls_srp_client_credentials (cred, 1, FUNC_NAME);
1888 SCM_VALIDATE_STRING (2, username);
1889 SCM_VALIDATE_STRING (3, password);
1891 c_username_len = scm_c_string_length (username);
1892 c_password_len = scm_c_string_length (password);
1894 c_username = (char *) alloca (c_username_len + 1);
1895 c_password = (char *) alloca (c_password_len + 1);
1897 (void) scm_to_locale_stringbuf (username, c_username, c_username_len + 1);
1898 c_username[c_username_len] = '\0';
1899 (void) scm_to_locale_stringbuf (password, c_password, c_password_len + 1);
1900 c_password[c_password_len] = '\0';
1902 err = gnutls_srp_set_client_credentials (c_cred, c_username, c_password);
1903 if (EXPECT_FALSE (err))
1904 scm_gnutls_error (err, FUNC_NAME);
1906 return SCM_UNSPECIFIED;
1911 SCM_DEFINE (scm_gnutls_server_session_srp_username,
1912 "server-session-srp-username",
1915 "Return the SRP username used in @var{session} (a server-side "
1917 #define FUNC_NAME s_scm_gnutls_server_session_srp_username
1920 const char *c_username;
1921 gnutls_session_t c_session;
1923 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
1924 c_username = gnutls_srp_server_get_username (c_session);
1926 if (EXPECT_FALSE (c_username == NULL))
1927 result = SCM_BOOL_F;
1929 result = scm_from_locale_string (c_username);
1936 SCM_DEFINE (scm_gnutls_srp_base64_encode, "srp-base64-encode",
1939 "Encode @var{str} using SRP's base64 algorithm. Return "
1940 "the encoded string.")
1941 #define FUNC_NAME s_scm_gnutls_srp_base64_encode
1944 char *c_str, *c_result;
1945 size_t c_str_len, c_result_len, c_result_actual_len;
1946 gnutls_datum_t c_str_d;
1948 SCM_VALIDATE_STRING (1, str);
1950 c_str_len = scm_c_string_length (str);
1951 c_str = (char *) alloca (c_str_len + 1);
1952 (void) scm_to_locale_stringbuf (str, c_str, c_str_len + 1);
1953 c_str[c_str_len] = '\0';
1955 /* Typical size ratio is 4/3 so 3/2 is an upper bound. */
1956 c_result_len = (c_str_len * 3) / 2;
1957 c_result = (char *) scm_malloc (c_result_len);
1958 if (EXPECT_FALSE (c_result == NULL))
1959 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR, FUNC_NAME);
1961 c_str_d.data = (unsigned char *) c_str;
1962 c_str_d.size = c_str_len;
1966 c_result_actual_len = c_result_len;
1967 err = gnutls_srp_base64_encode (&c_str_d, c_result,
1968 &c_result_actual_len);
1969 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1973 c_new_buf = scm_realloc (c_result, c_result_len * 2);
1974 if (EXPECT_FALSE (c_new_buf == NULL))
1977 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR, FUNC_NAME);
1980 c_result = c_new_buf, c_result_len *= 2;
1983 while (EXPECT_FALSE (err == GNUTLS_E_SHORT_MEMORY_BUFFER));
1985 if (EXPECT_FALSE (err))
1986 scm_gnutls_error (err, FUNC_NAME);
1988 if (c_result_actual_len + 1 < c_result_len)
1989 /* Shrink the buffer. */
1990 c_result = scm_realloc (c_result, c_result_actual_len + 1);
1992 c_result[c_result_actual_len] = '\0';
1994 return (scm_take_locale_string (c_result));
1999 SCM_DEFINE (scm_gnutls_srp_base64_decode, "srp-base64-decode",
2002 "Decode @var{str}, an SRP-base64 encoded string, and return "
2003 "the decoded string.")
2004 #define FUNC_NAME s_scm_gnutls_srp_base64_decode
2007 char *c_str, *c_result;
2008 size_t c_str_len, c_result_len, c_result_actual_len;
2009 gnutls_datum_t c_str_d;
2011 SCM_VALIDATE_STRING (1, str);
2013 c_str_len = scm_c_string_length (str);
2014 c_str = (char *) alloca (c_str_len + 1);
2015 (void) scm_to_locale_stringbuf (str, c_str, c_str_len + 1);
2016 c_str[c_str_len] = '\0';
2018 /* We assume that the decoded string is smaller than the encoded
2020 c_result_len = c_str_len;
2021 c_result = (char *) alloca (c_result_len);
2023 c_str_d.data = (unsigned char *) c_str;
2024 c_str_d.size = c_str_len;
2026 c_result_actual_len = c_result_len;
2027 err = gnutls_srp_base64_decode (&c_str_d, c_result, &c_result_actual_len);
2028 if (EXPECT_FALSE (err))
2029 scm_gnutls_error (err, FUNC_NAME);
2031 c_result[c_result_actual_len] = '\0';
2033 return (scm_from_locale_string (c_result));
2037 #endif /* ENABLE_SRP */
2040 /* PSK credentials. */
2042 SCM_DEFINE (scm_gnutls_make_psk_server_credentials,
2043 "make-psk-server-credentials",
2044 0, 0, 0, (void), "Return new PSK server credentials.")
2045 #define FUNC_NAME s_scm_gnutls_make_psk_server_credentials
2048 gnutls_psk_server_credentials_t c_cred;
2050 err = gnutls_psk_allocate_server_credentials (&c_cred);
2051 if (EXPECT_FALSE (err))
2052 scm_gnutls_error (err, FUNC_NAME);
2054 return (scm_from_gnutls_psk_server_credentials (c_cred));
2059 SCM_DEFINE (scm_gnutls_set_psk_server_credentials_file_x,
2060 "set-psk-server-credentials-file!",
2062 (SCM cred, SCM file),
2063 "Use @var{file} as the password file for PSK server "
2064 "credentials @var{cred}.")
2065 #define FUNC_NAME s_scm_gnutls_set_psk_server_credentials_file_x
2068 gnutls_psk_server_credentials_t c_cred;
2072 c_cred = scm_to_gnutls_psk_server_credentials (cred, 1, FUNC_NAME);
2073 SCM_VALIDATE_STRING (2, file);
2075 c_file_len = scm_c_string_length (file);
2076 c_file = (char *) alloca (c_file_len + 1);
2078 (void) scm_to_locale_stringbuf (file, c_file, c_file_len + 1);
2079 c_file[c_file_len] = '\0';
2081 err = gnutls_psk_set_server_credentials_file (c_cred, c_file);
2082 if (EXPECT_FALSE (err))
2083 scm_gnutls_error (err, FUNC_NAME);
2085 return SCM_UNSPECIFIED;
2090 SCM_DEFINE (scm_gnutls_make_psk_client_credentials,
2091 "make-psk-client-credentials",
2092 0, 0, 0, (void), "Return a new PSK client credentials object.")
2093 #define FUNC_NAME s_scm_gnutls_make_psk_client_credentials
2096 gnutls_psk_client_credentials_t c_cred;
2098 err = gnutls_psk_allocate_client_credentials (&c_cred);
2099 if (EXPECT_FALSE (err))
2100 scm_gnutls_error (err, FUNC_NAME);
2102 return (scm_from_gnutls_psk_client_credentials (c_cred));
2107 SCM_DEFINE (scm_gnutls_set_psk_client_credentials_x,
2108 "set-psk-client-credentials!",
2110 (SCM cred, SCM username, SCM key, SCM key_format),
2111 "Set the client credentials for @var{cred}, a PSK client "
2112 "credentials object.")
2113 #define FUNC_NAME s_scm_gnutls_set_psk_client_credentials_x
2116 gnutls_psk_client_credentials_t c_cred;
2117 gnutls_psk_key_flags c_key_format;
2118 scm_t_array_handle c_handle;
2121 size_t c_username_len, c_key_len;
2122 gnutls_datum_t c_datum;
2124 c_cred = scm_to_gnutls_psk_client_credentials (cred, 1, FUNC_NAME);
2125 SCM_VALIDATE_STRING (2, username);
2126 SCM_VALIDATE_ARRAY (3, key);
2127 c_key_format = scm_to_gnutls_psk_key_format (key_format, 4, FUNC_NAME);
2129 c_username_len = scm_c_string_length (username);
2130 c_username = (char *) alloca (c_username_len + 1);
2132 (void) scm_to_locale_stringbuf (username, c_username, c_username_len + 1);
2133 c_username[c_username_len] = '\0';
2135 c_key = scm_gnutls_get_array (key, &c_handle, &c_key_len, FUNC_NAME);
2136 c_datum.data = (unsigned char *) c_key;
2137 c_datum.size = c_key_len;
2139 err = gnutls_psk_set_client_credentials (c_cred, c_username,
2140 &c_datum, c_key_format);
2141 scm_gnutls_release_array (&c_handle);
2143 if (EXPECT_FALSE (err))
2144 scm_gnutls_error (err, FUNC_NAME);
2146 return SCM_UNSPECIFIED;
2151 SCM_DEFINE (scm_gnutls_server_session_psk_username,
2152 "server-session-psk-username",
2155 "Return the username associated with PSK server session "
2157 #define FUNC_NAME s_scm_gnutls_server_session_psk_username
2160 const char *c_username;
2161 gnutls_session_t c_session;
2163 c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
2164 c_username = gnutls_srp_server_get_username (c_session);
2166 if (EXPECT_FALSE (c_username == NULL))
2167 result = SCM_BOOL_F;
2169 result = scm_from_locale_string (c_username);
2177 /* X.509 certificates. */
2179 SCM_DEFINE (scm_gnutls_import_x509_certificate, "import-x509-certificate",
2181 (SCM data, SCM format),
2182 "Return a new X.509 certificate object resulting from the "
2183 "import of @var{data} (a uniform array) according to "
2185 #define FUNC_NAME s_scm_gnutls_import_x509_certificate
2188 gnutls_x509_crt_t c_cert;
2189 gnutls_x509_crt_fmt_t c_format;
2190 gnutls_datum_t c_data_d;
2191 scm_t_array_handle c_data_handle;
2195 SCM_VALIDATE_ARRAY (1, data);
2196 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
2198 c_data = scm_gnutls_get_array (data, &c_data_handle, &c_data_len,
2200 c_data_d.data = (unsigned char *) c_data;
2201 c_data_d.size = c_data_len;
2203 err = gnutls_x509_crt_init (&c_cert);
2204 if (EXPECT_FALSE (err))
2206 scm_gnutls_release_array (&c_data_handle);
2207 scm_gnutls_error (err, FUNC_NAME);
2210 err = gnutls_x509_crt_import (c_cert, &c_data_d, c_format);
2211 scm_gnutls_release_array (&c_data_handle);
2213 if (EXPECT_FALSE (err))
2215 gnutls_x509_crt_deinit (c_cert);
2216 scm_gnutls_error (err, FUNC_NAME);
2219 return (scm_from_gnutls_x509_certificate (c_cert));
2224 SCM_DEFINE (scm_gnutls_import_x509_private_key, "import-x509-private-key",
2226 (SCM data, SCM format),
2227 "Return a new X.509 private key object resulting from the "
2228 "import of @var{data} (a uniform array) according to "
2230 #define FUNC_NAME s_scm_gnutls_import_x509_private_key
2233 gnutls_x509_privkey_t c_key;
2234 gnutls_x509_crt_fmt_t c_format;
2235 gnutls_datum_t c_data_d;
2236 scm_t_array_handle c_data_handle;
2240 SCM_VALIDATE_ARRAY (1, data);
2241 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
2243 c_data = scm_gnutls_get_array (data, &c_data_handle, &c_data_len,
2245 c_data_d.data = (unsigned char *) c_data;
2246 c_data_d.size = c_data_len;
2248 err = gnutls_x509_privkey_init (&c_key);
2249 if (EXPECT_FALSE (err))
2251 scm_gnutls_release_array (&c_data_handle);
2252 scm_gnutls_error (err, FUNC_NAME);
2255 err = gnutls_x509_privkey_import (c_key, &c_data_d, c_format);
2256 scm_gnutls_release_array (&c_data_handle);
2258 if (EXPECT_FALSE (err))
2260 gnutls_x509_privkey_deinit (c_key);
2261 scm_gnutls_error (err, FUNC_NAME);
2264 return (scm_from_gnutls_x509_private_key (c_key));
2269 SCM_DEFINE (scm_gnutls_pkcs8_import_x509_private_key,
2270 "pkcs8-import-x509-private-key",
2272 (SCM data, SCM format, SCM pass, SCM encrypted),
2273 "Return a new X.509 private key object resulting from the "
2274 "import of @var{data} (a uniform array) according to "
2275 "@var{format}. Optionally, if @var{pass} is not @code{#f}, "
2276 "it should be a string denoting a passphrase. "
2277 "@var{encrypted} tells whether the private key is encrypted "
2278 "(@code{#t} by default).")
2279 #define FUNC_NAME s_scm_gnutls_pkcs8_import_x509_private_key
2282 gnutls_x509_privkey_t c_key;
2283 gnutls_x509_crt_fmt_t c_format;
2284 unsigned int c_flags;
2285 gnutls_datum_t c_data_d;
2286 scm_t_array_handle c_data_handle;
2289 size_t c_data_len, c_pass_len;
2291 SCM_VALIDATE_ARRAY (1, data);
2292 c_format = scm_to_gnutls_x509_certificate_format (format, 2, FUNC_NAME);
2293 if ((pass == SCM_UNDEFINED) || (scm_is_false (pass)))
2297 c_pass_len = scm_c_string_length (pass);
2298 c_pass = (char *) alloca (c_pass_len + 1);
2299 (void) scm_to_locale_stringbuf (pass, c_pass, c_pass_len + 1);
2300 c_pass[c_pass_len] = '\0';
2303 if (encrypted == SCM_UNDEFINED)
2307 SCM_VALIDATE_BOOL (4, encrypted);
2308 if (scm_is_true (encrypted))
2311 c_flags = GNUTLS_PKCS8_PLAIN;
2314 c_data = scm_gnutls_get_array (data, &c_data_handle, &c_data_len,
2316 c_data_d.data = (unsigned char *) c_data;
2317 c_data_d.size = c_data_len;
2319 err = gnutls_x509_privkey_init (&c_key);
2320 if (EXPECT_FALSE (err))
2322 scm_gnutls_release_array (&c_data_handle);
2323 scm_gnutls_error (err, FUNC_NAME);
2326 err = gnutls_x509_privkey_import_pkcs8 (c_key, &c_data_d, c_format, c_pass,
2328 scm_gnutls_release_array (&c_data_handle);
2330 if (EXPECT_FALSE (err))
2332 gnutls_x509_privkey_deinit (c_key);
2333 scm_gnutls_error (err, FUNC_NAME);
2336 return (scm_from_gnutls_x509_private_key (c_key));
2341 /* Provide the body of a `get_dn' function. */
2342 #define X509_CERTIFICATE_DN_FUNCTION_BODY(get_the_dn) \
2344 gnutls_x509_crt_t c_cert; \
2348 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME); \
2350 /* Get the DN size. */ \
2351 (void) get_the_dn (c_cert, NULL, &c_dn_len); \
2353 /* Get the DN itself. */ \
2354 c_dn = (char *) alloca (c_dn_len); \
2355 err = get_the_dn (c_cert, c_dn, &c_dn_len); \
2357 if (EXPECT_FALSE (err)) \
2358 scm_gnutls_error (err, FUNC_NAME); \
2360 /* XXX: The returned string is actually ASCII or UTF-8. */ \
2361 return (scm_from_locale_string (c_dn));
2363 SCM_DEFINE (scm_gnutls_x509_certificate_dn, "x509-certificate-dn",
2366 "Return the distinguished name (DN) of X.509 certificate "
2367 "@var{cert}. The form of the DN is as described in @uref{"
2368 "http://tools.ietf.org/html/rfc2253, RFC 2253}.")
2369 #define FUNC_NAME s_scm_gnutls_x509_certificate_dn
2371 X509_CERTIFICATE_DN_FUNCTION_BODY (gnutls_x509_crt_get_dn);
2376 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn,
2377 "x509-certificate-issuer-dn",
2380 "Return the distinguished name (DN) of X.509 certificate "
2382 #define FUNC_NAME s_scm_gnutls_x509_certificate_issuer_dn
2384 X509_CERTIFICATE_DN_FUNCTION_BODY (gnutls_x509_crt_get_issuer_dn);
2389 #undef X509_CERTIFICATE_DN_FUNCTION_BODY
2392 /* Provide the body of a `get_dn_oid' function. */
2393 #define X509_CERTIFICATE_DN_OID_FUNCTION_BODY(get_dn_oid) \
2395 gnutls_x509_crt_t c_cert; \
2396 unsigned int c_index; \
2398 size_t c_oid_actual_len, c_oid_len; \
2401 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME); \
2402 c_index = scm_to_uint (index); \
2405 c_oid = scm_malloc (c_oid_len); \
2409 c_oid_actual_len = c_oid_len; \
2410 err = get_dn_oid (c_cert, c_index, c_oid, &c_oid_actual_len); \
2411 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) \
2413 c_oid = scm_realloc (c_oid, c_oid_len * 2); \
2417 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER); \
2419 if (EXPECT_FALSE (err)) \
2423 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) \
2424 result = SCM_BOOL_F; \
2426 scm_gnutls_error (err, FUNC_NAME); \
2430 if (c_oid_actual_len < c_oid_len) \
2431 c_oid = scm_realloc (c_oid, c_oid_actual_len); \
2433 result = scm_take_locale_stringn (c_oid, \
2434 c_oid_actual_len); \
2439 SCM_DEFINE (scm_gnutls_x509_certificate_dn_oid, "x509-certificate-dn-oid",
2441 (SCM cert, SCM index),
2442 "Return OID (a string) at @var{index} from @var{cert}. "
2443 "Return @code{#f} if no OID is available at @var{index}.")
2444 #define FUNC_NAME s_scm_gnutls_x509_certificate_dn_oid
2446 X509_CERTIFICATE_DN_OID_FUNCTION_BODY (gnutls_x509_crt_get_dn_oid);
2451 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn_oid,
2452 "x509-certificate-issuer-dn-oid",
2454 (SCM cert, SCM index),
2455 "Return the OID (a string) at @var{index} from @var{cert}'s "
2456 "issuer DN. Return @code{#f} if no OID is available at "
2458 #define FUNC_NAME s_scm_gnutls_x509_certificate_issuer_dn_oid
2460 X509_CERTIFICATE_DN_OID_FUNCTION_BODY (gnutls_x509_crt_get_issuer_dn_oid);
2465 #undef X509_CERTIFICATE_DN_OID_FUNCTION_BODY
2468 SCM_DEFINE (scm_gnutls_x509_certificate_matches_hostname_p,
2469 "x509-certificate-matches-hostname?",
2471 (SCM cert, SCM hostname),
2472 "Return true if @var{cert} matches @var{hostname}, a string "
2473 "denoting a DNS host name. This is the basic implementation "
2474 "of @uref{http://tools.ietf.org/html/rfc2818, RFC 2818} (aka. "
2476 #define FUNC_NAME s_scm_gnutls_x509_certificate_matches_hostname_p
2479 gnutls_x509_crt_t c_cert;
2481 size_t c_hostname_len;
2483 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2484 SCM_VALIDATE_STRING (2, hostname);
2486 c_hostname_len = scm_c_string_length (hostname);
2487 c_hostname = (char *) alloca (c_hostname_len + 1);
2489 (void) scm_to_locale_stringbuf (hostname, c_hostname, c_hostname_len + 1);
2490 c_hostname[c_hostname_len] = '\0';
2492 if (gnutls_x509_crt_check_hostname (c_cert, c_hostname))
2493 result = SCM_BOOL_T;
2495 result = SCM_BOOL_F;
2502 SCM_DEFINE (scm_gnutls_x509_certificate_signature_algorithm,
2503 "x509-certificate-signature-algorithm",
2506 "Return the signature algorithm used by @var{cert} (i.e., "
2507 "one of the @code{sign-algorithm/} values).")
2508 #define FUNC_NAME s_scm_gnutls_x509_certificate_signature_algorithm
2511 gnutls_x509_crt_t c_cert;
2513 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2515 c_result = gnutls_x509_crt_get_signature_algorithm (c_cert);
2516 if (EXPECT_FALSE (c_result < 0))
2517 scm_gnutls_error (c_result, FUNC_NAME);
2519 return (scm_from_gnutls_sign_algorithm (c_result));
2524 SCM_DEFINE (scm_gnutls_x509_certificate_public_key_algorithm,
2525 "x509-certificate-public-key-algorithm",
2528 "Return two values: the public key algorithm (i.e., "
2529 "one of the @code{pk-algorithm/} values) of @var{cert} "
2530 "and the number of bits used.")
2531 #define FUNC_NAME s_scm_gnutls_x509_certificate_public_key_algorithm
2533 gnutls_x509_crt_t c_cert;
2534 gnutls_pk_algorithm_t c_pk;
2535 unsigned int c_bits;
2537 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2539 c_pk = gnutls_x509_crt_get_pk_algorithm (c_cert, &c_bits);
2541 return (scm_values (scm_list_2 (scm_from_gnutls_pk_algorithm (c_pk),
2542 scm_from_uint (c_bits))));
2547 SCM_DEFINE (scm_gnutls_x509_certificate_key_usage,
2548 "x509-certificate-key-usage",
2551 "Return the key usage of @var{cert} (i.e., a list of "
2552 "@code{key-usage/} values), or the empty list if @var{cert} "
2553 "does not contain such information.")
2554 #define FUNC_NAME s_scm_gnutls_x509_certificate_key_usage
2558 gnutls_x509_crt_t c_cert;
2559 unsigned int c_usage, c_critical;
2561 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2563 err = gnutls_x509_crt_get_key_usage (c_cert, &c_usage, &c_critical);
2564 if (EXPECT_FALSE (err))
2566 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2569 scm_gnutls_error (err, FUNC_NAME);
2572 usage = scm_from_gnutls_key_usage_flags (c_usage);
2579 SCM_DEFINE (scm_gnutls_x509_certificate_version, "x509-certificate-version",
2580 1, 0, 0, (SCM cert), "Return the version of @var{cert}.")
2581 #define FUNC_NAME s_scm_gnutls_x509_certificate_version
2584 gnutls_x509_crt_t c_cert;
2586 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2588 c_result = gnutls_x509_crt_get_version (c_cert);
2589 if (EXPECT_FALSE (c_result < 0))
2590 scm_gnutls_error (c_result, FUNC_NAME);
2592 return (scm_from_int (c_result));
2597 SCM_DEFINE (scm_gnutls_x509_certificate_key_id, "x509-certificate-key-id",
2600 "Return a statistically unique ID (a u8vector) for @var{cert} "
2601 "that depends on its public key parameters. This is normally "
2602 "a 20-byte SHA-1 hash.")
2603 #define FUNC_NAME s_scm_gnutls_x509_certificate_key_id
2607 scm_t_array_handle c_id_handle;
2608 gnutls_x509_crt_t c_cert;
2610 size_t c_id_len = 20;
2612 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2614 result = scm_make_u8vector (scm_from_uint (c_id_len), SCM_INUM0);
2615 scm_array_get_handle (result, &c_id_handle);
2616 c_id = scm_array_handle_u8_writable_elements (&c_id_handle);
2618 err = gnutls_x509_crt_get_key_id (c_cert, 0, c_id, &c_id_len);
2619 scm_array_handle_release (&c_id_handle);
2621 if (EXPECT_FALSE (err))
2622 scm_gnutls_error (err, FUNC_NAME);
2629 SCM_DEFINE (scm_gnutls_x509_certificate_authority_key_id,
2630 "x509-certificate-authority-key-id",
2633 "Return the key ID (a u8vector) of the X.509 certificate "
2634 "authority of @var{cert}.")
2635 #define FUNC_NAME s_scm_gnutls_x509_certificate_authority_key_id
2639 scm_t_array_handle c_id_handle;
2640 gnutls_x509_crt_t c_cert;
2642 size_t c_id_len = 20;
2644 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2646 result = scm_make_u8vector (scm_from_uint (c_id_len), SCM_INUM0);
2647 scm_array_get_handle (result, &c_id_handle);
2648 c_id = scm_array_handle_u8_writable_elements (&c_id_handle);
2650 err = gnutls_x509_crt_get_authority_key_id (c_cert, c_id, &c_id_len, NULL);
2651 scm_array_handle_release (&c_id_handle);
2653 if (EXPECT_FALSE (err))
2654 scm_gnutls_error (err, FUNC_NAME);
2661 SCM_DEFINE (scm_gnutls_x509_certificate_subject_key_id,
2662 "x509-certificate-subject-key-id",
2665 "Return the subject key ID (a u8vector) for @var{cert}.")
2666 #define FUNC_NAME s_scm_gnutls_x509_certificate_subject_key_id
2670 scm_t_array_handle c_id_handle;
2671 gnutls_x509_crt_t c_cert;
2673 size_t c_id_len = 20;
2675 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2677 result = scm_make_u8vector (scm_from_uint (c_id_len), SCM_INUM0);
2678 scm_array_get_handle (result, &c_id_handle);
2679 c_id = scm_array_handle_u8_writable_elements (&c_id_handle);
2681 err = gnutls_x509_crt_get_subject_key_id (c_cert, c_id, &c_id_len, NULL);
2682 scm_array_handle_release (&c_id_handle);
2684 if (EXPECT_FALSE (err))
2685 scm_gnutls_error (err, FUNC_NAME);
2692 SCM_DEFINE (scm_gnutls_x509_certificate_subject_alternative_name,
2693 "x509-certificate-subject-alternative-name",
2695 (SCM cert, SCM index),
2696 "Return two values: the alternative name type for @var{cert} "
2697 "(i.e., one of the @code{x509-subject-alternative-name/} values) "
2698 "and the actual subject alternative name (a string) at "
2699 "@var{index}. Both values are @code{#f} if no alternative name "
2700 "is available at @var{index}.")
2701 #define FUNC_NAME s_scm_gnutls_x509_certificate_subject_alternative_name
2705 gnutls_x509_crt_t c_cert;
2706 unsigned int c_index;
2708 size_t c_name_len = 512, c_name_actual_len;
2710 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME);
2711 c_index = scm_to_uint (index);
2713 c_name = scm_malloc (c_name_len);
2716 c_name_actual_len = c_name_len;
2717 err = gnutls_x509_crt_get_subject_alt_name (c_cert, c_index,
2718 c_name, &c_name_actual_len,
2720 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
2722 c_name = scm_realloc (c_name, c_name_len * 2);
2726 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER);
2728 if (EXPECT_FALSE (err < 0))
2732 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2733 result = scm_values (scm_list_2 (SCM_BOOL_F, SCM_BOOL_F));
2735 scm_gnutls_error (err, FUNC_NAME);
2739 if (c_name_actual_len < c_name_len)
2740 c_name = scm_realloc (c_name, c_name_actual_len);
2743 scm_values (scm_list_2
2744 (scm_from_gnutls_x509_subject_alternative_name (err),
2745 scm_take_locale_string (c_name)));
2756 static SCM log_procedure = SCM_BOOL_F;
2759 scm_gnutls_log (int level, const char *str)
2761 if (scm_is_true (log_procedure))
2762 (void) scm_call_2 (log_procedure, scm_from_int (level),
2763 scm_from_locale_string (str));
2766 SCM_DEFINE (scm_gnutls_set_log_procedure_x, "set-log-procedure!",
2769 "Use @var{proc} (a two-argument procedure) as the global "
2770 "GnuTLS log procedure.")
2771 #define FUNC_NAME s_scm_gnutls_set_log_procedure_x
2773 SCM_VALIDATE_PROC (1, proc);
2775 if (scm_is_true (log_procedure))
2776 (void) scm_gc_unprotect_object (log_procedure);
2778 log_procedure = scm_gc_protect_object (proc);
2779 gnutls_global_set_log_function (scm_gnutls_log);
2781 return SCM_UNSPECIFIED;
2786 SCM_DEFINE (scm_gnutls_set_log_level_x, "set-log-level!", 1, 0, 0,
2788 "Enable GnuTLS logging up to @var{level} (an integer).")
2789 #define FUNC_NAME s_scm_gnutls_set_log_level_x
2791 unsigned int c_level;
2793 c_level = scm_to_uint (level);
2794 gnutls_global_set_log_level (c_level);
2796 return SCM_UNSPECIFIED;
2802 /* Initialization. */
2805 scm_init_gnutls (void)
2809 /* Use Guile's allocation routines, which will run the GC if need be. */
2810 gnutls_malloc = scm_malloc;
2811 gnutls_realloc = scm_realloc;
2812 gnutls_secure_malloc = scm_malloc;
2815 (void) gnutls_global_init ();
2817 scm_gnutls_define_enums ();
2819 scm_init_gnutls_error ();
2821 scm_init_gnutls_session_record_port_type ();