1030 lines
50 KiB
HTML
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
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 ----> 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;
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
</html> |