/* Rexx */
/* PKCS#11 Key Generation Sample */
/*-------------------------------------------------------------------*/
/* Description: */
/* */
/* This REXX contains samples for PKCS#11 Key Generation: */
/* - Generate clear symmetric key (AES) */
/* - Generate secure symmetric key (DES3) */
/* - Generate clear asymmetric key (RSA) */
/* - Generate secure asymmetric key (ECC) */
/* */
/* How To Run: */
/* - Execute this script from TSO */
/* (e.g. EX 'HLQ.MLD.LLQ(P11GENKY)') */
/*-------------------------------------------------------------------*/
signal on novalue;
/*-------------------------------------------------------------------*/
/* PKCS#11 Constants (subset) */
/*-------------------------------------------------------------------*/
CKO_PUBLIC_KEY = '00000002'X
CKO_PRIVATE_KEY = '00000003'X
CKO_SECRET_KEY = '00000004'X
CKA_CLASS = '00000000'X
CKA_TOKEN = '00000001'X
CKA_PRIVATE = '00000002'X
CKA_LABEL = '00000003'X
CKA_KEY_TYPE = '00000100'X
CKA_SENSITIVE = '00000103'X
CKA_SIGN = '00000108'X
CKA_VERIFY = '0000010A'X
CKA_MODULUS_BITS = '00000121'X
CKA_PRIME = '00000130'X
CKA_SUBPRIME = '00000131'X
CKA_BASE = '00000132'X
CKA_VALUE_LEN = '00000161'X
CKA_EC_PARAMS = '00000180'X
CKA_IBM_SECURE = '80000006'X
/* Key Types */
CKK_RSA = '00000000'X
CKK_EC = '00000003'X
CKK_DES3 = '00000015'X
CKK_AES = '0000001F'X
/* DER encoded OIDs for EC supported curves */
secp192r1 = '06082a8648ce3d030101'x /* {1 2 840 10045 3 1 1} */
secp224r1 = '06052b81040021'x /* {1 3 132 0 33} */
secp256r1 = '06082a8648ce3d030107'x /* {1 2 840 10045 3 1 7} */
secp384r1 = '06052b81040022'x /* {1 3 132 0 34} */
secp521r1 = '06052b81040023'x /* {1 3 132 0 35} */
/*-------------------------------------------------------------------*/
/* Testcase Setup */
/*-------------------------------------------------------------------*/
Token_Handle = left('MY#PKCS11#TOKEN',44) ;
TRD_Handle = Token_Handle ;
Call DeleteToken;
Call CreateToken;
/*-------------------------------------------------------------------*/
/* Generate PKCS#11 AES clear key */
/*-------------------------------------------------------------------*/
GSK_AttrList = '0006'x||, /* number attributes */
CKA_CLASS ||'0004'x|| CKO_SECRET_KEY ||,
CKA_KEY_TYPE ||'0004'x|| CKK_AES ||,
CKA_TOKEN ||'0001'x|| '01'x ||, /* TKDS */
CKA_VALUE_LEN ||'0004'x|| '00000020'x ||,
CKA_LABEL ||'0011'X|| 'P11 Clear AES Key' ||,
CKA_IBM_SECURE ||'0001'X|| '00'x; /* clear */
GSK_AttrListLength = D2C( Length( GSK_AttrList ),4);
Call GenerateKey;
If GSK_RC \= '00000000'x Then
Exit;
/*-------------------------------------------------------------------*/
/* Generate PKCS#11 DES3 secure key */
/*-------------------------------------------------------------------*/
GSK_AttrList = '0006'x||, /* number attributes */
CKA_CLASS ||'0004'x|| CKO_SECRET_KEY ||,
CKA_KEY_TYPE ||'0004'x|| CKK_DES3 ||,
CKA_TOKEN ||'0001'x|| '01'x ||, /* TKDS */
CKA_VALUE_LEN ||'0004'x|| '00000018'x ||, /* 24 byte */
CKA_LABEL ||'0013'X|| 'P11 Secure DES3 Key' ||,
CKA_IBM_SECURE ||'0001'X|| '01'x; /* secure */
GSK_AttrListLength = D2C( Length( GSK_AttrList ),4);
Call GenerateKey;
If GSK_RC \= '00000000'x Then
Exit;
/*-------------------------------------------------------------------*/
/* Generate PKCS#11 RSA clear key */
/*-------------------------------------------------------------------*/
GKP_PubKey_Attr_List = '0006'x ||, /* number attributes */
CKA_CLASS || '0004'x || CKO_PUBLIC_KEY ||,
CKA_KEY_TYPE || '0004'x || CKK_RSA ||,
CKA_TOKEN || '0001'x || '01'x ||, /* TKDS */
CKA_MODULUS_BITS || '0004'x || '00000400'x ||, /* 1024 */
CKA_LABEL || '0018'X || 'P11 Clear RSA Public Key' ||,
CKA_IBM_SECURE || '0001'X || '00'x; /* clear */
GKP_PrivKey_Attr_List = '0005'x ||, /* number attributes */
CKA_CLASS || '0004'x || CKO_PRIVATE_KEY ||,
CKA_KEY_TYPE || '0004'x || CKK_RSA ||,
CKA_TOKEN || '0001'x || '01'x ||, /* TKDS */
CKA_LABEL || '0019'X || 'P11 Clear RSA Private Key' ||,
CKA_IBM_SECURE || '0001'x || '00'x; /* clear */
GKP_PubKey_Attr_List_Length = D2C(Length(GKP_PubKey_Attr_List),4)
GKP_PrivKey_Attr_List_Length = D2C(Length(GKP_PrivKey_Attr_List),4)
Call GenerateKeyPair;
If GKP_RC \= '00000000'x Then
Exit;
/*-------------------------------------------------------------------*/
/* Generate PKCS#11 ECC secure key */
/*-------------------------------------------------------------------*/
GKP_PubKey_Attr_List = '0007'x ||, /* number attributes */
CKA_CLASS || '0004'x || CKO_PUBLIC_KEY ||,
CKA_KEY_TYPE || '0004'x || CKK_EC ||,
CKA_TOKEN || '0001'x || '01'x ||, /* TKDS */
CKA_VERIFY || '0001'x || '01'x ||, /* ECDSA */
CKA_EC_PARAMS || D2C(Length(secp521r1),2) || secp521r1 ||,
CKA_LABEL || '001B'X || 'P11 Secure ECDSA Public Key' ||,
CKA_IBM_SECURE || '0001'X || '01'x; /* secure */
GKP_PrivKey_Attr_List = '0006'x ||, /* number attributes */
CKA_CLASS || '0004'x || CKO_PRIVATE_KEY ||,
CKA_KEY_TYPE || '0004'x || CKK_EC ||,
CKA_TOKEN || '0001'x || '01'x ||, /* TKDS */
CKA_SIGN || '0001'x || '01'x ||, /* ECDSA */
CKA_LABEL || '001C'X || 'P11 Secure ECDSA Private Key' ||,
CKA_IBM_SECURE || '0001'x || '01'x; /* secure */
GKP_PubKey_Attr_List_Length = D2C(Length(GKP_PubKey_Attr_List),4)
GKP_PrivKey_Attr_List_Length = D2C(Length(GKP_PrivKey_Attr_List),4)
Call GenerateKeyPair;
If GKP_RC \= '00000000'x Then
Exit;
Exit;
/* --------------------------------------------------------------- */
/* Call CreateToken */
/* --------------------------------------------------------------- */
CreateToken:
TRC_AttrList = ,
'IBM Corporation - Manufacturer ' ||, /* 32 char Manuf ID */
'Model# _P11GENKY' ||, /* 16 char Model */
'Serial#_P11GENKY' ||, /* 16 char Serial# */
'00000000'x; /* 4 char reserved */
TRC_AttrListLength = D2C( Length( TRC_AttrList ),4);
TRC_RC = 'FFFFFFFF'x ;
TRC_RS = 'FFFFFFFF'x ;
TRC_Exit_Length = '00000000'x ;
TRC_Exit_Data = '' ;
TRC_Rule_Count = '00000001'x;
TRC_Rule_Array = 'TOKEN ' ;
TRC_Handle = Token_Handle ;
/* call Token Record Create */
address linkpgm 'CSFPTRC' ,
'TRC_RC' 'TRC_RS' ,
'TRC_Exit_Length' 'TRC_Exit_Data' ,
'TRC_Handle' ,
'TRC_Rule_Count' 'TRC_Rule_Array' ,
'TRC_AttrListLength' 'TRC_AttrList' ;
if (TRC_RC = '00000000'x) & (TRC_RS = '00000000'x) Then
say 'TRC successful - Token';
else
do;
say 'TRC failed: rc =' c2x(TRC_rc) 'rs =' c2x(TRC_rs) ;
Exit;
end;
return;
/* --------------------------------------------------------------- */
/* Call GenerateKey */
/* --------------------------------------------------------------- */
GenerateKey:
GSK_RC = 'FFFFFFFF'x ;
GSK_RS = 'FFFFFFFF'x ;
GSK_Exit_Length = '00000000'x ;
GSK_Exit_Data = '' ;
GSK_Rule_Count = '00000001'x;
GSK_Rule_Array = 'KEY ';
GSK_Handle = Left(Token_Handle,44) ;
GSK_Parms_List = ''
GSK_Parms_List_Length = '00000000'x
/* call GSK */
address linkpgm 'CSFPGSK' ,
'GSK_RC' 'GSK_RS' ,
'GSK_Exit_Length' 'GSK_Exit_Data' ,
'GSK_Handle' ,
'GSK_Rule_Count' 'GSK_Rule_Array' ,
'GSK_AttrListLength' 'GSK_AttrList' ,
'GSK_Parms_List_Length' 'GSK_Parms_List' ;
say 'GSK: rc =' c2x(GSK_rc) 'rs =' c2x(GSK_rs) ;
if (GSK_RC = '00000000'x) & (GSK_RS = '00000000'x) Then
do;
say ' Secret key handle:' GSK_Handle;
end;
return;
GenerateKeyPair:
GKP_RC = 'FFFFFFFF'x
GKP_RS = 'FFFFFFFF'x
GKP_Exit_Length = '00000000'x
GKP_Exit_Data = ''
GKP_Handle = Left(Token_Handle,44)
GKP_Rule_Count = '00000000'x
GKP_Rule_Array = ''
GKP_PubKey_Handle = copies(' ',44)
GKP_PrivKey_Handle = copies(' ',44)
address linkpgm 'CSFPGKP',
'GKP_RC' 'GKP_RS',
'GKP_Exit_Length' 'GKP_Exit_Data',
'GKP_Handle',
'GKP_Rule_Count' 'GKP_Rule_Array',
'GKP_PubKey_Attr_List_Length',
'GKP_PubKey_Attr_List',
'GKP_PubKey_Handle',
'GKP_PrivKey_Attr_List_Length',
'GKP_PrivKey_Attr_List',
'GKP_PrivKey_Handle'
say 'GKP: rc =' c2x(GKP_rc) 'rs =' c2x(GKP_rs) ;
if (GKP_RC = '00000000'x) & (GKP_RS = '00000000'x) Then
do;
say ' Private key handle:' GKP_PrivKey_Handle;
say ' Public key handle:' GKP_PubKey_Handle;
end;
return;
/* --------------------------------------------------------------- */
/* Call DeleteToken */
/* --------------------------------------------------------------- */
DeleteToken:
TRD_RC = 'FFFFFFFF'x ;
TRD_RS = 'FFFFFFFF'x ;
TRD_Exit_Length = '00000000'x ;
TRD_Exit_Data = '' ;
TRD_Rule_Count = '00000001'x;
TRD_Rule_Array = 'TOKEN ';
/* call Token Record Create */
address linkpgm 'CSFPTRD' ,
'TRD_RC' 'TRD_RS' ,
'TRD_Exit_Length' 'TRD_Exit_Data' ,
'TRD_Handle' ,
'TRD_Rule_Count' 'TRD_Rule_Array' ;
say ' ';
say 'TRD: rc =' c2x(TRD_rc) 'rs =' c2x(TRD_rs) ;
return;