1 /* GNUTLS-EXTRA --- Guile bindings for GNUTLS-EXTRA.
2 Copyright (C) 2007 Free Software Foundation
4 GNUTLS-EXTRA is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 GNUTLS-EXTRA 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GNUTLS-EXTRA; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Important note: As written above, this part of the code is ditributed
19 under the GPL, not the LGPL. */
21 /* Written by Ludovic Courtès <ludo@chbouib.org>. */
25 #include <gnutls/gnutls.h>
26 #include <gnutls/extra.h>
27 #include <gnutls/openpgp.h>
36 #include "extra-enums.h"
37 #include "extra-smobs.h"
41 /* SMOB and enums type definitions. */
43 #include "extra-smob-types.i.c"
44 #include "extra-enum-map.i.c"
50 /* Maximum size we support for the name of OpenPGP keys. */
51 #define GUILE_GNUTLS_MAX_OPENPGP_NAME_LENGTH 2048
53 SCM_DEFINE (scm_gnutls_import_openpgp_certificate
, "import-openpgp-certificate",
55 (SCM data
, SCM format
),
56 "Return a new OpenPGP certificate object resulting from the "
57 "import of @var{data} (a uniform array) according to "
59 #define FUNC_NAME s_scm_gnutls_import_openpgp_certificate
62 gnutls_openpgp_crt_t c_key
;
63 gnutls_openpgp_crt_fmt_t c_format
;
64 gnutls_datum_t c_data_d
;
65 scm_t_array_handle c_data_handle
;
69 SCM_VALIDATE_ARRAY (1, data
);
70 c_format
= scm_to_gnutls_openpgp_certificate_format (format
, 2, FUNC_NAME
);
72 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
74 c_data_d
.data
= (unsigned char *) c_data
;
75 c_data_d
.size
= c_data_len
;
77 err
= gnutls_openpgp_crt_init (&c_key
);
78 if (EXPECT_FALSE (err
))
80 scm_gnutls_release_array (&c_data_handle
);
81 scm_gnutls_error (err
, FUNC_NAME
);
84 err
= gnutls_openpgp_crt_import (c_key
, &c_data_d
, c_format
);
85 scm_gnutls_release_array (&c_data_handle
);
87 if (EXPECT_FALSE (err
))
89 gnutls_openpgp_crt_deinit (c_key
);
90 scm_gnutls_error (err
, FUNC_NAME
);
93 return (scm_from_gnutls_openpgp_certificate (c_key
));
97 SCM_DEFINE (scm_gnutls_import_openpgp_private_key
, "import-openpgp-private-key",
99 (SCM data
, SCM format
, SCM pass
),
100 "Return a new OpenPGP private key object resulting from the "
101 "import of @var{data} (a uniform array) according to "
102 "@var{format}. Optionally, a passphrase may be provided.")
103 #define FUNC_NAME s_scm_gnutls_import_openpgp_private_key
106 gnutls_openpgp_privkey_t c_key
;
107 gnutls_openpgp_crt_fmt_t c_format
;
108 gnutls_datum_t c_data_d
;
109 scm_t_array_handle c_data_handle
;
112 size_t c_data_len
, c_pass_len
;
114 SCM_VALIDATE_ARRAY (1, data
);
115 c_format
= scm_to_gnutls_openpgp_certificate_format (format
, 2, FUNC_NAME
);
116 if ((pass
== SCM_UNDEFINED
) || (scm_is_false (pass
)))
120 c_pass_len
= scm_c_string_length (pass
);
121 c_pass
= (char *) alloca (c_pass_len
+ 1);
122 (void) scm_to_locale_stringbuf (pass
, c_pass
, c_pass_len
+ 1);
123 c_pass
[c_pass_len
] = '\0';
126 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
128 c_data_d
.data
= (unsigned char *) c_data
;
129 c_data_d
.size
= c_data_len
;
131 err
= gnutls_openpgp_privkey_init (&c_key
);
132 if (EXPECT_FALSE (err
))
134 scm_gnutls_release_array (&c_data_handle
);
135 scm_gnutls_error (err
, FUNC_NAME
);
138 err
= gnutls_openpgp_privkey_import (c_key
, &c_data_d
, c_format
, c_pass
,
139 0 /* currently unused */);
140 scm_gnutls_release_array (&c_data_handle
);
142 if (EXPECT_FALSE (err
))
144 gnutls_openpgp_privkey_deinit (c_key
);
145 scm_gnutls_error (err
, FUNC_NAME
);
148 return (scm_from_gnutls_openpgp_private_key (c_key
));
152 SCM_DEFINE (scm_gnutls_openpgp_certificate_id
, "openpgp-certificate-id",
155 "Return the ID (an 8-element u8vector) of certificate "
157 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_id
161 gnutls_openpgp_crt_t c_key
;
163 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
165 c_id
= (unsigned char * ) malloc (8);
167 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
169 err
= gnutls_openpgp_crt_get_id (c_key
, c_id
);
170 if (EXPECT_FALSE (err
))
171 scm_gnutls_error (err
, FUNC_NAME
);
173 return (scm_take_u8vector (c_id
, 8));
177 SCM_DEFINE (scm_gnutls_openpgp_certificate_id_x
, "openpgp-certificate-id!",
180 "Store the ID (an 8 byte sequence) of certificate "
181 "@var{key} in @var{id} (a u8vector).")
182 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_id_x
186 scm_t_array_handle c_id_handle
;
188 gnutls_openpgp_crt_t c_key
;
190 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
191 c_id
= scm_gnutls_get_writable_array (id
, &c_id_handle
, &c_id_size
,
194 if (EXPECT_FALSE (c_id_size
< 8))
196 scm_gnutls_release_array (&c_id_handle
);
197 scm_misc_error (FUNC_NAME
, "ID vector too small: ~A",
201 err
= gnutls_openpgp_crt_get_id (c_key
, (unsigned char *) c_id
);
202 scm_gnutls_release_array (&c_id_handle
);
204 if (EXPECT_FALSE (err
))
205 scm_gnutls_error (err
, FUNC_NAME
);
207 return SCM_UNSPECIFIED
;
211 SCM_DEFINE (scm_gnutls_openpgp_certificate_fingerpint_x
,
212 "openpgp-certificate-fingerprint!",
215 "Store in @var{fpr} (a u8vector) the fingerprint of @var{key}. "
216 "Return the number of bytes stored in @var{fpr}.")
217 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_fingerpint_x
220 gnutls_openpgp_crt_t c_key
;
222 scm_t_array_handle c_fpr_handle
;
223 size_t c_fpr_len
, c_actual_len
= 0;
225 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
226 SCM_VALIDATE_ARRAY (2, fpr
);
228 c_fpr
= scm_gnutls_get_writable_array (fpr
, &c_fpr_handle
, &c_fpr_len
,
231 err
= gnutls_openpgp_crt_get_fingerprint (c_key
, c_fpr
, &c_actual_len
);
232 scm_gnutls_release_array (&c_fpr_handle
);
234 if (EXPECT_FALSE (err
))
235 scm_gnutls_error (err
, FUNC_NAME
);
237 return (scm_from_size_t (c_actual_len
));
241 SCM_DEFINE (scm_gnutls_openpgp_certificate_fingerprint
,
242 "openpgp-certificate-fingerprint",
245 "Return a new u8vector denoting the fingerprint of "
247 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_fingerprint
250 gnutls_openpgp_crt_t c_key
;
251 unsigned char *c_fpr
;
252 size_t c_fpr_len
, c_actual_len
;
254 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
256 /* V4 fingerprints are 160-bit SHA-1 hashes (see RFC2440). */
258 c_fpr
= (unsigned char *) malloc (c_fpr_len
);
259 if (EXPECT_FALSE (c_fpr
== NULL
))
260 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
265 err
= gnutls_openpgp_crt_get_fingerprint (c_key
, c_fpr
,
267 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
270 unsigned char *c_new
;
272 c_new
= (unsigned char *) realloc (c_fpr
, c_fpr_len
* 2);
273 if (EXPECT_FALSE (c_new
== NULL
))
276 scm_gnutls_error (GNUTLS_E_MEMORY_ERROR
, FUNC_NAME
);
285 while (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
);
287 if (EXPECT_FALSE (err
))
290 scm_gnutls_error (err
, FUNC_NAME
);
293 if (c_actual_len
< c_fpr_len
)
295 c_fpr
= realloc (c_fpr
, c_actual_len
);
297 return (scm_take_u8vector (c_fpr
, c_actual_len
));
301 SCM_DEFINE (scm_gnutls_openpgp_certificate_name
, "openpgp-certificate-name",
303 (SCM key
, SCM index
),
304 "Return the @var{index}th name of @var{key}.")
305 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_name
308 gnutls_openpgp_crt_t c_key
;
310 char c_name
[GUILE_GNUTLS_MAX_OPENPGP_NAME_LENGTH
];
311 size_t c_name_len
= sizeof (c_name
);
313 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
314 c_index
= scm_to_int (index
);
316 err
= gnutls_openpgp_crt_get_name (c_key
, c_index
, c_name
,
318 if (EXPECT_FALSE (err
))
319 scm_gnutls_error (err
, FUNC_NAME
);
321 /* XXX: The name is really UTF-8. */
322 return (scm_from_locale_string (c_name
));
326 SCM_DEFINE (scm_gnutls_openpgp_certificate_names
, "openpgp-certificate-names",
329 "Return the list of names for @var{key}.")
330 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_names
333 SCM result
= SCM_EOL
;
334 gnutls_openpgp_crt_t c_key
;
336 char c_name
[GUILE_GNUTLS_MAX_OPENPGP_NAME_LENGTH
];
337 size_t c_name_len
= sizeof (c_name
);
339 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
343 err
= gnutls_openpgp_crt_get_name (c_key
, c_index
, c_name
,
347 result
= scm_cons (scm_from_locale_string (c_name
),
354 if (EXPECT_FALSE (err
!= GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
))
355 scm_gnutls_error (err
, FUNC_NAME
);
357 return (scm_reverse_x (result
, SCM_EOL
));
361 SCM_DEFINE (scm_gnutls_openpgp_certificate_algorithm
,
362 "openpgp-certificate-algorithm",
365 "Return two values: the certificate algorithm used by "
366 "@var{key} and the number of bits used.")
367 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_algorithm
369 gnutls_openpgp_crt_t c_key
;
371 gnutls_pk_algorithm_t c_algo
;
373 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
374 c_algo
= gnutls_openpgp_crt_get_pk_algorithm (c_key
, &c_bits
);
376 return (scm_values (scm_list_2 (scm_from_gnutls_pk_algorithm (c_algo
),
377 scm_from_uint (c_bits
))));
381 SCM_DEFINE (scm_gnutls_openpgp_certificate_version
,
382 "openpgp-certificate-version",
385 "Return the version of the OpenPGP message format (RFC2440) "
386 "honored by @var{key}.")
387 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_version
390 gnutls_openpgp_crt_t c_key
;
392 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
393 c_version
= gnutls_openpgp_crt_get_version (c_key
);
395 return (scm_from_int (c_version
));
399 SCM_DEFINE (scm_gnutls_openpgp_certificate_usage
, "openpgp-certificate-usage",
402 "Return a list of values denoting the key usage of @var{key}.")
403 #define FUNC_NAME s_scm_gnutls_openpgp_certificate_usage
406 unsigned int c_usage
= 0;
407 gnutls_openpgp_crt_t c_key
;
409 c_key
= scm_to_gnutls_openpgp_certificate (key
, 1, FUNC_NAME
);
411 err
= gnutls_openpgp_crt_get_key_usage (c_key
, &c_usage
);
412 if (EXPECT_FALSE (err
))
413 scm_gnutls_error (err
, FUNC_NAME
);
415 return (scm_from_gnutls_key_usage_flags (c_usage
));
421 /* OpenPGP keyrings. */
423 SCM_DEFINE (scm_gnutls_import_openpgp_keyring
, "import-openpgp-keyring",
425 (SCM data
, SCM format
),
426 "Import @var{data} (a u8vector) according to @var{format} "
427 "and return the imported keyring.")
428 #define FUNC_NAME s_scm_gnutls_import_openpgp_keyring
431 gnutls_openpgp_keyring_t c_keyring
;
432 gnutls_openpgp_crt_fmt_t c_format
;
433 gnutls_datum_t c_data_d
;
434 scm_t_array_handle c_data_handle
;
438 SCM_VALIDATE_ARRAY (1, data
);
439 c_format
= scm_to_gnutls_openpgp_certificate_format (format
, 2, FUNC_NAME
);
441 c_data
= scm_gnutls_get_array (data
, &c_data_handle
, &c_data_len
,
444 c_data_d
.data
= (unsigned char *) c_data
;
445 c_data_d
.size
= c_data_len
;
447 err
= gnutls_openpgp_keyring_init (&c_keyring
);
448 if (EXPECT_FALSE (err
))
450 scm_gnutls_release_array (&c_data_handle
);
451 scm_gnutls_error (err
, FUNC_NAME
);
454 err
= gnutls_openpgp_keyring_import (c_keyring
, &c_data_d
, c_format
);
455 scm_gnutls_release_array (&c_data_handle
);
457 if (EXPECT_FALSE (err
))
459 gnutls_openpgp_keyring_deinit (c_keyring
);
460 scm_gnutls_error (err
, FUNC_NAME
);
463 return (scm_from_gnutls_openpgp_keyring (c_keyring
));
467 SCM_DEFINE (scm_gnutls_openpgp_keyring_contains_key_id_p
,
468 "openpgp-keyring-contains-key-id?",
470 (SCM keyring
, SCM id
),
471 "Return @code{#f} if key ID @var{id} is in @var{keyring}, "
472 "@code{#f} otherwise.")
473 #define FUNC_NAME s_scm_gnutls_openpgp_keyring_contains_key_id_p
476 gnutls_openpgp_keyring_t c_keyring
;
477 scm_t_array_handle c_id_handle
;
481 c_keyring
= scm_to_gnutls_openpgp_keyring (keyring
, 1, FUNC_NAME
);
482 SCM_VALIDATE_ARRAY (1, id
);
484 c_id
= scm_gnutls_get_array (id
, &c_id_handle
, &c_id_len
,
486 if (EXPECT_FALSE (c_id_len
!= 8))
488 scm_gnutls_release_array (&c_id_handle
);
489 scm_wrong_type_arg (FUNC_NAME
, 1, id
);
492 c_result
= gnutls_openpgp_keyring_check_id (c_keyring
,
493 (unsigned char *) c_id
,
496 scm_gnutls_release_array (&c_id_handle
);
498 return (scm_from_bool (c_result
== 0));
505 SCM_DEFINE (scm_gnutls_set_certificate_credentials_openpgp_keys_x
,
506 "set-certificate-credentials-openpgp-keys!",
508 (SCM cred
, SCM pub
, SCM sec
),
509 "Use certificate @var{pub} and secret key @var{sec} in "
510 "certificate credentials @var{cred}.")
511 #define FUNC_NAME s_scm_gnutls_set_certificate_credentials_openpgp_keys_x
514 gnutls_certificate_credentials_t c_cred
;
515 gnutls_openpgp_crt_t c_pub
;
516 gnutls_openpgp_privkey_t c_sec
;
518 c_cred
= scm_to_gnutls_certificate_credentials (cred
, 1, FUNC_NAME
);
519 c_pub
= scm_to_gnutls_openpgp_certificate (pub
, 2, FUNC_NAME
);
520 c_sec
= scm_to_gnutls_openpgp_private_key (sec
, 3, FUNC_NAME
);
522 err
= gnutls_certificate_set_openpgp_key (c_cred
, c_pub
, c_sec
);
523 if (EXPECT_FALSE (err
))
524 scm_gnutls_error (err
, FUNC_NAME
);
526 return SCM_UNSPECIFIED
;
531 /* Initialization. */
534 scm_init_gnutls_extra (void)
538 (void) gnutls_global_init_extra ();
540 scm_gnutls_define_enums ();
543 /* arch-tag: 655f308d-5643-4bc7-9db4-1f84bd902bef