1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright 2001 Ximian, Inc. (www.ximian.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "camel-cipher-context.h"
33 #define CIPHER_LOCK(ctx) g_mutex_lock (((CamelCipherContext *) ctx)->priv->lock)
34 #define CIPHER_UNLOCK(ctx) g_mutex_unlock (((CamelCipherContext *) ctx)->priv->lock);
36 #define CIPHER_LOCK(ctx)
37 #define CIPHER_UNLOCK(ctx)
42 #define CCC_CLASS(o) CAMEL_CIPHER_CONTEXT_CLASS(CAMEL_OBJECT_GET_CLASS(o))
44 struct _CamelCipherContextPrivate {
50 static const char *cipher_hash_to_id (CamelCipherContext *context, CamelCipherHash hash);
51 static CamelCipherHash cipher_id_to_hash (CamelCipherContext *context, const char *id);
53 static int cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
54 CamelStream *istream, CamelStream *ostream, CamelException *ex);
55 static CamelCipherValidity *cipher_verify (CamelCipherContext *context, CamelCipherHash hash,
56 CamelStream *istream, CamelStream *sigstream,
58 static int cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
59 GPtrArray *recipients, CamelStream *istream,
60 CamelStream *ostream, CamelException *ex);
61 static int cipher_decrypt (CamelCipherContext *context, CamelStream *istream,
62 CamelStream *ostream, CamelException *ex);
63 static int cipher_import_keys (CamelCipherContext *context, CamelStream *istream,
65 static int cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
66 CamelStream *ostream, CamelException *ex);
69 static CamelObjectClass *parent_class;
73 camel_cipher_context_init (CamelCipherContext *context)
75 context->priv = g_new0 (struct _CamelCipherContextPrivate, 1);
77 context->priv->lock = g_mutex_new ();
82 camel_cipher_context_finalise (CamelObject *o)
84 CamelCipherContext *context = (CamelCipherContext *)o;
86 camel_object_unref (CAMEL_OBJECT (context->session));
89 g_mutex_free (context->priv->lock);
92 g_free (context->priv);
96 camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_class)
98 parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
100 camel_cipher_context_class->hash_to_id = cipher_hash_to_id;
101 camel_cipher_context_class->id_to_hash = cipher_id_to_hash;
102 camel_cipher_context_class->sign = cipher_sign;
103 camel_cipher_context_class->verify = cipher_verify;
104 camel_cipher_context_class->encrypt = cipher_encrypt;
105 camel_cipher_context_class->decrypt = cipher_decrypt;
106 camel_cipher_context_class->import_keys = cipher_import_keys;
107 camel_cipher_context_class->export_keys = cipher_export_keys;
111 camel_cipher_context_get_type (void)
113 static CamelType type = CAMEL_INVALID_TYPE;
115 if (type == CAMEL_INVALID_TYPE) {
116 type = camel_type_register (camel_object_get_type (),
117 "CamelCipherContext",
118 sizeof (CamelCipherContext),
119 sizeof (CamelCipherContextClass),
120 (CamelObjectClassInitFunc) camel_cipher_context_class_init,
122 (CamelObjectInitFunc) camel_cipher_context_init,
123 (CamelObjectFinalizeFunc) camel_cipher_context_finalise);
131 * camel_cipher_context_new:
132 * @session: CamelSession
134 * This creates a new CamelCipherContext object which is used to sign,
135 * verify, encrypt and decrypt streams.
137 * Return value: the new CamelCipherContext
140 camel_cipher_context_new (CamelSession *session)
142 CamelCipherContext *context;
144 g_return_val_if_fail (session != NULL, NULL);
146 context = CAMEL_CIPHER_CONTEXT (camel_object_new (CAMEL_CIPHER_CONTEXT_TYPE));
148 camel_object_ref (CAMEL_OBJECT (session));
149 context->session = session;
156 * camel_cipher_context_construct:
157 * @context: CamelCipherContext
158 * @session: CamelSession
160 * Constucts the CamelCipherContext
163 camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session)
165 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
166 g_return_if_fail (CAMEL_IS_SESSION (session));
168 camel_object_ref (CAMEL_OBJECT (session));
169 context->session = session;
174 cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash,
175 CamelStream *istream, CamelStream *ostream, CamelException *ex)
177 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
178 _("Signing is not supported by this cipher"));
184 * @context: Cipher Context
185 * @userid: private key to use to sign the stream
186 * @hash: preferred Message-Integrity-Check hash algorithm
187 * @istream: input stream
188 * @ostream: output stream
191 * Signs the input stream and writes the resulting signature to the output stream.
193 * Return value: 0 for success or -1 for failure.
196 camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
197 CamelStream *istream, CamelStream *ostream, CamelException *ex)
201 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
203 CIPHER_LOCK(context);
205 retval = CCC_CLASS (context)->sign (context, userid, hash, istream, ostream, ex);
207 CIPHER_UNLOCK(context);
213 static CamelCipherValidity *
214 cipher_verify (CamelCipherContext *context, CamelCipherHash hash, CamelStream *istream,
215 CamelStream *sigstream, CamelException *ex)
217 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
218 _("Verifying is not supported by this cipher"));
224 * camel_cipher_verify:
225 * @context: Cipher Context
226 * @istream: input stream
227 * @sigstream: optional detached-signature stream
230 * Verifies the signature. If @istream is a clearsigned stream,
231 * you should pass %NULL as the sigstream parameter. Otherwise
232 * @sigstream is assumed to be the signature stream and is used to
233 * verify the integirity of the @istream.
235 * Return value: a CamelCipherValidity structure containing information
236 * about the integrity of the input stream or %NULL on failure to
239 CamelCipherValidity *
240 camel_cipher_verify (CamelCipherContext *context, CamelCipherHash hash, CamelStream *istream,
241 CamelStream *sigstream, CamelException *ex)
243 CamelCipherValidity *valid;
245 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
247 CIPHER_LOCK(context);
249 valid = CCC_CLASS (context)->verify (context, hash, istream, sigstream, ex);
251 CIPHER_UNLOCK(context);
258 cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients,
259 CamelStream *istream, CamelStream *ostream, CamelException *ex)
261 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
262 _("Encryption is not supported by this cipher"));
267 * camel_cipher_encrypt:
268 * @context: Cipher Context
269 * @sign: sign as well as encrypt
270 * @userid: key id (or email address) to use when signing (assuming @sign is %TRUE)
271 * @recipients: an array of recipient key ids and/or email addresses
272 * @istream: cleartext input stream
273 * @ostream: ciphertext output stream
276 * Encrypts (and optionally signs) the cleartext input stream and
277 * writes the resulting ciphertext to the output stream.
279 * Return value: 0 for success or -1 for failure.
282 camel_cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients,
283 CamelStream *istream, CamelStream *ostream, CamelException *ex)
287 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
289 CIPHER_LOCK(context);
291 retval = CCC_CLASS (context)->encrypt (context, sign, userid, recipients, istream, ostream, ex);
293 CIPHER_UNLOCK(context);
300 cipher_decrypt (CamelCipherContext *context, CamelStream *istream,
301 CamelStream *ostream, CamelException *ex)
303 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
304 _("Decryption is not supported by this cipher"));
309 * camel_cipher_decrypt:
310 * @context: Cipher Context
311 * @ciphertext: ciphertext stream (ie input stream)
312 * @cleartext: cleartext stream (ie output stream)
315 * Decrypts the ciphertext input stream and writes the resulting
316 * cleartext to the output stream.
318 * Return value: 0 for success or -1 for failure.
321 camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream,
322 CamelStream *ostream, CamelException *ex)
326 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
328 CIPHER_LOCK(context);
330 retval = CCC_CLASS (context)->decrypt (context, istream, ostream, ex);
332 CIPHER_UNLOCK(context);
339 cipher_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex)
341 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
342 _("You may not import keys with this cipher"));
349 * camel_cipher_import_keys:
350 * @ctx: Cipher Context
351 * @istream: input stream (containing keys)
354 * Imports a stream of keys/certificates contained within @istream
355 * into the key/certificate database controlled by @ctx.
357 * Returns 0 on success or -1 on fail.
360 camel_cipher_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex)
362 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
363 g_return_val_if_fail (CAMEL_IS_STREAM (istream), -1);
365 return CCC_CLASS (context)->import_keys (context, istream, ex);
370 cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
371 CamelStream *ostream, CamelException *ex)
373 camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
374 _("You may not export keys with this cipher"));
381 * camel_cipher_export_keys:
382 * @ctx: Cipher Context
383 * @keys: an array of key ids
384 * @ostream: output stream
387 * Exports the keys/certificates in @keys to the stream @ostream from
388 * the key/certificate database controlled by @ctx.
390 * Returns 0 on success or -1 on fail.
393 camel_cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
394 CamelStream *ostream, CamelException *ex)
396 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
397 g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1);
398 g_return_val_if_fail (keys != NULL, -1);
400 return CCC_CLASS (context)->export_keys (context, keys, ostream, ex);
404 static CamelCipherHash
405 cipher_id_to_hash(CamelCipherContext *context, const char *id)
407 return CAMEL_CIPHER_HASH_DEFAULT;
410 /* a couple of util functions */
412 camel_cipher_id_to_hash(CamelCipherContext *context, const char *id)
414 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), CAMEL_CIPHER_HASH_DEFAULT);
416 return CCC_CLASS (context)->id_to_hash (context, id);
420 cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
426 camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
428 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
430 return CCC_CLASS (context)->hash_to_id (context, hash);
433 /* Cipher Validity stuff */
434 struct _CamelCipherValidity {
439 CamelCipherValidity *
440 camel_cipher_validity_new (void)
442 CamelCipherValidity *validity;
444 validity = g_new (CamelCipherValidity, 1);
445 validity->valid = FALSE;
446 validity->description = NULL;
452 camel_cipher_validity_init (CamelCipherValidity *validity)
454 g_assert (validity != NULL);
456 validity->valid = FALSE;
457 validity->description = NULL;
461 camel_cipher_validity_get_valid (CamelCipherValidity *validity)
463 if (validity == NULL)
466 return validity->valid;
470 camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid)
472 g_assert (validity != NULL);
474 validity->valid = valid;
478 camel_cipher_validity_get_description (CamelCipherValidity *validity)
480 if (validity == NULL)
483 return validity->description;
487 camel_cipher_validity_set_description (CamelCipherValidity *validity, const gchar *description)
489 g_assert (validity != NULL);
491 g_free (validity->description);
492 validity->description = g_strdup (description);
496 camel_cipher_validity_clear (CamelCipherValidity *validity)
498 g_assert (validity != NULL);
500 validity->valid = FALSE;
501 g_free (validity->description);
502 validity->description = NULL;
506 camel_cipher_validity_free (CamelCipherValidity *validity)
508 if (validity == NULL)
511 g_free (validity->description);