summaryrefslogtreecommitdiffstats
path: root/base/symkey/src/com/netscape/symkey/EncryptData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'base/symkey/src/com/netscape/symkey/EncryptData.cpp')
-rw-r--r--base/symkey/src/com/netscape/symkey/EncryptData.cpp140
1 files changed, 127 insertions, 13 deletions
diff --git a/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
index ccb817f7c..3963b5026 100644
--- a/base/symkey/src/com/netscape/symkey/EncryptData.cpp
+++ b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
@@ -37,6 +37,10 @@ extern "C"
#include <stdlib.h>
#include "Buffer.h"
#include "SymKey.h"
+
+// AC: KDF SPEC CHANGE: Include headers for NIST SP800-108 KDF functions.
+#include "NistSP800_108KDF.h"
+
#define DES2_WORKAROUND
PRFileDesc *d = NULL;
@@ -66,17 +70,24 @@ void GetKeyName(jbyte *keyVersion, char *keyname)
sprintf(keyname+index+4,"%.2d", keyVersion[1]);
}
-
+// AC: KDF SPEC CHANGE: function signature change - added jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD
extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_EncryptData
-(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyte, jboolean, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+// AC: KDF SPEC CHANGE: function signature change - added jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD
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,jstring keySet)
+Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstring j_tokenName, jstring j_keyName, jbyteArray j_in, jbyteArray keyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, jbyteArray CUID, jbyteArray KDD, jbyteArray kekKeyArray, jstring useSoftToken_s,jstring keySet)
{
jbyte * kek_key = NULL;
PK11SymKey *masterKey = NULL;
- PK11SymKey *kekKey = NULL;
+
+ // AC: KDF SPEC CHANGE: For the NIST SP800-108 KDF, we build all 3 keys despite only using one of them (Kek) in this function.
+ // We do this because our NIST SP800-108 KDF outputs the data for all three keys simultaneously.
+ // KDF output keys
+ PK11SymKey* macKey = NULL;
+ PK11SymKey* encKey = NULL;
+ PK11SymKey* kekKey = NULL;
Buffer out = Buffer(KEYLENGTH, (BYTE)0);
BYTE kekData[KEYLENGTH];
@@ -86,7 +97,13 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
jbyte *cc = NULL;
int cc_len = 0;
- jbyte * cuidValue = NULL;
+
+ // AC: KDF SPEC CHANGE: Need to retrieve KDD as well as CUID from JNI.
+ // Also added "len" variable for CUID (for sanity check).
+ jbyte* cuidValue = NULL;
+ jsize cuidValue_len = -1;
+ jbyte* kddValue = NULL;
+ jsize kddValue_len = -1;
if( kekKeyArray != NULL) {
kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL);
@@ -122,13 +139,30 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
goto done;
}
- if( CUID != NULL) {
- cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
- }
+ // AC: KDF SPEC CHANGE: Need to retrieve KDD as well as CUID from JNI.
+ // Also added "len" variable for CUID (for sanity check).
+ if ( CUID != NULL ) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ cuidValue_len = env->GetArrayLength(CUID);
+ }
if( cuidValue == NULL) {
goto done;
}
+ if ( cuidValue_len <= 0){ // check that CUID is at least 1 byte in length
+ goto done;
+ }
+ if ( KDD != NULL ){
+ kddValue = env->GetByteArrayElements(KDD, NULL);
+ kddValue_len = env->GetArrayLength(KDD);
+ }
+ if ( kddValue == NULL ){
+ goto done;
+ }
+ if ( kddValue_len != static_cast<jsize>(NistSP800_108KDF::KDD_SIZE_BYTES) ){ // check that KDD is expected size
+ goto done;
+ }
+
if( j_in != NULL) {
cc = (jbyte*)(env)->GetByteArrayElements( j_in, NULL);
@@ -139,7 +173,8 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
goto done;
}
- GetDiversificationData(cuidValue,kekData,kek);
+ // AC: KDF SPEC CHANGE: Moved this call down. (We don't necessarily need it anymore depending on the KDF we're going to use.)
+ //GetDiversificationData(cuidValue,kekData,kek);
PR_fprintf(PR_STDOUT,"In SessionKey: EncryptData! \n");
@@ -181,12 +216,75 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
{
masterKey = ReturnSymKey( slot,keyname);
- /* We need to use internal so that the key
- * can be exported by using PK11_GetKeyData()
- */
if (masterKey != NULL)
{
- kekKey = ComputeCardKeyOnToken(masterKey,kekData);
+
+
+ // ---------------------------------
+ // AC KDF SPEC CHANGE: Determine which KDF to use.
+ //
+ // Convert to unsigned types
+ BYTE nistSP800_108KdfOnKeyVersion_byte = static_cast<BYTE>(nistSP800_108KdfOnKeyVersion);
+ BYTE requestedKeyVersion_byte = static_cast<BYTE>(keyVersion[0]);
+ // if requested key version meets setting value, use NIST SP800-108 KDF
+ if (NistSP800_108KDF::useNistSP800_108KDF(nistSP800_108KdfOnKeyVersion_byte, requestedKeyVersion_byte) == true){
+
+ PR_fprintf(PR_STDOUT,"EncryptData NistSP800_108KDF code: Using NIST SP800-108 KDF.\n");
+
+ // react to "UseCUIDAsKDD" setting value
+ jbyte* context_jbyte = NULL;
+ jsize context_len_jsize = 0;
+ if (nistSP800_108KdfUseCuidAsKdd == JNI_TRUE){
+ context_jbyte = cuidValue;
+ context_len_jsize = cuidValue_len;
+ }else{
+ context_jbyte = kddValue;
+ context_len_jsize = kddValue_len;
+ }
+
+ // Converting this way is safe since jbyte is guaranteed to be 8 bits
+ // Of course, this assumes that "char" is 8 bits (not guaranteed, but typical),
+ // but it looks like this assumption is also made in GetDiversificationData
+ const BYTE* const context = reinterpret_cast<const BYTE*>(context_jbyte);
+
+ // Convert jsize to size_t
+ const size_t context_len = static_cast<size_t>(context_len_jsize);
+ if (context_len > 0x000000FF){ // sanity check (CUID should never be larger than 255 bytes)
+ PR_fprintf(PR_STDERR, "EncryptData NistSP800_108KDF code: Error; context_len larger than 255 bytes.\n");
+ goto done;
+ }
+
+ // call NIST SP800-108 KDF routine
+ try{
+ NistSP800_108KDF::ComputeCardKeys(masterKey, context, context_len, &encKey, &macKey, &kekKey);
+ }catch(std::runtime_error& ex){
+ PR_fprintf(PR_STDERR, "EncryptData NistSP800_108KDF code: Exception invoking NistSP800_108KDF::ComputeCardKeys: ");
+ PR_fprintf(PR_STDERR, "%s\n", ex.what() == NULL ? "null" : ex.what());
+ goto done;
+ }catch(...){
+ PR_fprintf(PR_STDERR, "EncryptData NistSP800_108KDF code: Unknown exception invoking NistSP800_108KDF::ComputeCardKeys.\n");
+ goto done;
+ }
+
+ // if not a key version where we use the NIST SP800-108 KDF, use the original KDF
+ }else{
+
+ PR_fprintf(PR_STDOUT,"EncryptData NistSP800_108KDF code: Using original KDF.\n");
+
+ // AC: KDF SPEC CHANGE: Moved this call down from the original location.
+ // (We don't always need to call it anymore; it depends on the KDF we're going to use.)
+ //
+ // Note the change from "cuidValue" to "kddValue".
+ // This change is necessary due to the semantics change in the parameters passed between TPS and TKS.
+ GetDiversificationData(kddValue,kekData,kek);
+
+ // AC: Derives the Kek key for the token.
+ kekKey = ComputeCardKeyOnToken(masterKey,kekData);
+
+ } // endif use original KDF
+ // ---------------------------------
+
+
if (kekKey != NULL)
{
Buffer input = Buffer((BYTE*)cc, cc_len);
@@ -213,6 +311,16 @@ done:
internal = NULL;
}
+ // AC: KDF SPEC CHANGE: For the NIST SP800-108 KDF, we build all 3 keys despite only using one of them (Kek) in this function.
+ // We do this because our NIST SP800-108 KDF outputs the data for all three keys simultaneously.
+ if( macKey ) {
+ PK11_FreeSymKey(macKey);
+ macKey = NULL;
+ }
+ if ( encKey ) {
+ PK11_FreeSymKey(encKey);
+ encKey = NULL;
+ }
if ( kekKey != NULL) {
PK11_FreeSymKey( kekKey);
kekKey = NULL;
@@ -246,5 +354,11 @@ done:
env->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
}
+ // AC: KDF SPEC CHANGE: Need to retrieve KDD as well as CUID from JNI.
+ if ( kddValue != NULL){
+ env->ReleaseByteArrayElements(KDD, kddValue, JNI_ABORT);
+ kddValue = NULL;
+ }
+
return handleBA;
}