| RSA BSAFE Cert-C |
Certificate Components for C |
| Crypto-C 6.2.1 Developer's Guide | ||
| Search |
/* $Id: certutil.c,v 1.3 2004/03/02 05:18:37 gsingh Exp $ */ /* certutil.c ** Copyright (c) 1999-2002, 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 contains routines that are used to print the information ** contained in a cert object in a readable manner, as well as routines used ** to gather user input to place into a cert object. */ #include "certutil.h" int RSA_SaveCertObjToFile (CERT_OBJ certObj) { int status = 0; ITEM certBer = {NULL, 0}; status = C_GetCertDER (certObj, &certBer.data, &certBer.len); if (status != 0) goto CLEANUP; status = RSA_WriteDataToFile (certBer.data, certBer.len, "Enter name of file to store cert binary"); CLEANUP: if (status != 0) RSA_PrintError ("RSA_SaveCertObjToFile", status); return status; } /* end RSA_SaveCertObjToFile */ int RSA_SaveCertListToFiles (LIST_OBJ certList) { int status = 0; unsigned int count, i; POINTER entry = NULL; status = C_GetListObjectCount (certList, &count); if (status != 0) goto CLEANUP; for (i = 0; i < count; i++) { status = C_GetListObjectEntry (certList, i, (POINTER *)&entry); if (status != 0) goto CLEANUP; status = RSA_PrintCertInfo ((CERT_OBJ)entry); if (status != 0) goto CLEANUP; status = RSA_SaveCertObjToFile ((CERT_OBJ)entry); if (status == RSA_DEMO_E_CANCEL) status = 0; /* saving to file is optional */ else if (status != 0) goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("RSA_SaveCertListToFiles", status); return status; } int RSA_PrintCertObject (CERT_OBJ certObj) { int status = 0; CERT_FIELDS certFields; B_KEY_OBJ publicKey = NULL; A_RSA_KEY *rsaPublicInfo = NULL; A_DSA_PUBLIC_KEY *dsaPublicInfo = NULL; ITEM keyData = {0}; unsigned int keyBits = 0; status = C_GetCertFields (certObj, &certFields); if (status != 0) goto CLEANUP; switch (certFields.version) { case CERT_VERSION_1: RSA_PrintMessage ("Version 1 certificate\n"); break; case CERT_VERSION_2: RSA_PrintMessage ("Version 2 certificate\n"); break; case CERT_VERSION_3: RSA_PrintMessage ("Version 3 certificate\n"); break; default: RSA_PrintMessage ("Unknown version: %u\n", certFields.version); } RSA_PrintBuf ("Serial Number", certFields.serialNumber.data, certFields.serialNumber.len); RSA_PrintSignatureAlgorithm (certFields.signatureAlgorithm); RSA_PrintNameObject ("Issuer Name", certFields.issuerName); RSA_PrintUint4Time ("Validity Start", certFields.validity.start); RSA_PrintUint4Time ("Validity End", certFields.validity.end); RSA_PrintNameObject ("Subject Name", certFields.subjectName); RSA_PrintMessage ("********************\n"); /* Print out the key size in bits */ status = B_CreateKeyObject (&publicKey); if (status != 0) goto CLEANUP; status = RSA_SetKeyBer (RSA_DEMO_PUBLIC_KEY, publicKey, certFields.publicKey); if (status != 0) goto CLEANUP; /* check if it's an RSA public key */ status = B_GetKeyInfo ((POINTER *)&rsaPublicInfo, publicKey, KI_RSAPublic); if (status == 0) { RSA_PrintMessage ("RSA"); keyData.data = rsaPublicInfo->modulus.data; keyData.len = rsaPublicInfo->modulus.len; } else { /* check if it's a DSA public key */ status = B_GetKeyInfo ((POINTER *)&dsaPublicInfo, publicKey, KI_DSAPublic); if (status == 0) { RSA_PrintMessage ("DSA"); keyData.data = dsaPublicInfo->params.prime.data; keyData.len = dsaPublicInfo->params.prime.len; } else { /* unrecognized key */ RSA_PrintMessage ("Unrecognized Key Data!\n"); status = RSA_DEMO_E_NOT_IMPLEMENTED; goto CLEANUP; } } keyBits = B_IntegerBits (keyData.data, keyData.len); RSA_PrintMessage (" Public Key - %u bits\n", keyBits); RSA_PrintBuf ("Public Key BER", certFields.publicKey.data, certFields.publicKey.len); if (certFields.version != CERT_VERSION_1) { RSA_PrintBitString ("Issuer Unique ID", certFields.issuerUniqueID); RSA_PrintBitString ("Subject Unique ID", certFields.subjectUniqueID); } RSA_PrintExtensionsObject (certFields.certExtensions); CLEANUP: if (status != 0) RSA_PrintError ("RSA_PrintCertObject", status); B_DestroyKeyObject (&publicKey); return status; } /* end RSA_PrintCertObject */ int RSA_PrintCertInfo (CERT_OBJ certObj) { int status = 0; CERT_FIELDS certFields; char *nameString = NULL; status = C_GetCertFields (certObj, &certFields); if (status != 0) goto CLEANUP; status = C_GetNameString (certFields.subjectName, &nameString); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Subject: %s\n", nameString); status = C_GetNameString (certFields.issuerName, &nameString); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Issuer: %s\n", nameString); RSA_PrintBuf ("Serial Number", certFields.serialNumber.data, certFields.serialNumber.len); CLEANUP: if (status != 0) RSA_PrintError ("RSA_PrintCertInfo", status); return status; } /* end RSA_PrintCertInfo */ int RSA_AddCertsToDbPrompt (CERTC_CTX ctx, SERVICE database) { int status = 0; ITEM certBer = {NULL, 0}; CERT_OBJ certObj = NULL; for (;;) { status = RSA_GetFileToAllocBuffer (&certBer.data, &certBer.len, "Enter name of cert binary file (blank when finished)"); if (status == RSA_DEMO_E_CANCEL) { status = 0; break; } else if (status != 0) goto CLEANUP; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer.data, certBer.len); if (status != 0) goto CLEANUP; /* Note that another option is to use C_InsertCertList, perhaps in * conjunction with RSA_AddCertsToListPrompt. */ status = C_InsertCert (database, certObj); if (status != 0) goto CLEANUP; T_free (certBer.data); certBer.data = NULL; C_DestroyCertObject (&certObj); } CLEANUP: if (status != 0) RSA_PrintError ("RSA_AddCertsToDbPrompt", status); C_DestroyCertObject (&certObj); return status; } /* end RSA_AddCertsToDbPrompt */ int RSA_AddCertsToListPrompt (CERTC_CTX ctx, LIST_OBJ certList) { int status = 0; ITEM certBer = {NULL, 0}; CERT_OBJ certObj = NULL; for (;;) { status = RSA_GetFileToAllocBuffer (&certBer.data, &certBer.len, "Enter name of cert binary file (blank when finished)"); if (status == RSA_DEMO_E_CANCEL) { status = 0; break; } else if (status != 0) goto CLEANUP; status = C_CreateCertObject (&certObj, ctx); if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer.data, certBer.len); if (status != 0) goto CLEANUP; /* C_AddUniqueCertToList is another option... */ status = C_AddCertToList (certList, certObj, NULL); if (status != 0) goto CLEANUP; T_free (certBer.data); certBer.data = NULL; C_DestroyCertObject (&certObj); } CLEANUP: if (status != 0) RSA_PrintError ("RSA_AddCertsToListPrompt", status); C_DestroyCertObject (&certObj); return status; } /* end RSA_AddCertsToListPrompt */ int RSA_PrintCertList (LIST_OBJ certs) { int status = 0; unsigned int numEntries = 0, i = 0; POINTER entry = NULL; status = C_GetListObjectCount (certs, &numEntries); if (status != 0) goto CLEANUP; if (numEntries == 0) RSA_PrintMessage ("No entries.\n"); for (i = 0; i < numEntries; i++) { status = C_GetListObjectEntry (certs, i, &entry); if (status != 0) goto CLEANUP; RSA_PrintMessage ("***Cert #%d:\n", i+1); status = RSA_PrintCertInfo ((CERT_OBJ)entry); if (status != 0) goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("RSA_PrintCertList", status); return status; } /* end RSA_PrintCertList */ int RSA_GetInputToCertObject (CERTC_CTX ctx, CERT_OBJ certObj, B_KEY_OBJ savedPrivate) { int status = 0; CERT_FIELDS certFields; ALGORITHM_IDENTIFIER signatureAlg; B_KEY_OBJ publicKey = NULL, privateKey = NULL; ITEM privateKeyBer = {NULL, 0}; T_memset ((POINTER)&certFields, 0, sizeof (certFields)); status = RSA_ChooseCertVersionPrompt (&certFields.version); if (status != 0) goto CLEANUP; status = RSA_GetItem (&certFields.serialNumber, "Enter hex-ascii serial number (blank to quit)"); if (status != 0) goto CLEANUP; status = RSA_ChooseSignatureAlgorithmPrompt (&signatureAlg); if (status != 0) goto CLEANUP; certFields.signatureAlgorithm = signatureAlg.algorithmId; status = C_CreateNameObject (&certFields.issuerName); if (status != 0) goto CLEANUP; status = RSA_GetNameObject (certFields.issuerName, "issuer"); if (status != 0) goto CLEANUP; status = RSA_GetInputToUint4Time (&certFields.validity.start, "Enter validity start"); if (status != 0) goto CLEANUP; status = RSA_GetInputToUint4Time (&certFields.validity.end, "Enter validity end"); if (status != 0) goto CLEANUP; status = C_CreateNameObject (&certFields.subjectName); if (status != 0) goto CLEANUP; status = RSA_GetNameObject (certFields.subjectName, "subject"); if (status != 0) goto CLEANUP; /* This code makes the assumption that if you generate a keypair, you will * want to sign the certificate with the private key you just generated. * If desired, this code can be modified to always ask for the signing key. * To do that, just use another B_KEY_OBJ and put the RSA_GetKeyObjFromFile * with RSA_DEMO_PRIVATE_KEY and the new key object outside the "else". */ status = RSA_GetFileToAllocBuffer (&certFields.publicKey.data, &certFields.publicKey.len, "Enter name of file containing public key BER (blank to create)"); if (status == RSA_DEMO_E_CANCEL) { status = RSA_GenerateKeypair (ctx, &publicKey, &privateKey); if (status != 0) goto CLEANUP; status = RSA_GetKeyBer (RSA_DEMO_PUBLIC_KEY, publicKey, &certFields.publicKey); if (status != 0) goto CLEANUP; } else if (status != 0) goto CLEANUP; else { RSA_PrintMessage ("We need a private key to sign the certificate.\n"); status = RSA_GetKeyObjFromFile (RSA_DEMO_PRIVATE_KEY, &privateKey); if (status != 0) goto CLEANUP; } if (certFields.version == CERT_VERSION_1) { certFields.issuerUniqueID.data = NULL_PTR; certFields.issuerUniqueID.len = 0; certFields.issuerUniqueID.unusedBits = 0; certFields.subjectUniqueID.data = NULL_PTR; certFields.subjectUniqueID.len = 0; certFields.subjectUniqueID.unusedBits = 0; } else { status = RSA_GetBitString (&certFields.issuerUniqueID, "Enter optional unique ID of cert issuer (blank to omit)"); if (status != 0 && status != RSA_DEMO_E_CANCEL) goto CLEANUP; status = RSA_GetBitString (&certFields.subjectUniqueID, "Enter optional unique ID of cert subject (blank to omit)"); if (status != 0 && status != RSA_DEMO_E_CANCEL) goto CLEANUP; } status = C_CreateExtensionsObject (&certFields.certExtensions, CERT_EXTENSIONS_OBJ, ctx); if (status != 0) goto CLEANUP; if (certFields.version == CERT_VERSION_3) { status = RSA_GetExtensionsObject (certFields.certExtensions, CERT_EXTENSIONS_OBJ); if (status != 0) goto CLEANUP; } certFields.reserved = NULL_PTR; status = C_SetCertFields (certObj, &certFields); if (status != 0) goto CLEANUP; status = C_SignCert (certObj, privateKey); if (status != 0) goto CLEANUP; /* check if the caller wants the private key */ if (savedPrivate != NULL) { status = RSA_GetKeyBer (RSA_DEMO_PRIVATE_KEY, privateKey, &privateKeyBer); if (status != 0) goto CLEANUP; status = RSA_SetKeyBer (RSA_DEMO_PRIVATE_KEY, savedPrivate, privateKeyBer); } CLEANUP: if (status != 0) RSA_PrintError ("RSA_GetInputToCertObject", status); C_DestroyNameObject (&certFields.issuerName); C_DestroyNameObject (&certFields.subjectName); B_DestroyKeyObject (&publicKey); B_DestroyKeyObject (&privateKey); C_DestroyExtensionsObject (&certFields.certExtensions); T_free (certFields.serialNumber.data); T_free (certFields.publicKey.data); T_free (certFields.issuerUniqueID.data); T_free (certFields.subjectUniqueID.data); return status; } /* end RSA_GetInputToCertObject */ int RSA_GetCertObject (CERTC_CTX ctx, CERT_OBJ certObj, B_KEY_OBJ savedPrivate) { int status = 0; unsigned char *certBer = NULL_PTR; unsigned int certBerLen = 0; RSA_PrintMessage ("Enter name of file containing cert object binary\n"); status = RSA_GetFileToAllocBuffer (&certBer, &certBerLen, "(blank to create a new one)"); if (status == RSA_DEMO_E_CANCEL) { status = RSA_GetInputToCertObject (ctx, certObj, savedPrivate); /* whatever happens, we're done here */ goto CLEANUP; } if (status != 0) goto CLEANUP; status = C_SetCertBER (certObj, certBer, certBerLen); if (status != 0) goto CLEANUP; CLEANUP: if (status != 0) RSA_PrintError ("RSA_GetCertObject", status); T_free (certBer); return status; } /* end RSA_GetCertObject */ int RSA_GetCertAndPvtKey (CERTC_CTX ctx, CERT_OBJ certObj, B_KEY_OBJ pvtKey) { int status = 0; ITEM certBer = {NULL, 0}, pvtKeyBer = {NULL, 0}; /* If the user gives a cert, the user must also give the private key. * Otherwise generate a cert and get the private key that was used to * generate the cert. We could be making a bad assumption here, that * the private key that signed the cert is the one to be associated with * the cert -- for example, chaining? -- this can be modified to ignore * the signing key and always ask the user for a private key. */ RSA_PrintMessage ("Enter name of file containing cert object binary\n"); status = RSA_GetFileToAllocBuffer (&certBer.data, &certBer.len, "(blank to generate a new one)"); if (status == RSA_DEMO_E_CANCEL) /* if user enters a blank */ status = RSA_GetInputToCertObject (ctx, certObj, pvtKey); else if (status == 0) { RSA_PrintMessage ("Enter name of file containing corresponding private"); status = RSA_GetFileToAllocBuffer (&pvtKeyBer.data, &pvtKeyBer.len, " key\n(blank to cancel)"); } if (status != 0) goto CLEANUP; if (certBer.len > 0) { status = C_SetCertBER (certObj, certBer.data, certBer.len); if (status != 0) goto CLEANUP; } if (pvtKeyBer.len > 0) { status = RSA_SetKeyBer (RSA_DEMO_PRIVATE_KEY, pvtKey, pvtKeyBer); if (status != 0) goto CLEANUP; } CLEANUP: if (status != 0) RSA_PrintError ("RSA_GetCertAndPvtKey", status); T_free (certBer.data); T_free (pvtKeyBer.data); return status; } /* end RSA_GetCertAndPvtKey */ int RSA_PrintCertId (CERT_IDENTIFIER certId) { int status = 0; char *nameString = NULL; switch (certId.type) { case ISSUER_SERIAL: status = C_GetNameStringReverse (certId.id.issuerSerialNumber.issuerName, &nameString); if (status != 0) goto CLEANUP; RSA_PrintMessage ("Issuer = %s\n", nameString); RSA_PrintBuf ("Serial Number", certId.id.issuerSerialNumber.serialNumber.data, certId.id.issuerSerialNumber.serialNumber.len); break; default: status = RSA_DEMO_E_INVALID_PARAMETER; } CLEANUP: if (status != 0) RSA_PrintError ("RSA_PrintCertId", status); return status; } /* end PrintCertId */ int RSA_ChooseCertVersionPrompt (UINT2 *version) { int status = 0; RSA_DEMO_TABLE_ENTRY verTable[3]; RSA_DEMO_TABLE_ENTRY *choice = (RSA_DEMO_TABLE_ENTRY *)NULL_PTR; verTable[0].description = "Version 1"; verTable[0].val.value = CERT_VERSION_1; verTable[1].description = "Version 2"; verTable[1].val.value = CERT_VERSION_2; verTable[2].description = "Version 3"; verTable[2].val.value = CERT_VERSION_3; status = ChooseTableEntryPrompt (verTable, sizeof (verTable) / sizeof (RSA_DEMO_TABLE_ENTRY), &choice); if (status != 0) goto CLEANUP; *version = (UINT2)choice->val.value; CLEANUP: if (status != 0) RSA_PrintError ("RSA_ChooseCertVersionPrompt", status); return status; } /* end RSA_ChooseCertVersionPrompt */