IBM Crypto Education Community - Group home

Rexx Sample: Generate Different Types of PKCS #11 Keys

  

/* 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;