Add key generation
[gpgme.git] / gpgme / genkey.c
1 /* genkey.c -  key generation
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GPGME 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "util.h"
28 #include "context.h"
29 #include "ops.h"
30
31 static void
32 genkey_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
33 {
34     if ( code == STATUS_PROGRESS )
35         return;
36
37     fprintf (stderr, "genkey_status: code=%d args=`%s'\n",
38              code, args );
39     /* FIXME: Need to do more */
40 }
41
42
43
44 /* 
45  * Here is how the parms should be formatted:
46 <GnupgKeyParms format="internal">
47 Key-Type: DSA
48 Key-Length: 1024
49 Subkey-Type: ELG-E
50 Subkey-Length: 1024
51 Name-Real: Joe Tester
52 Name-Comment: with stupid passphrase
53 Name-Email: joe@foo.bar
54 Expire-Date: 0
55 Passphrase: abc
56 </GnupgKeyParms>
57  * Strings should be given in UTF-8 encoding.  The format we support for now
58  * "internal".  The content of the <GnupgKeyParms> container is passed 
59  * verbatim to GnuPG.  Control statements (e.g. %pubring) are not allowed.
60  */
61
62 GpgmeError
63 gpgme_op_genkey_start ( GpgmeCtx c, const char *parms,
64                         GpgmeData pubkey, GpgmeData seckey )
65 {
66     int rc = 0;
67     int i;
68     const char *s, *s2, *sx;
69
70     fail_on_pending_request( c );
71     c->pending = 1;
72
73     gpgme_data_release (c->help_data_1); c->help_data_1 = NULL;
74
75     /* create a process object */
76     _gpgme_gpg_release (c->gpg); c->gpg = NULL;
77     rc = _gpgme_gpg_new ( &c->gpg );
78     if (rc)
79         goto leave;
80
81     /* We need a special mechanism to get the fd of a pipe here, so
82      * that we can use this for the %pubring and %secring parameters.
83      * We don't have this yet, so we implement only the adding to the
84      * standard keyrings */
85     if ( pubkey || seckey ) {
86         rc = mk_error (Not_Implemented);
87         goto leave;
88     }
89
90     _gpgme_gpg_set_status_handler ( c->gpg, genkey_status_handler, c );
91
92     /* build the commandline */
93     _gpgme_gpg_add_arg ( c->gpg, "--gen-key" );
94     if ( c->use_armor )
95         _gpgme_gpg_add_arg ( c->gpg, "--armor" );
96     for ( i=0; i < c->verbosity; i++ )
97         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
98
99     if ( !pubkey && !seckey )
100         ; /* okay: Add key to the keyrings */
101     else if ( !pubkey
102               || gpgme_data_get_type (pubkey) != GPGME_DATA_TYPE_NONE ) {
103         rc = mk_error (Invalid_Value);
104         goto leave;
105     }
106     else if ( !seckey
107               || gpgme_data_get_type (seckey) != GPGME_DATA_TYPE_NONE ) {
108         rc = mk_error (Invalid_Value);
109         goto leave;
110     }
111     
112     if ( pubkey ) {
113         _gpgme_data_set_mode (pubkey, GPGME_DATA_MODE_IN );
114         _gpgme_data_set_mode (seckey, GPGME_DATA_MODE_IN );
115         /* need some more things here */
116     }
117
118
119     if ( (parms = strstr (parms, "<GnupgKeyParms ")) 
120          && (s = strchr (parms, '>'))
121          && (sx = strstr (parms, "format=\"internal\""))
122          && sx < s
123          && (s2 = strstr (s+1, "</GnupgKeyParms>")) ) {
124         /* fixme: check that there are no control statements inside */
125         rc = gpgme_data_new_from_mem ( &c->help_data_1, s+1, s2-s-1, 1 );
126     }
127     else 
128         rc = mk_error (Invalid_Value);
129
130     if (rc )
131         goto leave;
132     
133     _gpgme_data_set_mode (c->help_data_1, GPGME_DATA_MODE_OUT );
134     _gpgme_gpg_add_data (c->gpg, c->help_data_1, 0);
135
136     rc = _gpgme_gpg_spawn ( c->gpg, c );
137     
138  leave:
139     if (rc) {
140         c->pending = 0; 
141         _gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
142     }
143     return rc;
144 }
145
146
147
148 /**
149  * gpgme_op_genkey:
150  * @c: the context
151  * @parms: XML string with the key parameters
152  * @pubkey: Returns the public key
153  * @seckey: Returns the secret key
154  * 
155  * Generate a new key and store the key in the default keyrings if both
156  * @pubkey and @seckey are NULL.  If @pubkey and @seckey are given, the newly
157  * created key will be returned in these data objects.
158  * See gpgme_op_genkey_start() for a description of @parms.
159  * 
160  * Return value: 0 for success or an error code
161  **/
162 GpgmeError
163 gpgme_op_genkey( GpgmeCtx c, const char *parms,
164                  GpgmeData pubkey, GpgmeData seckey )
165 {
166     int rc = gpgme_op_genkey_start ( c, parms, pubkey, seckey );
167     if ( !rc ) {
168         gpgme_wait (c, 1);
169         c->pending = 0;
170     }
171     return rc;
172 }
173
174
175
176
177