Change this program example to suit your needs for certifying a public key token.
/*-------------------------------------------------------------------*/ /* CERTKEY */ /* */ /* Sample program to certify a CCA public key certificate to be */ /* used for master key cloning. */ /* */ /* COPYRIGHT 5769-SS1 (C) IBM CORP. 1999, 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. */ /* */ /* */ /* Note: Input format is more fully described in Chapter 2 of */ /* IBM CCA Basic Services Reference and Guide */ /* (SC31-8609) publication. */ /* */ /* Parameters: FILENAME - File containing public key token */ /* RETAINED_KEY_NAME - Name of key to certify token */ /* */ /* Example: */ /* CALL PGM(CERTKEY) PARM(MYKEY.PUB CERTKEY) */ /* */ /* */ /* Note: This program assumes the card with the profile 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. */ /* */ /* The Common Cryptographic Architecture (CCA) verbs used are */ /* Digital_Signature_Generate (CSNDDSG) and One_Way_Hash (CSNBOWH). */ /* */ /* Use these commands to compile this program on the system: */ /* ADDLIBLE LIB(QCCA) */ /* CRTCMOD MODULE(CERTKEY) SRCFILE(SAMPLE) */ /* CRTPGM PGM(CERTKEY) MODULE(CERTKEY) */ /* BNDDIR(QCCA/QC6BNDDIR) */ /* */ /* Note: Authority to the CSNDDSG and CSNBOWH service programs */ /* in the QCCA library is assumed. */ /* */ /*-------------------------------------------------------------------*/ #include <stdio.h> #include <string.h> #include "csucincl.h" #include "decimal.h" extern void QDCXLATE(decimal(5,0), char *, char*, char *); #pragma linkage (QDCXLATE, OS, nowiden) int main(int argc, char *argv[]) { /*------------------------------------------------------------------*/ /* Declares for CCA parameters */ /*------------------------------------------------------------------*/ long return_code = 0; long reason_code = 0; long exit_data_length = 0; char exit_data[4]; char rule_array[24]; long rule_array_count; long token_len = 2500; char token[2500]; long chaining_vector_length = 128; long hash_length = 20; long text_length; unsigned char chaining_vector[128]; unsigned char hash[20]; long signature_length = 256; long signature_bit_length; /*------------------------------------------------------------------*/ /* Declares for working with a PKA token */ /*------------------------------------------------------------------*/ long pub_sec_len; /* Public section length */ long cert_sec_len; /* Certificate section length */ long offset; /* Offset into token */ long tempOffset; /* (Another) Offset into token */ long tempLength; /* Length variable */ char name[64]; /* Private key name */ char SAname[64]; /* Share administration or certifying */ /* key name. */ char SAnameASCII[64]; /* Share admin key name in ASCII */ long SAname_length = 64; /* Length of Share admin key name */ long count; /* Number of bytes read from file */ decimal(5,0) xlate_length = 64; /* Packed decimal variable */ /* needed for call to QDCXLATE. */ FILE *fp; /* File pointer */ if (argc < 3) /* Check the number of parameters passed */ { printf("Need to enter a public key name and SA key\n"); return 1; } name[0] = 0; /* Make copy of name parameters */ strcpy(name,argv[1]); memset(SAname, ' ', 64); /* Make copy of Share Admin key name */ memcpy(SAname,argv[2],strlen(argv[2])); fp = fopen(name,"rb"); /* Open the file containing the token */ if (!fp) { printf("File %s not found.\n",argv[1]); return 1; } memset(token,0,2500); /* Read the token from the file */ count = fread(token,1,2500,fp); fclose(fp); /* Determine length of token from length */ /* bytes at offset 2 and 3. */ token_len = ((256 * token[2]) + token[3]); if (count < token_len) /* Check if whole token was read in */ { printf("Incomplete token in file\n"); return 1; } /************************************************************/ /* Find the certificate offset in the token */ /* */ /* The layout of the token is */ /* */ /* - Token header - 8 bytes - including 2 length bytes */ /* - Public key section - length bytes at offset 10 overall */ /* - Private key name - 68 bytes */ /* - Certificate section */ /* */ /************************************************************/ pub_sec_len = ((256 * token[10]) + token[11]); offset = pub_sec_len + 68 + 8; /* Set offset to certiicate section */ /* Determine certificate section */ /* length from the length bytes at */ /* offset 2 of the section. */ cert_sec_len = ((256 * token[offset + 2]) + token[offset + 3]); tempOffset = offset + 4; /* Set offset to first subsection */ /*-----------------------------------------------------*/ /* Parse each subsection of the certificate until the */ /* signature subsection is found or the end is reached.*/ /* (Identifier for signature subsection is Hex 45.) */ /*-----------------------------------------------------*/ while(token[tempOffset] != 0x45 && tempOffset < offset + cert_sec_len) { tempOffset += 256 * token[tempOffset + 2] + token[tempOffset+3]; } /*----------------------------------------------------*/ /* Check if no signature was found before the end of */ /* the certificate section. */ /*----------------------------------------------------*/ if (token[tempOffset] != 0x45) { printf("Invalid certificate\n"); return 1; } /*******************************************************/ /* Replace Private key name in certificate with the */ /* Share admin key name (expressed in ASCII). */ /*******************************************************/ text_length = tempOffset - offset + 70; memcpy(SAnameASCII,SAname,64); /*----------------------------------------------------*/ /* Convert the Share Admin key name to ASCII */ /*----------------------------------------------------*/ QDCXLATE(xlate_length, SAnameASCII, "QASCII ", "QSYS "); memcpy(&token[tempOffset + 6], SAnameASCII, 64); /**************************************************************/ /* Hash the certificate */ /**************************************************************/ memcpy((void*)rule_array,"SHA-1 ",8); rule_array_count = 1; chaining_vector_length = 128; hash_length = 20; CSNBOWH( &return_code, &reason_code, &exit_data_length, exit_data, &rule_array_count, (unsigned char*)rule_array, &text_length, &token[offset], &chaining_vector_length, chaining_vector, &hash_length, hash); if (return_code != 0) { printf("One_Way_Hash Failed : return reason %d/%d\n", return_code, reason_code); return 1; } /**************************************************************/ /* Create a signature */ /**************************************************************/ memcpy((void*)rule_array,"ISO-9796",8); rule_array_count = 1; CSNDDSG( &return_code, &reason_code, &exit_data_length, exit_data, &rule_array_count, (unsigned char*)rule_array, &SAname_length, SAname, &hash_length, hash, &signature_length, &signature_bit_length, &token[tempOffset+70]); if (return_code != 0) { printf("Digital Signature Generate Failed : return reason %d/%d\n", return_code, reason_code); return 1; } /*-----------------------------------------------*/ /* Check if the new signature is longer than the */ /* original signature */ /*-----------------------------------------------*/ if((token[tempOffset + 2] * 256 + token[tempOffset + 3]) - 70 != signature_length) { printf("Signature Length change from %d to %d.\n", token[tempOffset + 2] * 256 + token[tempOffset + 3] - 70, signature_length); /* Adjust length in signature subsection */ token[tempOffset + 2] = signature_length >> 8; token[tempOffset + 3] = signature_length; /* Adjust length in certificate section */ token[offset + 2] = (text_length + signature_length) >> 8; token[offset + 3] = text_length + signature_length; /* Adjust length in token header section */ tempLength = 8 + pub_sec_len + 68 + text_length + signature_length; token[2] = tempLength >> 8; token[3] = tempLength; } else tempLength = token[2] * 256 + token[3]; /********************************************/ /* Write certified public key out to a file */ /********************************************/ strcat(name,".CRT"); /* Append .CRP to filename */ fp = fopen(name,"wb"); /* Open the certificate file */ if (!fp) { printf("File open failed for output\n"); } else { fwrite(token, 1, tempLength, fp); fclose(fp); printf("Public token written to file %s.\n",name); } }