5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2006 Pekka Riikonen
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.
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.
23 static char *silc_create_pk_identifier(void)
25 char *username = NULL, *realname = NULL;
26 char *hostname, email[256];
30 realname = silc_get_real_name();
33 hostname = silc_net_localhost();
37 /* Get username (mandatory) */
38 username = silc_get_username();
42 /* Create default email address, whether it is right or not */
43 snprintf(email, sizeof(email), "%s@%s", username, hostname);
45 ident = silc_pkcs_silc_encode_identifier(username, hostname, realname,
55 /* Generate key pair */
57 SilcBool 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 const char *passphrase,
63 SilcPublicKey *return_public_key,
64 SilcPrivateKey *return_private_key,
69 char *pkfile = pub_filename ? strdup(pub_filename) : NULL;
70 char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
71 char *alg = pkcs_name ? strdup(pkcs_name) : NULL;
72 char *identifier = pub_identifier ? strdup(pub_identifier) : NULL;
73 char *pass = passphrase ? strdup(passphrase) : NULL;
75 if (interactive && (!alg || !pub_filename || !prv_filename))
77 New pair of keys will be created. Please, answer to following questions.\n\
83 alg = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
87 if (*alg == 'l' || *alg == 'L') {
88 char *list = silc_pkcs_get_supported();
100 if (!silc_pkcs_find_algorithm(alg, NULL)) {
101 fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library"
102 "is not initialized", alg);
109 length = silc_get_input("Key length in key_len_bits [2048]: ", FALSE);
111 key_len_bits = atoi(length);
119 char *def = silc_create_pk_identifier();
122 memset(line, 0, sizeof(line));
124 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
126 snprintf(line, sizeof(line),
127 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
128 "RN=Jon Johnson, E=jon@dummy.com): ");
130 while (!identifier) {
131 identifier = silc_get_input(line, FALSE);
132 if (!identifier && def)
133 identifier = strdup(def);
137 fprintf(stderr, "Could not create public key identifier: %s\n",
141 identifier = strdup(def);
147 rng = silc_rng_alloc();
149 silc_rng_global_init(rng);
153 memset(line, 0, sizeof(line));
154 snprintf(line, sizeof(line), "Public key filename [public_key.pub]: ");
155 pkfile = silc_get_input(line, FALSE);
158 pkfile = strdup("public_key.pub");
163 memset(line, 0, sizeof(line));
164 snprintf(line, sizeof(line), "Private key filename [private_key.prv]: ");
165 prvfile = silc_get_input(line, FALSE);
168 prvfile = strdup("private_key.prv");
174 pass = silc_get_input("Private key passphrase: ", TRUE);
181 pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
184 match = !strcmp(pass, pass2);
188 fprintf(stderr, "\nPassphrases do not match\n\n");
194 if (!silc_pkcs_silc_generate_key(alg, "pkcs1-no-oid", key_len_bits,
195 identifier, rng, return_public_key,
199 /* Save public key into file */
200 silc_pkcs_save_public_key(pkfile, *return_public_key, SILC_PKCS_FILE_BASE64);
202 /* Save private key into file */
203 silc_pkcs_save_private_key(prvfile, *return_private_key,
204 (const unsigned char *)pass, strlen(pass),
205 SILC_PKCS_FILE_BIN, rng);
207 printf("Public key has been saved into `%s'.\n", pkfile);
208 printf("Private key has been saved into `%s'.\n", prvfile);
210 printf("Press <Enter> to continue...\n");
218 silc_free(identifier);
219 memset(pass, 0, strlen(pass));
227 SilcBool silc_load_key_pair(const char *pub_filename,
228 const char *prv_filename,
229 const char *passphrase,
230 SilcPublicKey *return_public_key,
231 SilcPrivateKey *return_private_key)
233 char *pass = passphrase ? strdup(passphrase) : NULL;
235 SILC_LOG_DEBUG(("Loading public and private keys"));
237 if (!silc_pkcs_load_public_key(pub_filename, return_public_key)) {
239 memset(pass, 0, strlen(pass));
245 pass = silc_get_input("Private key passphrase: ", TRUE);
250 if (!silc_pkcs_load_private_key(prv_filename,
251 (const unsigned char *)pass, strlen(pass),
252 return_private_key)) {
253 memset(pass, 0, strlen(pass));
258 memset(pass, 0, strlen(pass));
263 /* Dump public key into stdout */
265 SilcBool silc_show_public_key(const char *pub_filename)
267 SilcPublicKey public_key;
268 SilcSILCPublicKey silc_pubkey;
269 SilcPublicKeyIdentifier ident;
270 char *fingerprint, *babbleprint;
273 SilcUInt32 key_len = 0;
275 if (!silc_pkcs_load_public_key((char *)pub_filename, &public_key)) {
276 fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
280 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
282 silc_pkcs_public_key_free(public_key);
286 ident = &silc_pubkey->identifier;
287 key_len = silc_pkcs_public_key_get_len(public_key);
288 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
290 silc_pkcs_public_key_free(public_key);
293 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
294 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
296 printf("Public key file : %s\n", pub_filename);
297 printf("Algorithm : %s\n", silc_pkcs_get_name(public_key));
299 printf("Key length (bits) : %d\n", (unsigned int)key_len);
301 printf("Real name : %s\n", ident->realname);
303 printf("Username : %s\n", ident->username);
305 printf("Hostname : %s\n", ident->host);
307 printf("Email : %s\n", ident->email);
309 printf("Organization : %s\n", ident->org);
311 printf("Country : %s\n", ident->country);
312 printf("Fingerprint (SHA1) : %s\n", fingerprint);
313 printf("Babbleprint (SHA1) : %s\n", babbleprint);
317 silc_free(fingerprint);
318 silc_free(babbleprint);
320 silc_pkcs_public_key_free(public_key);
325 /* Change private key passphrase */
327 SilcBool silc_change_private_key_passphrase(const char *prv_filename,
328 const char *old_passphrase,
329 const char *new_passphrase)
331 SilcPrivateKey private_key;
335 pass = old_passphrase ? strdup(old_passphrase) : NULL;
337 pass = silc_get_input("Old passphrase: ", TRUE);
342 if (!silc_pkcs_load_private_key(prv_filename,
343 (const unsigned char *)pass, strlen(pass),
345 memset(pass, 0, strlen(pass));
347 fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
351 memset(pass, 0, strlen(pass));
354 pass = new_passphrase ? strdup(new_passphrase) : NULL;
357 fprintf(stdout, "\n");
358 pass = silc_get_input("New passphrase: ", TRUE);
364 pass2 = silc_get_input("Retype new passphrase: ", TRUE);
367 if (!strcmp(pass, pass2))
369 fprintf(stderr, "\nPassphrases do not match");
375 rng = silc_rng_alloc();
378 silc_pkcs_save_private_key((char *)prv_filename, private_key,
379 (unsigned char *)pass, strlen(pass),
380 SILC_PKCS_FILE_BIN, rng);
382 fprintf(stdout, "\nPassphrase changed\n");
384 memset(pass, 0, strlen(pass));
387 silc_pkcs_private_key_free(private_key);
393 /* Checks that the 'identifier' string is valid identifier string
394 and does not contain any unassigned or prohibited character. This
395 function is used to check for valid nicknames, channel names,
396 server names, usernames, hostnames, service names, algorithm names,
397 other security property names, and SILC Public Key name. */
399 unsigned char *silc_identifier_check(const unsigned char *identifier,
400 SilcUInt32 identifier_len,
401 SilcStringEncoding identifier_encoding,
402 SilcUInt32 max_allowed_length,
405 unsigned char *utf8s;
406 SilcUInt32 utf8s_len;
407 SilcStringprepStatus status;
409 if (!identifier || !identifier_len)
412 if (max_allowed_length && identifier_len > max_allowed_length)
415 status = silc_stringprep(identifier, identifier_len,
416 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
417 &utf8s, &utf8s_len, SILC_STRING_UTF8);
418 if (status != SILC_STRINGPREP_OK) {
419 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
424 *out_len = utf8s_len;
429 /* Same as above but does not allocate memory, just checks the
430 validity of the string. */
432 SilcBool silc_identifier_verify(const unsigned char *identifier,
433 SilcUInt32 identifier_len,
434 SilcStringEncoding identifier_encoding,
435 SilcUInt32 max_allowed_length)
437 SilcStringprepStatus status;
439 if (!identifier || !identifier_len)
442 if (max_allowed_length && identifier_len > max_allowed_length)
445 status = silc_stringprep(identifier, identifier_len,
446 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
447 NULL, NULL, SILC_STRING_UTF8);
448 if (status != SILC_STRINGPREP_OK) {
449 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
456 unsigned char *silc_channel_name_check(const unsigned char *identifier,
457 SilcUInt32 identifier_len,
458 SilcStringEncoding identifier_encoding,
459 SilcUInt32 max_allowed_length,
462 unsigned char *utf8s;
463 SilcUInt32 utf8s_len;
464 SilcStringprepStatus status;
466 if (!identifier || !identifier_len)
469 if (max_allowed_length && identifier_len > max_allowed_length)
472 status = silc_stringprep(identifier, identifier_len,
473 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
474 &utf8s, &utf8s_len, SILC_STRING_UTF8);
475 if (status != SILC_STRINGPREP_OK) {
476 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
481 *out_len = utf8s_len;
486 /* Same as above but does not allocate memory, just checks the
487 validity of the string. */
489 SilcBool silc_channel_name_verify(const unsigned char *identifier,
490 SilcUInt32 identifier_len,
491 SilcStringEncoding identifier_encoding,
492 SilcUInt32 max_allowed_length)
494 SilcStringprepStatus status;
496 if (!identifier || !identifier_len)
499 if (max_allowed_length && identifier_len > max_allowed_length)
502 status = silc_stringprep(identifier, identifier_len,
503 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
504 NULL, NULL, SILC_STRING_UTF8);
505 if (status != SILC_STRINGPREP_OK) {
506 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));