Added SILC Server library.
[silc.git] / lib / silcutil / silcapputil.c
index 6c0eccaaa8504eeb621c35d97817a78698b7a90e..d1d6739ff751b56e8f8173e93273d18a21f9b1cb 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcapputil.c 
+  silcapputil.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2005 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
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.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();
 
@@ -54,15 +54,16 @@ static char *silc_create_pk_identifier(void)
 
 /* Generate key pair */
 
-bool silc_create_key_pair(const char *pkcs_name,
+SilcBool silc_create_key_pair(const char *pkcs_name,
                          SilcUInt32 key_len_bits,
                          const char *pub_filename,
                          const char *prv_filename,
                          const char *pub_identifier,
+                         const char *passphrase,
                          SilcPKCS *return_pkcs,
                          SilcPublicKey *return_public_key,
                          SilcPrivateKey *return_private_key,
-                         bool interactive)
+                         SilcBool interactive)
 {
   SilcPKCS pkcs;
   SilcPublicKey pub_key;
@@ -75,6 +76,7 @@ bool silc_create_key_pair(const char *pkcs_name,
   char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
   char *alg = pkcs_name ? strdup(pkcs_name) : NULL;
   char *identifier = pub_identifier ? strdup(pub_identifier) : NULL;
+  char *pass = passphrase ? strdup(passphrase) : NULL;
 
   if (interactive && (!alg || !pub_filename || !prv_filename))
     printf("\
@@ -87,7 +89,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
        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);
@@ -155,7 +157,7 @@ New pair of keys will be created.  Please, answer to following questions.\n\
   if (!pkfile) {
     if (interactive) {
       memset(line, 0, sizeof(line));
-      snprintf(line, sizeof(line), "Public key filename [public_key.pub] ");
+      snprintf(line, sizeof(line), "Public key filename [public_key.pub]: ");
       pkfile = silc_get_input(line, FALSE);
     }
     if (!pkfile)
@@ -165,15 +167,37 @@ New pair of keys will be created.  Please, answer to following questions.\n\
   if (!prvfile) {
     if (interactive) {
       memset(line, 0, sizeof(line));
-      snprintf(line, sizeof(line), "Public key filename [private_key.prv] ");
+      snprintf(line, sizeof(line), "Private key filename [private_key.prv]: ");
       prvfile = silc_get_input(line, FALSE);
     }
     if (!prvfile)
       prvfile = strdup("private_key.prv");
   }
 
+  if (!pass) {
+    while (TRUE) {
+      char *pass2 = NULL;
+      pass = silc_get_input("Private key passphrase: ", TRUE);
+      if (!pass) {
+        pass = strdup("");
+       break;
+      } else {
+       SilcBool match;
+       printf("\n");
+       pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
+       if (!pass2)
+         pass2 = strdup("");
+       match = !strcmp(pass, pass2);
+       silc_free(pass2);
+       if (match)
+         break;
+       fprintf(stderr, "\nPassphrases do not match\n\n");
+      }
+    }
+  }
+
   /* Generate keys */
-  silc_pkcs_alloc(alg, &pkcs);
+  silc_pkcs_alloc(alg, SILC_PKCS_SILC, &pkcs);
   silc_pkcs_generate_key(pkcs, key_len_bits, rng);
 
   /* Save public key into file */
@@ -192,7 +216,9 @@ New pair of keys will be created.  Please, answer to following questions.\n\
   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);
+  silc_pkcs_save_private_key(prvfile, prv_key,
+                            (unsigned char *)pass, strlen(pass),
+                            SILC_PKCS_FILE_BIN);
   if (return_private_key)
     *return_private_key = prv_key;
   else
@@ -217,44 +243,66 @@ New pair of keys will be created.  Please, answer to following questions.\n\
   silc_free(pkfile);
   silc_free(prvfile);
   silc_free(identifier);
+  memset(pass, 0, strlen(pass));
+  silc_free(pass);
 
   return TRUE;
 }
 
 /* Load key pair */
 
-bool silc_load_key_pair(const char *pub_filename,
+SilcBool silc_load_key_pair(const char *pub_filename,
                        const char *prv_filename,
+                       const char *passphrase,
                        SilcPKCS *return_pkcs,
                        SilcPublicKey *return_public_key,
                        SilcPrivateKey *return_private_key)
 {
+  char *pass = passphrase ? strdup(passphrase) : NULL;
+
   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)
+                                 SILC_PKCS_FILE_BIN) == FALSE) {
+      if (pass)
+       memset(pass, 0, strlen(pass));
+      silc_free(pass);
       return FALSE;
+    }
+
+  if (!pass) {
+    pass = silc_get_input("Private key passphrase: ", TRUE);
+    if (!pass)
+      pass = strdup("");
+  }
 
   if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
