| RSA BSAFE Crypto-C |
Cryptographic Components for C |
| Search |
/* $Id: p11dsakeygen.c,v 1.7 2004/12/03 02:08:39 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 DSA keypair, using the specified hardware. * If parameters that are used to generate the keypair have already been * created then the user will have the option to use those otherwise * new parameters will be created. */ #include "bsafe.h" #include "demoutil.h" /* in samples/common/include */ #include "bsfutil.h" /* in samples/common/include */ #include "surrctx.h" /* in samples/common/include */ #define DSA_PRIME_BITS 512 #define BLOCK_SIZE 256 #ifdef CRYPTOC_APP #define MAIN p11dsakeygenMain #else #define MAIN main #endif int MAIN(int argc, char *argv[]) { B_ALGORITHM_OBJ dsaGen = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ random = (B_ALGORITHM_OBJ)NULL_PTR; B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR; B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR; A_SURRENDER_CTX generalSurrenderContext; int generalFlag; /* Used to hold the public key information */ ITEM *cryptocPublicKeyBER; ITEM myPublicKeyBER = {NULL, 0}; /* Used to hold the private key information */ ITEM *getPrivateKey; ITEM privateKeyBER = {NULL, 0}; KI_TOKEN_INFO *tokenInfo = NULL; /* Holds the parameters needed to generate the keys */ A_DSA_PUBLIC_KEY *pubKeyData; A_DSA_PARAMS DSAParams; /* Stores the device (hardware or software) that is * being used */ ITEM deviceName; /* Stores the information needed in order to access the * hardware installed */ B_PKCS11_SESSION p11Session; unsigned char *tokenLabel = NULL; unsigned int libraryNameLen = 0; /* The current chooser which holds the hardware AMs * that are to be used */ B_ALGORITHM_METHOD *DSA_GEN_HW_CHOOSER[] = { (B_ALGORITHM_METHOD *)&AM_DSA_PARAM_GEN, (B_ALGORITHM_METHOD *)&AM_PKCS11_DSA_KEY_GEN, (B_ALGORITHM_METHOD *)&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 }; /* The backup chooser which holds the software AMs that should * be used if the hardware AMs are not available */ B_ALGORITHM_METHOD *DSA_GEN_SW_CHOOSER[] = { &AM_SHA_RANDOM, &AM_SHA, &AM_DSA_KEY_GEN, &AM_DSA_PARAM_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 }; /* This will hold the new chooser created */ B_ALGORITHM_CHOOSER hwChooserGen = (B_ALGORITHM_CHOOSER)NULL_PTR; /* This is used to hold the already generated parameters */ B_KEYPAIR_GEN_PARAMS p11KeyGenParams; B_DSA_PARAM_GEN_PARAMS dsaParamGenParams; /* This generates and holds parameters if they have not been generated */ B_ALGORITHM_OBJ dsaParamGen = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ dsaParamStore = (B_ALGORITHM_OBJ)NULL_PTR; B_KEY_OBJ publicTemp = (B_KEY_OBJ)NULL_PTR; B_KEY_OBJ privateTemp = (B_KEY_OBJ)NULL_PTR; /* Used to check for errors */ int status; int usetoken = 0; char userInput[RSA_DEMO_MAX_LINE_LEN]; /* see samples/common/source/surrctx.c for RSA_GeneralSurrenderFunction */ generalSurrenderContext.Surrender = RSA_GeneralSurrenderFunction; generalSurrenderContext.handle = (POINTER)&generalFlag; generalSurrenderContext.reserved = NULL_PTR; T_memset ((POINTER)&DSAParams, 0, sizeof (DSAParams)); do { /* Initialize these fields to facilitate graceful cleanup on error conditions. */ T_memset ((POINTER)&p11Session, 0, sizeof (p11Session)); /* 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 ("DSA PKCS #11 Key Generation\n"); RSA_PrintMessage ("===========================\n"); /* The information needed in order to access the hardware platform */ p11Session.sessionHandle = 0; /* We could supply a CK_FUNCTION_LIST for the device we want this B_PKCS11_SESSION information to identify. However, we specify NULL here to indicate that Crypto-C should obtain the CK_FUNCTION_LIST using the libraryName and tokenLabel to identify the device for this session. */ p11Session.cryptokiFunctions = NULL_PTR; /* This name will be the one that Crypto-C tries to load with, for example, LoadLibrary. */ RSA_PrintMessage ("Enter name of PKCS #11 shared library"); if ((status = RSA_GetCommand (userInput, sizeof (userInput), " (blank to omit)")) != 0) break; /* p11Session.libraryName should be a NUL-terminated string */ libraryNameLen = T_strlen (userInput) + 1; p11Session.libraryName = (char *)T_malloc (libraryNameLen); if (p11Session.libraryName == NULL) { status = RSA_DEMO_E_ALLOC; break; } T_memcpy ((unsigned char *)p11Session.libraryName, (unsigned char *)userInput, libraryNameLen); RSA_PrintMessage ("Enter token name"); if ((status = RSA_GetCommand (userInput, sizeof (userInput), " (blank to omit)")) != 0) break; if (userInput[0] != '\0') { p11Session.tokenLabel.len = T_strlen (userInput); tokenLabel = T_malloc (p11Session.tokenLabel.len); /* we don't want to free p11Session.tokenLabel ourselves, since in the case where no token name is supplied, Crypto-C places its own buffer in p11Session.tokenLabel.data */ p11Session.tokenLabel.data = tokenLabel; if (p11Session.tokenLabel.data == NULL) { status = RSA_DEMO_E_ALLOC; break; } T_memcpy (p11Session.tokenLabel.data, (unsigned char *)userInput, p11Session.tokenLabel.len); } RSA_PrintMessage ("Enter passphrase or PIN to access PKCS #11 device"); if ((status = RSA_GetCommand (userInput, sizeof (userInput), " (blank to omit)")) != 0) break; if (userInput[0] != '\0') { p11Session.passPhrase.len = T_strlen (userInput); p11Session.passPhrase.data = T_malloc (p11Session.passPhrase.len); if (p11Session.passPhrase.data == NULL) { status = RSA_DEMO_E_ALLOC; break; } T_memcpy (p11Session.passPhrase.data, (unsigned char *)userInput, p11Session.passPhrase.len); T_memset ((unsigned char *)userInput, 0, sizeof (userInput)); } p11Session.surrenderContext = (A_SURRENDER_CTX *)NULL_PTR; /* Generate a random object that will be used to create the keys */ if ((status = RSA_CreateRandomAlgorithmObject (&random)) != 0) break; /* Use the two defined choosers to create a new chooser */ if ((status = B_CreateHardwareChooser (DSA_GEN_HW_CHOOSER, &hwChooserGen, DSA_GEN_SW_CHOOSER, HI_PKCS11Session, (POINTER)&p11Session)) != 0) break; /* Create the objects that will be used to generate the key pair */ if ((status = B_CreateKeyObject (&publicKey)) != 0) break; if ((status = B_CreateKeyObject (&privateKey)) != 0) break; if ((status = B_CreateAlgorithmObject(&dsaGen)) !=0) break; do{ /* Obtain the pre-generated Parameter data if it exists*/ RSA_PrintMessage("To use already generated parameters, "); RSA_PrintMessage ("please supply the following files \n"); status = RSA_GetFileToAllocBuffer (&DSAParams.prime.data, &DSAParams.prime.len, "Enter the file with the prime information: \n(blank otherwise)"); if ( status == RSA_DEMO_E_CANCEL ) { break; } else { RSA_PrintBuf("prime", DSAParams.prime.data, DSAParams.prime.len); } status = RSA_GetFileToAllocBuffer (&DSAParams.subPrime.data, &DSAParams.subPrime.len, "Enter the file with the subprime information: \n(blank otherwise)"); if ( status == RSA_DEMO_E_CANCEL ) { break; } else { RSA_PrintBuf("subprime", DSAParams.subPrime.data, DSAParams.subPrime.len); } status = RSA_GetFileToAllocBuffer (&DSAParams.base.data, &DSAParams.base.len, "Enter the file with the base information: \n(blank otherwise)"); if ( status == RSA_DEMO_E_CANCEL ) { break; } else { RSA_PrintBuf("base", DSAParams.base.data, DSAParams.base.len); } }while(0); /* If the parameters were not preGenerated then generate them */ if (status == RSA_DEMO_E_CANCEL) { /* The parameters need to be generated */ dsaParamGenParams.primeBits = DSA_PRIME_BITS; /* The algorithm object used to generate the parameters */ if ((status = B_CreateAlgorithmObject (&dsaParamGen)) != 0) break; /* In Crypto-C the only way to obtain these parameters is to * generate a keypair and then extract the parameters from the * keys generated. This will hopefully change in future version. * These next objects are used to create the key pair */ if ((status = B_CreateAlgorithmObject (&dsaParamStore)) !=0) break; if ((status = B_CreateKeyObject(&publicTemp)) !=0) break; if ((status = B_CreateKeyObject(&privateTemp)) !=0) break; /* The parameters must be generated in software */ if ((status = B_SetAlgorithmInfo ( dsaParamGen, AI_DSAParamGen, (POINTER)&dsaParamGenParams)) != 0) break; if ((status = B_GenerateInit (dsaParamGen, hwChooserGen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Generate the Parameters and store them in dsaGen so they can * be used to generate keys */ if ((status = B_GenerateParameters(dsaParamGen, dsaParamStore, random, &generalSurrenderContext)) !=0) break; /* Obtain the device used to generate the keys */ if ((status = B_GetDevice (&deviceName, dsaParamGen)) != 0) break; RSA_PrintBuf ("\nDevice Name for Generating Parameters", deviceName.data, deviceName.len); if ((status = B_GenerateInit (dsaParamStore, hwChooserGen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* The Parameter algorithm object is no longer needed */ B_DestroyAlgorithmObject(&dsaParamGen); /* Generate the Key Pair */ if ((status = B_GenerateKeypair (dsaParamStore, publicTemp, privateTemp, random, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Obtain the device used to generate the keys */ if ((status = B_GetDevice (&deviceName, dsaGen)) != 0) break; /* Retrieve the parameters so they can be stored for later use */ if ((status = B_GetKeyInfo ((POINTER *)&pubKeyData, publicTemp, KI_DSAPublic)) != 0) break; /* This Algorithm Object is no longer needed */ B_DestroyAlgorithmObject(&dsaParamStore); /* Store the Prime parameter */ DSAParams.prime.len = pubKeyData->params.prime.len; DSAParams.prime.data = T_malloc(DSAParams.prime.len); T_memcpy(DSAParams.prime.data, pubKeyData->params.prime.data, DSAParams.prime.len); RSA_PrintMessage ("\nThe DSA Parameters:\n"); RSA_PrintBuf ("Prime", DSAParams.prime.data, DSAParams.prime.len); status = RSA_WriteDataToFile (DSAParams.prime.data, DSAParams.prime.len, "Optionally enter name of file for the DSA prime"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; /* Store the subPrime parameter */ DSAParams.subPrime.len = pubKeyData->params.subPrime.len; DSAParams.subPrime.data = T_malloc(DSAParams.subPrime.len); T_memcpy(DSAParams.subPrime.data, pubKeyData->params.subPrime.data, DSAParams.subPrime.len); RSA_PrintBuf ("Subprime", DSAParams.subPrime.data, DSAParams.subPrime.len); status = RSA_WriteDataToFile (DSAParams.subPrime.data, DSAParams.subPrime.len, "Optionally enter name of file for the DSA subprime"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; /* Store the Base parameter */ DSAParams.base.len = pubKeyData->params.base.len; DSAParams.base.data = T_malloc(DSAParams.base.len); T_memcpy(DSAParams.base.data, pubKeyData->params.base.data, DSAParams.base.len); RSA_PrintBuf ("Base", DSAParams.base.data, DSAParams.base.len); status = RSA_WriteDataToFile (DSAParams.base.data, DSAParams.base.len, "Optionally enter name of file for the DSA base"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; } /* Generate the key pair from the previosly generated parameters */ /* The information needed to generate the keys */ p11KeyGenParams.privateKeyAttributes.keyUsage = CF_DIGITAL_SIGNATURE; p11KeyGenParams.privateKeyAttributes.tokenFlag = TF_PRIVATE; p11KeyGenParams.privateKeyAttributes.start = 0; p11KeyGenParams.privateKeyAttributes.end = 0; p11KeyGenParams.publicKeyAttributes.keyUsage = CF_DIGITAL_SIGNATURE; p11KeyGenParams.publicKeyAttributes.tokenFlag = TF_RESIDE_ON_TOKEN; p11KeyGenParams.publicKeyAttributes.start = 0; p11KeyGenParams.publicKeyAttributes.end = 0; p11KeyGenParams.keypairGenInfoType = AI_DSAKeyGen; p11KeyGenParams.keypairGenInfo = (POINTER)&DSAParams; /* Set the algorithm with the key information */ if ((status = B_SetAlgorithmInfo (dsaGen, AI_KeypairGen, (POINTER)&p11KeyGenParams)) != 0) break; /* Initialize the algorithm object with the correct chooser */ if ((status = B_GenerateInit (dsaGen, hwChooserGen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; if ((status = B_GetDevice (&deviceName, dsaGen)) != 0) break; RSA_PrintBuf ("Device Name for Key Generation", deviceName.data, deviceName.len); /* Generate the keypair */ if ((status = B_GenerateKeypair (dsaGen, publicKey, privateKey, random, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; RSA_PrintMessage ("\n Distributing Your Public Key\n"); RSA_PrintMessage (" ============================\n"); /* Obtain the public key information and print it out */ if ((status = B_GetKeyInfo ((POINTER *)&cryptocPublicKeyBER, publicKey, KI_DSAPublicBER)) != 0) break; myPublicKeyBER.len = cryptocPublicKeyBER->len; myPublicKeyBER.data = T_malloc (myPublicKeyBER.len); if (myPublicKeyBER.data == NULL_PTR) { status = RSA_DEMO_E_ALLOC; break; } T_memcpy (myPublicKeyBER.data, cryptocPublicKeyBER->data, myPublicKeyBER.len); RSA_PrintMessage ("The DER-encoded X.509 SubjectPublicKeyInfo\n"); RSA_PrintBuf ("SubjectPublicKeyInfo", myPublicKeyBER.data, myPublicKeyBER.len); status = RSA_WriteDataToFile (myPublicKeyBER.data, myPublicKeyBER.len, "Optionally enter name of file for public key BER"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; status = B_GetKeyInfo ((POINTER *)&tokenInfo, publicKey, KI_Token); if (status == 0) { /* we have a public key in hardware */ RSA_PrintMessage ("\nPublic key token information\n"); RSA_PrintBuf ("KI_TOKEN_INFO.manufacturerId", tokenInfo->manufacturerId.data, tokenInfo->manufacturerId.len); RSA_PrintBuf ("KI_TOKEN_INFO.internalKey", tokenInfo->internalKey.data, tokenInfo->internalKey.len); } else status = 0; /* not a fatal error */ /* Obtain the private key information and print it out */ status = B_GetKeyInfo ((POINTER *)&getPrivateKey, privateKey, KI_DSAPrivateBER); if (status == 0) { /* we have a KI_PKCS_RSAPrivateBER */ privateKeyBER.len = getPrivateKey->len; privateKeyBER.data = T_malloc (privateKeyBER.len); if (privateKeyBER.data == NULL_PTR) { status = RSA_DEMO_E_ALLOC; break; } T_memcpy (privateKeyBER.data, getPrivateKey->data, privateKeyBER.len); RSA_PrintMessage ("\nThe DER-encoded PKCS #8 PrivateKeyInfo\n"); RSA_PrintBuf ("PrivateKeyInfo", privateKeyBER.data, privateKeyBER.len); status = RSA_WriteDataToFile (privateKeyBER.data, privateKeyBER.len, "Optionally enter name of file for private key BER"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; } else status = 0; /* not a fatal error */ status = B_GetKeyInfo ((POINTER *)&tokenInfo, privateKey, KI_Token); if (status == 0) { /* we have a private key in hardware */ RSA_PrintMessage ("\nPrivate key token information\n"); RSA_PrintBuf ("KI_TOKEN_INFO.manufacturerId", tokenInfo->manufacturerId.data, tokenInfo->manufacturerId.len); RSA_PrintBuf ("KI_TOKEN_INFO.internalKey", tokenInfo->internalKey.data, tokenInfo->internalKey.len); status = RSA_WriteDataToFile (tokenInfo->manufacturerId.data, tokenInfo->manufacturerId.len, "Optionally enter name of file for token manufacturer ID"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; status = RSA_WriteDataToFile (tokenInfo->internalKey.data, tokenInfo->internalKey.len, "Optionally enter name of file for private key token info"); if ((status != 0) && (status != RSA_DEMO_E_CANCEL)) break; } else status = 0; /* not a fatal error */ RSA_PrintMessage ("Finished!\n"); } while (0); if (status != 0) RSA_PrintError ("p11keygen", status); /* Destroy all objects */ B_DestroyAlgorithmObject (&random); B_DestroyAlgorithmObject (&dsaGen); B_DestroyHardwareChooser (&hwChooserGen); B_DestroyKeyObject (&privateKey); B_DestroyKeyObject (&publicKey); /* Free up any memory allocated */ if (p11Session.libraryName != NULL) T_free ((unsigned char *)p11Session.libraryName); if (tokenLabel != NULL) T_free (tokenLabel); if (p11Session.passPhrase.data != NULL) T_free (p11Session.passPhrase.data); if (myPublicKeyBER.data != NULL_PTR) T_free (myPublicKeyBER.data); if (privateKeyBER.data != NULL_PTR) T_free (privateKeyBER.data); return (status); } /* end main */