1 /* GNUTLS --- Guile bindings for GnuTLS.
2 Copyright (C) 2007, 2008 Free Software Foundation
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>. */
22 #include <gnutls/gnutls.h>
34 /* SMOB and enums type definitions. */
35 #include "enum-map.i.c"
36 #include "smob-types.i.c"
38 const char scm_gnutls_array_error_message
[] =
39 "cannot handle non-contiguous array: ~A";
42 /* Data that are attached to `gnutls_session_t' objects.
44 We need to keep several pieces of information along with each session:
46 - A boolean indicating whether its underlying transport is a file
47 descriptor or Scheme port. This is used to decide whether to leave
48 "Guile mode" when invoking `gnutls_record_recv ()'.
50 - The record port attached to the session (returned by
51 `session-record-port'). This is so that several calls to
52 `session-record-port' return the same port.
54 Currently, this information is maintained into a pair. The whole pair is
55 marked by the session mark procedure. */
57 #define SCM_GNUTLS_MAKE_SESSION_DATA() \
58 scm_cons (SCM_BOOL_F, SCM_BOOL_F);
59 #define SCM_GNUTLS_SET_SESSION_DATA(c_session, data) \
60 gnutls_session_set_ptr (c_session, (void *) SCM_UNPACK (data))
61 #define SCM_GNUTLS_SESSION_DATA(c_session) \
62 SCM_PACK ((scm_t_bits) gnutls_session_get_ptr (c_session))
64 #define SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD(c_session, c_is_fd) \
65 SCM_SETCAR (SCM_GNUTLS_SESSION_DATA (c_session), \
66 scm_from_bool (c_is_fd))
67 #define SCM_GNUTLS_SET_SESSION_RECORD_PORT(c_session, port) \
68 SCM_SETCDR (SCM_GNUTLS_SESSION_DATA (c_session), port);
70 #define SCM_GNUTLS_SESSION_TRANSPORT_IS_FD(c_session) \
71 scm_to_bool (SCM_CAR (SCM_GNUTLS_SESSION_DATA (c_session)))
72 #define SCM_GNUTLS_SESSION_RECORD_PORT(c_session) \
73 SCM_CDR (SCM_GNUTLS_SESSION_DATA (c_session))
79 /* Mark the data associated with SESSION. */
80 SCM_SMOB_MARK (scm_tc16_gnutls_session
, mark_session
, session
)
82 gnutls_session_t c_session
;
84 c_session
= scm_to_gnutls_session (session
, 1, "mark_session");
86 return (SCM_GNUTLS_SESSION_DATA (c_session
));
89 SCM_DEFINE (scm_gnutls_version
, "gnutls-version", 0, 0, 0,
91 "Return a string denoting the version number of the underlying "
92 "GnuTLS library, e.g., @code{\"1.7.2\"}.")
93 #define FUNC_NAME s_scm_gnutls_version
95 return (scm_from_locale_string (gnutls_check_version (NULL
)));
99 SCM_DEFINE (scm_gnutls_make_session
, "make-session", 1, 0, 0,
101 "Return a new session for connection end @var{end}, either "
102 "@code{connection-end/server} or @code{connection-end/client}.")
103 #define FUNC_NAME s_scm_gnutls_make_session
106 gnutls_session_t c_session
;
107 gnutls_connection_end_t c_end
;
110 c_end
= scm_to_gnutls_connection_end (end
, 1, FUNC_NAME
);
112 session_data
= SCM_GNUTLS_MAKE_SESSION_DATA ();
113 err
= gnutls_init (&c_session
, c_end
);
115 if (EXPECT_FALSE (err
))
116 scm_gnutls_error (err
, FUNC_NAME
);
118 SCM_GNUTLS_SET_SESSION_DATA (c_session
, session_data
);
120 return (scm_from_gnutls_session (c_session
));
124 SCM_DEFINE (scm_gnutls_bye
, "bye", 2, 0, 0,
125 (SCM session
, SCM how
),
126 "Close @var{session} according to @var{how}.")
127 #define FUNC_NAME s_scm_gnutls_bye
130 gnutls_session_t c_session
;
131 gnutls_close_request_t c_how
;
133 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
134 c_how
= scm_to_gnutls_close_request (how
, 2, FUNC_NAME
);
136 err
= gnutls_bye (c_session
, c_how
);
137 if (EXPECT_FALSE (err
))
138 scm_gnutls_error (err
, FUNC_NAME
);
140 return SCM_UNSPECIFIED
;
144 SCM_DEFINE (scm_gnutls_handshake
, "handshake", 1, 0, 0,
146 "Perform a handshake for @var{session}.")
147 #define FUNC_NAME s_scm_gnutls_handshake
150 gnutls_session_t c_session
;
152 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
154 err
= gnutls_handshake (c_session
);
155 if (EXPECT_FALSE (err
))
156 scm_gnutls_error (err
, FUNC_NAME
);
158 return SCM_UNSPECIFIED
;
162 SCM_DEFINE (scm_gnutls_rehandshake
, "rehandshake", 1, 0, 0,
164 "Perform a re-handshaking for @var{session}.")
165 #define FUNC_NAME s_scm_gnutls_rehandshake
168 gnutls_session_t c_session
;
170 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
172 err
= gnutls_rehandshake (c_session
);
173 if (EXPECT_FALSE (err
))
174 scm_gnutls_error (err
, FUNC_NAME
);
176 return SCM_UNSPECIFIED
;
180 SCM_DEFINE (scm_gnutls_alert_get
, "alert-get", 1, 0, 0,
182 "Get an aleter from @var{session}.")
183 #define FUNC_NAME s_scm_gnutls_alert_get
185 gnutls_session_t c_session
;
186 gnutls_alert_description_t c_alert
;
188 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
190 c_alert
= gnutls_alert_get (c_session
);
192 return (scm_from_gnutls_alert_description (c_alert
));
196 SCM_DEFINE (scm_gnutls_alert_send
, "alert-send", 3, 0, 0,
197 (SCM session
, SCM level
, SCM alert
),
198 "Send @var{alert} via @var{session}.")
199 #define FUNC_NAME s_scm_gnutls_alert_send
202 gnutls_session_t c_session
;
203 gnutls_alert_level_t c_level
;
204 gnutls_alert_description_t c_alert
;
206 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
207 c_level
= scm_to_gnutls_alert_level (level
, 2, FUNC_NAME
);
208 c_alert
= scm_to_gnutls_alert_description (alert
, 3, FUNC_NAME
);
210 err
= gnutls_alert_send (c_session
, c_level
, c_alert
);
211 if (EXPECT_FALSE (err
))
212 scm_gnutls_error (err
, FUNC_NAME
);
214 return SCM_UNSPECIFIED
;
218 /* FIXME: Omitting `alert-send-appropriate'. */
221 /* Session accessors. */
223 SCM_DEFINE (scm_gnutls_session_cipher
, "session-cipher", 1, 0, 0,
225 "Return @var{session}'s cipher.")
226 #define FUNC_NAME s_scm_gnutls_session_cipher
228 gnutls_session_t c_session
;
229 gnutls_cipher_algorithm_t c_cipher
;
231 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
233 c_cipher
= gnutls_cipher_get (c_session
);
235 return (scm_from_gnutls_cipher (c_cipher
));
239 SCM_DEFINE (scm_gnutls_session_kx
, "session-kx", 1, 0, 0,
241 "Return @var{session}'s kx.")
242 #define FUNC_NAME s_scm_gnutls_session_kx
244 gnutls_session_t c_session
;
245 gnutls_kx_algorithm_t c_kx
;
247 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
249 c_kx
= gnutls_kx_get (c_session
);
251 return (scm_from_gnutls_kx (c_kx
));
255 SCM_DEFINE (scm_gnutls_session_mac
, "session-mac", 1, 0, 0,
257 "Return @var{session}'s MAC.")
258 #define FUNC_NAME s_scm_gnutls_session_mac
260 gnutls_session_t c_session
;
261 gnutls_mac_algorithm_t c_mac
;
263 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
265 c_mac
= gnutls_mac_get (c_session
);
267 return (scm_from_gnutls_mac (c_mac
));
271 SCM_DEFINE (scm_gnutls_session_compression_method
,
272 "session-compression-method", 1, 0, 0,
274 "Return @var{session}'s compression method.")
275 #define FUNC_NAME s_scm_gnutls_session_compression_method
277 gnutls_session_t c_session
;
278 gnutls_compression_method_t c_comp
;
280 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
282 c_comp
= gnutls_compression_get (c_session
);
284 return (scm_from_gnutls_compression_method (c_comp
));
288 SCM_DEFINE (scm_gnutls_session_certificate_type
,
289 "session-certificate-type", 1, 0, 0,
291 "Return @var{session}'s certificate type.")
292 #define FUNC_NAME s_scm_gnutls_session_certificate_type
294 gnutls_session_t c_session
;
295 gnutls_certificate_type_t c_cert
;
297 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
299 c_cert
= gnutls_certificate_type_get (c_session
);
301 return (scm_from_gnutls_certificate_type (c_cert
));
305 SCM_DEFINE (scm_gnutls_session_protocol
, "session-protocol", 1, 0, 0,
307 "Return the protocol used by @var{session}.")
308 #define FUNC_NAME s_scm_gnutls_session_protocol
310 gnutls_session_t c_session
;
311 gnutls_protocol_t c_protocol
;
313 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
315 c_protocol
= gnutls_protocol_get_version (c_session
);
317 return (scm_from_gnutls_protocol (c_protocol
));
321 SCM_DEFINE (scm_gnutls_session_authentication_type
,
322 "session-authentication-type",
325 "Return the authentication type (a @code{credential-type} value) "
326 "used by @var{session}.")
327 #define FUNC_NAME s_scm_gnutls_session_authentication_type
329 gnutls_session_t c_session
;
330 gnutls_credentials_type_t c_auth
;
332 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
334 c_auth
= gnutls_auth_get_type (c_session
);
336 return (scm_from_gnutls_credentials (c_auth
));
340 SCM_DEFINE (scm_gnutls_session_server_authentication_type
,
341 "session-server-authentication-type",
344 "Return the server authentication type (a "
345 "@code{credential-type} value) used in @var{session}.")
346 #define FUNC_NAME s_scm_gnutls_session_server_authentication_type
348 gnutls_session_t c_session
;
349 gnutls_credentials_type_t c_auth
;
351 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
353 c_auth
= gnutls_auth_server_get_type (c_session
);
355 return (scm_from_gnutls_credentials (c_auth
));
359 SCM_DEFINE (scm_gnutls_session_client_authentication_type
,
360 "session-client-authentication-type",
363 "Return the client authentication type (a "
364 "@code{credential-type} value) used in @var{session}.")
365 #define FUNC_NAME s_scm_gnutls_session_client_authentication_type
367 gnutls_session_t c_session
;
368 gnutls_credentials_type_t c_auth
;
370 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
372 c_auth
= gnutls_auth_client_get_type (c_session
);
374 return (scm_from_gnutls_credentials (c_auth
));
378 SCM_DEFINE (scm_gnutls_session_peer_certificate_chain
,
379 "session-peer-certificate-chain",
382 "Return the a list of certificates in raw format (u8vectors) "
383 "where the first one is the peer's certificate. In the case "
384 "of OpenPGP, there is always exactly one certificate. In the "
385 "case of X.509, subsequent certificates indicate form a "
386 "certificate chain. Return the empty list if no certificate "
388 #define FUNC_NAME s_scm_gnutls_session_peer_certificate_chain
391 gnutls_session_t c_session
;
392 const gnutls_datum_t
*c_cert
;
393 unsigned int c_list_size
;
395 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
397 c_cert
= gnutls_certificate_get_peers (c_session
, &c_list_size
);
399 if (EXPECT_FALSE (c_cert
== NULL
))
406 result
= scm_make_list (scm_from_uint (c_list_size
), SCM_UNSPECIFIED
);
408 for (i
= 0, pair
= result
;
410 i
++, pair
= SCM_CDR (pair
))
412 unsigned char *c_cert_copy
;
414 c_cert_copy
= (unsigned char *) malloc (c_cert
[i
].size
);
415 if (EXPECT_FALSE (c_cert_copy
== NULL
))
416 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
418 memcpy (c_cert_copy
, c_cert
[i
].data
, c_cert
[i
].size
);
420 SCM_SETCAR (pair
, scm_take_u8vector (c_cert_copy
, c_cert
[i
].size
));
428 SCM_DEFINE (scm_gnutls_session_our_certificate_chain
,
429 "session-our-certificate-chain",
432 "Return our certificate chain for @var{session} (as sent to "
433 "the peer) in raw format (a u8vector). In the case of OpenPGP "
434 "there is exactly one certificate. Return the empty list "
435 "if no certificate was used.")
436 #define FUNC_NAME s_scm_gnutls_session_our_certificate_chain
439 gnutls_session_t c_session
;
440 const gnutls_datum_t
*c_cert
;
441 unsigned char *c_cert_copy
;
443 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
445 /* XXX: Currently, the C function actually returns only one certificate.
446 Future versions of the API may provide the full certificate chain, as
447 for `gnutls_certificate_get_peers ()'. */
448 c_cert
= gnutls_certificate_get_ours (c_session
);
450 if (EXPECT_FALSE (c_cert
== NULL
))
454 c_cert_copy
= (unsigned char *) malloc (c_cert
->size
);
455 if (EXPECT_FALSE (c_cert_copy
== NULL
))
456 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
458 memcpy (c_cert_copy
, c_cert
->data
, c_cert
->size
);
460 result
= scm_list_1 (scm_take_u8vector (c_cert_copy
, c_cert
->size
));
467 SCM_DEFINE (scm_gnutls_set_server_session_certificate_request_x
,
468 "set-server-session-certificate-request!",
470 (SCM session
, SCM request
),
471 "Tell how @var{session}, a server-side session, should deal "
472 "with certificate requests. @var{request} should be either "
473 "@code{certificate-request/request} or "
474 "@code{certificate-request/require}.")
475 #define FUNC_NAME s_scm_gnutls_set_server_session_certificate_request_x
477 gnutls_session_t c_session
;
478 gnutls_certificate_status_t c_request
;
480 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
481 c_request
= scm_to_gnutls_certificate_request (request
, 2, FUNC_NAME
);
483 gnutls_certificate_server_set_request (c_session
, c_request
);
485 return SCM_UNSPECIFIED
;
490 /* Choice of a protocol and cipher suite. */
492 #include "priorities.i.c"
494 SCM_DEFINE (scm_gnutls_set_default_priority_x
,
495 "set-session-default-priority!", 1, 0, 0,
497 "Have @var{session} use the default priorities.")
498 #define FUNC_NAME s_scm_gnutls_set_default_priority_x
500 gnutls_session_t c_session
;
502 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
503 gnutls_set_default_priority (c_session
);
505 return SCM_UNSPECIFIED
;
509 SCM_DEFINE (scm_gnutls_set_default_export_priority_x
,
510 "set-session-default-export-priority!", 1, 0, 0,
512 "Have @var{session} use the default export priorities.")
513 #define FUNC_NAME s_scm_gnutls_set_default_export_priority_x
515 gnutls_session_t c_session
;
517 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
518 gnutls_set_default_export_priority (c_session
);
520 return SCM_UNSPECIFIED
;
524 SCM_DEFINE (scm_gnutls_cipher_suite_to_string
, "cipher-suite->string",
526 (SCM kx
, SCM cipher
, SCM mac
),
527 "Return the name of the given cipher suite.")
528 #define FUNC_NAME s_scm_gnutls_cipher_suite_to_string
530 gnutls_kx_algorithm_t c_kx
;
531 gnutls_cipher_algorithm_t c_cipher
;
532 gnutls_mac_algorithm_t c_mac
;
535 c_kx
= scm_to_gnutls_kx (kx
, 1, FUNC_NAME
);
536 c_cipher
= scm_to_gnutls_cipher (cipher
, 2, FUNC_NAME
);
537 c_mac
= scm_to_gnutls_mac (mac
, 3, FUNC_NAME
);
539 c_name
= gnutls_cipher_suite_get_name (c_kx
, c_cipher
, c_mac
);
541 return (scm_from_locale_string (c_name
));
545 SCM_DEFINE (scm_gnutls_set_session_credentials_x
, "set-session-credentials!",
547 (SCM session
, SCM cred
),
548 "Use @var{cred} as @var{session}'s credentials.")
549 #define FUNC_NAME s_scm_gnutls_set_session_credentials_x
552 gnutls_session_t c_session
;
554 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
556 if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_certificate_credentials
, cred
))
558 gnutls_certificate_credentials_t c_cred
;
560 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 2,
562 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_CERTIFICATE
, c_cred
);
564 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_anonymous_client_credentials
, cred
))
566 gnutls_anon_client_credentials_t c_cred
;
568 c_cred
= scm_to_gnutls_anonymous_client_credentials (cred
, 2,
570 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_ANON
, c_cred
);
572 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_anonymous_server_credentials
,
575 gnutls_anon_server_credentials_t c_cred
;
577 c_cred
= scm_to_gnutls_anonymous_server_credentials (cred
, 2,
579 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_ANON
, c_cred
);
581 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_client_credentials
,
584 gnutls_srp_client_credentials_t c_cred
;
586 c_cred
= scm_to_gnutls_srp_client_credentials (cred
, 2,
588 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_SRP
, c_cred
);
590 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_server_credentials
,
593 gnutls_srp_server_credentials_t c_cred
;
595 c_cred
= scm_to_gnutls_srp_server_credentials (cred
, 2,
597 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_SRP
, c_cred
);
599 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_client_credentials
,
602 gnutls_psk_client_credentials_t c_cred
;
604 c_cred
= scm_to_gnutls_psk_client_credentials (cred
, 2,
606 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_PSK
, c_cred
);
608 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_server_credentials
,
611 gnutls_psk_server_credentials_t c_cred
;
613 c_cred
= scm_to_gnutls_psk_server_credentials (cred
, 2,
615 err
= gnutls_credentials_set (c_session
, GNUTLS_CRD_PSK
, c_cred
);
618 scm_wrong_type_arg (FUNC_NAME
, 2, cred
);
620 if (EXPECT_FALSE (err
))
621 scm_gnutls_error (err
, FUNC_NAME
);
623 return SCM_UNSPECIFIED
;
630 SCM_DEFINE (scm_gnutls_record_send
, "record-send", 2, 0, 0,
631 (SCM session
, SCM array
),
632 "Send the record constituted by @var{array} through "
634 #define FUNC_NAME s_scm_gnutls_record_send
638 gnutls_session_t c_session
;
639 scm_t_array_handle c_handle
;
643 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
644 SCM_VALIDATE_ARRAY (2, array
);
646 c_array
= scm_gnutls_get_array (array
, &c_handle
, &c_len
,
649 c_result
= gnutls_record_send (c_session
, c_array
, c_len
);
651 scm_gnutls_release_array (&c_handle
);
653 if (EXPECT_TRUE (c_result
>= 0))
654 result
= scm_from_ssize_t (c_result
);
656 scm_gnutls_error (c_result
, FUNC_NAME
);
662 SCM_DEFINE (scm_gnutls_record_receive_x
, "record-receive!", 2, 0, 0,
663 (SCM session
, SCM array
),
664 "Receive data from @var{session} into @var{array}, a uniform "
665 "homogeneous array. Return the number of bytes actually "
667 #define FUNC_NAME s_scm_gnutls_record_receive_x
671 gnutls_session_t c_session
;
672 scm_t_array_handle c_handle
;
676 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
677 SCM_VALIDATE_ARRAY (2, array
);
679 c_array
= scm_gnutls_get_writable_array (array
, &c_handle
, &c_len
,
682 c_result
= gnutls_record_recv (c_session
, c_array
, c_len
);
684 scm_gnutls_release_array (&c_handle
);
686 if (EXPECT_TRUE (c_result
>= 0))
687 result
= scm_from_ssize_t (c_result
);
689 scm_gnutls_error (c_result
, FUNC_NAME
);
696 /* The session record port type. */
697 static scm_t_bits session_record_port_type
;
699 /* Return the session associated with PORT. */
700 #define SCM_GNUTLS_SESSION_RECORD_PORT_SESSION(_port) \
701 (SCM_PACK (SCM_STREAM (_port)))
703 /* Size of a session port's input buffer. */
704 #define SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE 4096
706 /* Hint for the `scm_gc_' functions. */
707 static const char session_record_port_gc_hint
[] = "gnutls-session-record-port";
709 /* Mark the session associated with PORT. */
711 mark_session_record_port (SCM port
)
713 return (SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port
));
717 free_session_record_port (SCM port
)
718 #define FUNC_NAME "free_session_record_port"
723 session
= SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port
);
725 /* SESSION _can_ be invalid at this point: it can be freed in the same GC
726 cycle as PORT, just before PORT. Thus, we need to check whether SESSION
727 still points to a session SMOB. */
728 if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_session
, session
))
730 /* SESSION is still valid. Disassociate PORT from SESSION. */
731 gnutls_session_t c_session
;
733 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
734 SCM_GNUTLS_SET_SESSION_RECORD_PORT (c_session
, SCM_BOOL_F
);
737 /* Free the input buffer of PORT. */
738 c_port
= SCM_PTAB_ENTRY (port
);
739 scm_gc_free (c_port
->read_buf
, c_port
->read_buf_size
,
740 session_record_port_gc_hint
);
746 /* Data passed to `do_fill_port ()'. */
750 gnutls_session_t c_session
;
753 /* Actually fill a session record port (see below). */
755 do_fill_port (void *data
)
760 const fill_port_data_t
*args
= (fill_port_data_t
*) data
;
762 c_port
= args
->c_port
;
763 result
= gnutls_record_recv (args
->c_session
,
764 c_port
->read_buf
, c_port
->read_buf_size
);
765 if (EXPECT_TRUE (result
> 0))
767 c_port
->read_pos
= c_port
->read_buf
;
768 c_port
->read_end
= c_port
->read_buf
+ result
;
769 chr
= (int) *c_port
->read_buf
;
771 else if (result
== 0)
774 scm_gnutls_error (result
, "fill_session_record_port_input");
776 return ((void *) chr
);
779 /* Fill in the input buffer of PORT. */
781 fill_session_record_port_input (SCM port
)
782 #define FUNC_NAME "fill_session_record_port_input"
785 scm_t_port
*c_port
= SCM_PTAB_ENTRY (port
);
787 if (c_port
->read_pos
>= c_port
->read_end
)
790 fill_port_data_t c_args
;
791 gnutls_session_t c_session
;
793 session
= SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port
);
794 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
796 c_args
.c_session
= c_session
;
797 c_args
.c_port
= c_port
;
799 if (SCM_GNUTLS_SESSION_TRANSPORT_IS_FD (c_session
))
800 /* SESSION's underlying transport is a raw file descriptor, so we
801 must leave "Guile mode" to allow the GC to run. */
802 chr
= (int) scm_without_guile (do_fill_port
, &c_args
);
804 /* SESSION's underlying transport is a port, so don't leave "Guile
806 chr
= (int) do_fill_port (&c_args
);
809 chr
= (int) *c_port
->read_pos
;
815 /* Write SIZE octets from DATA to PORT. */
817 write_to_session_record_port (SCM port
, const void *data
, size_t size
)
818 #define FUNC_NAME "write_to_session_record_port"
821 gnutls_session_t c_session
;
825 session
= SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port
);
826 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
828 while (c_sent
< size
)
830 c_result
= gnutls_record_send (c_session
, (char *) data
+ c_sent
,
832 if (EXPECT_FALSE (c_result
< 0))
833 scm_gnutls_error (c_result
, FUNC_NAME
);
840 /* Return a new session port for SESSION. */
842 make_session_record_port (SCM session
)
846 unsigned char *c_port_buf
;
847 const unsigned long mode_bits
= SCM_OPN
| SCM_RDNG
| SCM_WRTNG
;
850 (unsigned char *) scm_gc_malloc (SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE
,
851 session_record_port_gc_hint
);
853 /* Create a new port. */
854 port
= scm_new_port_table_entry (session_record_port_type
);
855 c_port
= SCM_PTAB_ENTRY (port
);
857 /* Mark PORT as open, readable and writable (hmm, how elegant...). */
858 SCM_SET_CELL_TYPE (port
, session_record_port_type
| mode_bits
);
860 /* Associate it with SESSION. */
861 SCM_SETSTREAM (port
, SCM_UNPACK (session
));
863 c_port
->read_pos
= c_port
->read_end
= c_port
->read_buf
= c_port_buf
;
864 c_port
->read_buf_size
= SCM_GNUTLS_SESSION_RECORD_PORT_BUFFER_SIZE
;
866 c_port
->write_buf
= c_port
->write_pos
= &c_port
->shortbuf
;
867 c_port
->write_buf_size
= 1;
872 SCM_DEFINE (scm_gnutls_session_record_port
, "session-record-port", 1, 0, 0,
874 "Return a read-write port that may be used to communicate over "
875 "@var{session}. All invocations of @code{session-port} on a "
876 "given session return the same object (in the sense of "
878 #define FUNC_NAME s_scm_gnutls_session_record_port
881 gnutls_session_t c_session
;
883 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
884 port
= SCM_GNUTLS_SESSION_RECORD_PORT (c_session
);
886 if (!SCM_PORTP (port
))
888 /* Lazily create a new session port. */
889 port
= make_session_record_port (session
);
890 SCM_GNUTLS_SET_SESSION_RECORD_PORT (c_session
, port
);
897 /* Create the session port type. */
899 scm_init_gnutls_session_record_port_type (void)
901 session_record_port_type
=
902 scm_make_port_type ("gnutls-session-port",
903 fill_session_record_port_input
,
904 write_to_session_record_port
);
905 scm_set_port_mark (session_record_port_type
, mark_session_record_port
);
906 scm_set_port_free (session_record_port_type
, free_session_record_port
);
912 SCM_DEFINE (scm_gnutls_set_session_transport_fd_x
, "set-session-transport-fd!",
914 (SCM session
, SCM fd
),
915 "Use file descriptor @var{fd} as the underlying transport for "
917 #define FUNC_NAME s_scm_gnutls_set_session_transport_fd_x
919 gnutls_session_t c_session
;
922 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
923 c_fd
= (int) scm_to_uint (fd
);
925 gnutls_transport_set_ptr (c_session
, (gnutls_transport_ptr_t
) c_fd
);
927 SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD (c_session
, 1);
929 return SCM_UNSPECIFIED
;
933 /* Pull SIZE octets from TRANSPORT (a Scheme port) into DATA. */
935 pull_from_port (gnutls_transport_ptr_t transport
, void *data
, size_t size
)
940 port
= SCM_PACK ((scm_t_bits
) transport
);
942 result
= scm_c_read (port
, data
, size
);
944 return ((ssize_t
) result
);
947 /* Write SIZE octets from DATA to TRANSPORT (a Scheme port). */
949 push_to_port (gnutls_transport_ptr_t transport
, const void *data
,
954 port
= SCM_PACK ((scm_t_bits
) transport
);
956 scm_c_write (port
, data
, size
);
958 /* All we can do is assume that all SIZE octets were written. */
962 SCM_DEFINE (scm_gnutls_set_session_transport_port_x
,
963 "set-session-transport-port!",
965 (SCM session
, SCM port
),
966 "Use @var{port} as the input/output port for @var{session}.")
967 #define FUNC_NAME s_scm_gnutls_set_session_transport_port_x
969 gnutls_session_t c_session
;
971 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
972 SCM_VALIDATE_PORT (2, port
);
974 /* Note: We do not attempt to optimize the case where PORT is a file port
975 (i.e., over a file descriptor), because of port buffering issues. Users
976 are expected to explicitly use `set-session-transport-fd!' and `fileno'
977 when they wish to do it. */
979 gnutls_transport_set_ptr (c_session
,
980 (gnutls_transport_ptr_t
) SCM_UNPACK (port
));
981 gnutls_transport_set_push_function (c_session
, push_to_port
);
982 gnutls_transport_set_pull_function (c_session
, pull_from_port
);
984 SCM_GNUTLS_SET_SESSION_TRANSPORT_IS_FD (c_session
, 0);
986 return SCM_UNSPECIFIED
;
991 /* Diffie-Hellman. */
993 typedef int (* pkcs_export_function_t
) (void *, gnutls_x509_crt_fmt_t
,
994 unsigned char *, size_t *);
996 /* Hint for the `scm_gc' functions. */
997 static const char pkcs_export_gc_hint
[] = "gnutls-pkcs-export";
1000 /* Export DH/RSA parameters PARAMS through EXPORT, using format FORMAT.
1001 Return a `u8vector'. */
1003 pkcs_export_parameters (pkcs_export_function_t export
,
1004 void *params
, gnutls_x509_crt_fmt_t format
,
1005 const char *func_name
)
1006 #define FUNC_NAME func_name
1009 unsigned char *output
;
1010 size_t output_len
, output_total_len
= 4096;
1012 output
= (unsigned char *) scm_gc_malloc (output_total_len
,
1013 pkcs_export_gc_hint
);
1016 output_len
= output_total_len
;
1017 err
= export (params
, format
, output
, &output_len
);
1019 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
1021 output
= scm_gc_realloc (output
, output_total_len
,
1022 output_total_len
* 2,
1023 pkcs_export_gc_hint
);
1024 output_total_len
*= 2;
1027 while (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
);
1029 if (EXPECT_FALSE (err
))
1031 scm_gc_free (output
, output_total_len
, pkcs_export_gc_hint
);
1032 scm_gnutls_error (err
, FUNC_NAME
);
1035 if (output_len
!= output_total_len
)
1036 /* Shrink the output buffer. */
1037 output
= scm_gc_realloc (output
, output_total_len
,
1038 output_len
, pkcs_export_gc_hint
);
1040 return (scm_take_u8vector (output
, output_len
));
1045 SCM_DEFINE (scm_gnutls_make_dh_parameters
, "make-dh-parameters", 1, 0, 0,
1047 "Return new Diffie-Hellman parameters.")
1048 #define FUNC_NAME s_scm_gnutls_make_dh_parameters
1052 gnutls_dh_params_t c_dh_params
;
1054 c_bits
= scm_to_uint (bits
);
1056 err
= gnutls_dh_params_init (&c_dh_params
);
1057 if (EXPECT_FALSE (err
))
1058 scm_gnutls_error (err
, FUNC_NAME
);
1060 err
= gnutls_dh_params_generate2 (c_dh_params
, c_bits
);
1061 if (EXPECT_FALSE (err
))
1063 gnutls_dh_params_deinit (c_dh_params
);
1064 scm_gnutls_error (err
, FUNC_NAME
);
1067 return (scm_from_gnutls_dh_parameters (c_dh_params
));
1071 SCM_DEFINE (scm_gnutls_pkcs3_import_dh_parameters
,
1072 "pkcs3-import-dh-parameters",
1074 (SCM array
, SCM format
),
1075 "Import Diffie-Hellman parameters in PKCS3 format (further "
1076 "specified by @var{format}, an @code{x509-certificate-format} "
1077 "value) from @var{array} (a homogeneous array) and return a "
1078 "new @code{dh-params} object.")
1079 #define FUNC_NAME s_scm_gnutls_pkcs3_import_dh_parameters
1082 gnutls_x509_crt_fmt_t c_format
;
1083 gnutls_dh_params_t c_dh_params
;
1084 scm_t_array_handle c_handle
;
1085 const char *c_array
;
1087 gnutls_datum_t c_datum
;
1089 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
1091 c_array
= scm_gnutls_get_array (array
, &c_handle
, &c_len
, FUNC_NAME
);
1092 c_datum
.data
= (unsigned char *) c_array
;
1093 c_datum
.size
= c_len
;
1095 err
= gnutls_dh_params_init (&c_dh_params
);
1096 if (EXPECT_FALSE (err
))
1098 scm_gnutls_release_array (&c_handle
);
1099 scm_gnutls_error (err
, FUNC_NAME
);
1102 err
= gnutls_dh_params_import_pkcs3 (c_dh_params
, &c_datum
, c_format
);
1103 scm_gnutls_release_array (&c_handle
);
1105 if (EXPECT_FALSE (err
))
1107 gnutls_dh_params_deinit (c_dh_params
);
1108 scm_gnutls_error (err
, FUNC_NAME
);
1111 return (scm_from_gnutls_dh_parameters (c_dh_params
));
1115 SCM_DEFINE (scm_gnutls_pkcs3_export_dh_parameters
,
1116 "pkcs3-export-dh-parameters",
1118 (SCM dh_params
, SCM format
),
1119 "Export Diffie-Hellman parameters @var{dh_params} in PKCS3 "
1120 "format according for @var{format} (an "
1121 "@code{x509-certificate-format} value). Return a "
1122 "@code{u8vector} containing the result.")
1123 #define FUNC_NAME s_scm_gnutls_pkcs3_export_dh_parameters
1126 gnutls_dh_params_t c_dh_params
;
1127 gnutls_x509_crt_fmt_t c_format
;
1129 c_dh_params
= scm_to_gnutls_dh_parameters (dh_params
, 1, FUNC_NAME
);
1130 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
1132 result
= pkcs_export_parameters ((pkcs_export_function_t
)
1133 gnutls_dh_params_export_pkcs3
,
1134 (void *) c_dh_params
,
1135 c_format
, FUNC_NAME
);
1141 SCM_DEFINE (scm_gnutls_set_session_dh_prime_bits_x
,
1142 "set-session-dh-prime-bits!", 2, 0, 0,
1143 (SCM session
, SCM bits
),
1144 "Use @var{bits} DH prime bits for @var{session}.")
1145 #define FUNC_NAME s_scm_gnutls_set_session_dh_prime_bits_x
1147 unsigned int c_bits
;
1148 gnutls_session_t c_session
;
1150 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
1151 c_bits
= scm_to_uint (bits
);
1153 gnutls_dh_set_prime_bits (c_session
, c_bits
);
1155 return SCM_UNSPECIFIED
;
1160 /* Anonymous credentials. */
1162 SCM_DEFINE (scm_gnutls_make_anon_server_credentials
,
1163 "make-anonymous-server-credentials",
1165 "Return anonymous server credentials.")
1166 #define FUNC_NAME s_scm_gnutls_make_anon_server_credentials
1169 gnutls_anon_server_credentials_t c_cred
;
1171 err
= gnutls_anon_allocate_server_credentials (&c_cred
);
1173 if (EXPECT_FALSE (err
))
1174 scm_gnutls_error (err
, FUNC_NAME
);
1176 return (scm_from_gnutls_anonymous_server_credentials (c_cred
));
1180 SCM_DEFINE (scm_gnutls_make_anon_client_credentials
,
1181 "make-anonymous-client-credentials",
1183 "Return anonymous client credentials.")
1184 #define FUNC_NAME s_scm_gnutls_make_anon_client_credentials
1187 gnutls_anon_client_credentials_t c_cred
;
1189 err
= gnutls_anon_allocate_client_credentials (&c_cred
);
1191 if (EXPECT_FALSE (err
))
1192 scm_gnutls_error (err
, FUNC_NAME
);
1194 return (scm_from_gnutls_anonymous_client_credentials (c_cred
));
1198 SCM_DEFINE (scm_gnutls_set_anonymous_server_dh_parameters_x
,
1199 "set-anonymous-server-dh-parameters!", 2, 0, 0,
1200 (SCM cred
, SCM dh_params
),
1201 "Set the Diffie-Hellman parameters of anonymous server "
1202 "credentials @var{cred}.")
1203 #define FUNC_NAME s_scm_gnutls_set_anonymous_server_dh_parameters_x
1205 gnutls_dh_params_t c_dh_params
;
1206 gnutls_anon_server_credentials_t c_cred
;
1208 c_cred
= scm_to_gnutls_anonymous_server_credentials (cred
, 1,
1210 c_dh_params
= scm_to_gnutls_dh_parameters (dh_params
, 2,
1213 gnutls_anon_set_server_dh_params (c_cred
, c_dh_params
);
1215 return SCM_UNSPECIFIED
;
1220 /* RSA parameters. */
1222 SCM_DEFINE (scm_gnutls_make_rsa_parameters
, "make-rsa-parameters", 1, 0, 0,
1224 "Return new RSA parameters.")
1225 #define FUNC_NAME s_scm_gnutls_make_rsa_parameters
1229 gnutls_rsa_params_t c_rsa_params
;
1231 c_bits
= scm_to_uint (bits
);
1233 err
= gnutls_rsa_params_init (&c_rsa_params
);
1234 if (EXPECT_FALSE (err
))
1235 scm_gnutls_error (err
, FUNC_NAME
);
1237 err
= gnutls_rsa_params_generate2 (c_rsa_params
, c_bits
);
1238 if (EXPECT_FALSE (err
))
1240 gnutls_rsa_params_deinit (c_rsa_params
);
1241 scm_gnutls_error (err
, FUNC_NAME
);
1244 return (scm_from_gnutls_rsa_parameters (c_rsa_params
));
1248 SCM_DEFINE (scm_gnutls_pkcs1_import_rsa_parameters
,
1249 "pkcs1-import-rsa-parameters",
1251 (SCM array
, SCM format
),
1252 "Import Diffie-Hellman parameters in PKCS1 format (further "
1253 "specified by @var{format}, an @code{x509-certificate-format} "
1254 "value) from @var{array} (a homogeneous array) and return a "
1255 "new @code{rsa-params} object.")
1256 #define FUNC_NAME s_scm_gnutls_pkcs1_import_rsa_parameters
1259 gnutls_x509_crt_fmt_t c_format
;
1260 gnutls_rsa_params_t c_rsa_params
;
1261 scm_t_array_handle c_handle
;
1262 const char *c_array
;
1264 gnutls_datum_t c_datum
;
1266 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
1268 c_array
= scm_gnutls_get_array (array
, &c_handle
, &c_len
, FUNC_NAME
);
1269 c_datum
.data
= (unsigned char *) c_array
;
1270 c_datum
.size
= c_len
;
1272 err
= gnutls_rsa_params_init (&c_rsa_params
);
1273 if (EXPECT_FALSE (err
))
1275 scm_gnutls_release_array (&c_handle
);
1276 scm_gnutls_error (err
, FUNC_NAME
);
1279 err
= gnutls_rsa_params_import_pkcs1 (c_rsa_params
, &c_datum
, c_format
);
1280 scm_gnutls_release_array (&c_handle
);
1282 if (EXPECT_FALSE (err
))
1284 gnutls_rsa_params_deinit (c_rsa_params
);
1285 scm_gnutls_error (err
, FUNC_NAME
);
1288 return (scm_from_gnutls_rsa_parameters (c_rsa_params
));
1292 SCM_DEFINE (scm_gnutls_pkcs1_export_rsa_parameters
,
1293 "pkcs1-export-rsa-parameters",
1295 (SCM rsa_params
, SCM format
),
1296 "Export Diffie-Hellman parameters @var{rsa_params} in PKCS1 "
1297 "format according for @var{format} (an "
1298 "@code{x509-certificate-format} value). Return a "
1299 "@code{u8vector} containing the result.")
1300 #define FUNC_NAME s_scm_gnutls_pkcs1_export_rsa_parameters
1303 gnutls_rsa_params_t c_rsa_params
;
1304 gnutls_x509_crt_fmt_t c_format
;
1306 c_rsa_params
= scm_to_gnutls_rsa_parameters (rsa_params
, 1, FUNC_NAME
);
1307 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
1309 result
= pkcs_export_parameters ((pkcs_export_function_t
)
1310 gnutls_rsa_params_export_pkcs1
,
1311 (void *) c_rsa_params
,
1312 c_format
, FUNC_NAME
);
1319 /* Certificate credentials. */
1321 typedef int (* certificate_set_file_function_t
) (gnutls_certificate_credentials_t
,
1323 gnutls_x509_crt_fmt_t
);
1325 typedef int (* certificate_set_data_function_t
) (gnutls_certificate_credentials_t
,
1326 const gnutls_datum_t
*,
1327 gnutls_x509_crt_fmt_t
);
1329 /* Helper function to implement the `set-file!' functions. */
1331 set_certificate_file (certificate_set_file_function_t set_file
,
1332 SCM cred
, SCM file
, SCM format
,
1333 const char *func_name
)
1334 #define FUNC_NAME func_name
1340 gnutls_certificate_credentials_t c_cred
;
1341 gnutls_x509_crt_fmt_t c_format
;
1343 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1344 SCM_VALIDATE_STRING (2, file
);
1345 c_format
= scm_to_gnutls_x509_certificate_format (format
, 3, FUNC_NAME
);
1347 c_file_len
= scm_c_string_length (file
);
1348 c_file
= (char *) alloca (c_file_len
+ 1);
1350 (void) scm_to_locale_stringbuf (file
, c_file
, c_file_len
+ 1);
1351 c_file
[c_file_len
] = '\0';
1353 err
= set_file (c_cred
, c_file
, c_format
);
1354 if (EXPECT_FALSE (err
< 0))
1355 scm_gnutls_error (err
, FUNC_NAME
);
1357 /* Return the number of certificates processed. */
1358 return ((unsigned int) err
);
1362 /* Helper function implementing the `set-data!' functions. */
1363 static inline unsigned int
1364 set_certificate_data (certificate_set_data_function_t set_data
,
1365 SCM cred
, SCM data
, SCM format
,
1366 const char *func_name
)
1367 #define FUNC_NAME func_name
1370 gnutls_certificate_credentials_t c_cred
;
1371 gnutls_x509_crt_fmt_t c_format
;
1372 gnutls_datum_t c_datum
;
1373 scm_t_array_handle c_handle
;
1377 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1378 SCM_VALIDATE_ARRAY (2, data
);
1379 c_format
= scm_to_gnutls_x509_certificate_format (format
, 3, FUNC_NAME
);
1381 c_data
= scm_gnutls_get_array (data
, &c_handle
, &c_len
, FUNC_NAME
);
1382 c_datum
.data
= (unsigned char *) c_data
;
1383 c_datum
.size
= c_len
;
1385 err
= set_data (c_cred
, &c_datum
, c_format
);
1386 scm_gnutls_release_array (&c_handle
);
1388 if (EXPECT_FALSE (err
< 0))
1389 scm_gnutls_error (err
, FUNC_NAME
);
1391 /* Return the number of certificates processed. */
1392 return ((unsigned int) err
);
1397 SCM_DEFINE (scm_gnutls_make_certificate_credentials
,
1398 "make-certificate-credentials",
1401 "Return new certificate credentials (i.e., for use with "
1402 "either X.509 or OpenPGP certificates.")
1403 #define FUNC_NAME s_scm_gnutls_make_certificate_credentials
1406 gnutls_certificate_credentials_t c_cred
;
1408 err
= gnutls_certificate_allocate_credentials (&c_cred
);
1410 scm_gnutls_error (err
, FUNC_NAME
);
1412 return (scm_from_gnutls_certificate_credentials (c_cred
));
1416 SCM_DEFINE (scm_gnutls_set_certificate_credentials_dh_params_x
,
1417 "set-certificate-credentials-dh-parameters!",
1419 (SCM cred
, SCM dh_params
),
1420 "Use Diffie-Hellman parameters @var{dh_params} for "
1421 "certificate credentials @var{cred}.")
1422 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_dh_params_x
1424 gnutls_dh_params_t c_dh_params
;
1425 gnutls_certificate_credentials_t c_cred
;
1427 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1428 c_dh_params
= scm_to_gnutls_dh_parameters (dh_params
, 2, FUNC_NAME
);
1430 gnutls_certificate_set_dh_params (c_cred
, c_dh_params
);
1432 return SCM_UNSPECIFIED
;
1436 SCM_DEFINE (scm_gnutls_set_certificate_credentials_rsa_export_params_x
,
1437 "set-certificate-credentials-rsa-export-parameters!",
1439 (SCM cred
, SCM rsa_params
),
1440 "Use RSA parameters @var{rsa_params} for certificate "
1441 "credentials @var{cred}.")
1442 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_rsa_export_params_x
1444 gnutls_rsa_params_t c_rsa_params
;
1445 gnutls_certificate_credentials_t c_cred
;
1447 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1448 c_rsa_params
= scm_to_gnutls_rsa_parameters (rsa_params
, 2, FUNC_NAME
);
1450 gnutls_certificate_set_rsa_export_params (c_cred
, c_rsa_params
);
1452 return SCM_UNSPECIFIED
;
1456 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_files_x
,
1457 "set-certificate-credentials-x509-key-files!",
1459 (SCM cred
, SCM cert_file
, SCM key_file
, SCM format
),
1460 "Use @var{file} as the password file for PSK server "
1461 "credentials @var{cred}.")
1462 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_key_files_x
1465 gnutls_certificate_credentials_t c_cred
;
1466 gnutls_x509_crt_fmt_t c_format
;
1467 char *c_cert_file
, *c_key_file
;
1468 size_t c_cert_file_len
, c_key_file_len
;
1470 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1471 SCM_VALIDATE_STRING (2, cert_file
);
1472 SCM_VALIDATE_STRING (3, key_file
);
1473 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
1475 c_cert_file_len
= scm_c_string_length (cert_file
);
1476 c_cert_file
= (char *) alloca (c_cert_file_len
+ 1);
1478 c_key_file_len
= scm_c_string_length (key_file
);
1479 c_key_file
= (char *) alloca (c_key_file_len
+ 1);
1481 (void) scm_to_locale_stringbuf (cert_file
, c_cert_file
,
1482 c_cert_file_len
+ 1);
1483 c_cert_file
[c_cert_file_len
] = '\0';
1484 (void) scm_to_locale_stringbuf (key_file
, c_key_file
,
1485 c_key_file_len
+ 1);
1486 c_key_file
[c_key_file_len
] = '\0';
1488 err
= gnutls_certificate_set_x509_key_file (c_cred
, c_cert_file
, c_key_file
,
1490 if (EXPECT_FALSE (err
))
1491 scm_gnutls_error (err
, FUNC_NAME
);
1493 return SCM_UNSPECIFIED
;
1497 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_file_x
,
1498 "set-certificate-credentials-x509-trust-file!",
1500 (SCM cred
, SCM file
, SCM format
),
1501 "Use @var{file} as the X.509 trust file for certificate "
1502 "credentials @var{cred}. On success, return the number of "
1503 "certificates processed.")
1504 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_trust_file_x
1508 count
= set_certificate_file (gnutls_certificate_set_x509_trust_file
,
1512 return scm_from_uint (count
);
1516 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_file_x
,
1517 "set-certificate-credentials-x509-crl-file!",
1519 (SCM cred
, SCM file
, SCM format
),
1520 "Use @var{file} as the X.509 CRL (certificate revocation list) "
1521 "file for certificate credentials @var{cred}. On success, "
1522 "return the number of CRLs processed.")
1523 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_crl_file_x
1527 count
= set_certificate_file (gnutls_certificate_set_x509_crl_file
,
1531 return scm_from_uint (count
);
1535 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_data_x
,
1536 "set-certificate-credentials-x509-trust-data!",
1538 (SCM cred
, SCM data
, SCM format
),
1539 "Use @var{data} (a uniform array) as the X.509 trust "
1540 "database for @var{cred}. On success, return the number "
1541 "of certificates processed.")
1542 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_trust_data_x
1546 count
= set_certificate_data (gnutls_certificate_set_x509_trust_mem
,
1550 return scm_from_uint (count
);
1554 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_data_x
,
1555 "set-certificate-credentials-x509-crl-data!",
1557 (SCM cred
, SCM data
, SCM format
),
1558 "Use @var{data} (a uniform array) as the X.509 CRL "
1559 "(certificate revocation list) database for @var{cred}. "
1560 "On success, return the number of CRLs processed.")
1561 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_crl_data_x
1565 count
= set_certificate_data (gnutls_certificate_set_x509_crl_mem
,
1569 return scm_from_uint (count
);
1573 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_data_x
,
1574 "set-certificate-credentials-x509-key-data!",
1576 (SCM cred
, SCM cert
, SCM key
, SCM format
),
1577 "Use X.509 certificate @var{cert} and private key @var{key}, "
1578 "both uniform arrays containing the X.509 certificate and key "
1579 "in format @var{format}, for certificate credentials "
1581 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_key_data_x
1584 gnutls_x509_crt_fmt_t c_format
;
1585 gnutls_certificate_credentials_t c_cred
;
1586 gnutls_datum_t c_cert_d
, c_key_d
;
1587 scm_t_array_handle c_cert_handle
, c_key_handle
;
1588 const char *c_cert
, *c_key
;
1589 size_t c_cert_len
, c_key_len
;
1591 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1592 c_format
= scm_to_gnutls_x509_certificate_format (format
, 4, FUNC_NAME
);
1593 SCM_VALIDATE_ARRAY (2, cert
);
1594 SCM_VALIDATE_ARRAY (3, key
);
1596 /* FIXME: If the second call fails, an exception is raised and
1597 C_CERT_HANDLE is not released. */
1598 c_cert
= scm_gnutls_get_array (cert
, &c_cert_handle
, &c_cert_len
,
1600 c_key
= scm_gnutls_get_array (key
, &c_key_handle
, &c_key_len
,
1603 c_cert_d
.data
= (unsigned char *) c_cert
;
1604 c_cert_d
.size
= c_cert_len
;
1605 c_key_d
.data
= (unsigned char *) c_key
;
1606 c_key_d
.size
= c_key_len
;
1608 err
= gnutls_certificate_set_x509_key_mem (c_cred
, &c_cert_d
, &c_key_d
,
1610 scm_gnutls_release_array (&c_cert_handle
);
1611 scm_gnutls_release_array (&c_key_handle
);
1613 if (EXPECT_FALSE (err
))
1614 scm_gnutls_error (err
, FUNC_NAME
);
1616 return SCM_UNSPECIFIED
;
1620 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_keys_x
,
1621 "set-certificate-credentials-x509-keys!",
1623 (SCM cred
, SCM certs
, SCM privkey
),
1624 "Have certificate credentials @var{cred} use the X.509 "
1625 "certificates listed in @var{certs} and X.509 private key "
1627 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_keys_x
1630 gnutls_x509_crt_t
*c_certs
;
1631 gnutls_x509_privkey_t c_key
;
1632 gnutls_certificate_credentials_t c_cred
;
1633 long int c_cert_count
, i
;
1635 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1636 SCM_VALIDATE_LIST_COPYLEN (2, certs
, c_cert_count
);
1637 c_key
= scm_to_gnutls_x509_private_key (privkey
, 3, FUNC_NAME
);
1639 c_certs
= (gnutls_x509_crt_t
*) alloca (c_cert_count
* sizeof (* c_certs
));
1641 scm_is_pair (certs
);
1642 certs
= SCM_CDR (certs
), i
++)
1644 c_certs
[i
] = scm_to_gnutls_x509_certificate (SCM_CAR (certs
),
1648 err
= gnutls_certificate_set_x509_key (c_cred
, c_certs
, c_cert_count
,
1650 if (EXPECT_FALSE (err
))
1651 scm_gnutls_error (err
, FUNC_NAME
);
1653 return SCM_UNSPECIFIED
;
1657 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_limits_x
,
1658 "set-certificate-credentials-verify-limits!",
1660 (SCM cred
, SCM max_bits
, SCM max_depth
),
1661 "Set the verification limits of @code{peer-certificate-status} "
1662 "for certificate credentials @var{cred} to @var{max_bits} "
1663 "bits for an acceptable certificate and @var{max_depth} "
1664 "as the maximum depth of a certificate chain.")
1665 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_verify_limits_x
1667 gnutls_certificate_credentials_t c_cred
;
1668 unsigned int c_max_bits
, c_max_depth
;
1670 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1671 c_max_bits
= scm_to_uint (max_bits
);
1672 c_max_depth
= scm_to_uint (max_depth
);
1674 gnutls_certificate_set_verify_limits (c_cred
, c_max_bits
, c_max_depth
);
1676 return SCM_UNSPECIFIED
;
1680 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_flags_x
,
1681 "set-certificate-credentials-verify-flags!",
1683 (SCM cred
, SCM flags
),
1684 "Set the certificate verification flags to @var{flags}, a "
1685 "series of @code{certificate-verify} values.")
1686 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_verify_flags_x
1688 unsigned int c_flags
, c_pos
;
1689 gnutls_certificate_credentials_t c_cred
;
1691 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
1693 for (c_flags
= 0, c_pos
= 2;
1694 !scm_is_null (flags
);
1695 flags
= SCM_CDR (flags
), c_pos
++)
1697 c_flags
|= (unsigned int)
1698 scm_to_gnutls_certificate_verify (SCM_CAR (flags
), c_pos
, FUNC_NAME
);
1701 gnutls_certificate_set_verify_flags (c_cred
, c_flags
);
1703 return SCM_UNSPECIFIED
;
1707 SCM_DEFINE (scm_gnutls_peer_certificate_status
, "peer-certificate-status",
1710 "Verify the peer certificate for @var{session} and return "
1711 "a list of @code{certificate-status} values (such as "
1712 "@code{certificate-status/revoked}), or the empty list if "
1713 "the certificate is valid.")
1714 #define FUNC_NAME s_scm_gnutls_peer_certificate_status
1717 unsigned int c_status
;
1718 gnutls_session_t c_session
;
1719 SCM result
= SCM_EOL
;
1721 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
1723 err
= gnutls_certificate_verify_peers2 (c_session
, &c_status
);
1724 if (EXPECT_FALSE (err
))
1725 scm_gnutls_error (err
, FUNC_NAME
);
1727 #define MATCH_STATUS(_value) \
1728 if (c_status & (_value)) \
1730 result = scm_cons (scm_from_gnutls_certificate_status (_value), \
1732 c_status &= ~(_value); \
1735 MATCH_STATUS (GNUTLS_CERT_INVALID
);
1736 MATCH_STATUS (GNUTLS_CERT_REVOKED
);
1737 MATCH_STATUS (GNUTLS_CERT_SIGNER_NOT_FOUND
);
1738 MATCH_STATUS (GNUTLS_CERT_SIGNER_NOT_CA
);
1739 MATCH_STATUS (GNUTLS_CERT_INSECURE_ALGORITHM
);
1741 if (EXPECT_FALSE (c_status
!= 0))
1742 /* XXX: We failed to interpret one of the status flags. */
1743 scm_gnutls_error (GNUTLS_E_UNIMPLEMENTED_FEATURE
, FUNC_NAME
);
1752 /* SRP credentials. */
1754 SCM_DEFINE (scm_gnutls_make_srp_server_credentials
,
1755 "make-srp-server-credentials",
1758 "Return new SRP server credentials.")
1759 #define FUNC_NAME s_scm_gnutls_make_srp_server_credentials
1762 gnutls_srp_server_credentials_t c_cred
;
1764 err
= gnutls_srp_allocate_server_credentials (&c_cred
);
1765 if (EXPECT_FALSE (err
))
1766 scm_gnutls_error (err
, FUNC_NAME
);
1768 return (scm_from_gnutls_srp_server_credentials (c_cred
));
1772 SCM_DEFINE (scm_gnutls_set_srp_server_credentials_files_x
,
1773 "set-srp-server-credentials-files!",
1775 (SCM cred
, SCM password_file
, SCM password_conf_file
),
1776 "Set the credentials files for @var{cred}, an SRP server "
1777 "credentials object.")
1778 #define FUNC_NAME s_scm_gnutls_set_srp_server_credentials_files_x
1781 gnutls_srp_server_credentials_t c_cred
;
1782 char *c_password_file
, *c_password_conf_file
;
1783 size_t c_password_file_len
, c_password_conf_file_len
;
1785 c_cred
= scm_to_gnutls_srp_server_credentials (cred
, 1, FUNC_NAME
);
1786 SCM_VALIDATE_STRING (2, password_file
);
1787 SCM_VALIDATE_STRING (3, password_conf_file
);
1789 c_password_file_len
= scm_c_string_length (password_file
);
1790 c_password_conf_file_len
= scm_c_string_length (password_conf_file
);
1792 c_password_file
= (char *) alloca (c_password_file_len
+ 1);
1793 c_password_conf_file
= (char *) alloca (c_password_conf_file_len
+ 1);
1795 (void) scm_to_locale_stringbuf (password_file
, c_password_file
,
1796 c_password_file_len
+ 1);
1797 c_password_file
[c_password_file_len
] = '\0';
1798 (void) scm_to_locale_stringbuf (password_conf_file
, c_password_conf_file
,
1799 c_password_conf_file_len
+ 1);
1800 c_password_conf_file
[c_password_conf_file_len
] = '\0';
1802 err
= gnutls_srp_set_server_credentials_file (c_cred
, c_password_file
,
1803 c_password_conf_file
);
1804 if (EXPECT_FALSE (err
))
1805 scm_gnutls_error (err
, FUNC_NAME
);
1807 return SCM_UNSPECIFIED
;
1811 SCM_DEFINE (scm_gnutls_make_srp_client_credentials
,
1812 "make-srp-client-credentials",
1815 "Return new SRP client credentials.")
1816 #define FUNC_NAME s_scm_gnutls_make_srp_client_credentials
1819 gnutls_srp_client_credentials_t c_cred
;
1821 err
= gnutls_srp_allocate_client_credentials (&c_cred
);
1822 if (EXPECT_FALSE (err
))
1823 scm_gnutls_error (err
, FUNC_NAME
);
1825 return (scm_from_gnutls_srp_client_credentials (c_cred
));
1830 SCM_DEFINE (scm_gnutls_set_srp_client_credentials_x
,
1831 "set-srp-client-credentials!",
1833 (SCM cred
, SCM username
, SCM password
),
1834 "Use @var{username} and @var{password} as the credentials "
1835 "for @var{cred}, a client-side SRP credentials object.")
1836 #define FUNC_NAME s_scm_gnutls_make_srp_client_credentials
1839 gnutls_srp_client_credentials_t c_cred
;
1840 char *c_username
, *c_password
;
1841 size_t c_username_len
, c_password_len
;
1843 c_cred
= scm_to_gnutls_srp_client_credentials (cred
, 1, FUNC_NAME
);
1844 SCM_VALIDATE_STRING (2, username
);
1845 SCM_VALIDATE_STRING (3, password
);
1847 c_username_len
= scm_c_string_length (username
);
1848 c_password_len
= scm_c_string_length (password
);
1850 c_username
= (char *) alloca (c_username_len
+ 1);
1851 c_password
= (char *) alloca (c_password_len
+ 1);
1853 (void) scm_to_locale_stringbuf (username
, c_username
,
1854 c_username_len
+ 1);
1855 c_username
[c_username_len
] = '\0';
1856 (void) scm_to_locale_stringbuf (password
, c_password
,
1857 c_password_len
+ 1);
1858 c_password
[c_password_len
] = '\0';
1860 err
= gnutls_srp_set_client_credentials (c_cred
, c_username
,
1862 if (EXPECT_FALSE (err
))
1863 scm_gnutls_error (err
, FUNC_NAME
);
1865 return SCM_UNSPECIFIED
;
1869 SCM_DEFINE (scm_gnutls_server_session_srp_username
,
1870 "server-session-srp-username",
1873 "Return the SRP username used in @var{session} (a server-side "
1875 #define FUNC_NAME s_scm_gnutls_server_session_srp_username
1878 const char *c_username
;
1879 gnutls_session_t c_session
;
1881 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
1882 c_username
= gnutls_srp_server_get_username (c_session
);
1884 if (EXPECT_FALSE (c_username
== NULL
))
1885 result
= SCM_BOOL_F
;
1887 result
= scm_from_locale_string (c_username
);
1893 SCM_DEFINE (scm_gnutls_srp_base64_encode
, "srp-base64-encode",
1896 "Encode @var{str} using SRP's base64 algorithm. Return "
1897 "the encoded string.")
1898 #define FUNC_NAME s_scm_gnutls_srp_base64_encode
1901 char *c_str
, *c_result
;
1902 size_t c_str_len
, c_result_len
, c_result_actual_len
;
1903 gnutls_datum_t c_str_d
;
1905 SCM_VALIDATE_STRING (1, str
);
1907 c_str_len
= scm_c_string_length (str
);
1908 c_str
= (char *) alloca (c_str_len
+ 1);
1909 (void) scm_to_locale_stringbuf (str
, c_str
, c_str_len
+ 1);
1910 c_str
[c_str_len
] = '\0';
1912 /* Typical size ratio is 4/3 so 3/2 is an upper bound. */
1913 c_result_len
= (c_str_len
* 3) / 2;
1914 c_result
= (char *) scm_malloc (c_result_len
);
1915 if (EXPECT_FALSE (c_result
== NULL
))
1916 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
1918 c_str_d
.data
= (unsigned char *) c_str
;
1919 c_str_d
.size
= c_str_len
;
1923 c_result_actual_len
= c_result_len
;
1924 err
= gnutls_srp_base64_encode (&c_str_d
, c_result
,
1925 &c_result_actual_len
);
1926 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
1930 c_new_buf
= scm_realloc (c_result
, c_result_len
* 2);
1931 if (EXPECT_FALSE (c_new_buf
== NULL
))
1934 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
1937 c_result
= c_new_buf
, c_result_len
*= 2;
1940 while (EXPECT_FALSE (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
));
1942 if (EXPECT_FALSE (err
))
1943 scm_gnutls_error (err
, FUNC_NAME
);
1945 if (c_result_actual_len
+ 1 < c_result_len
)
1946 /* Shrink the buffer. */
1947 c_result
= scm_realloc (c_result
, c_result_actual_len
+ 1);
1949 c_result
[c_result_actual_len
] = '\0';
1951 return (scm_take_locale_string (c_result
));
1955 SCM_DEFINE (scm_gnutls_srp_base64_decode
, "srp-base64-decode",
1958 "Decode @var{str}, an SRP-base64 encoded string, and return "
1959 "the decoded string.")
1960 #define FUNC_NAME s_scm_gnutls_srp_base64_decode
1963 char *c_str
, *c_result
;
1964 size_t c_str_len
, c_result_len
, c_result_actual_len
;
1965 gnutls_datum_t c_str_d
;
1967 SCM_VALIDATE_STRING (1, str
);
1969 c_str_len
= scm_c_string_length (str
);
1970 c_str
= (char *) alloca (c_str_len
+ 1);
1971 (void) scm_to_locale_stringbuf (str
, c_str
, c_str_len
+ 1);
1972 c_str
[c_str_len
] = '\0';
1974 /* We assume that the decoded string is smaller than the encoded
1976 c_result_len
= c_str_len
;
1977 c_result
= (char *) alloca (c_result_len
);
1979 c_str_d
.data
= (unsigned char *) c_str
;
1980 c_str_d
.size
= c_str_len
;
1982 c_result_actual_len
= c_result_len
;
1983 err
= gnutls_srp_base64_decode (&c_str_d
, c_result
,
1984 &c_result_actual_len
);
1985 if (EXPECT_FALSE (err
))
1986 scm_gnutls_error (err
, FUNC_NAME
);
1988 c_result
[c_result_actual_len
] = '\0';
1990 return (scm_from_locale_string (c_result
));
1995 /* PSK credentials. */
1997 SCM_DEFINE (scm_gnutls_make_psk_server_credentials
,
1998 "make-psk-server-credentials",
2001 "Return new PSK server credentials.")
2002 #define FUNC_NAME s_scm_gnutls_make_psk_server_credentials
2005 gnutls_psk_server_credentials_t c_cred
;
2007 err
= gnutls_psk_allocate_server_credentials (&c_cred
);
2008 if (EXPECT_FALSE (err
))
2009 scm_gnutls_error (err
, FUNC_NAME
);
2011 return (scm_from_gnutls_psk_server_credentials (c_cred
));
2015 SCM_DEFINE (scm_gnutls_set_psk_server_credentials_file_x
,
2016 "set-psk-server-credentials-file!",
2018 (SCM cred
, SCM file
),
2019 "Use @var{file} as the password file for PSK server "
2020 "credentials @var{cred}.")
2021 #define FUNC_NAME s_scm_gnutls_set_psk_server_credentials_file_x
2024 gnutls_psk_server_credentials_t c_cred
;
2028 c_cred
= scm_to_gnutls_psk_server_credentials (cred
, 1, FUNC_NAME
);
2029 SCM_VALIDATE_STRING (2, file
);
2031 c_file_len
= scm_c_string_length (file
);
2032 c_file
= (char *) alloca (c_file_len
+ 1);
2034 (void) scm_to_locale_stringbuf (file
, c_file
, c_file_len
+ 1);
2035 c_file
[c_file_len
] = '\0';
2037 err
= gnutls_psk_set_server_credentials_file (c_cred
, c_file
);
2038 if (EXPECT_FALSE (err
))
2039 scm_gnutls_error (err
, FUNC_NAME
);
2041 return SCM_UNSPECIFIED
;
2045 SCM_DEFINE (scm_gnutls_make_psk_client_credentials
,
2046 "make-psk-client-credentials",
2049 "Return a new PSK client credentials object.")
2050 #define FUNC_NAME s_scm_gnutls_make_psk_client_credentials
2053 gnutls_psk_client_credentials_t c_cred
;
2055 err
= gnutls_psk_allocate_client_credentials (&c_cred
);
2056 if (EXPECT_FALSE (err
))
2057 scm_gnutls_error (err
, FUNC_NAME
);
2059 return (scm_from_gnutls_psk_client_credentials (c_cred
));
2063 SCM_DEFINE (scm_gnutls_set_psk_client_credentials_x
,
2064 "set-psk-client-credentials!",
2066 (SCM cred
, SCM username
, SCM key
, SCM key_format
),
2067 "Set the client credentials for @var{cred}, a PSK client "
2068 "credentials object.")
2069 #define FUNC_NAME s_scm_gnutls_set_psk_client_credentials_x
2072 gnutls_psk_client_credentials_t c_cred
;
2073 gnutls_psk_key_flags c_key_format
;
2074 scm_t_array_handle c_handle
;
2077 size_t c_username_len
, c_key_len
;
2078 gnutls_datum_t c_datum
;
2080 c_cred
= scm_to_gnutls_psk_client_credentials (cred
, 1, FUNC_NAME
);
2081 SCM_VALIDATE_STRING (2, username
);
2082 SCM_VALIDATE_ARRAY (3, key
);
2083 c_key_format
= scm_to_gnutls_psk_key_format (key_format
, 4, FUNC_NAME
);
2085 c_username_len
= scm_c_string_length (username
);
2086 c_username
= (char *) alloca (c_username_len
+ 1);
2088 (void) scm_to_locale_stringbuf (username
, c_username
,
2089 c_username_len
+ 1);
2090 c_username
[c_username_len
] = '\0';
2092 c_key
= scm_gnutls_get_array (key
, &c_handle
, &c_key_len
, FUNC_NAME
);
2093 c_datum
.data
= (unsigned char *) c_key
;
2094 c_datum
.size
= c_key_len
;
2096 err
= gnutls_psk_set_client_credentials (c_cred
, c_username
,
2097 &c_datum
, c_key_format
);
2098 scm_gnutls_release_array (&c_handle
);
2100 if (EXPECT_FALSE (err
))
2101 scm_gnutls_error (err
, FUNC_NAME
);
2103 return SCM_UNSPECIFIED
;
2107 SCM_DEFINE (scm_gnutls_server_session_psk_username
,
2108 "server-session-psk-username",
2111 "Return the username associated with PSK server session "
2113 #define FUNC_NAME s_scm_gnutls_server_session_psk_username
2116 const char *c_username
;
2117 gnutls_session_t c_session
;
2119 c_session
= scm_to_gnutls_session (session
, 1, FUNC_NAME
);
2120 c_username
= gnutls_srp_server_get_username (c_session
);
2122 if (EXPECT_FALSE (c_username
== NULL
))
2123 result
= SCM_BOOL_F
;
2125 result
= scm_from_locale_string (c_username
);
2132 /* X.509 certificates. */
2134 SCM_DEFINE (scm_gnutls_import_x509_certificate
, "import-x509-certificate",
2136 (SCM data
, SCM format
),
2137 "Return a new X.509 certificate object resulting from the "
2138 "import of @var{data} (a uniform array) according to "
2140 #define FUNC_NAME s_scm_gnutls_import_x509_certificate
2143 gnutls_x509_crt_t c_cert
;
2144 gnutls_x509_crt_fmt_t c_format
;
2145 gnutls_datum_t c_data_d
;
2146 scm_t_array_handle c_data_handle
;
2150 SCM_VALIDATE_ARRAY (1, data
);
2151 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
2153 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
2155 c_data_d
.data
= (unsigned char *) c_data
;
2156 c_data_d
.size
= c_data_len
;
2158 err
= gnutls_x509_crt_init (&c_cert
);
2159 if (EXPECT_FALSE (err
))
2161 scm_gnutls_release_array (&c_data_handle
);
2162 scm_gnutls_error (err
, FUNC_NAME
);
2165 err
= gnutls_x509_crt_import (c_cert
, &c_data_d
, c_format
);
2166 scm_gnutls_release_array (&c_data_handle
);
2168 if (EXPECT_FALSE (err
))
2170 gnutls_x509_crt_deinit (c_cert
);
2171 scm_gnutls_error (err
, FUNC_NAME
);
2174 return (scm_from_gnutls_x509_certificate (c_cert
));
2178 SCM_DEFINE (scm_gnutls_import_x509_private_key
, "import-x509-private-key",
2180 (SCM data
, SCM format
),
2181 "Return a new X.509 private key object resulting from the "
2182 "import of @var{data} (a uniform array) according to "
2184 #define FUNC_NAME s_scm_gnutls_import_x509_private_key
2187 gnutls_x509_privkey_t c_key
;
2188 gnutls_x509_crt_fmt_t c_format
;
2189 gnutls_datum_t c_data_d
;
2190 scm_t_array_handle c_data_handle
;
2194 SCM_VALIDATE_ARRAY (1, data
);
2195 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
2197 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
2199 c_data_d
.data
= (unsigned char *) c_data
;
2200 c_data_d
.size
= c_data_len
;
2202 err
= gnutls_x509_privkey_init (&c_key
);
2203 if (EXPECT_FALSE (err
))
2205 scm_gnutls_release_array (&c_data_handle
);
2206 scm_gnutls_error (err
, FUNC_NAME
);
2209 err
= gnutls_x509_privkey_import (c_key
, &c_data_d
, c_format
);
2210 scm_gnutls_release_array (&c_data_handle
);
2212 if (EXPECT_FALSE (err
))
2214 gnutls_x509_privkey_deinit (c_key
);
2215 scm_gnutls_error (err
, FUNC_NAME
);
2218 return (scm_from_gnutls_x509_private_key (c_key
));
2222 SCM_DEFINE (scm_gnutls_pkcs8_import_x509_private_key
,
2223 "pkcs8-import-x509-private-key",
2225 (SCM data
, SCM format
, SCM pass
, SCM encrypted
),
2226 "Return a new X.509 private key object resulting from the "
2227 "import of @var{data} (a uniform array) according to "
2228 "@var{format}. Optionally, if @var{pass} is not @code{#f}, "
2229 "it should be a string denoting a passphrase. "
2230 "@var{encrypted} tells whether the private key is encrypted "
2231 "(@code{#t} by default).")
2232 #define FUNC_NAME s_scm_gnutls_pkcs8_import_x509_private_key
2235 gnutls_x509_privkey_t c_key
;
2236 gnutls_x509_crt_fmt_t c_format
;
2237 unsigned int c_flags
;
2238 gnutls_datum_t c_data_d
;
2239 scm_t_array_handle c_data_handle
;
2242 size_t c_data_len
, c_pass_len
;
2244 SCM_VALIDATE_ARRAY (1, data
);
2245 c_format
= scm_to_gnutls_x509_certificate_format (format
, 2, FUNC_NAME
);
2246 if ((pass
== SCM_UNDEFINED
) || (scm_is_false (pass
)))
2250 c_pass_len
= scm_c_string_length (pass
);
2251 c_pass
= (char *) alloca (c_pass_len
+ 1);
2252 (void) scm_to_locale_stringbuf (pass
, c_pass
, c_pass_len
+ 1);
2253 c_pass
[c_pass_len
] = '\0';
2256 if (encrypted
== SCM_UNDEFINED
)
2260 SCM_VALIDATE_BOOL (4, encrypted
);
2261 if (scm_is_true (encrypted
))
2264 c_flags
= GNUTLS_PKCS8_PLAIN
;
2267 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
2269 c_data_d
.data
= (unsigned char *) c_data
;
2270 c_data_d
.size
= c_data_len
;
2272 err
= gnutls_x509_privkey_init (&c_key
);
2273 if (EXPECT_FALSE (err
))
2275 scm_gnutls_release_array (&c_data_handle
);
2276 scm_gnutls_error (err
, FUNC_NAME
);
2279 err
= gnutls_x509_privkey_import_pkcs8 (c_key
, &c_data_d
, c_format
, c_pass
,
2281 scm_gnutls_release_array (&c_data_handle
);
2283 if (EXPECT_FALSE (err
))
2285 gnutls_x509_privkey_deinit (c_key
);
2286 scm_gnutls_error (err
, FUNC_NAME
);
2289 return (scm_from_gnutls_x509_private_key (c_key
));
2293 /* Provide the body of a `get_dn' function. */
2294 #define X509_CERTIFICATE_DN_FUNCTION_BODY(get_the_dn) \
2296 gnutls_x509_crt_t c_cert; \
2300 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME); \
2302 /* Get the DN size. */ \
2303 (void) get_the_dn (c_cert, NULL, &c_dn_len); \
2305 /* Get the DN itself. */ \
2306 c_dn = (char *) alloca (c_dn_len); \
2307 err = get_the_dn (c_cert, c_dn, &c_dn_len); \
2309 if (EXPECT_FALSE (err)) \
2310 scm_gnutls_error (err, FUNC_NAME); \
2312 /* XXX: The returned string is actually ASCII or UTF-8. */ \
2313 return (scm_from_locale_string (c_dn));
2315 SCM_DEFINE (scm_gnutls_x509_certificate_dn
, "x509-certificate-dn",
2318 "Return the distinguished name (DN) of X.509 certificate "
2319 "@var{cert}. The form of the DN is as described in @uref{"
2320 "http://tools.ietf.org/html/rfc2253, RFC 2253}.")
2321 #define FUNC_NAME s_scm_gnutls_x509_certificate_dn
2323 X509_CERTIFICATE_DN_FUNCTION_BODY (gnutls_x509_crt_get_dn
);
2327 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn
,
2328 "x509-certificate-issuer-dn",
2331 "Return the distinguished name (DN) of X.509 certificate "
2333 #define FUNC_NAME s_scm_gnutls_x509_certificate_issuer_dn
2335 X509_CERTIFICATE_DN_FUNCTION_BODY (gnutls_x509_crt_get_issuer_dn
);
2339 #undef X509_CERTIFICATE_DN_FUNCTION_BODY
2342 /* Provide the body of a `get_dn_oid' function. */
2343 #define X509_CERTIFICATE_DN_OID_FUNCTION_BODY(get_dn_oid) \
2345 gnutls_x509_crt_t c_cert; \
2346 unsigned int c_index; \
2348 size_t c_oid_actual_len, c_oid_len; \
2351 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME); \
2352 c_index = scm_to_uint (index); \
2355 c_oid = scm_malloc (c_oid_len); \
2359 c_oid_actual_len = c_oid_len; \
2360 err = get_dn_oid (c_cert, c_index, c_oid, &c_oid_actual_len); \
2361 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) \
2363 c_oid = scm_realloc (c_oid, c_oid_len * 2); \
2367 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER); \
2369 if (EXPECT_FALSE (err)) \
2373 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) \
2374 result = SCM_BOOL_F; \
2376 scm_gnutls_error (err, FUNC_NAME); \
2380 if (c_oid_actual_len < c_oid_len) \
2381 c_oid = scm_realloc (c_oid, c_oid_actual_len); \
2383 result = scm_take_locale_stringn (c_oid, \
2384 c_oid_actual_len); \
2389 SCM_DEFINE (scm_gnutls_x509_certificate_dn_oid
, "x509-certificate-dn-oid",
2391 (SCM cert
, SCM index
),
2392 "Return OID (a string) at @var{index} from @var{cert}. "
2393 "Return @code{#f} if no OID is available at @var{index}.")
2394 #define FUNC_NAME s_scm_gnutls_x509_certificate_dn_oid
2396 X509_CERTIFICATE_DN_OID_FUNCTION_BODY (gnutls_x509_crt_get_dn_oid
);
2400 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn_oid
,
2401 "x509-certificate-issuer-dn-oid",
2403 (SCM cert
, SCM index
),
2404 "Return the OID (a string) at @var{index} from @var{cert}'s "
2405 "issuer DN. Return @code{#f} if no OID is available at "
2407 #define FUNC_NAME s_scm_gnutls_x509_certificate_issuer_dn_oid
2409 X509_CERTIFICATE_DN_OID_FUNCTION_BODY (gnutls_x509_crt_get_issuer_dn_oid
);
2413 #undef X509_CERTIFICATE_DN_OID_FUNCTION_BODY
2416 SCM_DEFINE (scm_gnutls_x509_certificate_matches_hostname_p
,
2417 "x509-certificate-matches-hostname?",
2419 (SCM cert
, SCM hostname
),
2420 "Return true if @var{cert} matches @var{hostname}, a string "
2421 "denoting a DNS host name. This is the basic implementation "
2422 "of @uref{http://tools.ietf.org/html/rfc2818, RFC 2818} (aka. "
2424 #define FUNC_NAME s_scm_gnutls_x509_certificate_matches_hostname_p
2427 gnutls_x509_crt_t c_cert
;
2429 size_t c_hostname_len
;
2431 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2432 SCM_VALIDATE_STRING (2, hostname
);
2434 c_hostname_len
= scm_c_string_length (hostname
);
2435 c_hostname
= (char *) alloca (c_hostname_len
+ 1);
2437 (void) scm_to_locale_stringbuf (hostname
, c_hostname
, c_hostname_len
+ 1);
2438 c_hostname
[c_hostname_len
] = '\0';
2440 if (gnutls_x509_crt_check_hostname (c_cert
, c_hostname
))
2441 result
= SCM_BOOL_T
;
2443 result
= SCM_BOOL_F
;
2449 SCM_DEFINE (scm_gnutls_x509_certificate_signature_algorithm
,
2450 "x509-certificate-signature-algorithm",
2453 "Return the signature algorithm used by @var{cert} (i.e., "
2454 "one of the @code{sign-algorithm/} values).")
2455 #define FUNC_NAME s_scm_gnutls_x509_certificate_signature_algorithm
2458 gnutls_x509_crt_t c_cert
;
2460 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2462 c_result
= gnutls_x509_crt_get_signature_algorithm (c_cert
);
2463 if (EXPECT_FALSE (c_result
< 0))
2464 scm_gnutls_error (c_result
, FUNC_NAME
);
2466 return (scm_from_gnutls_sign_algorithm (c_result
));
2470 SCM_DEFINE (scm_gnutls_x509_certificate_public_key_algorithm
,
2471 "x509-certificate-public-key-algorithm",
2474 "Return two values: the public key algorithm (i.e., "
2475 "one of the @code{pk-algorithm/} values) of @var{cert} "
2476 "and the number of bits used.")
2477 #define FUNC_NAME s_scm_gnutls_x509_certificate_public_key_algorithm
2479 gnutls_x509_crt_t c_cert
;
2480 gnutls_pk_algorithm_t c_pk
;
2481 unsigned int c_bits
;
2483 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2485 c_pk
= gnutls_x509_crt_get_pk_algorithm (c_cert
, &c_bits
);
2487 return (scm_values (scm_list_2 (scm_from_gnutls_pk_algorithm (c_pk
),
2488 scm_from_uint (c_bits
))));
2492 SCM_DEFINE (scm_gnutls_x509_certificate_key_usage
,
2493 "x509-certificate-key-usage",
2496 "Return the key usage of @var{cert} (i.e., a list of "
2497 "@code{key-usage/} values), or the empty list if @var{cert} "
2498 "does not contain such information.")
2499 #define FUNC_NAME s_scm_gnutls_x509_certificate_key_usage
2503 gnutls_x509_crt_t c_cert
;
2504 unsigned int c_usage
, c_critical
;
2506 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2508 err
= gnutls_x509_crt_get_key_usage (c_cert
, &c_usage
, &c_critical
);
2509 if (EXPECT_FALSE (err
))
2511 if (err
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
2514 scm_gnutls_error (err
, FUNC_NAME
);
2517 usage
= scm_from_gnutls_key_usage_flags (c_usage
);
2523 SCM_DEFINE (scm_gnutls_x509_certificate_version
, "x509-certificate-version",
2526 "Return the version of @var{cert}.")
2527 #define FUNC_NAME s_scm_gnutls_x509_certificate_version
2530 gnutls_x509_crt_t c_cert
;
2532 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2534 c_result
= gnutls_x509_crt_get_version (c_cert
);
2535 if (EXPECT_FALSE (c_result
< 0))
2536 scm_gnutls_error (c_result
, FUNC_NAME
);
2538 return (scm_from_int (c_result
));
2542 SCM_DEFINE (scm_gnutls_x509_certificate_key_id
, "x509-certificate-key-id",
2545 "Return a statistically unique ID (a u8vector) for @var{cert} "
2546 "that depends on its public key parameters. This is normally "
2547 "a 20-byte SHA-1 hash.")
2548 #define FUNC_NAME s_scm_gnutls_x509_certificate_key_id
2552 scm_t_array_handle c_id_handle
;
2553 gnutls_x509_crt_t c_cert
;
2555 size_t c_id_len
= 20;
2557 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2559 result
= scm_make_u8vector (scm_from_uint (c_id_len
), SCM_INUM0
);
2560 scm_array_get_handle (result
, &c_id_handle
);
2561 c_id
= scm_array_handle_u8_writable_elements (&c_id_handle
);
2563 err
= gnutls_x509_crt_get_key_id (c_cert
, 0, c_id
, &c_id_len
);
2564 scm_array_handle_release (&c_id_handle
);
2566 if (EXPECT_FALSE (err
))
2567 scm_gnutls_error (err
, FUNC_NAME
);
2573 SCM_DEFINE (scm_gnutls_x509_certificate_authority_key_id
,
2574 "x509-certificate-authority-key-id",
2577 "Return the key ID (a u8vector) of the X.509 certificate "
2578 "authority of @var{cert}.")
2579 #define FUNC_NAME s_scm_gnutls_x509_certificate_authority_key_id
2583 scm_t_array_handle c_id_handle
;
2584 gnutls_x509_crt_t c_cert
;
2586 size_t c_id_len
= 20;
2588 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2590 result
= scm_make_u8vector (scm_from_uint (c_id_len
), SCM_INUM0
);
2591 scm_array_get_handle (result
, &c_id_handle
);
2592 c_id
= scm_array_handle_u8_writable_elements (&c_id_handle
);
2594 err
= gnutls_x509_crt_get_authority_key_id (c_cert
, c_id
, &c_id_len
,
2596 scm_array_handle_release (&c_id_handle
);
2598 if (EXPECT_FALSE (err
))
2599 scm_gnutls_error (err
, FUNC_NAME
);
2605 SCM_DEFINE (scm_gnutls_x509_certificate_subject_key_id
,
2606 "x509-certificate-subject-key-id",
2609 "Return the subject key ID (a u8vector) for @var{cert}.")
2610 #define FUNC_NAME s_scm_gnutls_x509_certificate_subject_key_id
2614 scm_t_array_handle c_id_handle
;
2615 gnutls_x509_crt_t c_cert
;
2617 size_t c_id_len
= 20;
2619 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2621 result
= scm_make_u8vector (scm_from_uint (c_id_len
), SCM_INUM0
);
2622 scm_array_get_handle (result
, &c_id_handle
);
2623 c_id
= scm_array_handle_u8_writable_elements (&c_id_handle
);
2625 err
= gnutls_x509_crt_get_subject_key_id (c_cert
, c_id
, &c_id_len
,
2627 scm_array_handle_release (&c_id_handle
);
2629 if (EXPECT_FALSE (err
))
2630 scm_gnutls_error (err
, FUNC_NAME
);
2636 SCM_DEFINE (scm_gnutls_x509_certificate_subject_alternative_name
,
2637 "x509-certificate-subject-alternative-name",
2639 (SCM cert
, SCM index
),
2640 "Return two values: the alternative name type for @var{cert} "
2641 "(i.e., one of the @code{x509-subject-alternative-name/} values) "
2642 "and the actual subject alternative name (a string) at "
2643 "@var{index}. Both values are @code{#f} if no alternative name "
2644 "is available at @var{index}.")
2645 #define FUNC_NAME s_scm_gnutls_x509_certificate_subject_alternative_name
2649 gnutls_x509_crt_t c_cert
;
2650 unsigned int c_index
;
2652 size_t c_name_len
= 512, c_name_actual_len
;
2654 c_cert
= scm_to_gnutls_x509_certificate (cert
, 1, FUNC_NAME
);
2655 c_index
= scm_to_uint (index
);
2657 c_name
= scm_malloc (c_name_len
);
2660 c_name_actual_len
= c_name_len
;
2661 err
= gnutls_x509_crt_get_subject_alt_name (c_cert
, c_index
,
2662 c_name
, &c_name_actual_len
,
2664 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
2666 c_name
= scm_realloc (c_name
, c_name_len
* 2);
2670 while (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
);
2672 if (EXPECT_FALSE (err
< 0))
2676 if (err
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
2677 result
= scm_values (scm_list_2 (SCM_BOOL_F
, SCM_BOOL_F
));
2679 scm_gnutls_error (err
, FUNC_NAME
);
2683 if (c_name_actual_len
< c_name_len
)
2684 c_name
= scm_realloc (c_name
, c_name_actual_len
);
2687 scm_values (scm_list_2
2688 (scm_from_gnutls_x509_subject_alternative_name (err
),
2689 scm_take_locale_string (c_name
)));
2699 static SCM log_procedure
= SCM_BOOL_F
;
2702 scm_gnutls_log (int level
, const char *str
)
2704 if (scm_is_true (log_procedure
))
2705 (void) scm_call_2 (log_procedure
, scm_from_int (level
),
2706 scm_from_locale_string (str
));
2709 SCM_DEFINE (scm_gnutls_set_log_procedure_x
, "set-log-procedure!",
2712 "Use @var{proc} (a two-argument procedure) as the global "
2713 "GnuTLS log procedure.")
2714 #define FUNC_NAME s_scm_gnutls_set_log_procedure_x
2716 SCM_VALIDATE_PROC (1, proc
);
2718 if (scm_is_true (log_procedure
))
2719 (void) scm_gc_unprotect_object (log_procedure
);
2721 log_procedure
= scm_gc_protect_object (proc
);
2722 gnutls_global_set_log_function (scm_gnutls_log
);
2724 return SCM_UNSPECIFIED
;
2728 SCM_DEFINE (scm_gnutls_set_log_level_x
, "set-log-level!", 1, 0, 0,
2730 "Enable GnuTLS logging up to @var{level} (an integer).")
2731 #define FUNC_NAME s_scm_gnutls_set_log_level_x
2733 unsigned int c_level
;
2735 c_level
= scm_to_uint (level
);
2736 gnutls_global_set_log_level (c_level
);
2738 return SCM_UNSPECIFIED
;
2743 /* Initialization. */
2746 scm_init_gnutls (void)
2750 (void) gnutls_global_init ();
2752 scm_gnutls_define_enums ();
2754 scm_init_gnutls_error ();
2756 scm_init_gnutls_session_record_port_type ();
2759 /* arch-tag: 58420abe-0769-4684-b522-da7f32f4474c