| RSA BSAFE Crypto-C |
Cryptographic Components for C |
| Search |
/* $Id: p11rsaencrypt.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 RSA keypair, then use the given hardware * to encrypt and decrypt data using this keypair. */ #include "bsafe.h" #include "demoutil.h" /* in samples/common/include */ #include "bsfutil.h" /* in samples/common/include */ #include "surrctx.h" /* in samples/common/include */ #include "rsautil.h" /* in samples/pkalg/rsa */ #define RSA_MODULUS_BITS 512 #define MAX_RSA_MODULUS_BITS 2048 #define MAX_BLOCK_SIZE ((MAX_RSA_MODULUS_BITS + 7) / 8) #ifdef CRYPTOC_APP #define MAIN p11rsaencryptMain #else #define MAIN main #endif int MAIN(int argc, char *argv[]) { B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ rsaDecryptor = (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; ITEM *cryptocPublicKeyBER; ITEM myPublicKeyBER = {NULL, 0}; ITEM *getPrivateKey; ITEM privateKeyBER = {NULL, 0}; /* This could be a DES or RC4 key, for example: */ unsigned char dataToEncryptWithRSA[] = { 0x4a, 0x72, 0x55, 0x36, 0xda, 0x2f, 0xb9, 0x51 }; unsigned int dataToEncryptLen = sizeof(dataToEncryptWithRSA); unsigned char encryptedData[MAX_BLOCK_SIZE]; unsigned char decryptedData[MAX_BLOCK_SIZE]; unsigned int outputLenUpdate, outputLenFinal, outputLenTotal; int status; char userInput[RSA_DEMO_MAX_LINE_LEN]; /* Stores the device (hardware or software) that is * being used */ ITEM deviceName = {NULL, 0}; /* Contains the information needed to connect to the hardware */ B_PKCS11_SESSION p11Session; ITEM passphrase = {NULL, 0}; unsigned char *tokenLabel = NULL; unsigned int libraryNameLen = 0; ITEM publicBER = {NULL, 0}; KI_TOKEN_INFO privateToken = {NULL, 0, NULL, 0}; KI_TOKEN_INFO *tokenInfo = NULL; /* This chooser contains the AMs to be used by the hardware. Since some * platforms do not support public key operations, (normally public key * operations are faster in software), the software AMs for the public key * operations are used. */ B_ALGORITHM_METHOD *RSA_GEN_HW_CHOOSER[] = { (B_ALGORITHM_METHOD *)&AM_PKCS11_RSA_PRIVATE_DECRYPT, &AM_RSA_ENCRYPT, &AM_SHA, (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 chooser contains the AMs to be used if the hardware AMs are not * available. Be careful not to insert two AMs that are for the same * operation as the new chooser will take the AM that is first and if * this is not the one that is needed an error will be generated. */ B_ALGORITHM_METHOD *RSA_GEN_SW_CHOOSER[] = { &AM_SHA, &AM_SHA_RANDOM, &AM_RSA_KEY_GEN, &AM_RSA_ENCRYPT, &AM_RSA_CRT_DECRYPT, (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 contains the new chooser that is generated */ B_ALGORITHM_CHOOSER hwChooserGen = (B_ALGORITHM_CHOOSER)NULL_PTR; /* see samples/common/source/surrctx.c for RSA_GeneralSurrenderFunction */ generalSurrenderContext.Surrender = RSA_GeneralSurrenderFunction; generalSurrenderContext.handle = (POINTER)&generalFlag; generalSurrenderContext.reserved = NULL_PTR; 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 ("RSA PKCS #11 Encryption Algorithm\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 ((unsigned char *)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 ((unsigned char *)p11Session.passPhrase.data, (unsigned char *)userInput, p11Session.passPhrase.len); T_memset ((unsigned char *)userInput, 0, sizeof (userInput)); } p11Session.surrenderContext = (A_SURRENDER_CTX *)NULL_PTR; RSA_PrintBuf ("Data to Encrypt", dataToEncryptWithRSA, dataToEncryptLen); if ((status = RSA_CreateRandomAlgorithmObject (&randomAlgorithm)) != 0) break; if ((status = B_CreateHardwareChooser (RSA_GEN_HW_CHOOSER, &hwChooserGen, RSA_GEN_SW_CHOOSER, HI_PKCS11Session, (POINTER)&p11Session)) != 0) break; /* We can either use the PKCS #11 device as one for hardware key storage or a crypto accelerator. If it's a key storage device, prompt the user for the files containing the token information. We make the assumption that the device will not be performing any public key operations; the user must supply the public key BER that corresponds to the private key token information. If it's strictly an accelerator, we give the option to generate a software keypair and then feed it to the encrypt routines. */ RSA_PrintMessage ("To use a key token, supply the file containing the"); status = RSA_GetFileToAllocBuffer (&privateToken.manufacturerId.data, &privateToken.manufacturerId.len, " manufacturer ID\n(blank otherwise)"); if (status != RSA_DEMO_E_CANCEL) { /* We want to use a token and have the manufacturer's ID */ if ((status = RSA_GetFileToAllocBuffer (&privateToken.internalKey.data, &privateToken.internalKey.len, "Enter private key token info (blank to cancel)")) != 0) break; RSA_PrintMessage ("Enter corresponding public key BER"); if ((status = RSA_GetFileToAllocBuffer (&publicBER.data, &publicBER.len, " (blank to cancel)")) != 0) break; if ((status = B_CreateKeyObject (&publicKey)) != 0) break; if ((status = B_SetKeyInfo (publicKey, KI_RSAPublicBER, (POINTER)&publicBER)) != 0) break; if ((status = B_CreateKeyObject (&privateKey)) != 0) break; if ((status = B_SetKeyInfo (privateKey, KI_Token, (POINTER)&privateToken)) != 0) break; } else { /* Generate a software keypair. The following function is in samples/pkalg/rsa/rsautil.c */ status = RSA_CreateRSAKeypair (&publicKey, &privateKey, RSA_MODULUS_BITS, randomAlgorithm); } if (status != 0) break; RSA_PrintMessage ("\n Distributing Your Public Key\n"); RSA_PrintMessage (" ============================\n"); status = B_GetKeyInfo ((POINTER *)&cryptocPublicKeyBER, publicKey, KI_RSAPublicBER); if (status == 0) { /* We are using a public key which has been set in software */ 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 public key DER-encoded as X.509\n"); RSA_PrintBuf ("SubjectPublicKeyInfo type", myPublicKeyBER.data, myPublicKeyBER.len); } else status = 0; /* not a fatal error */ RSA_PrintMessage (" Encrypting with the RSA Public Key\n"); RSA_PrintMessage (" ==================================\n"); /* Create an Algorithm Object */ if ((status = B_CreateAlgorithmObject (&rsaEncryptor)) != 0) break; /* Set the algorithm object to AI_PKCS_RSAPublic */ if ((status = B_SetAlgorithmInfo (rsaEncryptor, AI_PKCS_RSAPublic, NULL_PTR)) != 0) break; /* Init -- encrypt with the recipient's public key */ if ((status = B_EncryptInit (rsaEncryptor, publicKey, hwChooserGen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Find out which device is doing the signing */ if ((status = B_GetDevice (&deviceName, rsaEncryptor)) != 0) break; RSA_PrintBuf ("Device Used for Encryption", deviceName.data, deviceName.len); /* Update */ generalFlag = 0; if ((status = B_EncryptUpdate (rsaEncryptor, encryptedData, &outputLenUpdate, sizeof (encryptedData), dataToEncryptWithRSA, dataToEncryptLen, randomAlgorithm, &generalSurrenderContext)) != 0) break; /* Final */ generalFlag = 0; if ((status = B_EncryptFinal (rsaEncryptor, encryptedData + outputLenUpdate, &outputLenFinal, sizeof (encryptedData) - outputLenUpdate, randomAlgorithm, &generalSurrenderContext)) != 0) break; outputLenTotal = outputLenUpdate + outputLenFinal; RSA_PrintBuf ("Encrypted Data", encryptedData, outputLenTotal); RSA_PrintMessage (" Decrypting with the RSA Private Key\n"); RSA_PrintMessage (" ===================================\n"); status = B_GetKeyInfo ((POINTER *)&getPrivateKey, privateKey, KI_PKCS_RSAPrivateBER); if (status == 0) { /* We have a private key which was set in software */ 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 ("The private key encoded as a PKCS #8\n"); RSA_PrintBuf ("PrivateKeyInfo type", privateKeyBER.data, privateKeyBER.len); } 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); } else status = 0; /* not a fatal error */ /* Create an Algorithm Object */ if ((status = B_CreateAlgorithmObject (&rsaDecryptor)) != 0) break; /* Set the algorithm object to AI_PKCS_RSAPrivate */ if ((status = B_SetAlgorithmInfo (rsaDecryptor, AI_PKCS_RSAPrivate, NULL_PTR)) != 0) break; /* Init -- Use the private key associated with the public key used to encrypt */ if ((status = B_DecryptInit (rsaDecryptor, privateKey, hwChooserGen, (A_SURRENDER_CTX *)NULL_PTR)) != 0) break; /* Find out which device is doing the decrypting */ if ((status = B_GetDevice (&deviceName, rsaDecryptor)) != 0) break; RSA_PrintBuf ("Device Used for Decryption", deviceName.data, deviceName.len); /* Update */ generalFlag = 0; if ((status = B_DecryptUpdate (rsaDecryptor, decryptedData, &outputLenUpdate, sizeof (decryptedData), encryptedData, outputLenTotal, NULL_PTR, &generalSurrenderContext)) != 0) break; /* Final */ generalFlag = 0; if ((status = B_DecryptFinal (rsaDecryptor, decryptedData + outputLenUpdate, &outputLenFinal, sizeof (decryptedData) - outputLenUpdate, NULL_PTR, &generalSurrenderContext)) != 0) break; outputLenTotal = outputLenUpdate + outputLenFinal; RSA_PrintBuf ("Decrypted Data", decryptedData, outputLenTotal); if ((outputLenTotal == dataToEncryptLen) && (T_memcmp (dataToEncryptWithRSA, decryptedData, outputLenTotal)) == 0) { RSA_PrintMessage ("Success! "); RSA_PrintMessage ("The decrypted data matches the original data.\n"); } else { RSA_PrintMessage ("The decrypted data does not match the original data."); status = RSA_DEMO_E_INFO_DOES_NOT_VERIFY; } } while (0); if (status != 0) { RSA_PrintError ("pkcs11rsasign", status); if (status == BE_KEY_INFO) { RSA_PrintMessage("This could be due to an error when entering \n"); RSA_PrintMessage("the token information or the dll library \n"); } } /* Destroy all objects */ B_DestroyAlgorithmObject (&randomAlgorithm); B_DestroyAlgorithmObject (&rsaEncryptor); B_DestroyAlgorithmObject (&rsaDecryptor); B_DestroyHardwareChooser (&hwChooserGen); B_DestroyKeyObject (&privateKey); B_DestroyKeyObject (&publicKey); /* Free up any memory allocated */ if (myPublicKeyBER.data != NULL_PTR) T_free (myPublicKeyBER.data); if (privateKeyBER.data != NULL_PTR) T_free (privateKeyBER.data); if (publicBER.data != NULL) T_free (publicBER.data); if (privateToken.manufacturerId.data != NULL) T_free (privateToken.manufacturerId.data); if (privateToken.internalKey.data!= NULL) T_free (privateToken.internalKey.data); 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); return (status); } /* end main */