+                                (unsigned char *)pass, strlen(pass),
                                 SILC_PKCS_FILE_BIN) == FALSE)
     if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
-                                  SILC_PKCS_FILE_PEM) == FALSE)
+                                  (unsigned char *)pass, strlen(pass),
+                                  SILC_PKCS_FILE_PEM) == FALSE) {
+      memset(pass, 0, strlen(pass));
+      silc_free(pass);
       return FALSE;
+    }
 
   if (return_pkcs) {
-    silc_pkcs_alloc((*return_public_key)->name, return_pkcs);
+    silc_pkcs_alloc((*return_public_key)->name, SILC_PKCS_SILC, return_pkcs);
     silc_pkcs_public_key_set(*return_pkcs, *return_public_key);
     silc_pkcs_private_key_set(*return_pkcs, *return_private_key);
   }
 
+  memset(pass, 0, strlen(pass));
+  silc_free(pass);
   return TRUE;
 }
 
 /* Dump public key into stdout */
 
-bool silc_show_public_key(const char *pub_filename)
+SilcBool silc_show_public_key(const char *pub_filename)
 {
   SilcPublicKey public_key;
   SilcPublicKeyIdentifier ident;
@@ -278,7 +326,7 @@ bool silc_show_public_key(const char *pub_filename)
   fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
   babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
 
-  if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+  if (silc_pkcs_alloc(public_key->name, SILC_PKCS_SILC, &pkcs)) {
     key_len = silc_pkcs_public_key_set(pkcs, public_key);
     silc_pkcs_free(pkcs);
   }
@@ -299,8 +347,8 @@ bool silc_show_public_key(const char *pub_filename)
     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); 
+  printf("Fingerprint (SHA1) : %s\n", fingerprint);
+  printf("Babbleprint (SHA1) : %s\n", babbleprint);
 
   fflush(stdout);
 
@@ -312,3 +360,71 @@ bool silc_show_public_key(const char *pub_filename)
 
   return TRUE;
 }
+
+/* Change private key passphrase */
+
+SilcBool silc_change_private_key_passphrase(const char *prv_filename,
+                                       const char *old_passphrase,
+                                       const char *new_passphrase)
+{
+  SilcPrivateKey private_key;
+  SilcBool base64 = FALSE;
+  char *pass;
+
+  pass = old_passphrase ? strdup(old_passphrase) : NULL;
+  if (!pass) {
+    pass = silc_get_input("Old passphrase: ", TRUE);
+    if (!pass)
+      pass = strdup("");
+  }
+
+  if (silc_pkcs_load_private_key((char *)prv_filename, &private_key,
+                                (unsigned char *)pass, strlen(pass),
+                                SILC_PKCS_FILE_BIN) == FALSE) {
+    base64 = TRUE;
+    if (silc_pkcs_load_private_key((char *)prv_filename, &private_key,
+                                  (unsigned char *)pass, strlen(pass),
+                                  SILC_PKCS_FILE_PEM) == FALSE) {
+      memset(pass, 0, strlen(pass));
+      silc_free(pass);
+      fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
+      return FALSE;
+    }
+  }
+
+  memset(pass, 0, strlen(pass));
+  silc_free(pass);
+
+  pass = new_passphrase ? strdup(new_passphrase) : NULL;
+  if (!pass) {
+    char *pass2 = NULL;
+    fprintf(stdout, "\n");
+    pass = silc_get_input("New passphrase: ", TRUE);
+    if (!pass) {
+      pass = strdup("");
+    } else {
+      while (TRUE) {
+       printf("\n");
+       pass2 = silc_get_input("Retype new passphrase: ", TRUE);
+       if (!pass2)
+         pass2 = strdup("");
+       if (!strcmp(pass, pass2))
+         break;
+       fprintf(stderr, "\nPassphrases do not match");
+      }
+      silc_free(pass2);
+    }
+  }
+
+  silc_pkcs_save_private_key((char *)prv_filename, private_key,
+                            (unsigned char *)pass, strlen(pass),
+                            base64 ? SILC_PKCS_FILE_PEM : SILC_PKCS_FILE_BIN);
+
+  fprintf(stdout, "\nPassphrase changed\n");
+
+  memset(pass, 0, strlen(pass));
+  silc_free(pass);
+
+  silc_pkcs_private_key_free(private_key);
+  return TRUE;
+}