| RSA BSAFE Cert-C |
Certificate Components for C |
| Crypto-C 6.2.1 Developer's Guide | ||
| Search |
/* $Id: dbutil.c,v 1.8 2004/03/02 05:18:37 gsingh Exp $ */ /* dbutil.c ** Copyright (c) 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 useful in interfacing with database ** providers. */ #include "certc.h" #include "bsafe.h" #include "demoutil.h" #include "certutil.h" #include "crlutil.h" #include "keyutil.h" #include "dbutil.h" static int RSA_RsaPrivateToPublic (B_KEY_OBJ privateKey, B_KEY_OBJ *publicKey) { int status; A_PKCS_RSA_PRIVATE_KEY *privateKeyInfo; A_RSA_KEY publicKeyInfo; status = B_CreateKeyObject (publicKey); if (status != 0) goto CLEANUP; status = B_GetKeyInfo ((POINTER *)&privateKeyInfo, privateKey, KI_PKCS_RSAPrivate); if (status != 0) goto CLEANUP; publicKeyInfo.modulus.data = privateKeyInfo->modulus.data; publicKeyInfo.modulus.len = privateKeyInfo->modulus.len; publicKeyInfo.exponent.data = privateKeyInfo->publicExponent.data; publicKeyInfo.exponent.len = privateKeyInfo->publicExponent.len; status = B_SetKeyInfo (*publicKey, KI_RSAPublic, (POINTER)&publicKeyInfo); CLEANUP: if (status != 0) B_DestroyKeyObject (publicKey); return status; } /* end RSA_RsaPrivateToPublic */ static int TestDsaKeypair (CERTC_CTX ctx, B_KEY_OBJ privateKey, B_KEY_OBJ publicKey) { int status; B_ALGORITHM_OBJ signObj = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ verifyObj = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_OBJ randomObj; B_ALGORITHM_CHOOSER chooser; unsigned char dataToSign[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }; unsigned int dataToSignLen = sizeof (dataToSign); #define MAX_DSA_SIG_LEN 48 unsigned char signature[MAX_DSA_SIG_LEN]; unsigned int signatureLen; /* sign arbitrary data */ status = B_CreateAlgorithmObject (&signObj); if (status != 0) goto CLEANUP; status = B_SetAlgorithmInfo (signObj, AI_DSAWithSHA1, NULL_PTR); if (status != 0) goto CLEANUP; status = C_GetChooser (ctx, &chooser); if (status != 0) goto CLEANUP; status = B_SignInit (signObj, privateKey, chooser, NULL); if (status != 0) goto CLEANUP; status = B_SignUpdate (signObj, dataToSign, dataToSignLen, NULL); if (status != 0) goto CLEANUP; status = C_GetRandomObject (ctx, &randomObj); if (status != 0) goto CLEANUP; status = B_SignFinal (signObj, signature, &signatureLen, sizeof (signature), randomObj, NULL); if (status != 0) goto CLEANUP; /* verify signature to check keypair match */ status = B_CreateAlgorithmObject (&verifyObj); if (status != 0) goto CLEANUP; status = B_SetAlgorithmInfo (verifyObj, AI_DSAWithSHA1, NULL_PTR); if (status != 0) goto CLEANUP; status = B_VerifyInit (verifyObj, publicKey, chooser, NULL); if (status != 0) goto CLEANUP; status = B_VerifyUpdate (verifyObj, dataToSign, dataToSignLen, NULL); if (status != 0) goto CLEANUP; status = B_VerifyFinal (verifyObj, signature, signatureLen, NULL, NULL); CLEANUP: if (status != 0) RSA_PrintError ("TestDsaKeypair", status); B_DestroyAlgorithmObject (&signObj); B_DestroyAlgorithmObject (&verifyObj); return status; } /* end TestDsaKeypair */ static int RSA_DsaPrivateToPublic (CERTC_CTX ctx, B_KEY_OBJ privateKey, B_KEY_OBJ *publicKey) { int status; A_DSA_PUBLIC_KEY dsaPublicKeyInfo = {{0}}; A_DSA_PRIVATE_KEY *dsaPrivateInfo; B_KEY_OBJ tmpRsaPublic = (B_KEY_OBJ)NULL_PTR; A_RSA_KEY rsaPublicInfo; B_ALGORITHM_OBJ encryptObj = (B_ALGORITHM_OBJ)NULL_PTR; B_ALGORITHM_CHOOSER chooser; ITEM plaintext, ciphertext = {0}; unsigned int ciphertextMaxLen, outputLenUpdate, outputLenFinal; /* initialize our output argument first */ status = B_CreateKeyObject (publicKey); if (status != 0) goto CLEANUP; status = B_GetKeyInfo ((POINTER *)&dsaPrivateInfo, privateKey, KI_DSAPrivate); if (status != 0) goto CLEANUP; /* The DSA public value is y = g^x mod p, where g is the base, x is the private value, and p is the prime. Given g, x, and p, we can use an RSA encryption operation to derive y. Use g as the plaintext, x as the public exponent, and p as the modulus. */ status = B_CreateKeyObject (&tmpRsaPublic); if (status != 0) goto CLEANUP; rsaPublicInfo.modulus.data = dsaPrivateInfo->params.prime.data; rsaPublicInfo.modulus.len = dsaPrivateInfo->params.prime.len; rsaPublicInfo.exponent.data = dsaPrivateInfo->x.data; rsaPublicInfo.exponent.len = dsaPrivateInfo->x.len; status = B_SetKeyInfo (tmpRsaPublic, KI_RSAPublic, (POINTER)&rsaPublicInfo); if (status != 0) goto CLEANUP; status = B_CreateAlgorithmObject (&encryptObj); if (status != 0) goto CLEANUP; status = B_SetAlgorithmInfo (encryptObj, AI_RSAPublic, NULL_PTR); if (status != 0) goto CLEANUP; status = C_GetChooser (ctx, &chooser); if (status != 0) goto CLEANUP; status = B_EncryptInit (encryptObj, tmpRsaPublic, chooser, NULL); if (status != 0) goto CLEANUP; plaintext.data = dsaPrivateInfo->params.base.data; plaintext.len = dsaPrivateInfo->params.base.len; ciphertextMaxLen = plaintext.len; ciphertext.data = T_malloc (ciphertextMaxLen); if (ciphertext.data == NULL_PTR) { status = RSA_DEMO_E_ALLOC; goto CLEANUP; } status = B_EncryptUpdate (encryptObj, ciphertext.data, &outputLenUpdate, ciphertextMaxLen, plaintext.data, plaintext.len, NULL, NULL); if (status != 0) goto CLEANUP; status = B_EncryptFinal (encryptObj, ciphertext.data + outputLenUpdate, &outputLenFinal, ciphertextMaxLen - outputLenUpdate, NULL, NULL); if (status != 0) goto CLEANUP; ciphertext.len = outputLenUpdate + outputLenFinal; /* Now that we have derived the DSA public value, construct the public key */ dsaPublicKeyInfo.y.data = ciphertext.data; dsaPublicKeyInfo.y.len = ciphertext.len; dsaPublicKeyInfo.params.prime.data = dsaPrivateInfo->params.prime.data; dsaPublicKeyInfo.params.prime.len = dsaPrivateInfo->params.prime.len; dsaPublicKeyInfo.params.subPrime.data = dsaPrivateInfo->params.subPrime.data; dsaPublicKeyInfo.params.subPrime.len = dsaPrivateInfo->params.subPrime.len; dsaPublicKeyInfo.params.base.data = dsaPrivateInfo->params.base.data; dsaPublicKeyInfo.params.base.len = dsaPrivateInfo->params.base.len; status = B_SetKeyInfo (*publicKey, KI_DSAPublic, (POINTER)&dsaPublicKeyInfo); if (status != 0) goto CLEANUP; status = TestDsaKeypair (ctx, privateKey, *publicKey); CLEANUP: if (status != 0) B_DestroyKeyObject (publicKey); T_free (ciphertext.data); B_DestroyKeyObject (&tmpRsaPublic); B_DestroyAlgorithmObject (&encryptObj); return status; } /* end RSA_DsaPrivateToPublic */ int RSAUTIL_InsertPrivateKey (CERTC_CTX ctx, SERVICE db, B_KEY_OBJ privateKey) { int status; B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR; ITEM publicKeyBer = {0}; /* First, check if it's an RSA private key */ status = RSA_RsaPrivateToPublic (privateKey, &publicKey); if (status != 0) /* if not, maybe it's a DSA private key */ status = RSA_DsaPrivateToPublic (ctx, privateKey, &publicKey); if (status != 0) { /* some problem with derivation of public key info */ status = RSA_DEMO_E_NOT_IMPLEMENTED; goto CLEANUP; } status = RSA_GetKeyBer (RSA_DEMO_PUBLIC_KEY, publicKey, &publicKeyBer); if (status != 0) goto CLEANUP; status = C_InsertPrivateKeyBySPKI (db, &publicKeyBer, privateKey); CLEANUP: if (status != 0) RSA_PrintError ("RSA_InsertPrivateKey", status); T_free (publicKeyBer.data); B_DestroyKeyObject (&publicKey); return status; } /* end RSA_InsertPrivateKey */ int RSA_DumpDatabaseContents (CERTC_CTX ctx, char *dbName) { int status = 0; SERVICE db = (SERVICE)NULL_PTR; status = C_BindService (ctx, SPT_DATABASE, dbName, &db); if (status != 0) goto CLEANUP; status = RSA_DumpDatabaseServiceContents (db); CLEANUP: if (status != 0) RSA_PrintError ("RSA_DumpDatabaseContents", status); C_UnbindService (&db); return (status); } /* end RSA_DumpDatabaseContents */ static int DumpDatabaseCerts (SERVICE db) { int status = 0; 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_CreateListObject (&certList); if (status != 0) goto CLEANUP; /* 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 { RSA_PrintMessage ("Retrieving first cert...\n"); /* Retrieve all of the remaining certificates. When there are no more * certificates, the iterator will be set to NULL. */ for (;;) { status = C_SelectNextCert (&iterator, certList); if (iterator == NULL) { status = 0; break; } else if (status != 0) goto CLEANUP; RSA_PrintMessage ("Retrieving another cert from database...\n"); } } /* 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 corresponding private key.\n"); status = 0; } else if (status != 0) goto CLEANUP; else { RSA_PrintMessage ("Private key corresponding to certificate #%u:\n", i + 1); RSA_PrintPrivateKeyInfo (privateKey); RSA_PrintMessage ("***\n"); } B_DestroyKeyObject (&privateKey); } CLEANUP: if (status != 0) RSA_PrintError ("DumpDatabaseCertContents", status); B_DestroyKeyObject (&privateKey); C_DestroyListObject (&certList); C_FreeIterator (&iterator); return status; } /* end DumpDatabaseCerts */ static int DumpDatabaseCrls (SERVICE db) { int status = 0; LIST_OBJ crlList = (LIST_OBJ)NULL_PTR; DB_ITERATOR iterator = (DB_ITERATOR)NULL_PTR; RSA_PrintMessage ("\nChecking for CRLs...\n"); status = C_CreateListObject (&crlList); if (status != 0) goto CLEANUP; /* To walk through the certs in the database, we need to initialize an * iterator by first calling C_SelectFirstCRL(). Subsequent calls can * then be made to C_SelectNextCRL(). 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_SelectFirstCRL (db, &iterator, crlList); if (iterator == NULL) { RSA_PrintMessage ("Database empty.\n"); status = 0; } else if (status != 0) goto CLEANUP; else /* Retrieve all of the remaining CRLs. When there are no more * CRLs, the iterator will be set to NULL. */ for (;;) { RSA_PrintMessage ("Retrieving CRL...\n"); status = C_SelectNextCRL (&iterator, crlList); if (iterator == NULL) { status = 0; break; } else if (status != 0) goto CLEANUP; } /* Now that we have a list object filled with CRLs, print out some * information about each CRL. */ status = RSA_PrintCrlList (crlList); CLEANUP: if (status != 0) RSA_PrintError ("DumpDatabaseCrls", status); C_DestroyListObject (&crlList); C_FreeIterator (&iterator); return (status); } /* end DumpDatabaseCrls */ static int DumpDatabasePrivateKeys (SERVICE db) { int status = 0; unsigned int i; DB_ITERATOR iterator = (DB_ITERATOR)NULL_PTR; B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR; status = B_CreateKeyObject (&privateKey); if (status != 0) goto CLEANUP; status = C_SelectFirstPrivateKey (db, &iterator, privateKey); if (iterator == NULL) { RSA_PrintMessage ("No private keys in database.\n"); status = 0; } else if (status == 0) { RSA_PrintMessage ("\n***Private Key #%u:\n", 1); RSA_PrintPrivateKeyInfo (privateKey); /* Retrieve all of the remaining private keys. When there are no more * certificates, the iterator will be set to NULL. */ for (i = 2;; i++) { B_DestroyKeyObject (&privateKey); status = B_CreateKeyObject (&privateKey); if (status != 0) goto CLEANUP; status = C_SelectNextPrivateKey (&iterator, privateKey); if (iterator == NULL) { status = 0; break; } else if (status != 0) goto CLEANUP; RSA_PrintMessage ("\n***Private Key #%u:\n", i); RSA_PrintPrivateKeyInfo (privateKey); } } CLEANUP: if ( privateKey != (B_KEY_OBJ)NULL_PTR) { B_DestroyKeyObject (&privateKey); } if (status != 0) RSA_PrintError ("DumpDatabasePrivateKeys", status); C_FreeIterator (&iterator); return status; } /* end DumpDatabasePrivateKeys */ int RSA_DumpDatabaseServiceContents (SERVICE db) { int status = 0; status = DumpDatabaseCerts (db); if (status != 0) goto CLEANUP; status = DumpDatabaseCrls (db); if (status != 0) goto CLEANUP; status = DumpDatabasePrivateKeys (db); CLEANUP: if (status != 0) RSA_PrintError ("RSA_DumpDatabaseServiceContents", status); return status; } /* end RSA_DumpDatabaseServiceContents */