From 820b3f16d1cb3f0532a464aee399512725c2a858 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Mon, 10 Apr 2017 11:27:12 -0700
Subject: [PATCH] Tkstool, FIPS Mode fix.

Now the program can create and import shared secret keys while under FIPS mode.
---
 base/native-tools/src/tkstool/key.c     | 96 ++++++++++++++++++++++++++-------
 base/native-tools/src/tkstool/tkstool.c |  4 +-
 base/native-tools/src/tkstool/tkstool.h |  3 +-
 3 files changed, 81 insertions(+), 22 deletions(-)

diff --git a/base/native-tools/src/tkstool/key.c b/base/native-tools/src/tkstool/key.c
index 4fd3796..a027d27 100644
--- a/base/native-tools/src/tkstool/key.c
+++ b/base/native-tools/src/tkstool/key.c
@@ -19,6 +19,11 @@
 
 #include "tkstool.h"
 
+secuPWData    pwdata = { PW_NONE,
+                              0 };
+
+
+
 /*******************************/
 /**  local private functions  **/
 /*******************************/
@@ -534,16 +539,26 @@ TKS_ComputeAndDisplayKCV( PRUint8    *newKey,
             goto done;
         }
 
-        key = PK11_ImportSymKeyWithFlags(
-              /* slot           */        slot,
-              /* mechanism type */        CKM_DES3_ECB,
-              /* origin         */        PK11_OriginGenerated,
-              /* operation      */        CKA_ENCRYPT,
-              /* key            */        &keyItem,
-              /* flags          */        CKF_ENCRYPT,
-              /* isPerm         */        PR_FALSE,
-              /* wincx          */        0 );
+        key =  TKS_ImportSymmetricKey( NULL,
+                        slot,
+                        CKM_DES3_ECB,
+                        CKA_ENCRYPT,
+                        &keyItem,
+                        &pwdata, PR_FALSE );
 
