summaryrefslogtreecommitdiffstats
path: root/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp')
-rw-r--r--pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp
new file mode 100644
index 000000000..ff9e91df0
--- /dev/null
+++ b/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp
@@ -0,0 +1,246 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// 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.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "pk11func.h"
+#include "nspr.h"
+#ifdef __cplusplus
+#include <jni.h>
+#include <assert.h>
+#include <string.h>
+
+}
+#endif
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <cstdarg>
+#include <string>
+#include <stdlib.h>
+#include "Buffer.h"
+#include "SymKey.h"
+#define DES2_WORKAROUND
+
+PRFileDesc *d = NULL;
+
+/**
+ * Encrypt 'cc_len' bytes of data in 'input' with key kek_key.
+ * Result goes into buffer 'output'
+ * Returns PR_FAILURE if there was an error
+ */
+PRStatus EncryptData(const Buffer &kek_key, jbyte * input,int cc_len, Buffer &output)
+{
+ PRStatus rv = PR_FAILURE;
+
+ PK11SymKey *master = NULL;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11Context *context = NULL;
+ int i;
+ SECStatus s = SECFailure;
+ int len;
+ static SECItem noParams = { siBuffer, 0, 0 };
+#ifdef DES2_WORKAROUND
+ unsigned char masterKeyData[24];
+#else
+ unsigned char masterKeyData[16];
+#endif
+ SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) };
+ unsigned char result[8];
+
+// convert 16-byte to 24-byte triple-DES key
+ memcpy(masterKeyData, kek_key, 16);
+#ifdef DES2_WORKAROUND
+ memcpy(masterKeyData+16, kek_key, 8);
+#endif
+
+ master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
+ PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem,
+ CKF_ENCRYPT, PR_FALSE, 0);
+ if (master == NULL)
+ {
+ goto done;
+ }
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master,
+ &noParams);
+ if (context == NULL)
+ {
+ goto done;
+ }
+
+ for(i = 0;i < (int)cc_len;i += 8)
+ {
+ s = PK11_CipherOp(context, result, &len, 8,
+ (unsigned char *)(input+i), 8);
+
+ if (s != SECSuccess)
+ {
+ goto done;
+ }
+ output.replace(i, result, 8);
+ }
+
+ rv = PR_SUCCESS;
+
+done:
+ /* memset(masterKeyData, 0, sizeof masterKeyData); */
+ if (context != NULL)
+ {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+ if (slot != NULL)
+ {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+ if (master != NULL)
+ {
+ PK11_FreeSymKey(master);
+ master = NULL;
+ }
+
+ return rv;
+}
+
+void GetKeyName(jbyte *keyVersion, char *keyname)
+{
+ int index=0;
+ if(strlen(masterKeyPrefix)!=0)
+ {
+ index= strlen(masterKeyPrefix);
+ strcpy(keyname,masterKeyPrefix);
+ }
+ keyname[index+0]='#';
+ sprintf(keyname+index+1,"%.2d", keyVersion[0]);
+ keyname[index+3]='#';
+ sprintf(keyname+index+4,"%.2d", keyVersion[1]);
+}
+
+
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_EncryptData
+(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring);
+
+extern "C" JNIEXPORT jbyteArray JNICALL
+Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstring j_tokenName, jstring j_keyName, jbyteArray j_in, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s)
+{
+ int status = PR_FAILURE;
+ jbyte * kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL);
+ jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+ jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ jbyte *cc = (jbyte*)(env)->GetByteArrayElements( j_in, NULL);
+ int cc_len = (env)->GetArrayLength(j_in);
+
+ Buffer kek_buffer = Buffer((BYTE*)kek_key, 16);
+ Buffer out = Buffer(16, (BYTE)0);
+
+ /* generate kek key */
+ /* identify the masterKey by KeyInfo in TKS */
+ BYTE kekData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+ GetDiversificationData(cuidValue,kekData,kek);
+
+ PK11SlotInfo *slot = NULL;
+ if(j_tokenName != NULL)
+ {
+ char *tokenNameChars = (char *)(env)->GetStringUTFChars(j_tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(j_tokenName, (const char *)tokenNameChars);
+ tokenNameChars = NULL;
+ }
+
+ if(j_keyName != NULL)
+ {
+ char *keyNameChars= (char *)(env)->GetStringUTFChars(j_keyName, NULL);
+ strcpy(keyname,keyNameChars);
+ env->ReleaseStringUTFChars(j_keyName, (const char *)keyNameChars);
+ keyNameChars = NULL;
+ }
+ else
+ {
+ GetKeyName(keyVersion,keyname);
+ }
+
+ PK11SymKey *masterKey = NULL;
+
+ if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 ||
+ (keyVersion[0] == -1 && strstr(keyname, "#FF") ))
+ {
+ /* default development keyset */
+ status = EncryptData(kek_buffer, cc, cc_len, out);
+ }
+ else
+ {
+ if (slot!=NULL)
+ {
+ masterKey = ReturnSymKey( slot,keyname);
+
+ /* We need to use internal so that the key
+ * can be exported by using PK11_GetKeyData()
+ */
+ if (masterKey != NULL)
+ {
+ PK11SymKey *kekKey = ComputeCardKeyOnToken(masterKey,kekData);
+ if (kekKey != NULL)
+ {
+ Buffer input = Buffer((BYTE*)cc, cc_len);
+ status = EncryptDataWithCardKey(kekKey, input, out);
+
+ if (kekKey != NULL)
+ {
+ PK11_FreeSymKey( kekKey);
+ kekKey = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ if (masterKey != NULL)
+ {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( slot!= NULL )
+ {
+ PK11_FreeSlot( slot );
+ slot = NULL;
+ }
+
+ jbyteArray handleBA=NULL;
+ if (status != PR_FAILURE && (out.size()>0) )
+ {
+ jbyte *handleBytes=NULL;
+ handleBA = (env)->NewByteArray( out.size());
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+ BYTE* outp = (BYTE*)out;
+ memcpy(handleBytes, outp,out.size());
+ env->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ handleBytes=NULL;
+ }
+
+ env->ReleaseByteArrayElements(j_in, cc, JNI_ABORT);
+ env->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ env->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+
+ return handleBA;
+}