| RSA BSAFE Cert-C |
Certificate Components for C |
| Crypto-C 6.2.1 Developer's Guide | ||
| Search |
/* $Id: mscapicert.c,v 1.7 2004/03/02 05:18:39 gsingh Exp $ */ /* mscapicert.c ** Copyright (c) 2000-2003 RSA Security Inc. ** ** This file is used to demonstrate how to interface to an RSA Security ** licensed development product. You have a royalty-free right to use, ** modify, reproduce and distribute this demonstration file (including ** any modified version), provided that you agree that RSA Security has ** no warranty, implied or otherwise, or liability for this demonstration ** file or any modified version. ** ** Print out the certificates contained in "MY" CAPI cert store. ** ** When compiling, define the macro RSA_REQUIRE_FILE_LOG (-D compile ** option, or equivelent) to force the program to return an error code ** if file logging cannot be initialized. For example, if the file ** containing the log message format strings cannot be located (certc.msg ** or equivalent). ** ** Because CAPI is only supported on the Windows platform, this sample ** will only compile and run there. ** */ #include "certc.h" #include "filelog.h" #include "demoutil.h" #include "dbutil.h" #include "certutil.h" #include "capiprov.h" #include "rsacsp.h" /* The number of service providers used in this example. */ #define SP_COUNT 2 #ifdef WIN32 /* Do CryptoAPI stuff only on a Win32 machine */ /* Use certificates with corresponding private keys in the given database * to create a PKCS #7 SignedData messages. */ static int SignDataWithDbKeys (CERTC_CTX ctx, char *dbName); int main (int argc, char *argv[]) { int status = 0; CERTC_CTX ctx = NULL; SERVICE_HANDLER spTable[SP_COUNT]; POINTER spParams[SP_COUNT]; MS_CAPI_DB_PARAMS capiDbParams; FILE_LOG_PARAMS logParams = {NULL, NULL}; SERVICE_HANDLER logHandler = { SPT_LOG, "Default File Log", S_InitializeFileLog }; status = RSA_SetOptions (&logParams, argc, argv); if (status != 0) goto CLEANUP; spTable[0].type = SPT_DATABASE; /* Service Provider Type */ spTable[0].name = "CAPI Database"; /* unique null-terminated string */ spTable[0].Initialize = S_InitializeCryptoAPIDB; /* see capiprov.h */ /* We need to register a Crypto provider in order to do crypto operations, * in this case signing data, using the B_KEY_OBJ that we retrieved from * the CAPI store. */ spTable[1].type = SPT_CRYPTO; spTable[1].name = "Crypto Provider"; spTable[1].Initialize = S_InitializeDefaultCSP; /* If we have LIST_OBJs already containing certs, CRLs, or other info, we * can provide a MEMORY_DB_PARAMS structure filled with LIST_OBJs. However, * since that is not the case here, we pass in a NULL to let the Cert-C * library handle the management of the list objects. */ spParams[0] = (POINTER)&capiDbParams; spParams[1] = NULL; capiDbParams.pCryptoProviderName = "Microsoft Enhanced Cryptographic Provider v1.0"; capiDbParams.pKeyContainerName = ""; capiDbParams.pCertSystemStoreName = "MY"; capiDbParams.dwProviderType = 1; capiDbParams.dwKeySpec = 0; status = C_InitializeCertC (spTable, spParams, SP_COUNT, &ctx); if (status != 0) goto CLEANUP; /* Attempt to initialize file logging, but unless RSA_REQUIRE_FILE_LOG is * defined, treat it as a non-fatal condition. */ status = C_RegisterService (ctx, &logHandler, (POINTER)&logParams, SERVICE_ORDER_FIRST); #ifdef RSA_REQUIRE_FILE_LOG if (status != 0) goto CLEANUP; #endif status = SignDataWithDbKeys (ctx, spTable[0].name); CLEANUP: if (status != 0) RSA_PrintError ("mscapicert.c", status); /* Unregister all currently registered providers, free allocated memory, * and set ctx to NULL_PTR. */ C_FinalizeCertC (&ctx); return (status); } /* end main */ static int SignDataWithDbKeys (CERTC_CTX ctx, char *dbName) { int status = 0; SERVICE db = (SERVICE)NULL_PTR; LIST_OBJ certList = (LIST_OBJ)NULL_PTR; DB_ITERATOR iterator = (DB_ITERATOR)NULL_PTR; CERT_OBJ certObj = (CERT_OBJ)NULL_PTR; B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR; unsigned int certCount = 0, i = 0; status = C_BindService (ctx, SPT_DATABASE, dbName, &db); if (status != 0) goto CLEANUP; status = C_CreateListObject (&certList); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Retrieving first cert...\n"); /* To walk through the certs in the database, we need to initialize an * iterator by first calling C_SelectFirstCert(). Subsequent calls can * then be made to C_SelectNextCert(). When the iterator is NULL_PTR, we * know that any memory associated with it has been freed and no certs * remain in the database. Should you need to dispose of the iterator * before all certs have been retrieved, you may call C_FreeIterator(). */ status = C_SelectFirstCert (db, &iterator, certList); if (iterator == NULL) { RSA_PrintMessage ("Database empty.\n"); status = 0; } else if (status != 0) goto CLEANUP; else /* Retrieve all of the remaining certificates. When there are no more * certificates, the iterator will be set to NULL. */ for (;;) { RSA_PrintMessage ("Retrieving another cert from database...\n"); status = C_SelectNextCert (&iterator, certList); if (iterator == NULL) { status = 0; break; } else if (status != 0) goto CLEANUP; } /* Now that we have a list object filled with certificates, print out some * information about each certificate. */ status = C_GetListObjectCount (certList, &certCount); if (status != 0) goto CLEANUP; for (i = 0; i < certCount; i++) { status = C_GetListObjectEntry (certList, i, (POINTER *)&certObj); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\n***Certificate #%u:\n", i + 1); status = RSA_PrintCertInfo (certObj); if (status != 0) goto CLEANUP; status = B_CreateKeyObject (&privateKey); if (status != 0) goto CLEANUP; status = C_SelectPrivateKeyByCert (db, certObj, privateKey); if (status == E_NOT_FOUND) { RSA_PrintMessage ("No private key.\n"); break; } else if (status != 0) goto CLEANUP; RSA_PrintMessage ("Found corresponding private key.\n"); /* Sign some data using the key and cert we just got */ { ITEM dataToSign = {NULL, 0}, p7Data = {NULL, 0}; ITEM p7SignedData = {NULL, 0}; SIGNER_INFO signer; LIST_OBJ signerList = NULL; CERT_FIELDS certFields; T_memset ((POINTER)&signer, 0, sizeof (signer)); status = RSA_GetFileToAllocBuffer (&dataToSign.data, &dataToSign.len, "Enter name of file to sign"); if (status != 0) goto CLEANUP; status = C_WriteDataMsg (ctx, &dataToSign, &p7Data); if (status != 0) goto CLEANUP; status = C_CreateListObject (&signerList); if (status != 0) goto CLEANUP; status = C_GetCertFields (certObj, &certFields); if (status != 0) goto CLEANUP; signer.signerCertId.type = ISSUER_SERIAL; signer.signerCertId.id.issuerSerialNumber.issuerName = certFields.issuerName; signer.signerCertId.id.issuerSerialNumber.serialNumber.data = certFields.serialNumber.data; signer.signerCertId.id.issuerSerialNumber.serialNumber.len = certFields.serialNumber.len; signer.digestAlgorithmId.algorithmId = DAI_SHA1; signer.signatureAlgorithmId.algorithmId = SA_RSA_ENCRYPTION; status = C_AddSignerToList (signerList, &signer, NULL); if (status != 0) goto CLEANUP; status = C_WriteSignedDataMsg (ctx, NULL, db, &p7Data, 0, NULL, NULL, signerList, &p7SignedData); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (p7SignedData.data, p7SignedData.len, "Enter name of file to store signed data"); if (status != 0 && status != RSA_DEMO_E_CANCEL) goto CLEANUP; C_DestroyListObject (&signerList); T_free (dataToSign.data); T_free (p7Data.data); T_free (p7SignedData.data); } } CLEANUP: if (status != 0) RSA_PrintError ("DumpDatabaseContents", status); B_DestroyKeyObject (&privateKey); C_DestroyListObject (&certList); C_FreeIterator (&iterator); C_UnbindService (&db); return (status); } /* end SignDataWithDbKeys */ #else /* ! WIN32 */ int main (int argc, char *argv[]) { return 0; } #endif /* ! WIN32 */