Example: Signing a file with your Cryptographic Coprocessor

Change this program example to suit your needs for signing a file with your Cryptographic Coprocessor.

Note: Read the Code license and disclaimer information for important legal information.

If you choose to use this program example, change it to suit your specific needs. For security reasons, IBM® recommends that you individualize these program examples rather than using the default values provided.

/*---------------------------------------------------------------*/
/* Description:  Digitally signs a streams file.                    */
/*                                                               */
/*  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 programs.  All programs contained herein are        */
/*  provided to you "AS IS". THE IMPLIED WARRANTIES OF           */
/*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE     */
/*  EXPRESSLY DISCLAIMED. IBM provides no program services for   */
/*  these programs and files.                                    */
/*                                                               */
/* Parameters:  File to be signed                                */
/*              File to contain signature                        */
/*              Key label of key to use                          */
/*                                                               */
/* Examples:                                                     */
/*   CALL PGM(SIGNFILE) PARM('file_to_sign' 'file_to_hold_sign'  */
/*                           'key_label');                       */
/*                                                               */
/* Note: The CCA verbs used in the this program are more fully   */
/*       described in the IBM  CCA Basic Services Reference  */
/*       and Guide (SC31-8609) publication.                      */
/*                                                               */
/* Note: This program assumes the card you want to use is        */
/*       already identified either by defaulting to the CRP01    */
/*       device or has been 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 the following commands to compile this program:           */
/*    ADDLIBLE LIB(QCCA)                                         */
/*    CRTCMOD MODULE(SIGNFILE) SRCFILE(SAMPLE) SYSIFCOPT(*IFSIO) */
/*    CRTPGM  PGM(SIGNFILE) MODULE(SIGNFILE)                     */
/*            BNDSRVPGM(QCCA/CSNDDSG QCCA/CSNBOWH)               */
/*                                                               */
/* Note: authority to the CSNDDSG and CSNBOWH service programs   */
/*       in the QCCA library is assumed.                         */
/*                                                               */
/* Common Cryptographic Architecture (CCA) verbs used:           */
/*    Digital_Signature_Generate (CSNDDSG)                       */
/*    One_Way_Hash (CSNBOWH)                                     */
/*---------------------------------------------------------------*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "csucincl.h"        /* header file for CCA Cryptographic
			        Service Provider                */

/*-----------------------------------------------------------*/
/* standard return codes                                     */
/*-----------------------------------------------------------*/
#define ERROR -1
#define OK     0

int hash_file(long h_len, char h_out[128], FILE *t_in);

