If you have worked with cryptography before on your server, you may have cryptographic cross-domain files from Cryptographic Support (5769-CR1). You can migrate existing cross-domain keys to your new Cryptographic Coprocessor.
You can choose one of two methods for migrating the keys.
This method provides some solutions to the considerations listed above and is the recommended method to use.
To migrate the cross-domain keys from Cryptographic Support to CCA, you will need to use a key-encrypting key that is common to both. You can use the Cryptographic Support host master key as the common key between Cryptographic Support and CCA (in CCA, the host master key is known as the master key). Import the Cryptographic Support host master key clear value into CCA as an IMPORTER key-encrypting key. Because you enter the host master key in two separate parts, you should consider importing it into CCA as two parts using the Key_Part_Import (CSNBKPI) CCA API. If you had dual responsibility for the Cryptographic Support host master key, you should maintain this dual responsibility for this key-encrypting key. Alternatively, if you know both parts of the host master key, you could also perform an exclusive OR of the two parts and import the key in just one part. The program example uses this method of importing the host master key. You may want to consider importing the host master key in a completely separate process instead of combining it with the migration of all cross-domain keys like the program example does.
The CCA equivalent of receiving cross-domain keys are IMPORTER key-encrypting keys. Both are used for receiving or importing an encrypted key.
Sending-cross-domain keys are used for both a) encrypting data keys, which can then be sent to another system, and b) translating encrypted personal identification numbers (PIN). CCA has stricter key separation than the Cryptographic Support product, so you cannot generate or import a key that provides both functions. If the key is used as both an EXPORTER key-encrypting key and an OPINENC (outbound PIN encrypting) key, you need to import sending-cross-domain keys twice into two different keys with two different key types.
You may use PIN-cross-domain keys for generating PINs and verifying PINs. CCA separates these two usage's into PINGEN (PIN generation) and PINVER (PIN verification) keys. If the key is used for both generating and verifying PINs, you need to import PIN-cross-domain keys twice, as well.
The 8 byte values for creating master key variants are analogous to control vectors. The process of migrating keys can be thought of as changing control vectors on a key. The IBM® PCI Cryptographic Coprocessor CCA Basic Services Reference and Guide describes a method for this process. The method is the pre-exclusive-OR technique. If the clear key value of a key-encrypting key (the host master key, in this case) is 'exclusive-ORed' with control vector information before importing the key, you can effectively change the control vector for any key that this key-encrypting key imports.
The "pre-exclusive-OR" technique works well if you are working with single-length keys. For double-length keys, the technique must be changed because the control vector for the right half of a CCA key is different than the control vector for the left half. To overcome this difference, import the key twice, as follows:
You now have a CCA double-length key that behaves like the cross-domain key from the Cryptographic Support product. See [Using IMPORTER key-encrypting keys] for a summary of all the importer key-encrypting keys that are needed to import all of the cross-domain keys, as well as the steps required to create the importer key-encrypting keys.
You should not consider this method to be secure. All of the keys will have been in clear form in application storage at some time during this method.
Congratulations! You are now qualified to write a program to migrate cross-domain keys, or you can change the following program example to suit your needs for migrating Cryptographic Support cross-domain key files to your Cryptographic Coprocessor.
/*********************************************************************/ /* This program migrates keys stored in the file QACRKTBL in library */ /* QUSRSYS to key storage for Option 35 - CCA Cryptographic Service */ /* Provider. The QACRKTBL file contains cross domain keys that are */ /* used for the Cryptographic Support licensed program, 5722-CR1. */ /* */ /* COPYRIGHT 5769-SS1 (C) IBM CORP. 1999 */ /* */ /* This material contains programming source code for your */ /* consideration. These examples have not been thoroughly */ /* tested under all conditions. IBM, therefore, cannot */ /* guarantee or imply reliability, serviceability, or function */ /* of these program. All programs contained herein are */ /* provided to you "AS IS". THE IMPLIED WARRANTIES OF */ /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ /* ARE EXPRESSLY DISCLAIMED. IBM provides no program services for */ /* these programs and files. */ /* */ /* */ /* */ /* The keys are migrated by the following steps: */ /* */ /* 1 - The master key used for 5722-CR1 passed as a parameter. */ /* 2 - Build importer keys using the master key, 8 bytes of a mask */ /* to create a variant, and a control vector. */ /* 3 - The file QACRKTBL is opened for input. */ /* 4 - A record is read. */ /* 5 - Import the key using the pre-exclusive OR process. CCA uses */ /* control vectors while non-CCA implementations don't. 5722-CR1*/ /* creates master key variants similar to what 4700 finance */ /* controllers do. Since the control vector and master key */ /* variant material affect how the key is enciphered, the pre- */ /* exclusive OR process "fixes" the importer key so that it can */ /* correctly import a key. */ /* - *SND keys are imported twice as an EXPORTER and OPINENC keys. */ /* - *PIN keys are imported twice as a PINGEN and IPINENC keys. */ /* - *RCV keys are imported as a IMPORTER key. */ /* 6- A key record is created with a similar name as in QACRKTBL. */ /* For key names longer than 8 characters, a '.' will be */ /* inserted between the 8th and 9th characters. Also a 1 byte */ /* extension is appended that describes the key type. */ /* For example, MYKEY *RCV ----> MYKEY.R */ /* MYKEK00001 *RCV ----> MYKEK000.01.R */ /* */ /* For *SND and *PIN keys, a second key record is also created. */ /* For example, MYKEY *SND ----> MYKEY.S */ /* MYKEY.O */ /* MYPINKEY *PIN ----> MYPINKEY.P */ /* MYPINKEY.I */ /* */ /* 7 - The key is written out to key store. */ /* */ /* 8 - Steps 4 through 7 are repeated until all keys have been */ /* migrated. */ /* */ /* */ /* */ /* Note: Input format is more fully described in Chapter 2 of */ /* IBM CCA Basic Services Reference and Guide */ /* (SC31-8609) publication. */ /* */ /* Parameters: */ /* nonCCA master key - 8 bytes */ /* */ /* Example: */ /* CALL PGM(MIGRATECR) PARM(X'1C23456789ABCDEF') */ /* */ /* */ /* Note: This program assumes the device to be used is */ /* already identified either by defaulting to the CRP01 */ /* device or by being explicitly named using the */ /* Cryptographic_Resource_Allocate verb. Also this */ /* device must be varied on and you must be authorized */ /* to use this device description. */ /* */ /* */ /* Use these commands to compile this program on the system: */ /* ADDLIBLE LIB(QCCA) */ /* CRTCMOD MODULE(MIGRATECR) SRCFILE(SAMPLE) */ /* CRTPGM PGM(MIGRATECR) MODULE(MIGRATECR) */ /* BNDSRVPGM(QCCA/CSNBKIM QCCA/CSNBKPI QCCA/CSNBKRC */ /* QCCA/CSNBDEC QCCA/CSNBKRW) */ /* */ /* Note: Authority to the CSNBKIM, CSNBKPI, CSNBKRC, and CSNBKRW */ /* service programs in library QCCA is assumed. */ /* */ /* */ /* The Common Cryptographic Architecture (CCA) verbs used are: */ /* */ /* Key_Import (CSNBKIM) */ /* Key_Part_Import (CSNBKPI) */ /* Key_Record_Create (CSNBKRC) */ /* Key_Record_Write (CSNBKRW) */ /* */ /* */ /*********************************************************************/ /*********************************************************************/ /* Retrieve various structures/utilities that are used in program. */ /*********************************************************************/ #include <stdio.h> /* Standard I/O header. */ #include <stdlib.h> /* General utilities. */ #include <stddef.h> /* Standard definitions. */ #include <string.h> /* String handling utilities. */ #include "miptrnam.h" /* MI templates for pointer */ /* resolution instructions. */ #include "csucincl.h" /* Header file for security API */ /*********************************************************************/ /* Declare function prototype to build tokens to import keys */ /*********************************************************************/ int buildImporter(char * token, char * clearkey, char * preXORcv, char * variant); /*********************************************************************/ /* Declare function prototype to import a non-CCA key and put it */ /* into key store. */ /*********************************************************************/ int importNonCCA(char * label, char * left_importer, char * right_importer, char * cv, char * encrypted_key); /*********************************************************************/ /* Declares for working with files */ /*********************************************************************/ #include <xxfdbk.h> /* Feedback area structures. */ #include <recio.h> /* Record I/O routines */ _RFILE *dbfptr; /* Pointer to database file. */ _RIOFB_T *db_fdbk; /* I/O Feedback - data base file */ _XXOPFB_T *db_opfb; /*********************************************************************/ /* Define the record for cross domain key file QACRKTBL */ /*********************************************************************/ struct { char label[10]; char key_type; char key_value[8]; } key_rec; /*********************************************************************/ /* Define the structure for key tokens */ /*********************************************************************/ typedef struct { char tokenType; char reserved1; char MasterKeyVerifPattern[2]; char version; char reserved2; char flagByte1; char flagByte2; char reserved3[8]; char leftHalfKey[8]; char rightHalfKey[8]; char controlVectorBase[8]; char rightControlVector[8]; char reserved4[12]; char tvv[4]; } key_token_T; /*************************************************************/ /* Declare control vectors used for building keys */ /*************************************************************/ char pingen_cv[16] = { 0x00, 0x22, 0x7E, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x22, 0x7E, 0x00, 0x03, 0x21, 0x00, 0x00}; char ipinenc_cv[16] = { 0x00, 0x21, 0x5F, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x21, 0x5F, 0x00, 0x03, 0x21, 0x00, 0x00}; char opinenc_cv[16] = { 0x00, 0x24, 0x77, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x24, 0x77, 0x00, 0x03, 0x21, 0x00, 0x00}; char importer_cv[16] = { 0x00, 0x42, 0x7D, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x42, 0x7D, 0x00, 0x03, 0x21, 0x00, 0x00}; char exporter_cv[16] = { 0x00, 0x41, 0x7D, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x41, 0x7D, 0x00, 0x03, 0x21, 0x00, 0x00}; char importer_cv_part[16] = { 0x00, 0x42, 0x7D, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x42, 0x7D, 0x00, 0x03, 0x28, 0x00, 0x00}; char exporter_cv_part[16] = { 0x00, 0x41, 0x7D, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x41, 0x7D, 0x00, 0x03, 0x28, 0x00, 0x00}; /*********************************************************************/ /* Start of mainline code. */ /*********************************************************************/ int main(int argc, char *argv[]) { long i,j,k; /* Indexes for loops */ char key_label[64]; /* label of new key */ char key_label1[64]; /* label of new key */ /*************************************************************/ /* Declare importer keys - two keys are needed for each type */ /*************************************************************/ char EXPORTER_importerL[64]; char EXPORTER_importerR[64]; char OPINENC_importerL[64]; char OPINENC_importerR[64]; char IMPORTER_importerL[64]; char IMPORTER_importerR[64]; char PINGEN_importerL[64]; char PINGEN_importerR[64]; char IPINENC_importerL[64]; char IPINENC_importerR[64]; /****************************************************************/ /* Declare variables to hold bit strings to generate master key */ /* variants. */ /****************************************************************/ char variant1[16]; char variant2[16]; char variant3[16]; /*********************************************************************/ /* Build the key tokens for each of the importer keys using */ /* Key_Token_Build. Each key is built by using a variant, a control */ /* vector, and the clear key. Master key variant 1 is the result of */ /* an exlusive OR of the master key with hex '8888888888888888', */ /* Master key variant 2 is the result of an exclusive OR of the */ /* master key with hex '2222222222222222', and Master key varient 3 */ /* is the result of an exclusive OR of the master key with hex */ /* '4444444444444444'. During the import operation, the control */ /* vector is exclusive OR'ed with the importer key. The effect of */ /* the control vector is overcome by including the control vector as */ /* key part. Then when the import operation is done, the exclusive */ /* OR operation will result in the original key. For double keys, */ /* the left and right half of the control vector is not the same and */ /* therefore, XORing with the control vector will not result in the */ /* original key - only one half of it will be valid. So two keys are*/ /* needed - one for each half. */ /*********************************************************************/ memset(variant1, 0x88, 16); memset(variant2, 0x22, 16); memset(variant3, 0x44, 16); if (buildImporter(EXPORTER_importerL, argv[1], exporter_cv, variant1) || buildImporter(EXPORTER_importerR, argv[1], &exporter_cv[8], variant1) || buildImporter(IMPORTER_importerL, argv[1], importer_cv, variant2) || buildImporter(IMPORTER_importerR, argv[1], &importer_cv[8], variant2) || buildImporter(PINGEN_importerL, argv[1], pingen_cv, variant3) || buildImporter(PINGEN_importerR, argv[1], &pingen_cv[8], variant3) || buildImporter(IPINENC_importerL, argv[1], ipinenc_cv, variant3) || buildImporter(IPINENC_importerR, argv[1], &ipinenc_cv[8], variant3) || buildImporter(OPINENC_importerL, argv[1], opinenc_cv, variant1) || buildImporter(OPINENC_importerR, argv[1], &opinenc_cv[8], variant1)) { printf("An error occured creating the importer keys\n"); return; } /*********************************************************************/ /* Open database file. */ /*********************************************************************/ /* Open the input file. */ /* If the file pointer, */ /* dbfptr is not NULL, */ /* then the file was */ /* successfully opened. */ if (( dbfptr = _Ropen("QUSRSYS/QACRKTBL", "rr riofb=n")) != NULL) { db_opfb = _Ropnfbk( dbfptr ); /* Get pointer to the */ /* File open feedback */ /* area. */ j = db_opfb->num_records; /* Save number of records*/ /******************************************************************/ /* Read keys and migrate to key storage. */ /******************************************************************/ for (i=1; i<=j; i++) /* Repeat for each record */ { /* Read a record */ db_fdbk = _Rreadn(dbfptr, &key_rec, sizeof(key_rec), __DFT); /******************************************************************/ /* Generate a key label for the imported keys. */ /* The key label will be similar to the label that was used for */ /* the QACRKTBL file. If the label is longer than 8 characters, */ /* then a period '.' will be inserted at position 8 to make it */ /* conform to label naming conventions for CCA. Also one */ /* one character will be added to the end to indicate what type */ /* of key. 5722-CR1 does not require unique key names across all*/ /* key types. CCA requires unique labels for all keys. */ /******************************************************************/ memset((char *)key_label,' ',64); /* Initialize key label */ /* to all blanks. */ /* Copy first bytes of label */ memcpy((char *)key_label,(char *)key_rec.label,8); /* If label is longer than 8 characters, add a second element*/ if (key_rec.label[8] != ' ') { key_label[8] = '.'; key_label[9] = key_rec.label[8]; key_label[10] = key_rec.label[9]; } /* *SND keys and *PIN keys need to be imported twice so */ /* make a second label */ if (key_rec.key_type != 'R') memcpy((char *)key_label1,(char *)key_label,64); /* Add keytype to label name. Search until a space is found */ /* and if less than 8, add the 1 character keytype. If it */ /* is greater than 8, add a second element with the keytype */ /* 'R' is *RCV key, 'S' is *SND key, 'P' is *PIN key, */ /* 'I' is an IPINENC key and 'O' is OPINENC key */ for (k=1; k<=11; k++) { if (key_label[k] == ' ') { if (k != 8) { key_label[k] = key_rec.key_type; /* If this is a *SND or *PIN key, update the keytype */ /* in the second label as well */ if (key_rec.key_type != 'R') { memcpy((char *)key_label1,(char *)key_label,64); if (key_rec.key_type == 'S') key_label1[k] = 'O'; else key_label1[k] = 'I'; } } else { key_label[8] = '.'; key_label[9] = key_rec.key_type; /* If this is a *SND or *PIN key, update the keytype */ /* in the second label as well */ if (key_rec.key_type != 'R') { memcpy((char *)key_label1,(char *)key_label,64); if (key_rec.key_type == 'S') key_label1[9] = 'O'; else key_label1[9] = 'I'; } } k = 11; } } /******************************************************************/ /* Check for the type of key that was in the QACRKTBL file */ /* - S for SENDER key will become two keys - EXPORTER and OPINENC*/ /* - R for RECEIVER key will become IMPORTER key */ /* - P for PIN will become two keys - PINGEN and IPINENC */ /* Set the key id to the key token that contains the key under */ /* which the key in QACRKTBL is enciphered. */ /* Set the key_type SAPI parameter for the Secure_Key_Import verb*/ /******************************************************************/ if (key_rec.key_type == 'S') { /* Import the exporter key */ if(importNonCCA(key_label, EXPORTER_importerL, EXPORTER_importerR, exporter_cv, key_rec.key_value)) { printf("An error occured importing an exporter key\n"); break; } /* Import the OPINENC key */ if (importNonCCA(key_label1, OPINENC_importerL, OPINENC_importerR, opinenc_cv, key_rec.key_value)) { printf("An error occured importing an opinenc key\n"); break; } } else if (key_rec.key_type == 'R') { /* Import the importer key */ if (importNonCCA(key_label, IMPORTER_importerL, IMPORTER_importerR, importer_cv, key_rec.key_value)) { printf("An error occured importing an importer key\n"); break; } } else { /* Import the PINGEN key */ if(importNonCCA(key_label, PINGEN_importerL, PINGEN_importerR, pingen_cv, key_rec.key_value)) { printf("An error occured importing a PINGEN key\n"); break; } /* Import the IPINENC key */ if(importNonCCA(key_label1, IPINENC_importerL, IPINENC_importerR, ipinenc_cv, key_rec.key_value)) { printf("An error occured importing an ipinenc key\n"); break; } } } /* End loop repeating for each record */ /*********************************************************************/ /* Close database file. */ /*********************************************************************/ if (dbfptr != NULL) /* Close the file. */ _Rclose(dbfptr); } /* End if file open leg */ else { printf("An error occured openning the QACRKTBL file.\n"); } } /* End of main() */ /*********************************************************************/ /* buildImporter creates an importer token from a clearkey exclusive*/ /* OR'ed with a variant and a control vector. The control vector */ /* is XOR'ed in order to import non-CCA keys. The variant is XOR'ed*/ /* in order to import from implementations that use different */ /* master key variants to protect keys as does 5722-CR1. */ /*********************************************************************/ int buildImporter(char * token, char * clearkey, char * preXORcv, char * variant) { /****************************************/ /* Declare variables used by the SAPI's */ /****************************************/ char rule_array[16]; long rule_array_count; long return_code; long reason_code; long exit_data_length; char exit_data[4]; char keyvalue[16]; char keytype[8]; char ctl_vector[16]; key_token_T *token_ptr; /*************************************************/ /* Build an IMPORTER token */ /*************************************************/ memset(token, 0, 64); /* Initialize token to all 0's */ token_ptr = (key_token_T *)token; token_ptr->tokenType = 0x01; /* 01 is internal token */ token_ptr->version = 0x03; /* Version 3 token */ token_ptr->flagByte1 = 0x40; /* High order bit is 0 so key */ /* is not present. The 40 */ /* bit means that CV is present*/ /* Copy control vector into */ /* the token. */ memcpy(token_ptr->controlVectorBase, importer_cv_part, 16); /* Copy TVV into token. This */ /* was calculated manually by */ /* setting all the fields and */ /* then adding each 4 bytes of */ /* the token (excluding the */ /* TVV) together. */ memcpy(token_ptr->tvv,"\x0A\xF5\x3A\x00", 4); /*****************************************************************/ /* Import the control vector as a key part using Key_Part_Import */ /*****************************************************************/ exit_data_length = 0; rule_array_count = 1; memcpy(ctl_vector, preXORcv, 8); memcpy(&ctl_vector[8], preXORcv, 8); /* Need to copy the control vector into the second 8 bytes as well*/ memcpy(rule_array, "FIRST ", 8); CSNBKPI( &return_code, &reason_code, &exit_data_length, (char *) exit_data, (long *) &rule_array_count, (char *) rule_array, (char *) ctl_vector, (char *) token); if (return_code > 4) { printf("Key_Part_Import failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } /*****************************************************************/ /* Import the variant as a key part using Key_Part_Import */ /*****************************************************************/ memcpy(rule_array, "MIDDLE ", 8); CSNBKPI( &return_code, &reason_code, &exit_data_length, (char *) exit_data, (long *) &rule_array_count, (char *) rule_array, (char *) variant, (char *) token); if (return_code > 4) { printf("Key_Part_Import failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } /*****************************************************************/ /* Import the clear key as a key part using Key_Part_Import */ /*****************************************************************/ memcpy(keyvalue, clearkey, 8); memcpy(&keyvalue[8], clearkey, 8); /* Make key double length*/ memcpy(rule_array, "LAST ", 8); CSNBKPI( &return_code, &reason_code, &exit_data_length, (char *) exit_data, (long *) &rule_array_count, (char *) rule_array, (char *) keyvalue, (char *) token); if (return_code > 4) { printf("Key_Part_Import failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } return 0; } /********************************************************************/ /* importNonCCA imports a double length key into CCA from the */ /* non-CCA implementation */ /********************************************************************/ int importNonCCA(char * label, char * left_importer, char * right_importer, char * cv, char * encrypted_key) { /******************************************/ /* Declare vaiables used by the SAPIs */ /******************************************/ long return_code, reason_code; char exit_data[4]; long exit_data_length; long rule_array_count; char rule_array[24]; char keytoken[64]; char externalkey[64]; char keyvalue[16]; char keytype[8]; char *importer; char mkvp[2]; key_token_T *token_ptr; int tvv, tvv_part; char *tvv_pos; /**********************************************/ /* Build an external key token to IMPORT from */ /**********************************************/ memset((void *)externalkey,'\00',64); token_ptr = (key_token_T *)externalkey; token_ptr->tokenType = 0x02; /* 02 is external token */ token_ptr->version = 0x00; /* Version 0 token */ token_ptr->flagByte1 = 0xC0; /* High order bit is 1 so */ /* key is present. The */ /* 40 bit means that CV */ /* is present */ memcpy(token_ptr->controlVectorBase, cv, 16); /* Copy control vector into token */ memcpy(token_ptr->leftHalfKey,encrypted_key, 8); /* Copy key into left half */ memcpy(token_ptr->rightHalfKey,encrypted_key, 8); /* Copy key into right half */ /**********************************************/ /* Calculate the TVV by adding every 4 bytes */ /**********************************************/ tvv_pos = externalkey; tvv = 0; while (tvv_pos < (externalkey + 60)) { memcpy((void*)&tvv_part,tvv_pos,4); tvv += tvv_part; tvv_pos += 4; } memcpy(token_ptr->tvv, (void*)&tvv, 4); /***********************************************************/ /* Import the left half of the key using Key_Import and */ /* the importer built with left half of the control vector */ /***********************************************************/ exit_data_length = 0; memcpy(keytype, "TOKEN ", 8); memset((void *)keytoken,'\00',64); CSNBKIM( &return_code, &reason_code, &exit_data_length, (char *) exit_data, (char *) keytype, (char *) externalkey, (char *) left_importer, (char *) keytoken); if (return_code > 4) { printf("Key_Import failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } /******************************************/ /* Save left half of key out of key token */ /******************************************/ memcpy(keyvalue, &keytoken[16], 8); /***********************************************************/ /* Import the right half of the key using Key_Import and */ /* the importer built with right half of the control vector*/ /***********************************************************/ memcpy(keytype, "TOKEN ", 8); memset((void *)keytoken,'\00',64); CSNBKIM( &return_code, &reason_code, &exit_data_length, (char *) exit_data, (char *) keytype, (char *) externalkey, (char *) right_importer, (char *) keytoken); if (return_code > 4) { printf("Key_Import failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } /*******************************************/ /* Save right half of key out of key token */ /*******************************************/ memcpy(&keyvalue[8], &keytoken[24], 8); /**********************************************************************/ /* Get master key verification pattern from the last key token built */ /**********************************************************************/ mkvp[0] = keytoken[2]; mkvp[1] = keytoken[3]; /**********************************************************/ /* Build an internal key token using both key halves just */ /* imported and using the master key verification pattern */ /**********************************************************/ memset((void *)keytoken,'\00',64); exit_data_length = 0; token_ptr = (key_token_T *)keytoken; token_ptr->tokenType = 0x01; /* 01 is internal token */ token_ptr->version = 0x03; /* Version 3 token */ token_ptr->flagByte1 = 0xC0; /* High order bit is 1 so */ /* key is present. The */ /* 40 bit means that CV is */ /* present */ /* Set the first byte of */ /* Master key verification */ /* pattern. */ token_ptr->MasterKeyVerifPattern[0] = mkvp[0]; /* Set the second byte of */ /* Master key verification */ /* pattern. */ token_ptr->MasterKeyVerifPattern[1] = mkvp[1]; /* Copy control vector into*/ /* token */ memcpy(token_ptr->controlVectorBase, cv, 16); memcpy(token_ptr->leftHalfKey, keyvalue, 16); /*Copy key to token */ /**********************************************/ /* Calculate the TVV by adding every 4 bytes */ /**********************************************/ tvv_pos = externalkey; tvv = 0; while (tvv_pos < (externalkey + 60)) { memcpy((void*)&tvv_part,tvv_pos,4); tvv += tvv_part; tvv_pos += 4; } memcpy(token_ptr->tvv, (void*)&tvv, 4); /********************************************/ /* Create a Key Record in Key Store */ /********************************************/ exit_data_length = 0; CSNBKRC((long *) &return_code, (long *) &reason_code, (long *) &exit_data_length, (char *) exit_data, (char *) label); if (return_code > 4) { printf("Key_Record_Create failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } /********************************************/ /* Write the record out to Key Store */ /********************************************/ CSNBKRW((long *) &return_code, (long *) &reason_code, (long *) &exit_data_length, (char *) exit_data, (char *) keytoken, (char *) label); if (return_code > 4) { printf("Key_Record_Write failed with return/reason codes \ %d/%d \n",return_code, reason_code); return 1; } return 0; }