+
+
+
+     /*   key = PK11_ImportSymKeyWithFlags(
+                      slot,
+                      CKM_DES3_ECB,
+                      PK11_OriginGenerated,
+                      CKA_ENCRYPT,
+                      &keyItem,
+                      CKF_ENCRYPT,
+                      PR_FALSE,
+                      0 );
+     */
         if( ! key ) {
             PR_fprintf( PR_STDERR,
                         "ERROR:  Failed to import %s key!\n\n\n",
@@ -1062,10 +1077,18 @@ TKS_ImportSymmetricKey( char              *symmetricKeyName,
                         CK_MECHANISM_TYPE  mechanism,
                         CK_ATTRIBUTE_TYPE  operation,
                         SECItem           *sessionKeyShare,
-                        secuPWData        *pwdata )
+                        secuPWData        *pwdata, PRBool isPerm )
 {
     PK11Origin  origin = PK11_OriginGenerated;
     PK11SymKey *symKey = NULL;
+    PK11SymKey *sessKey = NULL;
+    PK11Context *context = NULL;
+    static SECItem noParams = { siBuffer, NULL, 0 };
+    SECItem wrappeditem = { siBuffer, NULL, 0 };
+
+    int len = 0;
+    unsigned char wrappedkey[DES_LENGTH * 3];
+    SECStatus s = SECSuccess;
 
     if( slot == NULL ) {
         return NULL;
@@ -1077,15 +1100,50 @@ TKS_ImportSymmetricKey( char              *symmetricKeyName,
                 "Generating %s symmetric key . . .\n\n",
                 symmetricKeyName );
 
-    symKey = PK11_ImportSymKeyWithFlags( 
-             /* slot           */        slot,
-             /* mechanism type */        mechanism,
-             /* origin         */        origin,
-             /* operation      */        operation,
-             /* key            */        sessionKeyShare,
-             /* flags          */        0,
-             /* isPerm         */        PR_FALSE,
-             /* wincx          */        pwdata );
+    sessKey =  PK11_TokenKeyGenWithFlags(slot,               // slot handle
+                   CKM_DES3_KEY_GEN,   // mechanism type
+                   NULL,               // pointer to params (SECItem structure)
+                   0,                  // keySize (per documentation in pk11skey.c, must be 0 for fixed key length algorithms)
+                   0,                  // pointer to keyid (SECItem structure)
+                   CKF_WRAP | CKF_UNWRAP | CKF_ENCRYPT | CKF_DECRYPT, // opFlags
+                   PK11_ATTR_PRIVATE | PK11_ATTR_UNEXTRACTABLE | PK11_ATTR_SENSITIVE, // attrFlags (AC: this is my "best guess" as to what flags should be set)
+                   NULL);
+
+    if( sessKey == NULL ) {
+        goto cleanup;
+    }
+
+    // Import the key onto the token using the temp session key and the key data.
+    //
+    
+    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT,
+        sessKey,
+        &noParams);
+
+    if (context == NULL) {
+        goto cleanup;
+    }
+
+    len = sessionKeyShare->len;
+    /* encrypt the key with the master key */
+    s = PK11_CipherOp(context, wrappedkey, &len, DES_LENGTH * 3 , sessionKeyShare->data ,DES_LENGTH * 3 );
+    if (s != SECSuccess)
+    {
+        goto cleanup;
+    }
+
+    wrappeditem.data = wrappedkey;
+    wrappeditem.len = len;
+
+    symKey = PK11_UnwrapSymKeyWithFlagsPerm(sessKey, CKM_DES3_ECB, &noParams,
+        &wrappeditem, CKM_DES3_KEY_GEN, CKA_DECRYPT, DES_LENGTH * 3,
+        (CKA_ENCRYPT | CKA_DECRYPT) & CKF_KEY_OPERATION_FLAGS, isPerm );
+
+cleanup:
+    if( sessKey != NULL) {
+        PK11_FreeSymKey( sessKey );
+        sessKey = NULL;
+    }
     return symKey;
 }
 
diff --git a/base/native-tools/src/tkstool/tkstool.c b/base/native-tools/src/tkstool/tkstool.c
index 6fd2a97..53781e4 100644
--- a/base/native-tools/src/tkstool/tkstool.c
+++ b/base/native-tools/src/tkstool/tkstool.c
@@ -1417,14 +1417,14 @@ main( int argc, char **argv )
                                                     CKM_DES3_KEY_GEN,
                                                     CKA_ENCRYPT,
                                                     &paddedFirstSessionKeyShare,
-                                                    &pwdata );
+                                                    &pwdata, PR_FALSE );
 #else
         firstSymmetricKey = TKS_ImportSymmetricKey( FIRST_SYMMETRIC_KEY,
                                                     internalSlot,
                                                     CKM_DES2_KEY_GEN,
                                                     CKA_ENCRYPT,
                                                     &firstSessionKeyShare,
-                                                    &pwdata );
+                                                    &pwdata , PR_FALSE );
 #endif
         if( firstSymmetricKey == NULL ) {
             PR_fprintf( PR_STDERR,
diff --git a/base/native-tools/src/tkstool/tkstool.h b/base/native-tools/src/tkstool/tkstool.h
index 4c276b0..80fdafd 100644
--- a/base/native-tools/src/tkstool/tkstool.h
+++ b/base/native-tools/src/tkstool/tkstool.h
@@ -124,6 +124,7 @@
                                                "and press enter to continue " \
                                                "(or ^C to break):  "
 
+#define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL
 
 /**************************************/
 /**  external function declarations  **/
@@ -222,7 +223,7 @@ TKS_ImportSymmetricKey( char              *symmetricKeyName,
                         CK_MECHANISM_TYPE  mechanism,
                         CK_ATTRIBUTE_TYPE  operation,
                         SECItem           *sessionKeyShare,
-                        secuPWData        *pwdata );
+                        secuPWData        *pwdata, PRBool isPerm );
 
 PK11SymKey *
 TKS_DeriveSymmetricKey( char              *symmetricKeyName,
-- 
2.5.0

