Tizen 2.0 Release
[external/libgnutls26.git] / lib / opencdk / main.c
1 /* main.c
2  * Copyright (C) 2001, 2002, 2003, 2007, 2008, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Timo Schulz
6  *
7  * This file is part of OpenCDK.
8  *
9  * The OpenCDK library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <stdio.h>
29 #include <errno.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #ifdef _WIN32
34 #include <windows.h>
35 #endif
36
37 #include "opencdk.h"
38 #include "main.h"
39 #include "packet.h"
40
41
42 /* Set a default cipher algorithm and a digest algorithm.
43    Even if AES and SHA-256 are not 'MUST' in the latest
44    OpenPGP draft, AES seems to be a good choice. */
45 #define DEFAULT_DIGEST_ALGO GNUTLS_DIG_SHA256
46
47 /* Use the passphrase callback in the handle HD or
48    return NULL if there is no valid callback. */
49 char *
50 _cdk_passphrase_get (cdk_ctx_t hd, const char *prompt)
51 {
52   if (!hd || !hd->passphrase_cb)
53     return NULL;
54   return hd->passphrase_cb (hd->passphrase_cb_value, prompt);
55 }
56
57
58 static void
59 handle_set_digest (cdk_ctx_t hd, int digest)
60 {
61   if (!hd)
62     return;
63   if (_gnutls_hash_get_algo_len (digest) <= 0)
64     digest = DEFAULT_DIGEST_ALGO;
65   hd->digest_algo = digest;
66 }
67
68
69 static void
70 handle_set_s2k (cdk_ctx_t hd, int mode, int digest)
71 {
72   if (!hd)
73     return;
74   if (_gnutls_hash_get_algo_len (digest) <= 0)
75     digest = DEFAULT_DIGEST_ALGO;
76   if (mode != CDK_S2K_SIMPLE &&
77       mode != CDK_S2K_SALTED && mode != CDK_S2K_ITERSALTED)
78     mode = CDK_S2K_ITERSALTED;
79   hd->_s2k.mode = mode;
80   hd->_s2k.digest_algo = digest;
81 }
82
83
84 static void
85 handle_set_compress (cdk_ctx_t hd, int algo, int level)
86 {
87   if (!hd)
88     return;
89   if (algo < 0 || algo > 2)
90     algo = 0;
91   hd->compress.algo = algo;
92   if (!algo)
93     hd->opt.compress = 0;
94   else
95     {
96       if (level > 0 && level < 10)
97         hd->compress.level = level;
98       else
99         hd->compress.level = 6;
100     }
101 }
102
103
104 /**
105  * cdk_handle_control:
106  * @hd: session handle
107  * @action: flag which indicates whether put or get is requested
108  * @cmd: command id
109  *
110  * Perform various control operations for the current session.
111  **/
112 int
113 cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...)
114 {
115   va_list arg_ptr;
116   int set = action == CDK_CTLF_SET, val = 0;
117
118   if (!hd)
119     return -1;
120
121   if (action != CDK_CTLF_SET && action != CDK_CTLF_GET)
122     return -1;
123   va_start (arg_ptr, cmd);
124   switch (cmd)
125     {
126     case CDK_CTL_ARMOR:
127       if (set)
128         hd->opt.armor = va_arg (arg_ptr, int);
129       else
130         val = hd->opt.armor;
131       break;
132
133     case CDK_CTL_DIGEST:
134       if (set)
135         handle_set_digest (hd, va_arg (arg_ptr, int));
136       else
137         val = hd->digest_algo;
138       break;
139
140     case CDK_CTL_OVERWRITE:
141       if (set)
142         hd->opt.overwrite = va_arg (arg_ptr, int);
143       else
144         val = hd->opt.overwrite;
145       break;
146
147     case CDK_CTL_COMPRESS:
148       if (set)
149         {
150           int algo = va_arg (arg_ptr, int);
151           int level = va_arg (arg_ptr, int);
152           handle_set_compress (hd, algo, level);
153         }
154       else
155         val = hd->compress.algo;
156       break;
157
158     case CDK_CTL_S2K:
159       if (set)
160         {
161           int mode = va_arg (arg_ptr, int);
162           int digest = va_arg (arg_ptr, int);
163           handle_set_s2k (hd, mode, digest);
164         }
165       else
166         val = hd->_s2k.mode;
167       break;
168
169     case CDK_CTL_FORCE_DIGEST:
170       if (set)
171         hd->opt.force_digest = va_arg (arg_ptr, int);
172       else
173         val = hd->opt.force_digest;
174       break;
175
176     case CDK_CTL_BLOCKMODE_ON:
177       if (set)
178         hd->opt.blockmode = va_arg (arg_ptr, int);
179       else
180         val = hd->opt.blockmode;
181       break;
182
183     default:
184       val = -1;
185       break;
186     }
187   va_end (arg_ptr);
188   return val;
189 }
190
191
192
193 /**
194  * cdk_handle_new:
195  * @r_ctx: context to store the handle
196  *
197  * create a new session handle.
198  **/
199 cdk_error_t
200 cdk_handle_new (cdk_ctx_t * r_ctx)
201 {
202   cdk_ctx_t c;
203
204   if (!r_ctx)
205     return CDK_Inv_Value;
206
207   c = cdk_calloc (1, sizeof *c);
208   if (!c)
209     return CDK_Out_Of_Core;
210
211   /* For S2K use the iterated and salted mode and use the
212      default digest and cipher algorithms. Because the MDC
213      feature will be used, the default cipher should use a 
214      blocksize of 128 bits. */
215   c->_s2k.mode = CDK_S2K_ITERSALTED;
216   c->_s2k.digest_algo = DEFAULT_DIGEST_ALGO;
217
218   c->opt.mdc = 1;
219   c->opt.compress = 1;
220   c->opt.armor = 0;
221   c->opt.textmode = 0;
222
223   c->digest_algo = DEFAULT_DIGEST_ALGO;
224
225   c->compress.algo = CDK_COMPRESS_ZIP;
226   c->compress.level = 6;
227
228   *r_ctx = c;
229   return 0;
230 }
231
232
233 /**
234  * cdk_handle_set_keyring:
235  * @hd: session handle
236  * @type: public=0 or secret=1 keyring type
237  * @kringname: file name of the keyring which shall be used.
238  * 
239  * Convenient function to set the keyring for the current session.
240  */
241 cdk_error_t
242 cdk_handle_set_keyring (cdk_ctx_t hd, int type, const char *kringname)
243 {
244   cdk_keydb_hd_t db;
245   cdk_error_t err;
246
247   err = cdk_keydb_new_from_file (&db, type, kringname);
248   if (err)
249     return err;
250
251   if (!type)
252     hd->db.pub = db;
253   else
254     hd->db.sec = db;
255   hd->db.close_db = 1;
256   return 0;
257 }
258
259
260 /**
261  * cdk_handle_set_keydb:
262  * @hd: session handle
263  * @db: the database handle
264  *
265  * set the key database handle.
266  * the function automatically detects whether this is a public or
267  * secret keyring and the right handle is set.
268  **/
269 void
270 cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db)
271 {
272   if (!hd)
273     return;
274   if (_cdk_keydb_is_secret (db))
275     hd->db.sec = db;
276   else
277     hd->db.pub = db;
278 }
279
280
281 /**
282  * cdk_handle_get_keydb:
283  * @hd: session handle
284  * @type: type of the keyring
285  *
286  * Return the keydb handle from the session handle.
287  * The caller should not free these handles.
288  **/
289 cdk_keydb_hd_t
290 cdk_handle_get_keydb (cdk_ctx_t hd, int type)
291 {
292   if (!hd)
293     return NULL;
294   if (type == CDK_DBTYPE_PK_KEYRING)
295     return hd->db.pub;
296   else if (type == CDK_DBTYPE_SK_KEYRING)
297     return hd->db.sec;
298   return NULL;
299 }
300
301
302 /**
303  * cdk_handle_set_passphrase_cb:
304  * @hd: session handle
305  * @cb: callback function
306  * @cb_value: the opaque value for the cb function
307  *
308  * set the passphrase callback.
309  **/
310 void
311 cdk_handle_set_passphrase_cb (cdk_ctx_t hd,
312                               char *(*cb) (void *opa, const char *prompt),
313                               void *cb_value)
314 {
315   if (!hd)
316     return;
317   hd->passphrase_cb = cb;
318   hd->passphrase_cb_value = cb_value;
319 }
320
321 /**
322  * cdk_handle_free:
323  * @hd: the handle
324  *
325  * Release the main handle.
326  **/
327 void
328 cdk_handle_free (cdk_ctx_t hd)
329 {
330   if (!hd)
331     return;
332
333   /* If cdk_handle_set_keyring() were used, we need to free the key db
334      handles here because the handles are not controlled by the user. */
335   if (hd->db.close_db)
336     {
337       if (hd->db.pub)
338         cdk_keydb_free (hd->db.pub);
339       if (hd->db.sec)
340         cdk_keydb_free (hd->db.sec);
341       hd->db.pub = hd->db.sec = NULL;
342     }
343   cdk_free (hd);
344 }