| RSA BSAFE Crypto-C |
Cryptographic Components for C |
| Search |
/* $Id: x931.c,v 1.7 2004/12/03 02:08:34 sparki Exp $ */ /* * Copyright (C) 1998-2004 RSA Security Inc. * * This file shall only be used to demonstrate how to interface to an * RSA Security Inc. licensed development product. * * You have a royalty-free right to use, reproduce and distribute this * demonstration file, provided that you agree that RSA Security Inc. * has no warranty, implied or otherwise, or liability for this * demonstration file (including any modified version). This software * is provided "as is" without warranties or representations of any * kind. RSA Security disclaims all conditions and warranties, statutory * and otherwise, both express and implied, with respect to the software, * its quality and performance, including but not limited to, all * implied warranties of merchantability, fitness for a particular * purpose, title and noninfringement of third party rights. Without * limiting the foregoing, RSA Security does not warrant that the * software is error-free or that errors in the product will be * corrected. You agree that RSA Security shall not be liable for any * direct, indirect, incidental, special, consequential, punitive or * other damages whatsoever resulting from your use of this software * or any modified version. * * */ /* This sample demonstrates how to perform RSA digital signing and * verifying according to the ANSI X9.31 standard. */ #include "bsafe.h" #include "demoutil.h" /* in samples/common/include */ #include "surrctx.h" /* in samples/common/include */ B_ALGORITHM_METHOD *X931_SAMPLE_CHOOSER[] = { &AM_X931_RANDOM, &AM_SHA, &AM_FORMAT_X931, &AM_RSA_CRT_X931_ENCRYPT, &AM_EXTRACT_X931, &AM_RSA_X931_DECRYPT, &AM_RSA_STRONG_KEY_GEN, (B_ALGORITHM_METHOD *)NULL_PTR /* This will fix a problem that the IA64 compiler finds when * * seeing a short chooser list */ #ifdef IA64_FORCE_LARGE IA64_FORCE_LARGE #endif }; #define NUMBER_OF_RANDOM_BYTES 128 #define MAX_SEED_BYTES 385 #define RSA_MODULUS_BITS 512 #define BLOCK_SIZE ((RSA_MODULUS_BITS + 7) / 8) #ifdef CRYPTOC_APP #define MAIN x931Main #else #define MAIN main #endif int MAIN(int argc, char *argv[]) { B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ keypairGenerator = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ digitalSigner = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ digitalVerifier = (B_ALGORITHM_OBJ)NULL_PTR; B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR; B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR; ITEM randomSeed = {NULL_PTR, 0}; unsigned char *randomByteBuffer = NULL_PTR; A_X931_RANDOM_PARAMS x931Params; A_RSA_KEY_GEN_PARAMS keygenParams; A_X931_PARAMS x931params; B_SIGN_VERIFY_PARAMS signVerifyParams; static unsigned char f4Data[] = {0x01, 0x00, 0x01}; A_SURRENDER_CTX generalSurrenderContext; int generalFlag; unsigned char inputData[] = "Sign and verify this sentence"; unsigned int inputDataLen; unsigned char signature[BLOCK_SIZE]; unsigned int signatureLen; int status; /* see samples/common/source/surrctx.c for RSA_GeneralSurrenderFunction */ generalSurrenderContext.Surrender = RSA_GeneralSurrenderFunction; generalSurrenderContext.handle = (POINTER)&generalFlag; generalSurrenderContext.reserved = NULL_PTR; do { /* The RSA_* demo code utilities are described in common/include/demoutil.h. This procedure simply checks the command-line arguments for input or output options. */ if ((status = RSA_SetOptions (argc, argv)) != 0) break; RSA_PrintMessage ("Digital Signature Generation and Verification in\n"); RSA_PrintMessage ("compliance with the X9.31 Standard.\n"); RSA_PrintMessage ("================================================\n"); /* Generate random bytes using AI_X931Random. This AI satisfies * the requirements of independent generation of large and private * prime factors, as specified by the ANSI X.931 standard. */ RSA_PrintMessage ("\nGenerating random bytes\n"); RSA_PrintMessage ("=======================\n"); /* Create a random algorithm object */ if ((status = B_CreateAlgorithmObject (&randomAlgorithm)) != 0) break; /* Set the random algorithm object to use AI_X931Random. Before we can call B_SetAlgorithmInfo, we need to prepare the X9.31 parameters. The A_X931_RANDOM_PARAMS structure contains two parameters: the number of independent streams of randomness and an ITEM containing random seed data to be divided up among the streams. */ /* Set the number of streams in the A_X931_RANDOM_PARAMS structure. */ x931Params.numberOfStreams = 6; /* In order to obtain a seed, we need to allocate space for it, and then request it from the user. Note that the following method of seed gathering is insecure. A real application would use a more secure method of seed gathering to ensure the security of the application. */ randomSeed.data = T_malloc (MAX_SEED_BYTES); if (randomSeed.data == NULL_PTR) { status = RSA_DEMO_E_ALLOC; break; } /* Prompt the user until enough seed data is provided */ randomSeed.len = 0; do { RSA_PrintMessage ("We need at least %d bytes of random seed data.\n", 20 * x931Params.numberOfStreams - randomSeed.len); RSA_PrintMessage ("Enter a random seed (%d bytes maximum): ", MAX_SEED_BYTES - 1 - randomSeed.len); RSA_GetCommand ((char *)randomSeed.data + randomSeed.len, MAX_SEED_BYTES - randomSeed.len, NULL); randomSeed.len = T_strlen ((char *)randomSeed.data); RSA_PrintBuf ("Random Seed", randomSeed.data, randomSeed.len); x931Params.seed.data = randomSeed.data; x931Params.seed.len = randomSeed.len; /* Specify the required operation and pass the parameters to the algorithm object */ status = B_SetAlgorithmInfo (randomAlgorithm, AI_X931Random, (POINTER)&x931Params); /* Quit if the buffer is filled, whether or not status is 0 */ if (randomSeed.len == MAX_SEED_BYTES - 1) break; } while (status == BE_ALGORITHM_INFO); if (status != 0) break; /* Initialize the random algorithm. */ if ((status = B_RandomInit (randomAlgorithm, X931_SAMPLE_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Since the random seed has already been passed in via the x931Params structure, we do not have to call B_RandomUpdate(). */ /* Generate -- First, prepare a buffer for receiving the random bytes before calling B_GenerateRandomBytes. */ randomByteBuffer = T_malloc (NUMBER_OF_RANDOM_BYTES); if (randomByteBuffer == NULL_PTR) { status = RSA_DEMO_E_ALLOC; break; } if ((status = B_GenerateRandomBytes (randomAlgorithm, randomByteBuffer, NUMBER_OF_RANDOM_BYTES, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; RSA_PrintBuf ("Random Bytes", randomByteBuffer, NUMBER_OF_RANDOM_BYTES); RSA_PrintMessage ("\nGenerating a Keypair (AI_RSAStrongKeyGen)\n"); RSA_PrintMessage ("====================\n"); /* Create the algorithm and key objects */ if ((status = B_CreateAlgorithmObject (&keypairGenerator)) != 0) break; if ((status = B_CreateKeyObject (&publicKey)) != 0) break; if ((status = B_CreateKeyObject (&privateKey)) != 0) break; /* Specify RSA Strong Key Generation and supply parameters */ keygenParams.modulusBits = RSA_MODULUS_BITS; keygenParams.publicExponent.data = f4Data; keygenParams.publicExponent.len = 3; if ((status = B_SetAlgorithmInfo (keypairGenerator, AI_RSAStrongKeyGen, (POINTER)&keygenParams)) != 0) break; /* Initialize using an appropriate routine from the chooser */ if ((status = B_GenerateInit (keypairGenerator, X931_SAMPLE_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Note that the update is not required for key generation */ /* Generate */ /* generalFlag is for the surrender function */ generalFlag = 0; if ((status = B_GenerateKeypair (keypairGenerator, publicKey, privateKey, randomAlgorithm, &generalSurrenderContext)) != 0) break; RSA_PrintMessage ("Key pair successfully generated!\n"); RSA_PrintMessage ("\nComputing a Digital Signature\n"); RSA_PrintMessage ("=============================\n"); inputDataLen = T_strlen ((char *)inputData); RSA_PrintBuf ("Data to Sign", inputData, inputDataLen); /* Create an algorithm object */ if ((status = B_CreateAlgorithmObject (&digitalSigner)) != 0) break; /* Set the algorithm object to AI_SignVerify */ x931params.blockLen = ((RSA_MODULUS_BITS + 7) / 8); x931params.oidNum = 3; /* Currently, x931params third parameter: ITEM OID of A_X931_PARAMS * is used only when "formatX931PKCS" is specified in the * formatMethodName in the B_SIGN_VERIFY_PARAMS struct. * In this case, since we are not interested in obtaining the * BER encoding of the OID, we can leave this information uninitialized. */ signVerifyParams.encryptionMethodName = (unsigned char *)"rsaSignX931"; signVerifyParams.encryptionParams = NULL_PTR; signVerifyParams.digestMethodName = (unsigned char *)"sha1"; signVerifyParams.digestParams = NULL_PTR; signVerifyParams.formatMethodName = (unsigned char *)"formatX931"; signVerifyParams.formatParams = (POINTER)&x931params; if ((status = B_SetAlgorithmInfo (digitalSigner, AI_SignVerify, (POINTER)&signVerifyParams)) != 0) break; /* Init */ if ((status = B_SignInit (digitalSigner, privateKey, X931_SAMPLE_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Update -- digest the data to sign */ RSA_PrintMessage ("Digesting the input data...\n"); if ((status = B_SignUpdate (digitalSigner, inputData, inputDataLen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Final -- Encrypt the digest and output the result to a signature buffer */ RSA_PrintMessage ("Encrypting the digest...\n"); if ((status = B_SignFinal (digitalSigner, signature, &signatureLen, sizeof (signature), (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; RSA_PrintBuf ("Digital Signature", signature, signatureLen); RSA_PrintMessage ("\nVerifying the Digital Signature\n"); RSA_PrintMessage ("===============================\n"); /* Create an algorithm object */ if ((status = B_CreateAlgorithmObject (&digitalVerifier)) != 0) break; /* Set the algorithm object to the same AI */ signVerifyParams.encryptionMethodName = (unsigned char *)"rsaVerifyX931"; signVerifyParams.encryptionParams = NULL_PTR; signVerifyParams.digestMethodName = (unsigned char *)"sha1"; signVerifyParams.digestParams = NULL_PTR; signVerifyParams.formatMethodName = (unsigned char *)"formatX931"; signVerifyParams.formatParams = (POINTER)&x931params; if ((status = B_SetAlgorithmInfo (digitalVerifier, AI_SignVerify, (POINTER)&signVerifyParams)) != 0) break; /* Init */ if ((status = B_VerifyInit (digitalVerifier, publicKey, X931_SAMPLE_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Update */ if ((status = B_VerifyUpdate (digitalVerifier, inputData, inputDataLen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Final */ generalFlag = 0; if ((status = B_VerifyFinal (digitalVerifier, signature, signatureLen, (B_ALGORITHM_OBJ)NULL_PTR, &generalSurrenderContext)) != 0) break; } while (0); if (status != 0) RSA_PrintError ("x931", status); else RSA_PrintMessage ("\nSuccess! Digital Signature verified.\n"); /* Destroy all key and algorithm objects */ B_DestroyAlgorithmObject (&randomAlgorithm); B_DestroyAlgorithmObject (&keypairGenerator); B_DestroyAlgorithmObject (&digitalSigner); B_DestroyAlgorithmObject (&digitalVerifier); B_DestroyKeyObject (&privateKey); B_DestroyKeyObject (&publicKey); /* Free up any memory allocated */ if (randomSeed.data != NULL_PTR) { T_memset (randomSeed.data, 0, randomSeed.len); T_free (randomSeed.data); } if (randomByteBuffer != NULL_PTR) { T_memset (randomByteBuffer, 0, NUMBER_OF_RANDOM_BYTES); T_free (randomByteBuffer); } return (status); } /* end main */