From aa2d1ebb0ef31c71a4db4435f3dc056cacf87209 Mon Sep 17 00:00:00 2001
From: Rickard Bellgrim <rickard@opendnssec.org>
Date: Sun, 26 Oct 2014 08:08:43 +0100
Subject: [PATCH 1/2] SOFTHSM-101: softhsm-keyconv creates files with sensitive
 material in insecure way. Also applies to softhsm when using --export or
 --optimize.

---
 NEWS                        |  8 ++++++++
 src/bin/softhsm-keyconv.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++---
 src/bin/softhsm.cpp         | 31 +++++++++++++++++++++++++++-
 3 files changed, 85 insertions(+), 4 deletions(-)

--- softhsm.orig/NEWS
+++ softhsm/NEWS
@@ -1,5 +1,13 @@
 NEWS for SoftHSM -- History of user visible changes
 
+SoftHSM develop
+
+Bugfixes:
+* SOFTHSM-101: softhsm-keyconv creates files with sensitive material
+  in insecure way. Also applies to softhsm when using --export or
+  --optimize.
+
+
 SoftHSM 1.3.7 - 2014-05-28
 
 Bugfixes:
--- softhsm.orig/src/bin/softhsm-keyconv.cpp
+++ softhsm/src/bin/softhsm-keyconv.cpp
@@ -48,6 +48,10 @@
 #include <iostream>
 #include <fstream>
 #include <stdint.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
 
 void usage() {
   printf("Converting between BIND .private-key format and PKCS#8 key file format.\n");
@@ -391,6 +395,15 @@ int to_pkcs8(char *in_path, char *out_pa
     return 1;
   }
 
+  // Create and set file permissions if the file does not exist.
+  int fd = open(out_path, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            out_path, errno);
+    return 1;
+  }
+  close(fd);
+
   // Save the the key to the disk
   switch(algorithm) {
     case DNS_KEYALG_ERROR:
@@ -735,8 +748,16 @@ int save_rsa_bind(char *name, int ttl, B
   snprintf(priv_out, MAX_LINE, "K%s+%03i+%05i.private", name, algorithm, key_tag);
   snprintf(pub_out, MAX_LINE, "K%s+%03i+%05i.key", name, algorithm, key_tag);
 
-  // Create the private key file
+  // Create and set file permissions if the file does not exist.
+  int fd = open(priv_out, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            priv_out, errno);
+    return 1;
+  }
+  close(fd);
 
+  // Create the private key file
   file_pointer = fopen(priv_out, "w");
   if (!file_pointer) {
     fprintf(stderr, "Error: Could not open output file %.100s for writing.\n", priv_out);
@@ -786,8 +807,16 @@ int save_rsa_bind(char *name, int ttl, B
 
   printf("The private key has been written to %s\n", priv_out);
 
-  // Create the public key file
+  // Create and set file permissions if the file does not exist.
+  fd = open(pub_out, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            pub_out, errno);
+    return 1;
+  }
+  close(fd);
 
+  // Create the public key file
   file_pointer = fopen(pub_out, "w");
   if (!file_pointer) {
     fprintf(stderr, "Error: Could not open output file %.100s for writing.\n", pub_out);
@@ -836,6 +865,15 @@ int save_dsa_bind(char *name, int ttl, B
   snprintf(priv_out, MAX_LINE, "K%s+%03i+%05i.private", name, algorithm, key_tag);
   snprintf(pub_out, MAX_LINE, "K%s+%03i+%05i.key", name, algorithm, key_tag);
 
+  // Create and set file permissions if the file does not exist.
+  int fd = open(priv_out, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            priv_out, errno);
+    return 1;
+  }
+  close(fd);
+
   file_pointer = fopen(priv_out, "w");
   if (!file_pointer) {
     fprintf(stderr, "Error: Could not open output file %.100s for writing.\n", priv_out);
@@ -873,8 +911,16 @@ int save_dsa_bind(char *name, int ttl, B
 
   printf("The private key has been written to %s\n", priv_out);
 
-  // Create the public key file
+  // Create and set file permissions if the file does not exist.
+  fd = open(pub_out, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            pub_out, errno);
+    return 1;
+  }
+  close(fd);
 
+  // Create the public key file
   file_pointer = fopen(pub_out, "w");
   if (!file_pointer) {
     fprintf(stderr, "Error: Could not open output file %.100s for writing.\n", pub_out);
--- softhsm.orig/src/bin/softhsm.cpp
+++ softhsm/src/bin/softhsm.cpp
@@ -46,6 +46,10 @@
 #include <iostream>
 #include <fstream>
 #include <sched.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
 
 #ifdef HAVE_DLOPEN
 #include <dlfcn.h>
@@ -1005,6 +1009,15 @@ int removeSessionObjs(char *dbPath) {
   CK_BBOOL ckFalse = CK_FALSE;
   int retVal = 0;
 
+  // Create and set file permissions if the DB does not exist.
+  int fd = open(dbPath, O_CREAT, S_IRUSR | S_IWUSR);
+  if(fd == -1) {
+    fprintf(stderr, "Could not open the token database. errno=%i. "
+                    "Probably wrong privileges: %s", errno, dbPath);
+    return 1;
+  }
+  close(fd);
+
   if(sqlite3_open(dbPath, &db) != 0) {
     fprintf(stderr, "ERROR: Could not connect to database.\n");
     return 1;
@@ -1278,6 +1291,15 @@ CK_RV writeKeyToDisk(char *filePath, cha
     return CKR_GENERAL_ERROR;
   }
 
+  // Create and set file permissions if the file does not exist.
+  int fd = open(filePath, O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1) {
+    fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+            filePath, errno);
+    return CKR_GENERAL_ERROR;
+  }
+  close(fd);
+
   std::ofstream privFile(filePath);
 
   if(!privFile) {
@@ -1468,6 +1490,15 @@ Botan::Private_Key* getPrivKey(char *dbP
   sqlite3_stmt *select_sql = NULL;
   Botan::Private_Key *privKey = NULL;
 
+  // Create and set file permissions if the DB does not exist.
+  int fd = open(dbPath, O_CREAT, S_IRUSR | S_IWUSR);
+  if(fd == -1) {
+    fprintf(stderr, "Could not open the token database. errno=%i. "
+                    "Probably wrong privileges: %s", errno, dbPath);
+    return NULL;
+  }
+  close(fd);
+
   if(sqlite3_open(dbPath, &db) == 0 && sqlite3_prepare_v2(db, select_str, -1, &select_sql, NULL) == 0) {
     if(getObjectClass(select_sql, oHandle) == CKO_PRIVATE_KEY && getKeyType(select_sql, oHandle) == CKK_RSA) {
       Botan::BigInt bigN = getBigIntAttribute(select_sql, oHandle, CKA_MODULUS);
@@ -1477,7 +1508,7 @@ Botan::Private_Key* getPrivKey(char *dbP
       Botan::BigInt bigQ = getBigIntAttribute(select_sql, oHandle, CKA_PRIME_2);
 
       Botan::AutoSeeded_RNG *rng = new Botan::AutoSeeded_RNG();
-      
+
       try {
         privKey = new Botan::RSA_PrivateKey(*rng, bigP, bigQ, bigE, bigD, bigN);
       }
