| RSA BSAFE Cert-C |
Certificate Components for C |
| Crypto-C 6.2.1 Developer's Guide | ||
| Search |
/* $Id: pkcs12.c,v 1.4 2004/03/02 05:18:41 gsingh Exp $ */ /* pkcs12.c ** Copyright (c) 1999-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. ** ** This file takes in a PKCS #12 message and parses it, outputting any certs, ** CRLs, and private keys contained in the message. ** ** 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). */ #include "certc.h" #include "filelog.h" #include "rsacsp.h" #include "imdb.h" #include "fileio.h" #include "demoutil.h" #include "p12util.h" #include "certutil.h" #include "crlutil.h" #include "keyutil.h" #ifdef _MSC_VER # pragma warning (disable: 171) /* invalid type conversion (often of very similar ptrs) */ #endif #define SP_COUNT 3 #define DB_NAME "In-memory DB" /* Takes in a SERVICE which should be bound to a database provider instance * and outputs any certs, CRLs, and private keys to files. */ static int DumpDbContents (SERVICE db); int main (int argc, char *argv[]) { int status = 0, p12Options = 0; char fileName[RSA_DEMO_MAX_LINE_LEN], password[RSA_DEMO_MAX_LINE_LEN]; ITEM macPasswordItem = {NULL, 0}, encPasswordItem = {NULL, 0}; CERTC_CTX ctx = NULL; SERVICE db = NULL; SERVICE_HANDLER spTable[SP_COUNT] = { {SPT_CRYPTO, "Default CSP", S_InitializeDefaultCSP}, {SPT_DATABASE, DB_NAME, S_InitializeMemoryDB}, {SPT_IO, "File IO", S_InitializeFileIO} }; POINTER spParams[SP_COUNT] = {NULL, NULL}; 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; RSA_PrintMessage ("PKCS #12 Example\n"); RSA_PrintMessage ("================\n"); 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 = C_BindService (ctx, SPT_DATABASE, DB_NAME, &db); if (status != 0) goto CLEANUP; status = RSA_GetCommand (fileName, sizeof (fileName), "Enter name of PKCS #12 binary (blank to cancel)"); if (status != 0 || fileName[0] == '\0') goto CLEANUP; status = RSA_GetCommand (password, sizeof (password), "Enter MAC password to verify message integrity"); if (status != 0) goto CLEANUP; status = RSA_FormatPkcs12Password (password, &macPasswordItem); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Enter decryption password to decrypt private key\n"); status = RSA_GetCommand (password, sizeof (password), "(blank to use the same password)"); if (T_strlen (password) == 0) { status = C_ImportPKCS12 (ctx, fileName, &macPasswordItem, db, p12Options); if (status != 0) { /* RSA_FormatPkcs12Password will turn a blank password into the two-byte value {0x00, 0x00}. This is the blank password used by Netscape, but not IE/CryptoAPI. If the initial call failed, try again with the IE/CryptoAPI blank password. */ if (macPasswordItem.len == 2) { RSA_PrintMessage ("Trying password of length 0...\n"); macPasswordItem.len = 0; status = C_ImportPKCS12 (ctx, fileName, &macPasswordItem, db, p12Options); } if (status != 0) goto CLEANUP; } } else if (status != 0) { goto CLEANUP; } else { status = RSA_FormatPkcs12Password (password, &encPasswordItem); if (status != 0) goto CLEANUP; p12Options |= PKCS12_USE_TWO_PASSWORDS; status = C_ImportPKCS12 (ctx, fileName, &macPasswordItem, db, p12Options, &encPasswordItem); if (status != 0) goto CLEANUP; } status = DumpDbContents (db); if (status != 0) goto CLEANUP; CLEANUP: if (status != 0) RSA_PrintError ("pkcs12", status); T_memset ((unsigned char *)password, 0, sizeof (password)); T_memset (macPasswordItem.data, 0, macPasswordItem.len); T_memset (encPasswordItem.data, 0, encPasswordItem.len); T_free (macPasswordItem.data); T_free (encPasswordItem.data); C_UnbindService (&db); C_FinalizeCertC (&ctx); return status; } /* end main */ int DumpDbContents (SERVICE db) { int status = 0; DB_ITERATOR iterator = NULL; LIST_OBJ certList = NULL, crlList = NULL; ITEM certBer = {NULL, 0}, crlBer = {NULL, 0}, privateKeyBer = {NULL, 0}; unsigned int certCount = 0, crlCount = 0, i = 0; CERT_OBJ certObj = NULL; CRL_OBJ crlObj = NULL; B_KEY_OBJ privateKeyObj = NULL; /* Create containers for certs, CRLs, and private keys */ status = C_CreateListObject (&certList); if (status != 0) goto CLEANUP; status = C_CreateListObject (&crlList); if (status != 0) goto CLEANUP; /* Populate the containers with the database contents. Note that if * C_SelectFirstCert is unsuccessful or when C_SelectNextCert is * unsuccessful, iterator is destroyed and set to NULL by Cert-C. * On the status==E_NOT_FOUND condition, we do not need to set status to 0 * before continuing because it is subsequently set before its value is * checked again. If that is not the case, the application may want to set * status to 0 before continuing. */ status = C_SelectFirstCert (db, &iterator, certList); if (status == E_NOT_FOUND) RSA_PrintMessage ("No certificates present.\n"); else if (status != 0) goto CLEANUP; else for (;;) { status = C_SelectNextCert (&iterator, certList); if (status == E_NOT_FOUND) break; else if (status != 0) goto CLEANUP; } /* save the certs to files */ 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; status = C_GetCertDER (certObj, &certBer.data, &certBer.len); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nCertificate #%u\n", i+1); status = RSA_PrintCertInfo (certObj); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (certBer.data, certBer.len, "Enter name of file to store cert binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* don't force user to save cert */ else if (status != 0) goto CLEANUP; } /* extract CRLs */ status = C_SelectFirstCRL (db, &iterator, crlList); if (status == E_NOT_FOUND) RSA_PrintMessage ("No CRLs present.\n"); else if (status != 0) goto CLEANUP; else for (;;) { status = C_SelectNextCRL (&iterator, crlList); if (status == E_NOT_FOUND) break; else if (status != 0) goto CLEANUP; } /* save the CRLs to files */ status = C_GetListObjectCount (crlList, &crlCount); if (status != 0) goto CLEANUP; for (i = 0; i < crlCount; i++) { status = C_GetListObjectEntry (crlList, i, (POINTER *)&crlObj); if (status != 0) goto CLEANUP; status = C_GetCRLDER (crlObj, &crlBer.data, &crlBer.len); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nCRL #%u\n", i+1); status = RSA_PrintCrlInfo (crlObj); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (crlBer.data, crlBer.len, "Enter name of file to store CRL binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* don't force user to save CRL */ else if (status != 0) goto CLEANUP; } status = B_CreateKeyObject (&privateKeyObj); if (status != 0) goto CLEANUP; /* save private keys to files */ status = C_SelectFirstPrivateKey (db, &iterator, privateKeyObj); if (status == E_NOT_FOUND) { RSA_PrintMessage ("No private keys present.\n"); status = 0; } else if (status != 0) goto CLEANUP; else for (i = 0;; i++) { status = RSA_GetKeyBer (RSA_DEMO_PRIVATE_KEY, privateKeyObj, &privateKeyBer); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nPrivate Key #%u\n", i+1); status = RSA_WriteDataToFile (privateKeyBer.data, privateKeyBer.len, "Enter name of file to store private key binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* don't force user to save key */ if (status != 0) goto CLEANUP; B_DestroyKeyObject (&privateKeyObj); status = B_CreateKeyObject (&privateKeyObj); if (status != 0) goto CLEANUP; status = C_SelectNextPrivateKey (&iterator, privateKeyObj); if (status == E_NOT_FOUND) { status = 0; break; } else if (status != 0) goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("DumpDbContents", status); T_memset (privateKeyBer.data, 0, privateKeyBer.len); T_free (privateKeyBer.data); B_DestroyKeyObject (&privateKeyObj); C_FreeIterator (&iterator); C_DestroyListObject (&certList); C_DestroyListObject (&crlList); return status; } /* end DumpDbContents */