guile: Don't declare `inline' functions that use `alloca ()'.
[gnutls.git] / guile / src / core.c
blobca544d4a6bd7aec1f3ea89b47e9541ad60b4337f
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>. */
20 #include <stdio.h>
21 #include <string.h>
22 #include <gnutls/gnutls.h>
23 #include <libguile.h>
25 #include <alloca.h>
27 #include "enums.h"
28 #include "smobs.h"
29 #include "errors.h"
30 #include "utils.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))
77 /* Bindings. */
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,
90 (void),
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)));
97 #undef FUNC_NAME
99 SCM_DEFINE (scm_gnutls_make_session, "make-session", 1, 0, 0,
100 (SCM end),
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
105 int err;
106 gnutls_session_t c_session;
107 gnutls_connection_end_t c_end;
108 SCM session_data;
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));
122 #undef FUNC_NAME
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
129 int err;
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;
142 #undef FUNC_NAME
144 SCM_DEFINE (scm_gnutls_handshake, "handshake", 1, 0, 0,
145 (SCM session),
146 "Perform a handshake for @var{session}.")
147 #define FUNC_NAME s_scm_gnutls_handshake
149 int err;
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;
160 #undef FUNC_NAME
162 SCM_DEFINE (scm_gnutls_rehandshake, "rehandshake", 1, 0, 0,
163 (SCM session),
164 "Perform a re-handshaking for @var{session}.")
165 #define FUNC_NAME s_scm_gnutls_rehandshake
167 int err;
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;
178 #undef FUNC_NAME
180 SCM_DEFINE (scm_gnutls_alert_get, "alert-get", 1, 0, 0,
181 (SCM session),
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));
194 #undef FUNC_NAME
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
201 int err;
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;
216 #undef FUNC_NAME
218 /* FIXME: Omitting `alert-send-appropriate'. */
221 /* Session accessors. */
223 SCM_DEFINE (scm_gnutls_session_cipher, "session-cipher", 1, 0, 0,
224 (SCM session),
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));
237 #undef FUNC_NAME
239 SCM_DEFINE (scm_gnutls_session_kx, "session-kx", 1, 0, 0,
240 (SCM session),
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));
253 #undef FUNC_NAME
255 SCM_DEFINE (scm_gnutls_session_mac, "session-mac", 1, 0, 0,
256 (SCM session),
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));
269 #undef FUNC_NAME
271 SCM_DEFINE (scm_gnutls_session_compression_method,
272 "session-compression-method", 1, 0, 0,
273 (SCM session),
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));
286 #undef FUNC_NAME
288 SCM_DEFINE (scm_gnutls_session_certificate_type,
289 "session-certificate-type", 1, 0, 0,
290 (SCM session),
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));
303 #undef FUNC_NAME
305 SCM_DEFINE (scm_gnutls_session_protocol, "session-protocol", 1, 0, 0,
306 (SCM session),
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));
319 #undef FUNC_NAME
321 SCM_DEFINE (scm_gnutls_session_authentication_type,
322 "session-authentication-type",
323 1, 0, 0,
324 (SCM session),
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));
338 #undef FUNC_NAME
340 SCM_DEFINE (scm_gnutls_session_server_authentication_type,
341 "session-server-authentication-type",
342 1, 0, 0,
343 (SCM session),
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));
357 #undef FUNC_NAME
359 SCM_DEFINE (scm_gnutls_session_client_authentication_type,
360 "session-client-authentication-type",
361 1, 0, 0,
362 (SCM session),
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));
376 #undef FUNC_NAME
378 SCM_DEFINE (scm_gnutls_session_peer_certificate_chain,
379 "session-peer-certificate-chain",
380 1, 0, 0,
381 (SCM session),
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 "
387 "was sent.")
388 #define FUNC_NAME s_scm_gnutls_session_peer_certificate_chain
390 SCM result;
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))
400 result = SCM_EOL;
401 else
403 SCM pair;
404 unsigned int i;
406 result = scm_make_list (scm_from_uint (c_list_size), SCM_UNSPECIFIED);
408 for (i = 0, pair = result;
409 i < c_list_size;
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));
424 return result;
426 #undef FUNC_NAME
428 SCM_DEFINE (scm_gnutls_session_our_certificate_chain,
429 "session-our-certificate-chain",
430 1, 0, 0,
431 (SCM session),
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
438 SCM result;
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))
451 result = SCM_EOL;
452 else
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));
463 return result;
465 #undef FUNC_NAME
467 SCM_DEFINE (scm_gnutls_set_server_session_certificate_request_x,
468 "set-server-session-certificate-request!",
469 2, 0, 0,
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;
487 #undef FUNC_NAME
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,
496 (SCM session),
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;
507 #undef FUNC_NAME
509 SCM_DEFINE (scm_gnutls_set_default_export_priority_x,
510 "set-session-default-export-priority!", 1, 0, 0,
511 (SCM session),
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;
522 #undef FUNC_NAME
524 SCM_DEFINE (scm_gnutls_cipher_suite_to_string, "cipher-suite->string",
525 3, 0, 0,
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;
533 const char *c_name;
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));
543 #undef FUNC_NAME
545 SCM_DEFINE (scm_gnutls_set_session_credentials_x, "set-session-credentials!",
546 2, 0, 0,
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
551 int err = 0;
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,
561 FUNC_NAME);
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,
569 FUNC_NAME);
570 err = gnutls_credentials_set (c_session, GNUTLS_CRD_ANON, c_cred);
572 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_anonymous_server_credentials,
573 cred))
575 gnutls_anon_server_credentials_t c_cred;
577 c_cred = scm_to_gnutls_anonymous_server_credentials (cred, 2,
578 FUNC_NAME);
579 err = gnutls_credentials_set (c_session, GNUTLS_CRD_ANON, c_cred);
581 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_client_credentials,
582 cred))
584 gnutls_srp_client_credentials_t c_cred;
586 c_cred = scm_to_gnutls_srp_client_credentials (cred, 2,
587 FUNC_NAME);
588 err = gnutls_credentials_set (c_session, GNUTLS_CRD_SRP, c_cred);
590 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_srp_server_credentials,
591 cred))
593 gnutls_srp_server_credentials_t c_cred;
595 c_cred = scm_to_gnutls_srp_server_credentials (cred, 2,
596 FUNC_NAME);
597 err = gnutls_credentials_set (c_session, GNUTLS_CRD_SRP, c_cred);
599 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_client_credentials,
600 cred))
602 gnutls_psk_client_credentials_t c_cred;
604 c_cred = scm_to_gnutls_psk_client_credentials (cred, 2,
605 FUNC_NAME);
606 err = gnutls_credentials_set (c_session, GNUTLS_CRD_PSK, c_cred);
608 else if (SCM_SMOB_PREDICATE (scm_tc16_gnutls_psk_server_credentials,
609 cred))
611 gnutls_psk_server_credentials_t c_cred;
613 c_cred = scm_to_gnutls_psk_server_credentials (cred, 2,
614 FUNC_NAME);
615 err = gnutls_credentials_set (c_session, GNUTLS_CRD_PSK, c_cred);
617 else
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;
625 #undef FUNC_NAME
628 /* Record layer. */
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 "
633 "@var{session}.")
634 #define FUNC_NAME s_scm_gnutls_record_send
636 SCM result;
637 ssize_t c_result;
638 gnutls_session_t c_session;
639 scm_t_array_handle c_handle;
640 const char *c_array;
641 size_t c_len;
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,
647 FUNC_NAME);
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);
655 else
656 scm_gnutls_error (c_result, FUNC_NAME);
658 return (result);
660 #undef 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 "
666 "received.")
667 #define FUNC_NAME s_scm_gnutls_record_receive_x
669 SCM result;
670 ssize_t c_result;
671 gnutls_session_t c_session;
672 scm_t_array_handle c_handle;
673 char *c_array;
674 size_t c_len;
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,
680 FUNC_NAME);
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);
688 else
689 scm_gnutls_error (c_result, FUNC_NAME);
691 return (result);
693 #undef 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. */
710 static SCM
711 mark_session_record_port (SCM port)
713 return (SCM_GNUTLS_SESSION_RECORD_PORT_SESSION (port));
716 static size_t
717 free_session_record_port (SCM port)
718 #define FUNC_NAME "free_session_record_port"
720 SCM session;
721 scm_t_port *c_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);
742 return 0;
744 #undef FUNC_NAME
746 /* Data passed to `do_fill_port ()'. */
747 typedef struct
749 scm_t_port *c_port;
750 gnutls_session_t c_session;
751 } fill_port_data_t;
753 /* Actually fill a session record port (see below). */
754 static void *
755 do_fill_port (void *data)
757 int chr;
758 ssize_t result;
759 scm_t_port *c_port;
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)
772 chr = EOF;
773 else
774 scm_gnutls_error (result, "fill_session_record_port_input");
776 return ((void *) chr);
779 /* Fill in the input buffer of PORT. */
780 static int
781 fill_session_record_port_input (SCM port)
782 #define FUNC_NAME "fill_session_record_port_input"
784 int chr;
785 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
787 if (c_port->read_pos >= c_port->read_end)
789 SCM session;
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);
803 else
804 /* SESSION's underlying transport is a port, so don't leave "Guile
805 mode". */
806 chr = (int) do_fill_port (&c_args);
808 else
809 chr = (int) *c_port->read_pos;
811 return chr;
813 #undef FUNC_NAME
815 /* Write SIZE octets from DATA to PORT. */
816 static void
817 write_to_session_record_port (SCM port, const void *data, size_t size)
818 #define FUNC_NAME "write_to_session_record_port"
820 SCM session;
821 gnutls_session_t c_session;
822 ssize_t c_result;
823 size_t c_sent = 0;
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,
831 size - c_sent);
832 if (EXPECT_FALSE (c_result < 0))
833 scm_gnutls_error (c_result, FUNC_NAME);
834 else
835 c_sent += c_result;
838 #undef FUNC_NAME
840 /* Return a new session port for SESSION. */
841 static inline SCM
842 make_session_record_port (SCM session)
844 SCM port;
845 scm_t_port *c_port;
846 unsigned char *c_port_buf;
847 const unsigned long mode_bits = SCM_OPN | SCM_RDNG | SCM_WRTNG;
849 c_port_buf =
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;
869 return (port);
872 SCM_DEFINE (scm_gnutls_session_record_port, "session-record-port", 1, 0, 0,
873 (SCM session),
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 "
877 "@code{eq?}).")
878 #define FUNC_NAME s_scm_gnutls_session_record_port
880 SCM 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);
893 return (port);
895 #undef FUNC_NAME
897 /* Create the session port type. */
898 static inline void
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);
910 /* Transport. */
912 SCM_DEFINE (scm_gnutls_set_session_transport_fd_x, "set-session-transport-fd!",
913 2, 0, 0,
914 (SCM session, SCM fd),
915 "Use file descriptor @var{fd} as the underlying transport for "
916 "@var{session}.")
917 #define FUNC_NAME s_scm_gnutls_set_session_transport_fd_x
919 gnutls_session_t c_session;
920 int c_fd;
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;
931 #undef FUNC_NAME
933 /* Pull SIZE octets from TRANSPORT (a Scheme port) into DATA. */
934 static ssize_t
935 pull_from_port (gnutls_transport_ptr_t transport, void *data, size_t size)
937 SCM port;
938 ssize_t result;
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). */
948 static ssize_t
949 push_to_port (gnutls_transport_ptr_t transport, const void *data,
950 size_t size)
952 SCM port;
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. */
959 return (size);
962 SCM_DEFINE (scm_gnutls_set_session_transport_port_x,
963 "set-session-transport-port!",
964 2, 0, 0,
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;
988 #undef FUNC_NAME
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'. */
1002 static inline SCM
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
1008 int err;
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));
1042 #undef FUNC_NAME
1045 SCM_DEFINE (scm_gnutls_make_dh_parameters, "make-dh-parameters", 1, 0, 0,
1046 (SCM bits),
1047 "Return new Diffie-Hellman parameters.")
1048 #define FUNC_NAME s_scm_gnutls_make_dh_parameters
1050 int err;
1051 unsigned c_bits;
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));
1069 #undef FUNC_NAME
1071 SCM_DEFINE (scm_gnutls_pkcs3_import_dh_parameters,
1072 "pkcs3-import-dh-parameters",
1073 2, 0, 0,
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
1081 int err;
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;
1086 size_t c_len;
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));
1113 #undef FUNC_NAME
1115 SCM_DEFINE (scm_gnutls_pkcs3_export_dh_parameters,
1116 "pkcs3-export-dh-parameters",
1117 2, 0, 0,
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
1125 SCM result;
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);
1137 return (result);
1139 #undef 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;
1157 #undef FUNC_NAME
1160 /* Anonymous credentials. */
1162 SCM_DEFINE (scm_gnutls_make_anon_server_credentials,
1163 "make-anonymous-server-credentials",
1164 0, 0, 0, (void),
1165 "Return anonymous server credentials.")
1166 #define FUNC_NAME s_scm_gnutls_make_anon_server_credentials
1168 int err;
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));
1178 #undef FUNC_NAME
1180 SCM_DEFINE (scm_gnutls_make_anon_client_credentials,
1181 "make-anonymous-client-credentials",
1182 0, 0, 0, (void),
1183 "Return anonymous client credentials.")
1184 #define FUNC_NAME s_scm_gnutls_make_anon_client_credentials
1186 int err;
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));
1196 #undef FUNC_NAME
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,
1209 FUNC_NAME);
1210 c_dh_params = scm_to_gnutls_dh_parameters (dh_params, 2,
1211 FUNC_NAME);
1213 gnutls_anon_set_server_dh_params (c_cred, c_dh_params);
1215 return SCM_UNSPECIFIED;
1217 #undef FUNC_NAME
1220 /* RSA parameters. */
1222 SCM_DEFINE (scm_gnutls_make_rsa_parameters, "make-rsa-parameters", 1, 0, 0,
1223 (SCM bits),
1224 "Return new RSA parameters.")
1225 #define FUNC_NAME s_scm_gnutls_make_rsa_parameters
1227 int err;
1228 unsigned c_bits;
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));
1246 #undef FUNC_NAME
1248 SCM_DEFINE (scm_gnutls_pkcs1_import_rsa_parameters,
1249 "pkcs1-import-rsa-parameters",
1250 2, 0, 0,
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
1258 int err;
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;
1263 size_t c_len;
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));
1290 #undef FUNC_NAME
1292 SCM_DEFINE (scm_gnutls_pkcs1_export_rsa_parameters,
1293 "pkcs1-export-rsa-parameters",
1294 2, 0, 0,
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
1302 SCM result;
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);
1314 return (result);
1316 #undef FUNC_NAME
1319 /* Certificate credentials. */
1321 typedef int (* certificate_set_file_function_t) (gnutls_certificate_credentials_t,
1322 const char *,
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. */
1330 static unsigned int
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
1336 int err;
1337 char *c_file;
1338 size_t c_file_len;
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);
1360 #undef FUNC_NAME
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
1369 int err;
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;
1374 const char *c_data;
1375 size_t c_len;
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);
1394 #undef FUNC_NAME
1397 SCM_DEFINE (scm_gnutls_make_certificate_credentials,
1398 "make-certificate-credentials",
1399 0, 0, 0,
1400 (void),
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
1405 int err;
1406 gnutls_certificate_credentials_t c_cred;
1408 err = gnutls_certificate_allocate_credentials (&c_cred);
1409 if (err)
1410 scm_gnutls_error (err, FUNC_NAME);
1412 return (scm_from_gnutls_certificate_credentials (c_cred));
1414 #undef FUNC_NAME
1416 SCM_DEFINE (scm_gnutls_set_certificate_credentials_dh_params_x,
1417 "set-certificate-credentials-dh-parameters!",
1418 2, 0, 0,
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;
1434 #undef FUNC_NAME
1436 SCM_DEFINE (scm_gnutls_set_certificate_credentials_rsa_export_params_x,
1437 "set-certificate-credentials-rsa-export-parameters!",
1438 2, 0, 0,
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;
1454 #undef FUNC_NAME
1456 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_files_x,
1457 "set-certificate-credentials-x509-key-files!",
1458 4, 0, 0,
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
1464 int err;
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,
1489 c_format);
1490 if (EXPECT_FALSE (err))
1491 scm_gnutls_error (err, FUNC_NAME);
1493 return SCM_UNSPECIFIED;
1495 #undef FUNC_NAME
1497 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_file_x,
1498 "set-certificate-credentials-x509-trust-file!",
1499 3, 0, 0,
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
1506 unsigned int count;
1508 count = set_certificate_file (gnutls_certificate_set_x509_trust_file,
1509 cred, file, format,
1510 FUNC_NAME);
1512 return scm_from_uint (count);
1514 #undef FUNC_NAME
1516 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_file_x,
1517 "set-certificate-credentials-x509-crl-file!",
1518 3, 0, 0,
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
1525 unsigned int count;
1527 count = set_certificate_file (gnutls_certificate_set_x509_crl_file,
1528 cred, file, format,
1529 FUNC_NAME);
1531 return scm_from_uint (count);
1533 #undef FUNC_NAME
1535 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_trust_data_x,
1536 "set-certificate-credentials-x509-trust-data!",
1537 3, 0, 0,
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
1544 unsigned int count;
1546 count = set_certificate_data (gnutls_certificate_set_x509_trust_mem,
1547 cred, data, format,
1548 FUNC_NAME);
1550 return scm_from_uint (count);
1552 #undef FUNC_NAME
1554 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_crl_data_x,
1555 "set-certificate-credentials-x509-crl-data!",
1556 3, 0, 0,
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
1563 unsigned int count;
1565 count = set_certificate_data (gnutls_certificate_set_x509_crl_mem,
1566 cred, data, format,
1567 FUNC_NAME);
1569 return scm_from_uint (count);
1571 #undef FUNC_NAME
1573 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_key_data_x,
1574 "set-certificate-credentials-x509-key-data!",
1575 4, 0, 0,
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 "
1580 "@var{cred}.")
1581 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_key_data_x
1583 int err;
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,
1599 FUNC_NAME);
1600 c_key = scm_gnutls_get_array (key, &c_key_handle, &c_key_len,
1601 FUNC_NAME);
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,
1609 c_format);
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;
1618 #undef FUNC_NAME
1620 SCM_DEFINE (scm_gnutls_set_certificate_credentials_x509_keys_x,
1621 "set-certificate-credentials-x509-keys!",
1622 3, 0, 0,
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 "
1626 "@var{privkey}.")
1627 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_x509_keys_x
1629 int err;
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));
1640 for (i = 0;
1641 scm_is_pair (certs);
1642 certs = SCM_CDR (certs), i++)
1644 c_certs[i] = scm_to_gnutls_x509_certificate (SCM_CAR (certs),
1645 2, FUNC_NAME);
1648 err = gnutls_certificate_set_x509_key (c_cred, c_certs, c_cert_count,
1649 c_key);
1650 if (EXPECT_FALSE (err))
1651 scm_gnutls_error (err, FUNC_NAME);
1653 return SCM_UNSPECIFIED;
1655 #undef FUNC_NAME
1657 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_limits_x,
1658 "set-certificate-credentials-verify-limits!",
1659 3, 0, 0,
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;
1678 #undef FUNC_NAME
1680 SCM_DEFINE (scm_gnutls_set_certificate_credentials_verify_flags_x,
1681 "set-certificate-credentials-verify-flags!",
1682 1, 0, 1,
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;
1705 #undef FUNC_NAME
1707 SCM_DEFINE (scm_gnutls_peer_certificate_status, "peer-certificate-status",
1708 1, 0, 0,
1709 (SCM session),
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
1716 int err;
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), \
1731 result); \
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);
1745 #undef MATCH_STATUS
1747 return (result);
1749 #undef FUNC_NAME
1752 /* SRP credentials. */
1754 SCM_DEFINE (scm_gnutls_make_srp_server_credentials,
1755 "make-srp-server-credentials",
1756 0, 0, 0,
1757 (void),
1758 "Return new SRP server credentials.")
1759 #define FUNC_NAME s_scm_gnutls_make_srp_server_credentials
1761 int err;
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));
1770 #undef FUNC_NAME
1772 SCM_DEFINE (scm_gnutls_set_srp_server_credentials_files_x,
1773 "set-srp-server-credentials-files!",
1774 3, 0, 0,
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
1780 int err;
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;
1809 #undef FUNC_NAME
1811 SCM_DEFINE (scm_gnutls_make_srp_client_credentials,
1812 "make-srp-client-credentials",
1813 0, 0, 0,
1814 (void),
1815 "Return new SRP client credentials.")
1816 #define FUNC_NAME s_scm_gnutls_make_srp_client_credentials
1818 int err;
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));
1827 #undef FUNC_NAME
1830 SCM_DEFINE (scm_gnutls_set_srp_client_credentials_x,
1831 "set-srp-client-credentials!",
1832 3, 0, 0,
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
1838 int err;
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,
1861 c_password);
1862 if (EXPECT_FALSE (err))
1863 scm_gnutls_error (err, FUNC_NAME);
1865 return SCM_UNSPECIFIED;
1867 #undef FUNC_NAME
1869 SCM_DEFINE (scm_gnutls_server_session_srp_username,
1870 "server-session-srp-username",
1871 1, 0, 0,
1872 (SCM session),
1873 "Return the SRP username used in @var{session} (a server-side "
1874 "session).")
1875 #define FUNC_NAME s_scm_gnutls_server_session_srp_username
1877 SCM result;
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;
1886 else
1887 result = scm_from_locale_string (c_username);
1889 return (result);
1891 #undef FUNC_NAME
1893 SCM_DEFINE (scm_gnutls_srp_base64_encode, "srp-base64-encode",
1894 1, 0, 0,
1895 (SCM str),
1896 "Encode @var{str} using SRP's base64 algorithm. Return "
1897 "the encoded string.")
1898 #define FUNC_NAME s_scm_gnutls_srp_base64_encode
1900 int err;
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)
1928 char *c_new_buf;
1930 c_new_buf = scm_realloc (c_result, c_result_len * 2);
1931 if (EXPECT_FALSE (c_new_buf == NULL))
1933 free (c_result);
1934 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR, FUNC_NAME);
1936 else
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));
1953 #undef FUNC_NAME
1955 SCM_DEFINE (scm_gnutls_srp_base64_decode, "srp-base64-decode",
1956 1, 0, 0,
1957 (SCM str),
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
1962 int err;
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
1975 string. */
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));
1992 #undef FUNC_NAME
1995 /* PSK credentials. */
1997 SCM_DEFINE (scm_gnutls_make_psk_server_credentials,
1998 "make-psk-server-credentials",
1999 0, 0, 0,
2000 (void),
2001 "Return new PSK server credentials.")
2002 #define FUNC_NAME s_scm_gnutls_make_psk_server_credentials
2004 int err;
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));
2013 #undef FUNC_NAME
2015 SCM_DEFINE (scm_gnutls_set_psk_server_credentials_file_x,
2016 "set-psk-server-credentials-file!",
2017 2, 0, 0,
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
2023 int err;
2024 gnutls_psk_server_credentials_t c_cred;
2025 char *c_file;
2026 size_t c_file_len;
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;
2043 #undef FUNC_NAME
2045 SCM_DEFINE (scm_gnutls_make_psk_client_credentials,
2046 "make-psk-client-credentials",
2047 0, 0, 0,
2048 (void),
2049 "Return a new PSK client credentials object.")
2050 #define FUNC_NAME s_scm_gnutls_make_psk_client_credentials
2052 int err;
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));
2061 #undef FUNC_NAME
2063 SCM_DEFINE (scm_gnutls_set_psk_client_credentials_x,
2064 "set-psk-client-credentials!",
2065 4, 0, 0,
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
2071 int err;
2072 gnutls_psk_client_credentials_t c_cred;
2073 gnutls_psk_key_flags c_key_format;
2074 scm_t_array_handle c_handle;
2075 const char *c_key;
2076 char *c_username;
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;
2105 #undef FUNC_NAME
2107 SCM_DEFINE (scm_gnutls_server_session_psk_username,
2108 "server-session-psk-username",
2109 1, 0, 0,
2110 (SCM session),
2111 "Return the username associated with PSK server session "
2112 "@var{session}.")
2113 #define FUNC_NAME s_scm_gnutls_server_session_psk_username
2115 SCM result;
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;
2124 else
2125 result = scm_from_locale_string (c_username);
2127 return (result);
2129 #undef FUNC_NAME
2132 /* X.509 certificates. */
2134 SCM_DEFINE (scm_gnutls_import_x509_certificate, "import-x509-certificate",
2135 2, 0, 0,
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 "
2139 "@var{format}.")
2140 #define FUNC_NAME s_scm_gnutls_import_x509_certificate
2142 int err;
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;
2147 const char *c_data;
2148 size_t c_data_len;
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,
2154 FUNC_NAME);
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));
2176 #undef FUNC_NAME
2178 SCM_DEFINE (scm_gnutls_import_x509_private_key, "import-x509-private-key",
2179 2, 0, 0,
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 "
2183 "@var{format}.")
2184 #define FUNC_NAME s_scm_gnutls_import_x509_private_key
2186 int err;
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;
2191 const char *c_data;
2192 size_t c_data_len;
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,
2198 FUNC_NAME);
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));
2220 #undef FUNC_NAME
2222 SCM_DEFINE (scm_gnutls_pkcs8_import_x509_private_key,
2223 "pkcs8-import-x509-private-key",
2224 2, 2, 0,
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
2234 int err;
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;
2240 const char *c_data;
2241 char *c_pass;
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)))
2247 c_pass = NULL;
2248 else
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)
2257 c_flags = 0;
2258 else
2260 SCM_VALIDATE_BOOL (4, encrypted);
2261 if (scm_is_true (encrypted))
2262 c_flags = 0;
2263 else
2264 c_flags = GNUTLS_PKCS8_PLAIN;
2267 c_data = scm_gnutls_get_array (data, &c_data_handle, &c_data_len,
2268 FUNC_NAME);
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,
2280 c_flags);
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));
2291 #undef FUNC_NAME
2293 /* Provide the body of a `get_dn' function. */
2294 #define X509_CERTIFICATE_DN_FUNCTION_BODY(get_the_dn) \
2295 int err; \
2296 gnutls_x509_crt_t c_cert; \
2297 char *c_dn; \
2298 size_t c_dn_len; \
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",
2316 1, 0, 0,
2317 (SCM cert),
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);
2325 #undef FUNC_NAME
2327 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn,
2328 "x509-certificate-issuer-dn",
2329 1, 0, 0,
2330 (SCM cert),
2331 "Return the distinguished name (DN) of X.509 certificate "
2332 "@var{cert}.")
2333 #define FUNC_NAME s_scm_gnutls_x509_certificate_issuer_dn
2335 X509_CERTIFICATE_DN_FUNCTION_BODY (gnutls_x509_crt_get_issuer_dn);
2337 #undef FUNC_NAME
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) \
2344 int err; \
2345 gnutls_x509_crt_t c_cert; \
2346 unsigned int c_index; \
2347 char *c_oid; \
2348 size_t c_oid_actual_len, c_oid_len; \
2349 SCM result; \
2351 c_cert = scm_to_gnutls_x509_certificate (cert, 1, FUNC_NAME); \
2352 c_index = scm_to_uint (index); \
2354 c_oid_len = 256; \
2355 c_oid = scm_malloc (c_oid_len); \
2357 do \
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); \
2364 c_oid_len *= 2; \
2367 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER); \
2369 if (EXPECT_FALSE (err)) \
2371 free (c_oid); \
2373 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) \
2374 result = SCM_BOOL_F; \
2375 else \
2376 scm_gnutls_error (err, FUNC_NAME); \
2378 else \
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); \
2387 return result;
2389 SCM_DEFINE (scm_gnutls_x509_certificate_dn_oid, "x509-certificate-dn-oid",
2390 2, 0, 0,
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);
2398 #undef FUNC_NAME
2400 SCM_DEFINE (scm_gnutls_x509_certificate_issuer_dn_oid,
2401 "x509-certificate-issuer-dn-oid",
2402 2, 0, 0,
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 "
2406 "@var{index}.")
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);
2411 #undef FUNC_NAME
2413 #undef X509_CERTIFICATE_DN_OID_FUNCTION_BODY
2416 SCM_DEFINE (scm_gnutls_x509_certificate_matches_hostname_p,
2417 "x509-certificate-matches-hostname?",
2418 2, 0, 0,
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. "
2423 "HTTPS).")
2424 #define FUNC_NAME s_scm_gnutls_x509_certificate_matches_hostname_p
2426 SCM result;
2427 gnutls_x509_crt_t c_cert;
2428 char *c_hostname;
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;
2442 else
2443 result = SCM_BOOL_F;
2445 return result;
2447 #undef FUNC_NAME
2449 SCM_DEFINE (scm_gnutls_x509_certificate_signature_algorithm,
2450 "x509-certificate-signature-algorithm",
2451 1, 0, 0,
2452 (SCM cert),
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
2457 int c_result;
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));
2468 #undef FUNC_NAME
2470 SCM_DEFINE (scm_gnutls_x509_certificate_public_key_algorithm,
2471 "x509-certificate-public-key-algorithm",
2472 1, 0, 0,
2473 (SCM cert),
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))));
2490 #undef FUNC_NAME
2492 SCM_DEFINE (scm_gnutls_x509_certificate_key_usage,
2493 "x509-certificate-key-usage",
2494 1, 0, 0,
2495 (SCM cert),
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
2501 int err;
2502 SCM 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)
2512 usage = SCM_EOL;
2513 else
2514 scm_gnutls_error (err, FUNC_NAME);
2516 else
2517 usage = scm_from_gnutls_key_usage_flags (c_usage);
2519 return usage;
2521 #undef FUNC_NAME
2523 SCM_DEFINE (scm_gnutls_x509_certificate_version, "x509-certificate-version",
2524 1, 0, 0,
2525 (SCM cert),
2526 "Return the version of @var{cert}.")
2527 #define FUNC_NAME s_scm_gnutls_x509_certificate_version
2529 int c_result;
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));
2540 #undef FUNC_NAME
2542 SCM_DEFINE (scm_gnutls_x509_certificate_key_id, "x509-certificate-key-id",
2543 1, 0, 0,
2544 (SCM cert),
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
2550 int err;
2551 SCM result;
2552 scm_t_array_handle c_id_handle;
2553 gnutls_x509_crt_t c_cert;
2554 scm_t_uint8 *c_id;
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);
2569 return result;
2571 #undef FUNC_NAME
2573 SCM_DEFINE (scm_gnutls_x509_certificate_authority_key_id,
2574 "x509-certificate-authority-key-id",
2575 1, 0, 0,
2576 (SCM cert),
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
2581 int err;
2582 SCM result;
2583 scm_t_array_handle c_id_handle;
2584 gnutls_x509_crt_t c_cert;
2585 scm_t_uint8 *c_id;
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,
2595 NULL);
2596 scm_array_handle_release (&c_id_handle);
2598 if (EXPECT_FALSE (err))
2599 scm_gnutls_error (err, FUNC_NAME);
2601 return result;
2603 #undef FUNC_NAME
2605 SCM_DEFINE (scm_gnutls_x509_certificate_subject_key_id,
2606 "x509-certificate-subject-key-id",
2607 1, 0, 0,
2608 (SCM cert),
2609 "Return the subject key ID (a u8vector) for @var{cert}.")
2610 #define FUNC_NAME s_scm_gnutls_x509_certificate_subject_key_id
2612 int err;
2613 SCM result;
2614 scm_t_array_handle c_id_handle;
2615 gnutls_x509_crt_t c_cert;
2616 scm_t_uint8 *c_id;
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,
2626 NULL);
2627 scm_array_handle_release (&c_id_handle);
2629 if (EXPECT_FALSE (err))
2630 scm_gnutls_error (err, FUNC_NAME);
2632 return result;
2634 #undef FUNC_NAME
2636 SCM_DEFINE (scm_gnutls_x509_certificate_subject_alternative_name,
2637 "x509-certificate-subject-alternative-name",
2638 2, 0, 0,
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
2647 int err;
2648 SCM result;
2649 gnutls_x509_crt_t c_cert;
2650 unsigned int c_index;
2651 char *c_name;
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,
2663 NULL);
2664 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
2666 c_name = scm_realloc (c_name, c_name_len * 2);
2667 c_name_len *= 2;
2670 while (err == GNUTLS_E_SHORT_MEMORY_BUFFER);
2672 if (EXPECT_FALSE (err < 0))
2674 free (c_name);
2676 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2677 result = scm_values (scm_list_2 (SCM_BOOL_F, SCM_BOOL_F));
2678 else
2679 scm_gnutls_error (err, FUNC_NAME);
2681 else
2683 if (c_name_actual_len < c_name_len)
2684 c_name = scm_realloc (c_name, c_name_actual_len);
2686 result =
2687 scm_values (scm_list_2
2688 (scm_from_gnutls_x509_subject_alternative_name (err),
2689 scm_take_locale_string (c_name)));
2692 return result;
2694 #undef FUNC_NAME
2697 /* Debugging. */
2699 static SCM log_procedure = SCM_BOOL_F;
2701 static void
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!",
2710 1, 0, 0,
2711 (SCM proc),
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;
2726 #undef FUNC_NAME
2728 SCM_DEFINE (scm_gnutls_set_log_level_x, "set-log-level!", 1, 0, 0,
2729 (SCM level),
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;
2740 #undef FUNC_NAME
2743 /* Initialization. */
2745 void
2746 scm_init_gnutls (void)
2748 #include "core.x"
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