From dbb05dc8bb36fe50bf04e54d81a38aa1bdb6a7d5 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 29 Oct 2002 20:18:04 +0000 Subject: [PATCH] Added silcapputil.[ch] for application utility functions for convenience. Moved code around from irssi and server to this new file. --- CHANGES | 7 + apps/irssi/src/silc/core/clientutil.c | 316 +++----------------------- apps/irssi/src/silc/core/clientutil.h | 7 - apps/irssi/src/silc/core/silc-core.c | 6 +- apps/silcd/silcd.c | 121 +--------- includes/silcincludes.h | 2 + lib/silccrypt/silcpkcs.h | 6 +- lib/silcutil/DIRECTORY | 1 + lib/silcutil/Makefile.am | 4 +- lib/silcutil/silcapputil.c | 314 +++++++++++++++++++++++++ lib/silcutil/silcapputil.h | 134 +++++++++++ 11 files changed, 505 insertions(+), 413 deletions(-) create mode 100644 lib/silcutil/silcapputil.c create mode 100644 lib/silcutil/silcapputil.h diff --git a/CHANGES b/CHANGES index 6eb656d8..79505994 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +Tue Oct 29 21:48:55 EET 2002 Pekka Riikonen + + * Added lib/silcutil/silcapputil.[ch] for application + utility functions. It includes routines for applications' + convenience. Added silc_create_key_pair, silc_show_public_key + and silc_load_key_pair functions. + Tue Oct 29 17:36:44 EET 2002 Pekka Riikonen * Send RESUME_CLIENT packet from router to backup routers diff --git a/apps/irssi/src/silc/core/clientutil.c b/apps/irssi/src/silc/core/clientutil.c index 5a0f3438..cdc0fc9e 100644 --- a/apps/irssi/src/silc/core/clientutil.c +++ b/apps/irssi/src/silc/core/clientutil.c @@ -80,174 +80,6 @@ void silc_client_list_pkcs() silc_free(pkcs); } -/* Returns identifier string for public key generation. */ - -char *silc_client_create_identifier() -{ - char *username = NULL, *realname = NULL; - char *hostname, email[256]; - char *ident; - - /* Get realname */ - realname = silc_get_real_name(); - - /* Get hostname */ - hostname = silc_net_localhost(); - if (!hostname) - return NULL; - - /* Get username (mandatory) */ - username = silc_get_username(); - if (!username) - return NULL; - - /* Create default email address, whether it is right or not */ - snprintf(email, sizeof(email), "%s@%s", username, hostname); - - ident = silc_pkcs_encode_identifier(username, hostname, realname, email, - NULL, NULL); - if (realname) - silc_free(realname); - silc_free(hostname); - silc_free(username); - - return ident; -} - -/* Creates new public key and private key pair. This is used only - when user wants to create new key pair from command line. */ - -int silc_client_create_key_pair(char *pkcs_name, int bits, - char *public_key, char *private_key, - char *identifier, - SilcPublicKey *ret_pub_key, - SilcPrivateKey *ret_prv_key) -{ - SilcPKCS pkcs; - SilcPublicKey pub_key; - SilcPrivateKey prv_key; - SilcRng rng; - unsigned char *key; - SilcUInt32 key_len; - char line[256]; - char *pkfile = NULL, *prvfile = NULL; - - if (!pkcs_name || !public_key || !private_key) - printf("\ -New pair of keys will be created. Please, answer to following questions.\n\ -"); - - if (!pkcs_name) { - again_name: - pkcs_name = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE); - if (!pkcs_name) - pkcs_name = strdup("rsa"); - - if (*pkcs_name == 'l' || *pkcs_name == 'L') { - silc_client_list_pkcs(); - silc_free(pkcs_name); - goto again_name; - } - } - - if (!silc_pkcs_is_supported(pkcs_name)) { - fprintf(stderr, "Unknown PKCS `%s'", pkcs_name); - return FALSE; - } - - if (!bits) { - char *length = NULL; - length = silc_get_input("Key length in bits [2048]: ", FALSE); - if (!length) - bits = 2048; - else - bits = atoi(length); - } - - if (!identifier) { - char *def = silc_client_create_identifier(); - - memset(line, 0, sizeof(line)); - if (def) - snprintf(line, sizeof(line), "Identifier [%s]: ", def); - else - snprintf(line, sizeof(line), - "Identifier (eg. UN=jon, HN=jon.dummy.com, " - "RN=Jon Johnson, E=jon@dummy.com): "); - - while (!identifier) { - identifier = silc_get_input(line, FALSE); - if (!identifier && def) - identifier = strdup(def); - } - - if (def) - silc_free(def); - } - - rng = silc_rng_alloc(); - silc_rng_init(rng); - silc_rng_global_init(rng); - - if (!public_key) { - memset(line, 0, sizeof(line)); - snprintf(line, sizeof(line), "Public key filename [%s] ", - SILC_CLIENT_PUBLIC_KEY_NAME); - pkfile = silc_get_input(line, FALSE); - if (!pkfile) - pkfile = SILC_CLIENT_PUBLIC_KEY_NAME; - } else { - pkfile = public_key; - } - - if (!private_key) { - memset(line, 0, sizeof(line)); - snprintf(line, sizeof(line), "Public key filename [%s] ", - SILC_CLIENT_PRIVATE_KEY_NAME); - prvfile = silc_get_input(line, FALSE); - if (!prvfile) - prvfile = SILC_CLIENT_PRIVATE_KEY_NAME; - } else { - prvfile = private_key; - } - - /* Generate keys */ - silc_pkcs_alloc(pkcs_name, &pkcs); - silc_pkcs_generate_key(pkcs, bits, rng); - - /* Save public key into file */ - key = silc_pkcs_get_public_key(pkcs, &key_len); - pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs), identifier, - key, key_len); - silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM); - if (ret_pub_key) - *ret_pub_key = pub_key; - - memset(key, 0, key_len); - silc_free(key); - - /* Save private key into file */ - key = silc_pkcs_get_private_key(pkcs, &key_len); - prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs), - key, key_len); - silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN); - if (ret_prv_key) - *ret_prv_key = prv_key; - - printf("Public key has been saved into `%s'.\n", pkfile); - printf("Private key has been saved into `%s'.\n", prvfile); - printf("Press to continue...\n"); - getchar(); - - memset(key, 0, key_len); - silc_free(key); - - silc_rng_free(rng); - silc_pkcs_free(pkcs); - - return TRUE; -} - /* This checks stats for various SILC files and directories. First it checks if ~/.silc directory exist and is owned by the correct user. If it doesn't exist, it will create the directory. After that it checks if @@ -259,10 +91,8 @@ int silc_client_check_silc_dir() { char filename[256], file_public_key[256], file_private_key[256]; char servfilename[256], clientfilename[256], friendsfilename[256]; - char *identifier; struct stat st; struct passwd *pw; - int firstime = FALSE; time_t curtime, modtime; SILC_LOG_DEBUG(("Checking ~./silc directory")); @@ -271,13 +101,9 @@ int silc_client_check_silc_dir() memset(file_public_key, 0, sizeof(file_public_key)); memset(file_private_key, 0, sizeof(file_private_key)); - identifier = silc_client_create_identifier(); - pw = getpwuid(getuid()); if (!pw) { fprintf(stderr, "silc: %s\n", strerror(errno)); - if (identifier) - silc_free(identifier); return FALSE; } @@ -301,9 +127,6 @@ int silc_client_check_silc_dir() fprintf(stderr, "Couldn't create `%s' directory\n", filename); return FALSE; } - - /* Directory was created. First time running SILC */ - firstime = TRUE; } else { fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n", filename); @@ -408,30 +231,22 @@ int silc_client_check_silc_dir() snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s", filename, SILC_CLIENT_PRIVATE_KEY_NAME); - /* If running SILC first time */ - if (firstime) { - fprintf(stdout, "Running SILC for the first time\n"); - silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS, - SILC_CLIENT_DEF_PKCS_LEN, - file_public_key, file_private_key, - identifier, NULL, NULL); - return TRUE; - } - if ((stat(file_public_key, &st)) == -1) { /* If file doesn't exist */ if (errno == ENOENT) { - fprintf(stdout, "Your public key doesn't exist\n"); - silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS, - SILC_CLIENT_DEF_PKCS_LEN, - file_public_key, - file_private_key, identifier, NULL, NULL); + fprintf(stdout, "Running SILC for the first time\n"); + silc_create_key_pair(SILC_CLIENT_DEF_PKCS, + SILC_CLIENT_DEF_PKCS_LEN, + file_public_key, file_private_key, NULL, + NULL, NULL, NULL, FALSE); + printf("Press to continue...\n"); + getchar(); } else { fprintf(stderr, "%s\n", strerror(errno)); return FALSE; } } - + /* Check the owner of the public key */ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { fprintf(stderr, "You don't seem to own your public key!?\n"); @@ -442,10 +257,12 @@ int silc_client_check_silc_dir() /* If file doesn't exist */ if (errno == ENOENT) { fprintf(stdout, "Your private key doesn't exist\n"); - silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS, - SILC_CLIENT_DEF_PKCS_LEN, - file_public_key, - file_private_key, identifier, NULL, NULL); + silc_create_key_pair(SILC_CLIENT_DEF_PKCS, + SILC_CLIENT_DEF_PKCS_LEN, + file_public_key, file_private_key, NULL, + NULL, NULL, NULL, FALSE); + printf("Press to continue...\n"); + getchar(); } else { fprintf(stderr, "%s\n", strerror(errno)); return FALSE; @@ -492,10 +309,12 @@ int silc_client_check_silc_dir() answer = silc_get_input("Would you like to create a new key pair " "([y]/n)?: ", FALSE); if (!answer || answer[0] == 'Y' || answer[0] == 'y') { - silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS, - SILC_CLIENT_DEF_PKCS_LEN, - file_public_key, - file_private_key, identifier, NULL, NULL); + silc_create_key_pair(SILC_CLIENT_DEF_PKCS, + SILC_CLIENT_DEF_PKCS_LEN, + file_public_key, file_private_key, NULL, + NULL, NULL, NULL, FALSE); + printf("Press to continue...\n"); + getchar(); } else { #ifdef HAVE_UTIME struct utimbuf utim; @@ -507,9 +326,6 @@ int silc_client_check_silc_dir() silc_free(answer); } - if (identifier) - silc_free(identifier); - return TRUE; } @@ -517,7 +333,7 @@ int silc_client_check_silc_dir() int silc_client_load_keys(SilcClient client) { - char filename[256]; + char pub[256], prv[256]; struct passwd *pw; SILC_LOG_DEBUG(("Loading public and private keys")); @@ -526,90 +342,14 @@ int silc_client_load_keys(SilcClient client) if (!pw) return FALSE; - memset(filename, 0, sizeof(filename)); - snprintf(filename, sizeof(filename) - 1, "%s/%s", + memset(prv, 0, sizeof(prv)); + snprintf(prv, sizeof(prv) - 1, "%s/%s", get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME); - if (silc_pkcs_load_private_key(filename, &client->private_key, - SILC_PKCS_FILE_BIN) == FALSE) - if (silc_pkcs_load_private_key(filename, &client->private_key, - SILC_PKCS_FILE_PEM) == FALSE) - return FALSE; - - memset(filename, 0, sizeof(filename)); - snprintf(filename, sizeof(filename) - 1, "%s/%s", + memset(pub, 0, sizeof(pub)); + snprintf(pub, sizeof(pub) - 1, "%s/%s", get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME); - - if (silc_pkcs_load_public_key(filename, &client->public_key, - SILC_PKCS_FILE_PEM) == FALSE) - if (silc_pkcs_load_public_key(filename, &client->public_key, - SILC_PKCS_FILE_BIN) == FALSE) - return FALSE; - - silc_pkcs_alloc(client->public_key->name, &client->pkcs); - silc_pkcs_public_key_set(client->pkcs, client->public_key); - silc_pkcs_private_key_set(client->pkcs, client->private_key); - - return TRUE; -} - -/* Dumps the public key on screen. Used from the command line option. */ - -int silc_client_show_key(char *keyfile) -{ - SilcPublicKey public_key; - SilcPublicKeyIdentifier ident; - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - SilcPKCS pkcs; - int key_len = 0; - - if (silc_pkcs_load_public_key(keyfile, &public_key, - SILC_PKCS_FILE_PEM) == FALSE) - if (silc_pkcs_load_public_key(keyfile, &public_key, - SILC_PKCS_FILE_BIN) == FALSE) { - fprintf(stderr, "Could not load public key file `%s'\n", keyfile); - return FALSE; - } - - ident = silc_pkcs_decode_identifier(public_key->identifier); - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - if (silc_pkcs_alloc(public_key->name, &pkcs)) { - key_len = silc_pkcs_public_key_set(pkcs, public_key); - silc_pkcs_free(pkcs); - } - - printf("Public key file : %s\n", keyfile); - printf("Algorithm : %s\n", public_key->name); - if (key_len) - printf("Key length (bits) : %d\n", key_len); - if (ident->realname) - printf("Real name : %s\n", ident->realname); - if (ident->username) - printf("Username : %s\n", ident->username); - if (ident->host) - printf("Hostname : %s\n", ident->host); - if (ident->email) - printf("Email : %s\n", ident->email); - if (ident->org) - printf("Organization : %s\n", ident->org); - if (ident->country) - printf("Country : %s\n", ident->country); - printf("Fingerprint (SHA1) : %s\n", fingerprint); - printf("Babbleprint (SHA1) : %s\n", babbleprint); - - fflush(stdout); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - silc_pkcs_public_key_free(public_key); - silc_pkcs_free_identifier(ident); - - return TRUE; + + return silc_load_key_pair(pub, prv, &client->pkcs, &client->public_key, + &client->private_key); } diff --git a/apps/irssi/src/silc/core/clientutil.h b/apps/irssi/src/silc/core/clientutil.h index 3f4a6046..6b703f5d 100644 --- a/apps/irssi/src/silc/core/clientutil.h +++ b/apps/irssi/src/silc/core/clientutil.h @@ -28,14 +28,7 @@ void silc_client_list_ciphers(); void silc_client_list_hash_funcs(); void silc_client_list_hmacs(); void silc_client_list_pkcs(); -char *silc_client_create_identifier(); -int silc_client_create_key_pair(char *pkcs_name, int bits, - char *public_key, char *private_key, - char *identifier, - SilcPublicKey *ret_pub_key, - SilcPrivateKey *ret_prv_key); int silc_client_check_silc_dir(); int silc_client_load_keys(SilcClient client); -int silc_client_show_key(char *keyfile); #endif diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 2253c9ec..f1410e7f 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -264,7 +264,7 @@ void silc_opt_callback(poptContext con, silc_pkcs_register_default(); silc_hash_register_default(); silc_hmac_register_default(); - silc_client_show_key((char *)arg); + silc_show_public_key((char *)arg); exit(0); } @@ -310,8 +310,8 @@ void silc_opt_callback(poptContext con, silc_pkcs_register_default(); silc_hash_register_default(); silc_hmac_register_default(); - silc_client_create_key_pair(opt_pkcs, opt_bits, - NULL, NULL, NULL, NULL, NULL); + silc_create_key_pair(opt_pkcs, opt_bits, NULL, NULL, NULL, + NULL, NULL, NULL, TRUE); exit(0); } } diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index 306f771a..c110a649 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -33,11 +33,6 @@ static SilcServer silcd; static void silc_usage(void); -static char *silc_server_create_identifier(void); -static int silc_server_create_key_pair(char *pkcs_name, int bits, char *path, - char *identifier, - SilcPublicKey *ret_pub_key, - SilcPrivateKey *ret_prv_key); /* Long command line options */ static struct option long_opts[] = @@ -519,12 +514,19 @@ int main(int argc, char **argv) if (opt_create_keypair == TRUE) { /* Create new key pair and exit */ + char pubfile[256], prvfile[256]; + + memset(pubfile, 0, sizeof(pubfile)); + memset(prvfile, 0, sizeof(prvfile)); + snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath); + snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath); + silc_cipher_register_default(); silc_pkcs_register_default(); silc_hash_register_default(); silc_hmac_register_default(); - silc_server_create_key_pair(opt_pkcs, opt_bits, opt_keypath, - opt_identifier, NULL, NULL); + silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile, + opt_identifier, NULL, NULL, NULL, FALSE); exit(0); } @@ -606,108 +608,3 @@ int main(int argc, char **argv) silc_free(opt_keypath); exit(1); } - -/* Returns identifier string for public key generation. */ - -static char *silc_server_create_identifier(void) -{ - char *username = NULL, *realname = NULL; - char hostname[256], email[256]; - - /* Get realname */ - realname = silc_get_real_name(); - - /* Get hostname */ - memset(hostname, 0, sizeof(hostname)); - gethostname(hostname, sizeof(hostname)); - - /* Get username (mandatory) */ - username = silc_get_username(); - if (!username) - return NULL; - - /* Create default email address, whether it is right or not */ - snprintf(email, sizeof(email), "%s@%s", username, hostname); - - return silc_pkcs_encode_identifier(username, hostname, realname, email, - NULL, NULL); -} - -/* Creates new public key and private key pair. This is used only - when user wants to create new key pair from command line. */ - -static int -silc_server_create_key_pair(char *pkcs_name, int bits, char *path, - char *identifier, - SilcPublicKey *ret_pub_key, - SilcPrivateKey *ret_prv_key) -{ - SilcPKCS pkcs; - SilcPublicKey pub_key; - SilcPrivateKey prv_key; - SilcRng rng; - unsigned char *key; - SilcUInt32 key_len; - char pkfile[256], prvfile[256]; - - if (!pkcs_name || !path) - return FALSE; - - if (!silc_pkcs_is_supported(pkcs_name)) { - fprintf(stderr, "Unsupported PKCS `%s'", pkcs_name); - return FALSE; - } - - if (!bits) - bits = 2048; - - if (!identifier) - identifier = silc_server_create_identifier(); - - rng = silc_rng_alloc(); - silc_rng_init(rng); - silc_rng_global_init(rng); - - snprintf(pkfile, sizeof(pkfile) - 1, "%s%s", path, - SILC_SERVER_PUBLIC_KEY_NAME); - snprintf(prvfile, sizeof(prvfile) - 1, "%s%s", path, - SILC_SERVER_PRIVATE_KEY_NAME); - - /* Generate keys */ - silc_pkcs_alloc(pkcs_name, &pkcs); - silc_pkcs_generate_key(pkcs, bits, rng); - - /* Save public key into file */ - key = silc_pkcs_get_public_key(pkcs, &key_len); - pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs), identifier, - key, key_len); - silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM); - if (ret_pub_key) - *ret_pub_key = pub_key; - else - silc_pkcs_public_key_free(pub_key); - - memset(key, 0, sizeof(key_len)); - silc_free(key); - - /* Save private key into file */ - key = silc_pkcs_get_private_key(pkcs, &key_len); - prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs), - key, key_len); - silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN); - if (ret_prv_key) - *ret_prv_key = prv_key; - else - silc_pkcs_private_key_free(prv_key); - - printf("Public key has been saved into `%s'\n", pkfile); - printf("Private key has been saved into `%s'\n", prvfile); - - memset(key, 0, sizeof(key_len)); - silc_free(key); - - silc_rng_free(rng); - silc_pkcs_free(pkcs); - - return TRUE; -} diff --git a/includes/silcincludes.h b/includes/silcincludes.h index 9933b084..1e5a8ad0 100644 --- a/includes/silcincludes.h +++ b/includes/silcincludes.h @@ -266,6 +266,8 @@ extern "C" { #include "silcauth.h" #include "silcprivate.h" #include "silcattrs.h" +#include "silcvcard.h" +#include "silcapputil.h" #ifdef SILC_SIM /* SILC Module library includes */ diff --git a/lib/silccrypt/silcpkcs.h b/lib/silccrypt/silcpkcs.h index 43d602aa..7b704b44 100644 --- a/lib/silccrypt/silcpkcs.h +++ b/lib/silccrypt/silcpkcs.h @@ -399,7 +399,8 @@ const char *silc_pkcs_get_name(SilcPKCS pkcs); * * DESCRIPTION * - * Returns SILC style public key. + * Returns SILC style public key. The caller must free the returned + * data. * ***/ unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len); @@ -413,7 +414,8 @@ unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len); * * DESCRIPTION * - * Returns SILC style private key. + * Returns SILC style private key. The caller must free the returned + * data and SHOULD zero the memory area before freeing. * ***/ unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len); diff --git a/lib/silcutil/DIRECTORY b/lib/silcutil/DIRECTORY index 7341eafb..6e178a56 100644 --- a/lib/silcutil/DIRECTORY +++ b/lib/silcutil/DIRECTORY @@ -20,6 +20,7 @@ @LINK=silclist.html:SILC List Interface @LINK=silcdlist.html:SILC Dynamic List Interface @LINK=silcvcard.html:SILC VCard Interface +@LINK=silcapputil.html:SILC Application Utilities --> SILC Utility Library diff --git a/lib/silcutil/Makefile.am b/lib/silcutil/Makefile.am index c9c6d702..96ae75c0 100644 --- a/lib/silcutil/Makefile.am +++ b/lib/silcutil/Makefile.am @@ -59,7 +59,8 @@ libsilcutil_a_SOURCES = \ silchashtable.c \ silcsockconn.c \ silcprotocol.c \ - silcvcard.c + silcvcard.c \ + silcapputil.c if SILC_DIST_TOOLKIT include_HEADERS = \ @@ -82,6 +83,7 @@ include_HEADERS = \ silcutil.h \ silcstrutil.h \ silcvcard.h \ + silcapputil.h \ silctypes.h endif diff --git a/lib/silcutil/silcapputil.c b/lib/silcutil/silcapputil.c new file mode 100644 index 00000000..6c0eccaa --- /dev/null +++ b/lib/silcutil/silcapputil.c @@ -0,0 +1,314 @@ +/* + + silcapputil.c + + Author: Pekka Riikonen + + Copyright (C) 2002 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ +/* $Id$ */ + +#include "silcincludes.h" + +static char *silc_create_pk_identifier(void) +{ + char *username = NULL, *realname = NULL; + char *hostname, email[256]; + char *ident; + + /* Get realname */ + realname = silc_get_real_name(); + + /* Get hostname */ + hostname = silc_net_localhost(); + if (!hostname) + return NULL; + + /* Get username (mandatory) */ + username = silc_get_username(); + if (!username) + return NULL; + + /* Create default email address, whether it is right or not */ + snprintf(email, sizeof(email), "%s@%s", username, hostname); + + ident = silc_pkcs_encode_identifier(username, hostname, realname, email, + NULL, NULL); + if (realname) + silc_free(realname); + silc_free(hostname); + silc_free(username); + + return ident; +} + +/* Generate key pair */ + +bool silc_create_key_pair(const char *pkcs_name, + SilcUInt32 key_len_bits, + const char *pub_filename, + const char *prv_filename, + const char *pub_identifier, + SilcPKCS *return_pkcs, + SilcPublicKey *return_public_key, + SilcPrivateKey *return_private_key, + bool interactive) +{ + SilcPKCS pkcs; + SilcPublicKey pub_key; + SilcPrivateKey prv_key; + SilcRng rng; + unsigned char *key; + SilcUInt32 key_len; + char line[256]; + char *pkfile = pub_filename ? strdup(pub_filename) : NULL; + char *prvfile = prv_filename ? strdup(prv_filename) : NULL; + char *alg = pkcs_name ? strdup(pkcs_name) : NULL; + char *identifier = pub_identifier ? strdup(pub_identifier) : NULL; + + if (interactive && (!alg || !pub_filename || !prv_filename)) + printf("\ +New pair of keys will be created. Please, answer to following questions.\n\ +"); + + if (!alg) { + if (interactive) { + while (!alg) { + alg = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE); + if (!alg) + alg = strdup("rsa"); + + if (*alg == 'l' || *alg == 'L') { + char *list = silc_pkcs_get_supported(); + printf("%s\n", list); + silc_free(list); + silc_free(alg); + alg = NULL; + } + } + } else { + alg = strdup("rsa"); + } + } + + if (!silc_pkcs_is_supported(alg)) { + fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library" + "is not initialized", alg); + return FALSE; + } + + if (!key_len_bits) { + if (interactive) { + char *length = NULL; + length = silc_get_input("Key length in key_len_bits [2048]: ", FALSE); + if (length) + key_len_bits = atoi(length); + silc_free(length); + } + if (!key_len_bits) + key_len_bits = 2048; + } + + if (!identifier) { + char *def = silc_create_pk_identifier(); + + if (interactive) { + memset(line, 0, sizeof(line)); + if (def) + snprintf(line, sizeof(line), "Identifier [%s]: ", def); + else + snprintf(line, sizeof(line), + "Identifier (eg. UN=jon, HN=jon.dummy.com, " + "RN=Jon Johnson, E=jon@dummy.com): "); + + while (!identifier) { + identifier = silc_get_input(line, FALSE); + if (!identifier && def) + identifier = strdup(def); + } + } else { + if (!def) { + fprintf(stderr, "Could not create public key identifier: %s\n", + strerror(errno)); + return FALSE; + } + identifier = strdup(def); + } + + silc_free(def); + } + + rng = silc_rng_alloc(); + silc_rng_init(rng); + silc_rng_global_init(rng); + + if (!pkfile) { + if (interactive) { + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "Public key filename [public_key.pub] "); + pkfile = silc_get_input(line, FALSE); + } + if (!pkfile) + pkfile = strdup("public_key.pub"); + } + + if (!prvfile) { + if (interactive) { + memset(line, 0, sizeof(line)); + snprintf(line, sizeof(line), "Public key filename [private_key.prv] "); + prvfile = silc_get_input(line, FALSE); + } + if (!prvfile) + prvfile = strdup("private_key.prv"); + } + + /* Generate keys */ + silc_pkcs_alloc(alg, &pkcs); + silc_pkcs_generate_key(pkcs, key_len_bits, rng); + + /* Save public key into file */ + key = silc_pkcs_get_public_key(pkcs, &key_len); + pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs), + identifier, key, key_len); + silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM); + if (return_public_key) + *return_public_key = pub_key; + else + silc_pkcs_public_key_free(pub_key); + memset(key, 0, key_len); + silc_free(key); + + /* Save private key into file */ + key = silc_pkcs_get_private_key(pkcs, &key_len); + prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs), + key, key_len); + silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN); + if (return_private_key) + *return_private_key = prv_key; + else + silc_pkcs_private_key_free(prv_key); + memset(key, 0, key_len); + silc_free(key); + + printf("Public key has been saved into `%s'.\n", pkfile); + printf("Private key has been saved into `%s'.\n", prvfile); + if (interactive) { + printf("Press to continue...\n"); + getchar(); + } + + if (return_pkcs) + *return_pkcs = pkcs; + else + silc_pkcs_free(pkcs); + + silc_rng_free(rng); + silc_free(alg); + silc_free(pkfile); + silc_free(prvfile); + silc_free(identifier); + + return TRUE; +} + +/* Load key pair */ + +bool silc_load_key_pair(const char *pub_filename, + const char *prv_filename, + SilcPKCS *return_pkcs, + SilcPublicKey *return_public_key, + SilcPrivateKey *return_private_key) +{ + SILC_LOG_DEBUG(("Loading public and private keys")); + + if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key, + SILC_PKCS_FILE_PEM) == FALSE) + if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key, + SILC_PKCS_FILE_BIN) == FALSE) + return FALSE; + + if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key, + SILC_PKCS_FILE_BIN) == FALSE) + if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key, + SILC_PKCS_FILE_PEM) == FALSE) + return FALSE; + + if (return_pkcs) { + silc_pkcs_alloc((*return_public_key)->name, return_pkcs); + silc_pkcs_public_key_set(*return_pkcs, *return_public_key); + silc_pkcs_private_key_set(*return_pkcs, *return_private_key); + } + + return TRUE; +} + +/* Dump public key into stdout */ + +bool silc_show_public_key(const char *pub_filename) +{ + SilcPublicKey public_key; + SilcPublicKeyIdentifier ident; + char *fingerprint, *babbleprint; + unsigned char *pk; + SilcUInt32 pk_len; + SilcPKCS pkcs; + SilcUInt32 key_len = 0; + + if (silc_pkcs_load_public_key((char *)pub_filename, &public_key, + SILC_PKCS_FILE_PEM) == FALSE) + if (silc_pkcs_load_public_key((char *)pub_filename, &public_key, + SILC_PKCS_FILE_BIN) == FALSE) { + fprintf(stderr, "Could not load public key file `%s'\n", pub_filename); + return FALSE; + } + + ident = silc_pkcs_decode_identifier(public_key->identifier); + + pk = silc_pkcs_public_key_encode(public_key, &pk_len); + fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); + babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + + if (silc_pkcs_alloc(public_key->name, &pkcs)) { + key_len = silc_pkcs_public_key_set(pkcs, public_key); + silc_pkcs_free(pkcs); + } + + printf("Public key file : %s\n", pub_filename); + printf("Algorithm : %s\n", public_key->name); + if (key_len) + printf("Key length (bits) : %d\n", (unsigned int)key_len); + if (ident->realname) + printf("Real name : %s\n", ident->realname); + if (ident->username) + printf("Username : %s\n", ident->username); + if (ident->host) + printf("Hostname : %s\n", ident->host); + if (ident->email) + printf("Email : %s\n", ident->email); + if (ident->org) + printf("Organization : %s\n", ident->org); + if (ident->country) + printf("Country : %s\n", ident->country); + printf("Fingerprint (SHA1) : %s\n", fingerprint); + printf("Babbleprint (SHA1) : %s\n", babbleprint); + + fflush(stdout); + + silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); + silc_pkcs_public_key_free(public_key); + silc_pkcs_free_identifier(ident); + + return TRUE; +} diff --git a/lib/silcutil/silcapputil.h b/lib/silcutil/silcapputil.h new file mode 100644 index 00000000..f054fa4d --- /dev/null +++ b/lib/silcutil/silcapputil.h @@ -0,0 +1,134 @@ +/* + + silcapputil.h + + Author: Pekka Riikonen + + Copyright (C) 2002 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +/****h* silcutil/SILC Application Utilities + * + * DESCRIPTION + * + * This interface provides utility functions for applications' + * convenience. It provides functions that may be used for example by + * command line applications but also other applications may find some + * routines helpful. None of these routines are mandatory in any other + * SILC routines or libraries, and are purely provided for convenience. + * These routines for example provide simple public key and private key + * pair generation, public key and private key file saving and loading + * for application, and other similar routines. + * + ***/ + +#ifndef SILCAPPUTIL_H +#define SILCAPPUTIL_H + +/****f* silcutil/SilcAppUtil/silc_create_key_pair + * + * SYNOPSIS + * + * bool silc_create_key_pair(const char *pkcs_name, + * SilcUInt32 key_len_bits, + * const char *pub_filename, + * const char *prv_filename, + * const char *pub_identifier, + * SilcPKCS *return_pkcs, + * SilcPublicKey *return_public_key, + * SilcPrivateKey *return_private_key, + * bool interactive); + * + * DESCRIPTION + * + * This routine can be used to generate new public key and private key + * pair. The `pkcs_name' is the name of public key algorithm, or if + * NULL it defaults to "rsa". The `key_len_bits' is the key length + * in bits and if zero (0) it defaults to 2048 bits. The `pub_filename' + * and `prv_filename' is the public key and private key filenames. + * The `pub_identifier' is the public key identifier (for example: + * "UN=foobar, HN=hostname"), or if NULL the routine generates it + * automatically. + * + * The routine returns FALSE if error occurs during key generation. + * Function returns TRUE when success and returns the created SilcPKCS + * object, which can be used to perform public key cryptography into + * `return_pkcs' pointer, created public key into `return_public_key', + * and created private key into `return_private_key' pointer. + * + * If the `interactive' is TRUE then this asks the user (by blocking + * the process for input) some questions about key generation (like + * public key algorithm, key length, filenames, etc). If all + * arguments are provided to this function already then `interactive' + * has no effect. + * + * NOTES + * + * Before calling this function the application must have initialized + * the crypto library by registering the public key algorithms with + * silc_pkcs_register_default function. + * + ***/ +bool silc_create_key_pair(const char *pkcs_name, + SilcUInt32 key_len_bits, + const char *pub_filename, + const char *prv_filename, + const char *pub_identifier, + SilcPKCS *return_pkcs, + SilcPublicKey *return_public_key, + SilcPrivateKey *return_private_key, + bool interactive); + +/****f* silcutil/SilcAppUtil/silc_load_key_pair + * + * SYNOPSIS + * + * bool silc_load_key_pair(const char *pub_filename, + * const char *prv_filename, + * SilcPKCS *return_pkcs, + * SilcPublicKey *return_public_key, + * SilcPrivateKey *return_private_key); + * + * DESCRIPTION + * + * This routine can be used to load the public key and private key + * from files. This retuns FALSE it either of the key could not be + * loaded. This function returns TRUE on success and returns the + * public key into `return_public_key' pointer, private key into + * `return_private_key' pointer and the SilcPKCS object to the + * `return_pkcs'. The SilcPKCS can be used to perform public key + * cryptographic operations. + * + ***/ +bool silc_load_key_pair(const char *pub_filename, + const char *prv_filename, + SilcPKCS *return_pkcs, + SilcPublicKey *return_public_key, + SilcPrivateKey *return_private_key); + +/****f* silcutil/SilcAppUtil/silc_show_public_key + * + * SYNOPSIS + * + * bool silc_show_public_key(const char *pub_filename); + * + * DESCRIPTION + * + * This routine can be used to dump the contents of the public key + * in the public key file `pub_filename'. This dumps the public key + * into human readable form into stdout. Returns FALSE on error. + * + ***/ +bool silc_show_public_key(const char *pub_filename); + +#endif /* SILCAPPUTIL_H */ -- 2.24.0