Added silcapputil.[ch] for application utility functions for
[silc.git] / lib / silcutil / silcapputil.c
1 /*
2
3   silcapputil.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silcincludes.h"
22
23 static char *silc_create_pk_identifier(void)
24 {
25   char *username = NULL, *realname = NULL;
26   char *hostname, email[256];
27   char *ident;
28   
29   /* Get realname */
30   realname = silc_get_real_name();
31
32   /* Get hostname */
33   hostname = silc_net_localhost();
34   if (!hostname)
35     return NULL;
36
37   /* Get username (mandatory) */
38   username = silc_get_username();
39   if (!username)
40     return NULL;
41
42   /* Create default email address, whether it is right or not */
43   snprintf(email, sizeof(email), "%s@%s", username, hostname);
44
45   ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
46                                       NULL, NULL);
47   if (realname)
48     silc_free(realname);
49   silc_free(hostname);
50   silc_free(username);
51
52   return ident;
53 }
54
55 /* Generate key pair */
56
57 bool silc_create_key_pair(const char *pkcs_name,
58                           SilcUInt32 key_len_bits,
59                           const char *pub_filename,
60                           const char *prv_filename,
61                           const char *pub_identifier,
62                           SilcPKCS *return_pkcs,
63                           SilcPublicKey *return_public_key,
64                           SilcPrivateKey *return_private_key,
65                           bool interactive)
66 {
67   SilcPKCS pkcs;
68   SilcPublicKey pub_key;
69   SilcPrivateKey prv_key;
70   SilcRng rng;
71   unsigned char *key;
72   SilcUInt32 key_len;
73   char line[256];
74   char *pkfile = pub_filename ? strdup(pub_filename) : NULL;
75   char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
76   char *alg = pkcs_name ? strdup(pkcs_name) : NULL;
77   char *identifier = pub_identifier ? strdup(pub_identifier) : NULL;
78
79   if (interactive && (!alg || !pub_filename || !prv_filename))
80     printf("\
81 New pair of keys will be created.  Please, answer to following questions.\n\
82 ");
83
84   if (!alg) {
85     if (interactive) {
86       while (!alg) {
87         alg = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
88         if (!alg)
89           alg = strdup("rsa");
90     
91         if (*alg == 'l' || *alg == 'L') {
92           char *list = silc_pkcs_get_supported();
93           printf("%s\n", list);
94           silc_free(list);
95           silc_free(alg);
96           alg = NULL;
97         }
98       }
99     } else {
100       alg = strdup("rsa");
101     }
102   }
103
104   if (!silc_pkcs_is_supported(alg)) {
105     fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library"
106             "is not initialized", alg);
107     return FALSE;
108   }
109
110   if (!key_len_bits) {
111     if (interactive) {
112       char *length = NULL;
113       length = silc_get_input("Key length in key_len_bits [2048]: ", FALSE);
114       if (length)
115         key_len_bits = atoi(length);
116       silc_free(length);
117     }
118     if (!key_len_bits)
119       key_len_bits = 2048;
120   }
121
122   if (!identifier) {
123     char *def = silc_create_pk_identifier();
124
125     if (interactive) {
126       memset(line, 0, sizeof(line));
127       if (def)
128         snprintf(line, sizeof(line), "Identifier [%s]: ", def);
129       else
130         snprintf(line, sizeof(line),
131                "Identifier (eg. UN=jon, HN=jon.dummy.com, "
132                "RN=Jon Johnson, E=jon@dummy.com): ");
133
134       while (!identifier) {
135         identifier = silc_get_input(line, FALSE);
136         if (!identifier && def)
137           identifier = strdup(def);
138       }
139     } else {
140       if (!def) {
141         fprintf(stderr, "Could not create public key identifier: %s\n",
142                 strerror(errno));
143         return FALSE;
144       }
145       identifier = strdup(def);
146     }
147
148     silc_free(def);
149   }
150
151   rng = silc_rng_alloc();
152   silc_rng_init(rng);
153   silc_rng_global_init(rng);
154
155   if (!pkfile) {
156     if (interactive) {
157       memset(line, 0, sizeof(line));
158       snprintf(line, sizeof(line), "Public key filename [public_key.pub] ");
159       pkfile = silc_get_input(line, FALSE);
160     }
161     if (!pkfile)
162       pkfile = strdup("public_key.pub");
163   }
164
165   if (!prvfile) {
166     if (interactive) {
167       memset(line, 0, sizeof(line));
168       snprintf(line, sizeof(line), "Public key filename [private_key.prv] ");
169       prvfile = silc_get_input(line, FALSE);
170     }
171     if (!prvfile)
172       prvfile = strdup("private_key.prv");
173   }
174
175   /* Generate keys */
176   silc_pkcs_alloc(alg, &pkcs);
177   silc_pkcs_generate_key(pkcs, key_len_bits, rng);
178
179   /* Save public key into file */
180   key = silc_pkcs_get_public_key(pkcs, &key_len);
181   pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs),
182                                        identifier, key, key_len);
183   silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
184   if (return_public_key)
185     *return_public_key = pub_key;
186   else
187     silc_pkcs_public_key_free(pub_key);
188   memset(key, 0, key_len);
189   silc_free(key);
190
191   /* Save private key into file */
192   key = silc_pkcs_get_private_key(pkcs, &key_len);
193   prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs),
194                                         key, key_len);
195   silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
196   if (return_private_key)
197     *return_private_key = prv_key;
198   else
199     silc_pkcs_private_key_free(prv_key);
200   memset(key, 0, key_len);
201   silc_free(key);
202
203   printf("Public key has been saved into `%s'.\n", pkfile);
204   printf("Private key has been saved into `%s'.\n", prvfile);
205   if (interactive) {
206     printf("Press <Enter> to continue...\n");
207     getchar();
208   }
209
210   if (return_pkcs)
211     *return_pkcs = pkcs;
212   else
213     silc_pkcs_free(pkcs);
214
215   silc_rng_free(rng);
216   silc_free(alg);
217   silc_free(pkfile);
218   silc_free(prvfile);
219   silc_free(identifier);
220
221   return TRUE;
222 }
223
224 /* Load key pair */
225
226 bool silc_load_key_pair(const char *pub_filename,
227                         const char *prv_filename,
228                         SilcPKCS *return_pkcs,
229                         SilcPublicKey *return_public_key,
230                         SilcPrivateKey *return_private_key)
231 {
232   SILC_LOG_DEBUG(("Loading public and private keys"));
233
234   if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key,
235                                 SILC_PKCS_FILE_PEM) == FALSE)
236     if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key,
237                                   SILC_PKCS_FILE_BIN) == FALSE)
238       return FALSE;
239
240   if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
241                                  SILC_PKCS_FILE_BIN) == FALSE)
242     if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
243                                    SILC_PKCS_FILE_PEM) == FALSE)
244       return FALSE;
245
246   if (return_pkcs) {
247     silc_pkcs_alloc((*return_public_key)->name, return_pkcs);
248     silc_pkcs_public_key_set(*return_pkcs, *return_public_key);
249     silc_pkcs_private_key_set(*return_pkcs, *return_private_key);
250   }
251
252   return TRUE;
253 }
254
255 /* Dump public key into stdout */
256
257 bool silc_show_public_key(const char *pub_filename)
258 {
259   SilcPublicKey public_key;
260   SilcPublicKeyIdentifier ident;
261   char *fingerprint, *babbleprint;
262   unsigned char *pk;
263   SilcUInt32 pk_len;
264   SilcPKCS pkcs;
265   SilcUInt32 key_len = 0;
266
267   if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
268                                 SILC_PKCS_FILE_PEM) == FALSE)
269     if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
270                                   SILC_PKCS_FILE_BIN) == FALSE) {
271       fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
272       return FALSE;
273     }
274
275   ident = silc_pkcs_decode_identifier(public_key->identifier);
276
277   pk = silc_pkcs_public_key_encode(public_key, &pk_len);
278   fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
279   babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
280
281   if (silc_pkcs_alloc(public_key->name, &pkcs)) {
282     key_len = silc_pkcs_public_key_set(pkcs, public_key);
283     silc_pkcs_free(pkcs);
284   }
285
286   printf("Public key file    : %s\n", pub_filename);
287   printf("Algorithm          : %s\n", public_key->name);
288   if (key_len)
289     printf("Key length (bits)  : %d\n", (unsigned int)key_len);
290   if (ident->realname)
291     printf("Real name          : %s\n", ident->realname);
292   if (ident->username)
293     printf("Username           : %s\n", ident->username);
294   if (ident->host)
295     printf("Hostname           : %s\n", ident->host);
296   if (ident->email)
297     printf("Email              : %s\n", ident->email);
298   if (ident->org)
299     printf("Organization       : %s\n", ident->org);
300   if (ident->country)
301     printf("Country            : %s\n", ident->country);
302   printf("Fingerprint (SHA1) : %s\n", fingerprint); 
303   printf("Babbleprint (SHA1) : %s\n", babbleprint); 
304
305   fflush(stdout);
306
307   silc_free(fingerprint);
308   silc_free(babbleprint);
309   silc_free(pk);
310   silc_pkcs_public_key_free(public_key);
311   silc_pkcs_free_identifier(ident);
312
313   return TRUE;
314 }