| RSA BSAFE Cert-C |
Certificate Components for C |
| Crypto-C 6.2.1 Developer's Guide | ||
| Search |
/* $Id: cert.c,v 1.5 2004/03/02 05:18:35 gsingh Exp $ */ /* cert.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. ** ** Demonstrate how to parse certificates or generate certificates. ** ** 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 "demoutil.h" #include "certutil.h" #include "filelog.h" #include "rsacsp.h" /* The number of service providers used in this example. Here, we must * register a crypto service provider. */ #define SP_COUNT 1 /* DisplayCertObj reads in the BER encoding of a certificate from a file * and then prints out the information in this certificate. A properly * initialized CERTC_CTX must be passed in. */ static int DisplayCertObj (CERTC_CTX ctx); /* GenerateCertObj obtains information from the user and creates a * certificate object. It then stores the BER encoding of the * certificate in a file specified by the user. A properly initialized * CERTC_CTX must be passed in. */ static int GenerateCertObj (CERTC_CTX ctx); /* VerifyCertSignature reads in the BER encoding of a certificate * from a file and verifies that certificate's signature, given a public key. * It then prints out a message stating whether or not the certificate was * verified. A properly initialized CERTC_CTX must be passed in. To do path * validation for certificate validity checking, see the * samples/validate/chain.c or samples/validate/validate.c sample for the use * of C_BuildCertPath. */ static int VerifyCertSignature (CERTC_CTX ctx); /* ExtractObjsFromCert reads in the BER encoding of a certificate * from a file. It then extracts the fields in the cert, prints * them out, and optionally saves them to a file. A properly * initialized CERTC_CTX must be passed in. */ static int ExtractObjsFromCert (CERTC_CTX ctx); int main (int argc, char *argv[]) { int status = 0; char command[RSA_DEMO_MAX_LINE_LEN]; CERTC_CTX ctx = NULL; SERVICE_HANDLER spTable[SP_COUNT]; POINTER spParams[SP_COUNT]; FILE_LOG_PARAMS logParams = {NULL, NULL}; SERVICE_HANDLER logHandler = { SPT_LOG, "Default File Log", S_InitializeFileLog }; /* Since we are going to be performing operations using Crypto-C, we need to register an instance of the crypto provider. */ spTable[0].type = SPT_CRYPTO; spTable[0].name = "BSAFE Crypto-C"; spTable[0].Initialize = S_InitializeDefaultCSP; spParams[0] = NULL; status = RSA_SetOptions (&logParams, argc, argv); if (status != 0) goto CLEANUP; 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 RSA_PrintMessage ("Cert Object Demonstration\n"); RSA_PrintMessage ("=========================\n"); for (;;) { RSA_PrintMessage ("\nCert Object Operations\n"); RSA_PrintMessage (" A - Display certificate object from a file\n"); RSA_PrintMessage (" B - Generate certificate object\n"); RSA_PrintMessage (" C - Verify certificate signature\n"); RSA_PrintMessage (" D - Extract objects from certificate\n"); status = RSA_GetCommand (command, sizeof (command), "Enter choice (blank to quit)"); if (status != 0) goto CLEANUP; switch (command[0]) { case 'a': case 'A': status = DisplayCertObj (ctx); break; case 'b': case 'B': status = GenerateCertObj (ctx); break; case 'c': case 'C': status = VerifyCertSignature (ctx); break; case 'd': case 'D': status = ExtractObjsFromCert (ctx); break; case '\0': case 'q': case 'Q': goto CLEANUP; default: RSA_PrintMessage ("Unrecognized Option: %c\n", command[0]); status = RSA_DEMO_E_INVALID_PARAMETER; } if (status != 0) RSA_PrintMessage ("Operation not completed.\n"); else RSA_PrintMessage ("Operation successful!\n"); } CLEANUP: if (status != 0) RSA_PrintError ("cert.c", status); C_FinalizeCertC (&ctx); return status; } /* end main */ /* See function declaration at the top for a description */ static int DisplayCertObj (CERTC_CTX ctx) { int status = 0; unsigned char *certBer = NULL; unsigned int certBerLen = 0; CERT_OBJ certObj = NULL; ITEM output; status = RSA_GetFileToAllocBuffer (&certBer, &certBerLen, "Enter name of cert object binary"); if (status != 0) goto CLEANUP; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer, certBerLen); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nCert Object Contents\n"); /* RSA_PrintCertObject is described in samples/common/include/certutil.h */ status = RSA_PrintCertObject (certObj); if (status != 0) goto CLEANUP; /* Check the cert for any inconsistencies. Cert-C is lenient in allowing certs with abnormalities to be imported using C_SetCertBER, but will not allow the export of certs with incorrect encodings to be exported using C_GetCertDER. */ status = C_GetCertDER (certObj, &output.data, &output.len); if (status != 0) { RSA_PrintMessage ("Please examine the certificate binary "); RSA_PrintMessage ("for problems with the encoding.\n"); RSA_PrintMessage ("C_SetCertBER passed but C_GetCertDER fails.\n"); goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("DisplayCertObj", status); C_DestroyCertObject (&certObj); T_free (certBer); return status; } /* end DisplayCertObj */ /* See function declaration at the top for a description */ static int GenerateCertObj (CERTC_CTX ctx) { int status = 0; CERT_OBJ certObj = (CERT_OBJ)NULL_PTR; unsigned char *certBer = NULL_PTR; unsigned int certBerLen = 0; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; /* RSA_GetInputToCertObject is described in samples/common/include/certutil.h. */ status = RSA_GetInputToCertObject (ctx, certObj, NULL); if (status != 0) goto CLEANUP; status = C_GetCertDER (certObj, &certBer, &certBerLen); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (certBer, certBerLen, "Enter file name to store cert object binary"); if (status != 0) goto CLEANUP; CLEANUP: if (status != 0) RSA_PrintError ("GenerateCertObj", status); C_DestroyCertObject (&certObj); return status; } /* end GenerateCertObj */ /* See function declaration at the top for a description */ static int VerifyCertSignature (CERTC_CTX ctx) { int status = 0; unsigned char *certBer = NULL_PTR; unsigned int certBerLen = 0; B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR; CERT_OBJ certObj = (CERT_OBJ)NULL_PTR; status = RSA_GetFileToAllocBuffer (&certBer, &certBerLen, "Enter name of cert object binary"); if (status != 0) goto CLEANUP; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer, certBerLen); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Supply public key to verify signature, or enter blank\n"); RSA_PrintMessage ("to use the key contained in the cert.\n"); /* RSA_GetKeyObjFromFile and RSA_GetPubKeyFromCert are described in samples/common/include/keyutil.h */ status = RSA_GetKeyObjFromFile (RSA_DEMO_PUBLIC_KEY, &publicKey); if (status == RSA_DEMO_E_CANCEL) { status = RSA_GetPubKeyFromCert (certObj, &publicKey); } if (status != 0) goto CLEANUP; /* Note that this procedure only verifies the certificate signature given * the appropriate public key. Should more sophisticated checking be * required (for example, verifying a chain of certs or checking the validity * period), see the APIs for Certification Path Processing * (namely C_BuildCertPath). */ status = C_VerifyCertSignature (certObj, publicKey); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Signature verified!\n"); CLEANUP: if (status != 0) RSA_PrintError ("VerifyCertSignature", status); B_DestroyKeyObject (&publicKey); C_DestroyCertObject (&certObj); T_free (certBer); return status; } /* end VerifyCertSignature */ /* See function declaration at the top for a description */ static int ExtractObjsFromCert (CERTC_CTX ctx) { int status = 0; unsigned char *certBer = NULL, *ber = NULL; unsigned int certBerLen, berLen = 0; B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR; CERT_OBJ certObj = (CERT_OBJ)NULL_PTR; CERT_FIELDS certFields; char *nameStr = NULL; status = RSA_GetFileToAllocBuffer (&certBer, &certBerLen, "Enter name of cert object binary"); if (status != 0) goto CLEANUP; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer, certBerLen); if (status != 0) goto CLEANUP; status = C_GetCertFields (certObj, &certFields); if (status != 0) goto CLEANUP; status = C_GetNameStringReverse (certFields.issuerName, &nameStr); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nIssuer Name: %s\n", nameStr); status = C_GetNameDER (certFields.issuerName, &ber, &berLen); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (ber, berLen, "Enter name of file to store issuer name binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* you don't have to save if you don't want to */ else if (status != 0) goto CLEANUP; status = C_GetNameStringReverse (certFields.subjectName, &nameStr); if (status != 0) goto CLEANUP; RSA_PrintMessage ("\nSubject Name: %s\n", nameStr); status = C_GetNameDER (certFields.subjectName, &ber, &berLen); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (ber, berLen, "Enter name of file to store subject name binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* you don't have to save if you don't want to */ else if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (certFields.publicKey.data, certFields.publicKey.len, "Enter name of file to store public key BER"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* you don't have to save if you don't want to */ else if (status != 0) goto CLEANUP; if (certFields.version == CERT_VERSION_3) { status = C_GetExtensionsObjectDER (certFields.certExtensions, &ber, &berLen); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (ber, berLen, "Enter name of file to store cert extensions binary"); if (status == RSA_DEMO_E_CANCEL) status = 0; /* you don't have to save if you don't want to */ else if (status != 0) goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("ExtractObjsFromCert", status); B_DestroyKeyObject (&publicKey); C_DestroyCertObject (&certObj); T_free (certBer); return status; } /* end ExtractObjsFromCert */