int main(int argc, char *argv[])
{
    /*-----------------------------------------------------------*/
    /* standard CCA parameters                                   */
    /*-----------------------------------------------------------*/
    long return_code;
    long reason_code;
    long exit_data_length = 0L;
    char exit_data[2];
    long rule_array_count = 0L;
    char rule_array[1][8];

    /*-----------------------------------------------------------*/
    /* parameters unique to this sample program                  */
    /*-----------------------------------------------------------*/
    long PKA_private_key_identifier_length = 64;
    char PKA_private_key_identifier[64];
    long hash_length = 16L;
    char hash[128];
    long signature_field_length = 128L;
    long signature_bit_length = 0L;
    char signature_field[256];
    char key_label[64];
    long key_token_length = 2500L;
    char key_token[2500];

    FILE *file2sign;
    FILE *signature;
    int hash_return;

     if (argc < 2)
     {
	 printf("Name of file to be signed is missing.");
	 return ERROR;
     }
     else if (argc < 3)
     {
	 printf("Name of file where the signature should ");
	 printf("be written is missing.");
	 return ERROR;
     }
     else if (argc < 4)
     {
	 printf("Key label for the key to be used for signing is missing.");
	 return ERROR;
     }


     if ( (strlen(argv[3])) > 64 )
     {
	 printf("Invalid Key Label.  Key label longer than 64.");
	 return ERROR;
     }
     else
     {
	 memset(PKA_private_key_identifier, ' ', 64);
	 memcpy(PKA_private_key_identifier, argv[3],strlen(argv[3]));
     }


     /* Open the file that is being signed. */
     if ( (file2sign = fopen(argv[1],"rb")) == NULL)
     {
	 printf("Opening of file %s failed.",argv[1]);
	 return ERROR;
     }

     /* Obtain a hash value for the file. */
     hash_return = hash_file(hash_length, hash, file2sign);

     /* Close the file. */
     fclose(file2sign);

     if (hash_return != OK)
     {
	 printf("Signature generation failed due to hash error.\n");
     }


     else
     {
	 /* Use CSNDDSG to generate the signature. */
	 CSNDDSG(&return_code,
		 &reason_code,
		 &exit_data_length,
		 exit_data,
		 &rule_array_count,
		 (char *) rule_array,
		 &PKA_private_key_identifier_length,
		 PKA_private_key_identifier,
		 &hash_length,
		 hash,
		 &signature_field_length,
		 &signature_bit_length,
		 signature_field);
     }

     if (return_code != 0)
     {
	 printf("Signature generation failed with return/reason code %ld/%ld",
		return_code, reason_code);
	 return ERROR;
     }
     else
     {
	 printf("Signature generation was successful.");
	 printf("Return/Reason codes = %ld/%ld\n", return_code, reason_code);
  printf("Signature has length = %ld\n",signature_field_length);

     signature = fopen(argv[2],"wb");
     if (signature == NULL)
     {
	 printf("Open of file %s failed.",argv[2]);
	 printf("Signature was not saved.");
	 return ERROR;
     }

     fwrite(signature_field, 1, signature_field_length, signature);
     fclose(signature);
     printf("Signature was saved successfully in %s.", argv[2]);
     return OK;
     }
}

int hash_file(long h_len, char h_out[128], FILE *t_in)
{
    /*-----------------------------------------------------------*/
    /* standard CCA parameters                                   */
    /*-----------------------------------------------------------*/
    long return_code;
    long reason_code;
    long exit_data_length = 0;
    char exit_data[2];
    long rule_array_count = 2;
    char rule_array[2][8];

    /*-----------------------------------------------------------*/
    /* parameters unique to this function                        */
    /*-----------------------------------------------------------*/
    long text_length;
    char text[1024];
    long chaining_vector_length = 128;
    char chaining_vector[128];

    long file_length;

    fseek(t_in, 0, SEEK_END);
    file_length = ftell(t_in);
    rewind(t_in);

    text_length = fread(text, 1, 1024, t_in);

    memcpy(rule_array[0], "MD5     ", 8);

    if (file_length <= 1024) {
	memcpy(rule_array[1], "ONLY    ", 8);
    }
    else {
	memcpy(rule_array[1], "FIRST   ", 8);
    }
	
    while (file_length > 0)
    {
	CSNBOWH(&return_code,
		&reason_code,
		&exit_data_length,
		exit_data,
		&rule_array_count,
		(char *) rule_array,
		&text_length,
		text,
		&chaining_vector_length,
		chaining_vector,
		&h_len,
		h_out);

	if (return_code != 0)
	    break;

	printf("Hash iteration worked.\n");

	file_length -= text_length;

	if (file_length > 0)
	{
	    text_length = fread(text, 1, 1024, t_in);

	    if (file_length <= 1024) {
		memcpy(rule_array[1], "LAST    ", 8);
	    }
	    else {
		memcpy(rule_array[1], "MIDDLE  ", 8);
	    }
	}
    }

    if (return_code != 0)
    {
	printf("Hash function failed with return/reason code %ld/%ld\n",
	       return_code, reason_code);
	return ERROR;
    }
    else
    {
	printf("Hash completed successfully.\n");
 printf("hash length = %ld\n", h_len);
 printf("hash = %.32s\n\n", h_out);
	return OK;
    }
}