Example: Verifying a digital signature with your Cryptographic Coprocessor

Change this program example to suit your needs for verifying a digital signature with your Cryptographic Coprocessor

Note: Read the Code license and disclaimer information for important legal information.
/*---------------------------------------------------------------*/
/* Description:  Verifies the digital signature of an IFS file   */
/*               produced by the SIGNFILE sample program.        */
/*                                                               */
/*  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:  Signed file                                      */
/*              File containing the signature                    */
/*              Key label of the key to use                      */
/*                                                               */
/* Examples:                                                     */
/*   CALL PGM(VERFILESIG) PARM('name_of_signed_file' +           */
/*                             'name_of_file_w_signature' +      */
/*                             '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(VERFILESIG) SRCFILE(SAMPLE) SYSIFCOPT(*IFSIO)*/
/*   CRTPGM  PGM(SIGNFILE) MODULE(SIGNFILE) +                    */
/*           BNDSRVPGM(QCCA/CSNDDSV QCCA/CSNBOWH)                */
/*                                                               */
/* Note: authority to the CSNDDSV and CSNBOWH service programs   */
/*       in the QCCA library is assumed.                         */
/*                                                               */
/* Common Cryptographic Architecture (CCA) verbs used:           */
/*    Digital_Signature_Verify (CSNDDSV)                         */
/*    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_public_key_identifier_length = 64;
    char PKA_public_key_identifier[64];
    long hash_length = 16L;
    char hash[128];
    long signature_field_length;
    char signature_field[256];
    char key_label[64];

    FILE *file2verify;
    FILE *signature;
    int hash_return;

     if (argc < 2)
     {
	 printf("Name of file to be verified is missing.\n");
	 return ERROR;
     }
     else if (argc < 3)
     {
	 printf("Name of file containing the signature is missing.\n");
	 return ERROR;
     }
     else if (argc < 4)
     {
	 printf("Key label for the key to be used for verification is missing.\n");
	 return ERROR;
     }


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

     /* Open the file that is being verified. */
     if ( (file2verify = 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, file2verify);

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

     if (hash_return != OK)
     {
	 printf("Signature verification failed due to hash error.\n");
	 return ERROR;
     }
     else
     {
	 signature = fopen(argv[2],"rb");
	 if (signature == NULL)
	 {
	     printf("Open of signature file %s failed.",argv[2]);
	     printf("Signature was not verified.");
	     return ERROR;
	 }

	 memset(signature_field, ' ', 256);

	 fseek(signature, 0, SEEK_END);
	 signature_field_length = ftell(signature);
	 rewind(signature);

	 fread(signature_field, 1, signature_field_length, signature);
	 fclose(signature);

	 /* Use CSNDDSV to verify the signature. */
	 CSNDDSV(&return_code,
		 &reason_code,
		 &exit_data_length,
		 exit_data,
		 &rule_array_count,
		 (char *) rule_array,
		 &PKA_public_key_identifier_length,
		 PKA_public_key_identifier,
		 &hash_length,
		 hash,
		 &signature_field_length,
		 signature_field);
     }

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


     }
}



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;
    }
}