| RSA BSAFE Crypto-C |
Cryptographic Components for C |
| Search |
/* $Id: bsliteds.c,v 1.4 2004/12/03 02:08:36 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. * * */ #include <stdio.h> #include "aglobal.h" #include "bsafe.h" #include "bsafe.h" #include "bsliteds.h" #include "fileio.h" #include "demochos.h" int BSL_MakeDSAKeyPairFromSeed(unsigned char *publicKey, unsigned int *publicKeyLen, unsigned char *ppPrivateKey, unsigned int *ppPrivateKeyLen, unsigned int maxPrivateKeyLen, unsigned char *pbeParams, unsigned int *pbeParamsLen, unsigned int keySizeBits, unsigned char *seed, unsigned int seedLen, unsigned char *password, unsigned int passwordLen) { B_DSA_PARAM_GEN_PARAMS parameters; B_ALGORITHM_OBJ keyGenAlgorithmObj = NULL_PTR; B_ALGORITHM_OBJ paramGenAlgorithmObj = NULL_PTR; B_ALGORITHM_OBJ pbEncryptionAlgorithmObj = NULL_PTR; B_ALGORITHM_OBJ randomAlgorithmObj = NULL_PTR; B_ALGORITHM_OBJ saltDigestAlgorithmObj = NULL_PTR; B_KEY_OBJ passwordKeyObj = NULL_PTR; B_KEY_OBJ privateKeyObj = NULL_PTR; B_KEY_OBJ publicKeyObj = NULL_PTR; B_PBE_PARAMS pbeParamsStruct; ITEM passwordItem, *keyItemPtr, *pbeBERItemPtr; int status; unsigned char pbeSaltBuf[20]; unsigned int digestLen, outputLen; /* do {} while(0); provides convenient way to ensure cleanup upon error */ do { /* create random algorithm objects and set algorithm info */ status = B_CreateAlgorithmObject (&randomAlgorithmObj); if (status != 0) break; status = B_SetAlgorithmInfo (randomAlgorithmObj, AI_MD2Random, NULL_PTR); if (status != 0) break; /* call random init, update with supplied seed bytes */ status = B_RandomInit (randomAlgorithmObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_RandomUpdate (randomAlgorithmObj, seed, seedLen, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* create param and key gen algorithm object */ status = B_CreateAlgorithmObject (¶mGenAlgorithmObj); if (status != 0) break; status = B_CreateAlgorithmObject (&keyGenAlgorithmObj); if (status != 0) break; /* set up parameters generation DSA parameter */ parameters.primeBits = keySizeBits; status = B_SetAlgorithmInfo (paramGenAlgorithmObj, AI_DSAParamGen, (POINTER)¶meters); if (status != 0) break; status = B_GenerateInit (paramGenAlgorithmObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_GenerateParameters (paramGenAlgorithmObj, keyGenAlgorithmObj, randomAlgorithmObj, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* init the dsa key gen algorithm */ status = B_GenerateInit (keyGenAlgorithmObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* create private and public key objects */ status = B_CreateKeyObject (&privateKeyObj); if (status != 0) break; status = B_CreateKeyObject (&publicKeyObj); if (status != 0) break; /* generate keys and store in key objects (may take a few moments) */ status = B_GenerateKeypair (keyGenAlgorithmObj, publicKeyObj, privateKeyObj, randomAlgorithmObj, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* request the Distinguished Encoding (DER) of the public key */ status = B_GetKeyInfo ((POINTER *)&keyItemPtr, publicKeyObj, KI_DSAPublicBER); if (status != 0) break; T_memcpy ((POINTER)publicKey, (POINTER)keyItemPtr->data, keyItemPtr->len); *publicKeyLen = keyItemPtr->len; /* request the Distinguished Encoding (DER) of the private key info */ status = B_GetKeyInfo ((POINTER *)&keyItemPtr, privateKeyObj, KI_DSAPrivateBER); if (status != 0) break; /* if supplied password is NULL, copy unencrypted private key info to the supplied buffer */ if (password == (unsigned char *)NULL_PTR) { T_memcpy ((POINTER)ppPrivateKey, (POINTER)keyItemPtr->data, keyItemPtr->len); *ppPrivateKeyLen = keyItemPtr->len; } /* otherwise; encrypt the private key under the supplied password */ else { /* first, generate a password-based encryption salt value by digesting the private key and the supplied password */ status = B_CreateAlgorithmObject (&saltDigestAlgorithmObj); if (status != 0) break; status = B_SetAlgorithmInfo (saltDigestAlgorithmObj, AI_SHA1, NULL_PTR); if (status != 0) break; status = B_DigestInit (saltDigestAlgorithmObj, NULL_PTR, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_DigestUpdate (saltDigestAlgorithmObj, password, passwordLen, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_DigestUpdate (saltDigestAlgorithmObj, keyItemPtr->data, keyItemPtr->len, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_DigestFinal (saltDigestAlgorithmObj, pbeSaltBuf, &digestLen, sizeof(pbeSaltBuf), (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* create password-based encryption algorithm object */ status = B_CreateAlgorithmObject (&pbEncryptionAlgorithmObj); if (status != 0) break; /* setup password-based encryption parameters */ pbeParamsStruct.salt = pbeSaltBuf; pbeParamsStruct.iterationCount = 1; /* set algorithm object */ status = B_SetAlgorithmInfo (pbEncryptionAlgorithmObj, AI_SHA1WithDES_CBCPad, (POINTER)&pbeParamsStruct); if (status != 0) break; /* get the PBE parameters in their BER encoded form */ status = B_GetAlgorithmInfo ((POINTER *)&pbeBERItemPtr, pbEncryptionAlgorithmObj, AI_SHA1WithDES_CBCPadBER); if (status != 0) break; /* return encoded pbe parameters and length to the caller in the supplied args. */ T_memcpy ((POINTER)pbeParams, (POINTER)pbeBERItemPtr->data, pbeBERItemPtr->len); *pbeParamsLen = pbeBERItemPtr->len; /* create key object */ status = B_CreateKeyObject (&passwordKeyObj); if (status != 0) break; /* setup password item and set key info */ passwordItem.data = password; passwordItem.len = passwordLen; status = B_SetKeyInfo (passwordKeyObj, KI_Item, (POINTER)&passwordItem); if (status != 0) break; /* encrypt the private key DER */ status = B_EncryptInit (pbEncryptionAlgorithmObj, passwordKeyObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_EncryptUpdate (pbEncryptionAlgorithmObj, ppPrivateKey, &outputLen, maxPrivateKeyLen, keyItemPtr->data, keyItemPtr->len, (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; *ppPrivateKeyLen = outputLen; status = B_EncryptFinal (pbEncryptionAlgorithmObj, ppPrivateKey + *ppPrivateKeyLen, &outputLen, maxPrivateKeyLen - *ppPrivateKeyLen, (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; *ppPrivateKeyLen += outputLen; } } while (0); /* cleanup objects */ B_DestroyAlgorithmObject (¶mGenAlgorithmObj); B_DestroyAlgorithmObject (&keyGenAlgorithmObj); B_DestroyAlgorithmObject (&pbEncryptionAlgorithmObj); B_DestroyAlgorithmObject (&randomAlgorithmObj); B_DestroyAlgorithmObject (&saltDigestAlgorithmObj); B_DestroyKeyObject (&passwordKeyObj); B_DestroyKeyObject (&privateKeyObj); B_DestroyKeyObject (&publicKeyObj); return (status); } /***************************************************************************** * * BSL_SHAWithDSASignFile * ---------------------- * Creates a DSA Digital Signature on a data file using the SHA message * digest algorithm and the supplied private key. If the value of the * password is NULL_PTR, the private key should be supplied in its * unprotected form. The signature is then stored in the specified file. * *****************************************************************************/ /* unsigned char *ppPrivateKey: input: buffer of private key bytes */ /* unsigned int ppPrivateKeyLen: input: number of private key bytes */ /* unsigned char *password: input: buffer of private key protection */ /* password bytes */ /* unsigned int passwordLen: input: number of password bytes */ /* unsigned char *pbeParams: input: buffer of password-based */ /* encryption algorithm parameters */ /* bytes */ /* unsigned int pbeParamsLen: input: number of PBE params bytes */ /* unsigned char *seed: input: random seed for DSA signature */ int BSL_SHAWithDSASignFile(char *signatureOutFilename, char *dataInFilename, unsigned char *ppPrivateKey, unsigned int ppPrivateKeyLen, unsigned char *password, unsigned int passwordLen, unsigned char *pbeParams, unsigned int pbeParamsLen, unsigned char *seed, unsigned int seedLen) { B_ALGORITHM_OBJ algorithmObject = NULL_PTR; B_ALGORITHM_OBJ randomAlgorithmObj = NULL_PTR; int status; unsigned char inputBuffer[1024], signature[512]; unsigned int inputLen, signatureLen; FILE *inputFile = (FILE *) NULL_PTR; do { /* Open the data file to be signed */ if ((inputFile = fopen (dataInFilename, "rb")) == NULL) { return (BE_DATA); } /* create and set random algorithm that is needed for DSA signature */ status = B_CreateAlgorithmObject (&randomAlgorithmObj); if (status != 0) break; status = B_SetAlgorithmInfo (randomAlgorithmObj, AI_MD2Random, NULL_PTR); if (status != 0) break; /* call random init, update with supplied seed bytes */ status = B_RandomInit (randomAlgorithmObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_RandomUpdate (randomAlgorithmObj, seed, seedLen, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; /* Initializate algorithm objects used to calculate signatures */ if ((status = BSL_SHAWithDSASignInit (&algorithmObject, ppPrivateKey, ppPrivateKeyLen, password, passwordLen, pbeParams, pbeParamsLen)) != 0) break; /* Create signature by iteratively processing contents of inputFile */ do { inputLen = fread (inputBuffer, 1, 1024, inputFile); if ((status = BSL_SHAWithDSASignUpdate (&algorithmObject, inputBuffer, inputLen)) != 0) break; } while (inputLen == 1024); if (status != 0) break; /* Finalizes the signature computation */ if ((status = BSL_SHAWithDSASignFinal (&algorithmObject, signature, &signatureLen, 512, randomAlgorithmObj)) != 0) break; /* Write the signature to the specified file */ if ((status = RSA_WriteFile (signatureOutFilename, signature, signatureLen)) != 0) break; } while (0); if (inputFile != NULL) fclose (inputFile); B_DestroyAlgorithmObject (&randomAlgorithmObj); return (status); } /***************************************************************************** * * BSL_SHAWithDSAVerifyFile * ------------------------ * Verifies a DSA Digital Signature on a data file using the SHA message * digest algorithm and the supplied public key. A zero is returned if * the signature is successfully verified, a non-zero error value is * returned otherwise. * *****************************************************************************/ /* unsigned char *publicKey: input: buffer of public key bytes */ /* unsigned int publicKeyLen: input: number of public key bytes */ int BSL_SHAWithDSAVerifyFile(char *signatureInFilename, char *dataInFilename, unsigned char *publicKey, unsigned int publicKeyLen) { B_ALGORITHM_OBJ algorithmObject = NULL_PTR; int status; unsigned char inputBuffer[1024], signature[512]; unsigned int inputLen, signatureLen; FILE *inputFile = (FILE *) NULL_PTR; do { /* Open the input file to be verified. */ if ((inputFile = fopen (dataInFilename, "rb")) == NULL) { return (BE_DATA); break; } /* Read the signature that is used to verify the inputBuffer */ if ((status = RSA_ReadFile (signatureInFilename, signature, &signatureLen, 512)) != 0) break; /* Initializate algorithm objects used to verify signatures */ if ((status = BSL_SHAWithDSAVerifyInit (&algorithmObject, publicKey, publicKeyLen)) != 0) break; /* Iteratively process data in inputFile to verify it against the signature */ do { inputLen = fread (inputBuffer, 1, 1024, inputFile); if ((status = BSL_SHAWithDSAVerifyUpdate (&algorithmObject, inputBuffer, inputLen)) != 0) break; } while (inputLen == 1024); /* Finalizes signature verification using the supplied signature */ if ((status = BSL_SHAWithDSAVerifyFinal (&algorithmObject, signature, signatureLen)) != 0) break; } while (0); if (inputFile != NULL) fclose (inputFile); /* A zero return status means signature verification was successful */ return (status); } /***********************************************************************/ int BSL_SHAWithDSASignInit(B_ALGORITHM_OBJ *algorithmObject, unsigned char *ppPrivateKey, unsigned int ppPrivateKeyLen, unsigned char *password, unsigned int passwordLen, unsigned char *pbeParams, unsigned int pbeParamsLen) { B_ALGORITHM_OBJ pbEncryptionAlgorithmObj = NULL_PTR; B_KEY_OBJ passwordKeyObj = NULL_PTR; B_KEY_OBJ privateKeyObj = NULL_PTR; ITEM passwordItem, privateKeyItem, pbEncryptionInfoItem; int status; unsigned char *privateKeyBuf = NULL_PTR; unsigned int outputLen, privateKeyBufLen; /* initialize algorithm object to NULL pointer */ *algorithmObject = NULL_PTR; /* do {} while(0); provides convenient way to ensure cleanup upon error */ do { /* set up an algorithm to create signature */ status = B_CreateAlgorithmObject (algorithmObject); if (status != 0) break; /* set algorithm info to make signature with SHA and DSA */ status = B_SetAlgorithmInfo (*algorithmObject, AI_DSAWithSHA1, NULL_PTR); if (status != 0) break; /* create a key object for the private key */ status = B_CreateKeyObject (&privateKeyObj); if (status != 0) break; /* if supplied password is NULL, use the private key data supplied */ if (password == (unsigned char *)NULL_PTR) { privateKeyItem.data = ppPrivateKey; privateKeyItem.len = ppPrivateKeyLen; } else { /* otherwise, a password is supplied, so decrypt the private key with the password and set the key info with the result */ /* create password-based encryption algorithm object */ status = B_CreateAlgorithmObject (&pbEncryptionAlgorithmObj); if (status != 0) break; /* set up the ITEM which supplies the password-based encryption algorithm info. This contains the salt and iteration count which were specified when the private key was password-encrypted. */ pbEncryptionInfoItem.data = pbeParams; pbEncryptionInfoItem.len = pbeParamsLen; /* set algorithm object */ status = B_SetAlgorithmInfo (pbEncryptionAlgorithmObj, AI_SHA1WithDES_CBCPadBER, (POINTER)&pbEncryptionInfoItem); if (status != 0) break; /* create key object */ status = B_CreateKeyObject (&passwordKeyObj); if (status != 0) break; /* setup password item and set key info */ passwordItem.data = password; passwordItem.len = passwordLen; status = B_SetKeyInfo (passwordKeyObj, KI_Item, (POINTER)&passwordItem); if (status != 0) break; /* allocate a buffer to hold the decrypted private key. Since the decrypted size will be smaller than the encrypted size, we can allocate a buffer of the size of the encrypted key. */ if ((privateKeyBuf = (unsigned char *)T_malloc (ppPrivateKeyLen)) == (unsigned char *)NULL_PTR) { status = BE_ALLOC; break; } /* decrypt the private key DER */ status = B_DecryptInit (pbEncryptionAlgorithmObj, passwordKeyObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; status = B_DecryptUpdate (pbEncryptionAlgorithmObj, privateKeyBuf, &outputLen, ppPrivateKeyLen, ppPrivateKey, ppPrivateKeyLen, (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; privateKeyBufLen = outputLen; status = B_DecryptFinal (pbEncryptionAlgorithmObj, privateKeyBuf + privateKeyBufLen, &outputLen, ppPrivateKeyLen - privateKeyBufLen, (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; privateKeyBufLen += outputLen; /* use the decrypted private key bytes */ privateKeyItem.data = privateKeyBuf; privateKeyItem.len = privateKeyBufLen; } /* set the private key info */ status = B_SetKeyInfo (privateKeyObj, KI_DSAPrivateBER, (POINTER)&privateKeyItem); if (status != 0) break; /* call the signature init */ status = B_SignInit (*algorithmObject, privateKeyObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; } while (0); /* cleanup only if an error occurred */ if (status != 0) B_DestroyAlgorithmObject (algorithmObject); /* cleanup objects */ B_DestroyAlgorithmObject (&pbEncryptionAlgorithmObj); B_DestroyKeyObject (&passwordKeyObj); B_DestroyKeyObject (&privateKeyObj); /* if privateKeyBuf is not NULL, zeroize and free memory */ if (privateKeyBuf != (unsigned char *)NULL_PTR) { T_memset ((POINTER)privateKeyBuf, 0, ppPrivateKeyLen); T_free ((POINTER)privateKeyBuf); } return (status); } /***********************************************************************/ int BSL_SHAWithDSASignUpdate(B_ALGORITHM_OBJ *algorithmObject, unsigned char *input, unsigned int inputLen) { int status; /* call sign update to process input data */ status = B_SignUpdate (*algorithmObject, input, inputLen, (A_SURRENDER_CTX *)NULL_PTR); /* cleanup only if an error occurred */ if (status != 0) B_DestroyAlgorithmObject (algorithmObject); return (status); } /***********************************************************************/ int BSL_SHAWithDSASignFinal(B_ALGORITHM_OBJ *algorithmObject, unsigned char *signature, unsigned int *signatureLen, unsigned int maxSignatureLen, B_ALGORITHM_OBJ randomObject) { int status; status = B_SignFinal (*algorithmObject, signature, signatureLen, maxSignatureLen, randomObject, (A_SURRENDER_CTX *)NULL_PTR); /* cleanup object */ B_DestroyAlgorithmObject (algorithmObject); return (status); } /***********************************************************************/ int BSL_SHAWithDSAVerifyInit(B_ALGORITHM_OBJ *algorithmObject, unsigned char *publicKey, unsigned int publicKeyLen) { B_KEY_OBJ publicKeyObj = NULL_PTR; ITEM publicKeyItem; int status; /* initialize algorithm object to NULL pointer */ *algorithmObject = NULL_PTR; /* do {} while(0); provides convenient way to ensure cleanup upon error */ do { /* create algorithm object for verifying signature */ status = B_CreateAlgorithmObject (algorithmObject); if (status != 0) break; /* set algorithm object to SHA with DSA signature */ status = B_SetAlgorithmInfo (*algorithmObject, AI_DSAWithSHA1, NULL_PTR); if (status != 0) break; /* create and set up a key object for public key decryption */ status = B_CreateKeyObject (&publicKeyObj); if (status != 0) break; publicKeyItem.data = publicKey; publicKeyItem.len = publicKeyLen; status = B_SetKeyInfo (publicKeyObj, KI_DSAPublicBER, (POINTER)&publicKeyItem); if (status != 0) break; /* call the verify init */ status = B_VerifyInit (*algorithmObject, publicKeyObj, DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR); if (status != 0) break; } while (0); /* cleanup only if an error occurred */ if (status != 0) B_DestroyAlgorithmObject (algorithmObject); /* cleanup object */ B_DestroyKeyObject (&publicKeyObj); return (status); } /***********************************************************************/ int BSL_SHAWithDSAVerifyUpdate(B_ALGORITHM_OBJ *algorithmObject, unsigned char *input, unsigned int inputLen) { int status; /* call the verify update */ status = B_VerifyUpdate (*algorithmObject, input, inputLen, (A_SURRENDER_CTX *)NULL_PTR); /* cleanup only if an error occurred */ if (status != 0) B_DestroyAlgorithmObject (algorithmObject); return (status); } /***********************************************************************/ int BSL_SHAWithDSAVerifyFinal(B_ALGORITHM_OBJ *algorithmObject, unsigned char *signature, unsigned int signatureLen) { int status; /* call the verify final */ status = B_VerifyFinal (*algorithmObject, signature, signatureLen, (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR); /* cleanup object */ B_DestroyAlgorithmObject (algorithmObject); return (status); }