ibm-information-center/dist/eclipse/plugins/i5OS.ic.rzajc_5.4.0.1/rzajcmigratedomain.htm

1030 lines
50 KiB
HTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="concept" />
<meta name="DC.Title" content="Migrate Cryptographic Support for system cross-domain key files" />
<meta name="abstract" content="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." />
<meta name="description" content="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." />
<meta name="DC.Relation" scheme="URI" content="rzajcmigrate4758.htm" />
<meta name="DC.Relation" scheme="URI" content="rzajcimporter.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="migratedomain" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Migrate Cryptographic Support for system cross-domain key files</title>
</head>
<body>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<div class="nested0" id="migratedomain"><a name="migratedomain"><!-- --></a><h1 class="topictitle1">Migrate Cryptographic Support for system cross-domain key files</h1>
<div><p>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.</p>
<div class="p">The Cryptographic Support for OS/400<sup>®</sup> product (5769-CR1 or 5722-CR1)
encrypts its cross-domain keys under the host master key and stores them in
a file. Common Cryptographic Architecture (CCA) cannot use them in this form,
but you can migrate them from the Cryptographic Support product for the CCA
to use with your Coprocessor. You must consider a number of things before
completing this task:<ul><li><strong>Encryption of cross-domain keys by cross-domain keys:</strong> Cryptographic
Support supports importing clear key values for cross-domain keys and encrypting
data keys under cross-domain keys. However, it does not support encrypting
cross-domain keys under cross-domain keys, nor does it support returning the
clear key value of any cross-domain key. Because of this, migrating cross-domain
keys is considerably more involved than just performing an export and import
operation.</li>
<li><strong>Single-length keys versus double-length keys:</strong> All keys in Cryptographic
Support are single-length keys. In CCA, all key-encrypting keys and PIN keys
are double-length keys. Although the key lengths are different, you can build
a double-length key from a single-length key and have that double-length key
behave like the single-length key. If both halves of a double-length key are
the same, the result of any encryption operation will be the same as if a
single-length key was used. Therefore, when you migrate keys from Cryptographic
Support to CCA, you will need to copy the key value of the cross-domain key
into both halves of the key value for a CCA key.</li>
<li><strong>CCA control vectors versus master key variants:</strong> In CCA, when a
key is said to be encrypted under a key-encrypting key, it is really encrypted
under a key that is formed by an exclusive OR operation of the key-encrypting
key and a control vector. For Cryptographic Support, cross-domain keys are
encrypted under one of three different master key variants. A master key variant
is the result of the exclusive OR operation of the host master key with either
8 bytes of hexadecimal 22, 44, or 88. Both control vectors and master key
variants provide key separation and thereby restrict keys to their intended
use. In CCA, the value of the control vector determines its use. In Cryptographic
Support how a key is used determines which master key variant will be used
to decrypt it. In both cases, any attempt to use the key for other than its
intended use will result in an error. Although control vectors and master
key variants may work similarly, the values used to form master key variants
are not the same as control vectors.</li>
<li><strong>Asymmetry of CCA control vectors for double-length keys:</strong> Double-length
keys behave like single-length keys only when both halves of the double-length
key are identical. Control vectors for double-length keys are asymmetric.
Any double-length key that is exclusive ORed with a control vector will not
result in a key with identical halves. This double-length key will not behave
like a single length key.</li>
</ul>
You can choose one of two methods for migrating the keys.</div>
<p>You can choose one of two methods for migrating the keys.</p>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="rzajcmigrate4758.htm" title="If you have worked with cryptography before, you may have a requirement to migrate from a previous cryptography product to the 4764 or 4758 Cryptographic Coprocessor.">Migrate to the Cryptographic Coprocessor</a></div>
</div>
</div></div>
<div class="nested0" xml:lang="en-us" id="method1"><a name="method1"><!-- --></a><h1 class="topictitle1">Method 1 (recommended)</h1>
<div><div class="section"><p>This method provides some solutions to the considerations listed
above and is the recommended method to use.</p>
<p>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.</p>
<div class="p">There are three types of cross-domain keys: <ul><li>Receiving cross-domain keys</li>
<li>Sending cross-domain keys</li>
<li>PIN cross-domain keys</li>
</ul>
</div>
<p>The CCA equivalent of receiving cross-domain keys are IMPORTER
key-encrypting keys. Both are used for receiving or importing an encrypted
key.</p>
<p>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.</p>
<p>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. </p>
<div class="p">While the host master
key encrypts data keys, different master key variants encrypt cross-domain
keys. <ul><li>Master key variant 1 encrypts sending cross-domain keys. Variant 1 is
the result of an exclusive-OR operation of the host master key with 8 bytes
of hexadecimal 88.</li>
<li>Master key variant 2 encrypts receiving cross-domain keys. Variant 2 is
the result of an exclusive-OR operation of the host master key and 8 bytes
of hexadecimal 22.</li>
<li>Master key variant 3 encrypts PIN cross-domain keys. Variant 3 is the
result of an exclusive-OR operation of the host master key and 8 bytes of
hexadecimal 44.</li>
</ul>
</div>
<div class="note"><span class="notetitle">Note:</span> If you only import the clear key value of the host master
key into CCA, you will not be able to migrate any keys. You need to factor
in which master key variant encrypts the key in order to migrate it. </div>
<p>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 <a href="http://www.ibm.com/security/cryptocards/library.shtml" target="_blank">IBM<sup>®</sup> PCI Cryptographic Coprocessor CCA Basic Services
Reference and Guide</a><img src="www.gif" alt="Link&#xA;outside Information Center" /> describes a method for this process.
The method is the <span class="uicontrol">pre-exclusive-OR</span> 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.</p>
<p>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: </p>
</div>
<ol><li><span>Create a 16 byte value such that each 8 byte half is identical
to the left half of the control vector of the key you want to import. Use
this 16 byte value in the pre-exclusive-OR technique to create an importer
key-encrypting key that you can refer to as the "left-importer." Only the
left half of keys that are imported using this key-encrypting key will be
valid.</span></li>
<li><span>Create another 16 byte value such that each 8 byte half is identical
to the right half of the control vector of the key you want to import. Use
this 16 byte value in the pre-exclusive-OR technique to create an importer
key-encrypting key. Using this importer key-encrypting key, only the right
half of the keys that are imported will be valid</span></li>
<li><span>Import the cross-domain key, twice:</span><ol type="a"><li><span>First use the key-encrypting key created in step 1 and save
the left half of the result.</span></li>
<li><span>Then use the key-encrypting key created in step 2 and save the
right half of the result.</span></li>
</ol>
</li>
<li><span>In the final step, concatenate the left half of the result from
step A with the right half of the result from step B. Place the combined results
in a new key token.</span></li>
</ol>
<div class="section"> <p>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.</p>
</div>
</div>
<div><div class="reltasks"><strong>Related tasks</strong><br />
<div><a href="rzajcimporter.htm" title="Read this information for a summary all of the importer key-encrypting keys that are needed to import all of the cross-domain keys. This information also describes how to create the importer key-encrypting keys.">Using IMPORTER key-encrypting keys</a></div>
</div>
</div></div>
<div class="nested0" xml:lang="en-us" id="method2"><a name="method2"><!-- --></a><h1 class="topictitle1">Method 2</h1>
<div><div class="section">You should only use this method if you feel comfortable with the
security of your system and environment. This method is easier than the
recommended method, but it presents a greater security risk for your cross-domain
key files, since the cross-domain keys will be in clear form in application
storage.</div>
<ol><li class="stepexpand"><span>Import the host master key into CCA as a data key by using the
Clear_Key_Import (CSNBCKI) CCA API. Remember to perform an exclusive OR operation
on the key with the values needed to produce data keys equivalent to the master
key variants as follows: </span><ol type="a"><li><span>Master key variant 1 encrypts sending cross-domain keys. Variant
1 is the result of an exclusive-OR operation of the host master key with 8
bytes of hexadecimal 88.</span></li>
<li><span>Master key variant 2 encrypts receiving cross-domain keys. Variant
2 is the result of an exclusive-OR operation of the host master key and 8
bytes of hexadecimal 22. </span></li>
<li><span>Master key variant 3 encrypts PIN cross-domain keys. Variant
3 is the result of an exclusive-OR operation of the host master key and 8
bytes of hexadecimal 44.</span></li>
</ol>
You will have 3 different data keys after this step.</li>
<li class="stepexpand"><span>Use the Decrypt (CSNBDEC) CCA API to decrypt the cross-domain keys
to return the clear key values. Use the correct data key to decrypt it.</span></li>
<li class="stepexpand"><span>Use the Key_Part_Import (CSNBKPI) CCA API to import the clear key
into CCA.</span></li>
</ol>
<div class="section"><p>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.</p>
<p>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.</p>
<div class="note"><span class="notetitle">Note:</span> Read the <a href="codedisclaimer.htm#codedisclaimer">Code license and disclaimer information</a> for
important legal information.</div>
</div>
<div class="example"><pre>/*********************************************************************/
/* 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 ----&gt; MYKEY.R */
/* MYKEK00001 *RCV ----&gt; MYKEK000.01.R */
/* */
/* For *SND and *PIN keys, a second key record is also created. */
/* For example, MYKEY *SND ----&gt; MYKEY.S */
/* MYKEY.O */
/* MYPINKEY *PIN ----&gt; 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 &lt;stdio.h&gt; /* Standard I/O header. */
#include &lt;stdlib.h&gt; /* General utilities. */
#include &lt;stddef.h&gt; /* Standard definitions. */
#include &lt;string.h&gt; /* 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 &lt;xxfdbk.h&gt; /* Feedback area structures. */
#include &lt;recio.h&gt; /* 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],
&amp;exporter_cv[8], variant1) ||
buildImporter(IMPORTER_importerL, argv[1],
importer_cv, variant2) ||
buildImporter(IMPORTER_importerR, argv[1],
&amp;importer_cv[8], variant2) ||
buildImporter(PINGEN_importerL, argv[1],
pingen_cv, variant3) ||
buildImporter(PINGEN_importerR, argv[1],
&amp;pingen_cv[8], variant3) ||
buildImporter(IPINENC_importerL, argv[1],
ipinenc_cv, variant3) ||
buildImporter(IPINENC_importerR, argv[1],
&amp;ipinenc_cv[8], variant3) ||
buildImporter(OPINENC_importerL, argv[1],
opinenc_cv, variant1) ||
buildImporter(OPINENC_importerR, argv[1],
&amp;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-&gt;num_records; /* Save number of records*/
/******************************************************************/
/* Read keys and migrate to key storage. */
/******************************************************************/
for (i=1; i&lt;=j; i++) /* Repeat for each record */
{ /* Read a record */
db_fdbk = _Rreadn(dbfptr, &amp;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&lt;=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-&gt;tokenType = 0x01; /* 01 is internal token */
token_ptr-&gt;version = 0x03; /* Version 3 token */
token_ptr-&gt;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-&gt;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-&gt;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(&amp;ctl_vector[8], preXORcv, 8); /* Need to copy the
control vector into the
second 8 bytes as well*/
memcpy(rule_array, "FIRST ", 8);
CSNBKPI( &amp;return_code, &amp;reason_code, &amp;exit_data_length,
(char *) exit_data,
(long *) &amp;rule_array_count,
(char *) rule_array,
(char *) ctl_vector,
(char *) token);
if (return_code &gt; 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( &amp;return_code, &amp;reason_code, &amp;exit_data_length,
(char *) exit_data,
(long *) &amp;rule_array_count,
(char *) rule_array,
(char *) variant,
(char *) token);
if (return_code &gt; 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(&amp;keyvalue[8], clearkey, 8); /* Make key double length*/
memcpy(rule_array, "LAST ", 8);
CSNBKPI( &amp;return_code, &amp;reason_code, &amp;exit_data_length,
(char *) exit_data,
(long *) &amp;rule_array_count,
(char *) rule_array,
(char *) keyvalue,
(char *) token);
if (return_code &gt; 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-&gt;tokenType = 0x02; /* 02 is external token */
token_ptr-&gt;version = 0x00; /* Version 0 token */
token_ptr-&gt;flagByte1 = 0xC0; /* High order bit is 1 so */
/* key is present. The */
/* 40 bit means that CV */
/* is present */
memcpy(token_ptr-&gt;controlVectorBase, cv, 16); /* Copy control
vector into token */
memcpy(token_ptr-&gt;leftHalfKey,encrypted_key, 8); /* Copy key
into left half */
memcpy(token_ptr-&gt;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 &lt; (externalkey + 60))
{
memcpy((void*)&amp;tvv_part,tvv_pos,4);
tvv += tvv_part;
tvv_pos += 4;
}
memcpy(token_ptr-&gt;tvv, (void*)&amp;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( &amp;return_code, &amp;reason_code, &amp;exit_data_length,
(char *) exit_data,
(char *) keytype,
(char *) externalkey,
(char *) left_importer,
(char *) keytoken);
if (return_code &gt; 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, &amp;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( &amp;return_code, &amp;reason_code, &amp;exit_data_length,
(char *) exit_data,
(char *) keytype,
(char *) externalkey,
(char *) right_importer,
(char *) keytoken);
if (return_code &gt; 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(&amp;keyvalue[8], &amp;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-&gt;tokenType = 0x01; /* 01 is internal token */
token_ptr-&gt;version = 0x03; /* Version 3 token */
token_ptr-&gt;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-&gt;MasterKeyVerifPattern[0] = mkvp[0];
/* Set the second byte of */
/* Master key verification */
/* pattern. */
token_ptr-&gt;MasterKeyVerifPattern[1] = mkvp[1];
/* Copy control vector into*/
/* token */
memcpy(token_ptr-&gt;controlVectorBase, cv, 16);
memcpy(token_ptr-&gt;leftHalfKey, keyvalue, 16); /*Copy key to token */
/**********************************************/
/* Calculate the TVV by adding every 4 bytes */
/**********************************************/
tvv_pos = externalkey;
tvv = 0;
while (tvv_pos &lt; (externalkey + 60))
{
memcpy((void*)&amp;tvv_part,tvv_pos,4);
tvv += tvv_part;
tvv_pos += 4;
}
memcpy(token_ptr-&gt;tvv, (void*)&amp;tvv, 4);
/********************************************/
/* Create a Key Record in Key Store */
/********************************************/
exit_data_length = 0;
CSNBKRC((long *) &amp;return_code,
(long *) &amp;reason_code,
(long *) &amp;exit_data_length,
(char *) exit_data,
(char *) label);
if (return_code &gt; 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 *) &amp;return_code,
(long *) &amp;reason_code,
(long *) &amp;exit_data_length,
(char *) exit_data,
(char *) keytoken,
(char *) label);
if (return_code &gt; 4)
{
printf("Key_Record_Write failed with return/reason codes \
%d/%d \n",return_code, reason_code);
return 1;
}
return 0;
}</pre>
</div>
</div>
</div>
</body>
</html>