| RSA BSAFE Crypto-C |
Cryptographic Components for C |
| Search |
/* $Id: intelrnd.c,v 1.8 2004/12/03 02:08:40 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 program will generate a series of random values using the * Intel hardware random device. You must link with sec32ipi.lib. */ #include "bsafe.h" #include "demoutil.h" /* in samples/common/include */ #define BYTES_TO_GENERATE 128 /* GenerateSeed will place a random seed in seedBytes. The amount of * data placed in seedBytes will be less than or equal to * seedMaxLength. If the Intel hardware random number generator is * not available, then GenerateSeed will fall back to gathering seed * data from the user. */ int GenerateSeed(unsigned char *seedBytes, unsigned int seedMaxLength) { int status; B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR; #if RSA_PLATFORM == RSA_I386_486 POINTER *oemTagList = (POINTER *)NULL_PTR; B_ALGORITHM_METHOD *CHOOSER[] = { (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 }; /* The software chooser. The AM_HW_RANDOM method in this chooser will be replaced with the hardware method. */ B_ALGORITHM_METHOD *SOFTWARE_CHOOSER[] = { &AM_HW_RANDOM, (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 }; /* This table lists the hardware algorithm methods that could be available. This list isn't the list of algorithms that will be used. That is determined by the hardware availablity. */ HW_TABLE_ENTRY *HARDWARE_CHOOSER[] = { &HW_INTEL_RANDOM, (HW_TABLE_ENTRY *)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 }; unsigned int index, intelHardwarePresent = 0; #endif do { /* Create the session chooser. This call will combine the elements of the software chooser, with those in the hardware chooser. For each item in the software chooser that references a hardware method, the hardware method replaces it. This function will associate a hardware method with a software method so that when a software method is called, it turns to the hardware. In this case, HW_INTEL_RANDOM will be called when AM_HW_RANDOM is referenced. If more than one hardware method can be matched to a single software method, then the hardware method listed first in the hardware chooser is associated with that software method. The list can be modified at run time by creating the hardware chooser at run time. */ #if RSA_PLATFORM == RSA_I386_486 if ((status = B_CreateSessionChooser (SOFTWARE_CHOOSER, &CHOOSER, (POINTER *)HARDWARE_CHOOSER, (ITEM *)NULL_PTR, (POINTER *)NULL_PTR, &oemTagList)) != 0) break; RSA_PrintMessage ("Session chooser successfully created.\n"); RSA_PrintMessage ("OEM tag(s) returned by B_CreateSessionChooser:\n"); index = 0; do { status = T_strcmp ((char *)oemTagList[index], "AM_HW_RANDOM.com.Intel"); if (status == 0) intelHardwarePresent = 1; RSA_PrintMessage (" %s\n", oemTagList[index++]); } while (oemTagList[index] != NULL_PTR); RSA_PrintMessage ("End of OEM tag list.\n"); if (intelHardwarePresent) { RSA_PrintMessage ("Intel hardware found. Continuing.\n"); } else { RSA_PrintMessage ("Intel hardware not found. Using software.\n"); status = 1; break; } /* Create the algorithm object. This object will "control" the random byte generation, storing any state that needs to be stored. */ if ((status = B_CreateAlgorithmObject (&randomAlgorithm)) != 0) break; RSA_PrintMessage ("Created the random algorithm object.\n"); /* Set the algorithm info. We will specify AI_HW_Random, which will point to the hardware method that was associated to AI_HW_Random in the call to B_CreateSessionChooser. */ if ((status = B_SetAlgorithmInfo (randomAlgorithm, AI_HW_Random, NULL_PTR)) != 0) break; RSA_PrintMessage ("Set the algorithm info.\n"); /* Initialize randomAlgorithm to generate random bytes. Here we pass the CHOOSER that was created in the call to B_CreateSessionChooser above. This chooser contains pointers to the hardware method that was associated with AI_HW_Random. If the Intel hardware was not available, then we will fall back to gathering the seed from the user. */ if ((status = B_RandomInit (randomAlgorithm, CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; RSA_PrintMessage ("Initialized the random algorithm object for\n"); RSA_PrintMessage ("random number generation.\n"); /* Generate the random bytes. Here we are asking the Crypto-C SDK to generate some 64 random bytes, storing the data in seedBytes. The last parameter is a surrender context. In this case, generating 64 random bytes should be very quick, so we will pass in a properly cast NULL_PTR. */ if ((status = B_GenerateRandomBytes (randomAlgorithm, seedBytes, seedMaxLength, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Destroy the algorithm object. This step will free any allocated memory used by randomAlgorithm. The memory is zeroized before it is deallocated, so that potentially sensitive information is not left in memory. */ B_DestroyAlgorithmObject (&randomAlgorithm); RSA_PrintMessage ("Destroyed random algorithm object.\n"); /* Free the session chooser. It is important to free the session chooser, so that any handles to hardware and allocated memory are released. */ if ((status = B_FreeSessionChooser (&CHOOSER, &oemTagList)) != 0) break; RSA_PrintMessage ("Free'd session chooser.\n"); #else status = RSA_DEMO_E_NOT_IMPLEMENTED; break; #endif } while (0); /* If an error has ocurred, then print out a summary of the error. */ if (status != 0) { /* There's been an error. Return the status code. */ RSA_PrintError ("Intel RNG unavailable!\n", 0); /* Print out the extended error information, if available. This information will give us a better idea of what went wrong with the hardware. */ { ITEM errorData = {NULL, 0}; POINTER am = NULL; /* Call B_GetExtendedErrorInfo to retrieve the error information. The data returned in the data field of errorData is a structure of A_RSA_EXTENDED_ERROR type. The third parameter will contain a pointer to the alorithm method (AM) that was in use when the error was encountered. */ if (randomAlgorithm != NULL) B_GetExtendedErrorInfo (randomAlgorithm, &errorData, &am); #if RSA_PLATFORM == RSA_I386_486 if (am == (POINTER)&HW_INTEL_RANDOM) { /* Print out the error information. */ RSA_PrintMessage ("Code: %d\n", ((A_RSA_EXTENDED_ERROR *)errorData.data)->errorCode); RSA_PrintMessage ("Message: %s", ((A_RSA_EXTENDED_ERROR *)errorData.data)->errorMsg); } #endif } /* Try the following to deallocate and clear any memory properly. */ B_DestroyAlgorithmObject (&randomAlgorithm); #if RSA_PLATFORM == RSA_I386_486 if ((CHOOSER != (B_ALGORITHM_METHOD **)NULL_PTR) || (oemTagList != (POINTER *)NULL_PTR)) B_FreeSessionChooser (&CHOOSER, &oemTagList); #endif /* An error occurred, so it is necessary to request a seed directly from the user. In this case, we will demonstrate the less secure method of having the user type in the seed. A better method would use the intra-keystroke timings along with mouse movement timings. */ RSA_PrintMessage ("Please type a seed (%d chars max): ", seedMaxLength); RSA_GetCommand ((char *)seedBytes, seedMaxLength, NULL); } RSA_PrintBuf ("Random seed", seedBytes, seedMaxLength); return (seedMaxLength); } /* end GenerateSeed */ #ifdef CRYPTOC_APP #define MAIN intelrndMain #else #define MAIN main #endif int MAIN(int argc, char *argv[]) { B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR; unsigned char *randomSeed = NULL_PTR; unsigned int randomSeedLen = 0; unsigned char *randomByteBuffer = NULL_PTR; int status; B_ALGORITHM_METHOD *RANDOM_CHOOSER[] = { &AM_SHA_RANDOM, (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 }; 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 ("Generating random bytes.\n"); /* Create a random algorithm object. */ if ((status = B_CreateAlgorithmObject (&randomAlgorithm)) != 0) break; /* Set the random algorithm object to SHA1. */ if ((status = B_SetAlgorithmInfo (randomAlgorithm, AI_SHA1Random, NULL_PTR)) != 0) break; /* Initialize the random algorithm. */ if ((status = B_RandomInit (randomAlgorithm, RANDOM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Get a random seed, and pass it to the random algorithm object. This seed will be generated by the Intel hardware random device. If the device cannot be found, or fails during processing, we will request that the user enters a seed value. */ RSA_PrintMessage ("Getting seed value.\n"); randomSeedLen = BYTES_TO_GENERATE; randomSeed = (unsigned char *)T_malloc (randomSeedLen); GenerateSeed (randomSeed, randomSeedLen); /* Now we have a random seed and its length. Pass both into B_RandomUpdate. */ if ((status = B_RandomUpdate (randomAlgorithm, randomSeed, randomSeedLen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Generate. First, prepare a buffer for receiving the random bytes before calling B_GenerateRandomBytes. */ randomByteBuffer = T_malloc (BYTES_TO_GENERATE); if (randomByteBuffer == NULL_PTR) { status = RSA_DEMO_E_ALLOC; break; } RSA_PrintMessage ("Generated random bytes.\n"); T_memset (randomByteBuffer, 0, BYTES_TO_GENERATE); if ((status = B_GenerateRandomBytes (randomAlgorithm, randomByteBuffer, BYTES_TO_GENERATE, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; RSA_PrintBuf ("Random data", randomByteBuffer, BYTES_TO_GENERATE); } while (0); if (status != 0) RSA_PrintError ("intelrnd", status); /* Remember to destroy all objects, and free all memory */ B_DestroyAlgorithmObject (&randomAlgorithm); if (randomSeed != NULL_PTR) { T_memset (randomSeed, 0, randomSeedLen); T_free (randomSeed); } if (randomByteBuffer != NULL_PTR) T_free (randomByteBuffer); return (status); } /* end main */ #if RSA_PLATFORM == RSA_I386_486 /* This function is required to link properly when using the Intel * hardware random device. In this case, though, we will not use the * function, so we will return a 0, to indicate success. */ int T_GetDynamicList(HW_TABLE_LIST *hardwareTable, POINTER *tagList) { /* These arguments are not used and are only included to suppress some compiler warnings. */ UNUSED_ARG(hardwareTable); UNUSED_ARG(tagList); return 0; } #endif