unusual behavior in cryptExportCert

Ed Curren <[email protected]>
Newsgroups gmane.comp.encryption.cryptlib
Message-ID <[email protected]>
Hi Peter,
I am experiencing some unusual behavior when allocating buffer memory for receiving a certificate using cryptExportCert.  If you look in the generate_keypair function I create a buffer to receive the certificate using the returned certificate length from cryptlib with the following lines of code:

 result = cryptExportCert(NULL, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, certificate);
 char *buffer = new char[certLength];
 result = cryptExportCert(buffer, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, certificate);

If you then take a look in the make_cert function virtually the same lines of code are used, except this time rather than using the certificate length returned by cryptlib I use the buffer size I pass as the maximum size to cryptExportCert

result = cryptExportCert(NULL, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, cert);
char *buffer = new char[4096];
result = cryptExportCert(buffer, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, cert);

This is because when I use certLength the second call to cryptExportCert (the one with 'buffer' as the first argument) returns a -1.  I'm confused about when I need to use certLength and the maximum length.  The whole program is below.

Thanks Peter!
Ed

/*********  Code  **********/

#include <string>
#include <cryptlib.h>
 
using namespace std;
 
void create_ca(string caKeysFileName, string caKeyname, string caKeyPassword, string caDbName)
{
            int result;
 
            CRYPT_KEYSET caKeys;
            CRYPT_KEYSET caDb;
            CRYPT_CONTEXT context;
            CRYPT_CERTIFICATE certificate;
 
            result = cryptKeysetOpen(&caDb, CRYPT_UNUSED, CRYPT_KEYSET_ODBC_STORE, caDbName.c_str(), CRYPT_KEYOPT_CREATE);
            result = cryptKeysetOpen(&caKeys, CRYPT_UNUSED, CRYPT_KEYSET_FILE, caKeysFileName.c_str(), CRYPT_KEYOPT_CREATE);
            
            result = cryptCreateContext(&context, CRYPT_UNUSED, CRYPT_ALGO_RSA);
            result = cryptSetAttributeString(context, CRYPT_CTXINFO_LABEL, caKeyname.c_str(), caKeyname.length());
            result = cryptGenerateKey(context);
            result = cryptAddPrivateKey(caKeys, context, caKeyPassword.c_str());
            
            result = cryptCreateCert(&certificate, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE);
            result = cryptSetAttribute(certificate, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, context);
            result = cryptSetAttributeString(certificate, CRYPT_CERTINFO_COUNTRYNAME, "US", 2);
            result = cryptSetAttributeString(certificate, CRYPT_CERTINFO_COMMONNAME, "catest", 4);
            result = cryptSetAttribute(certificate, CRYPT_CERTINFO_SELFSIGNED, 1);
            result = cryptSetAttribute(certificate, CRYPT_CERTINFO_CA, 1);
            result = cryptSignCert(certificate, context);
            result = cryptAddPublicKey(caKeys, certificate);
 
            result = cryptKeysetClose(caKeys);
            result = cryptKeysetClose(caDb);
            result = cryptDestroyCert(certificate);
            result = cryptDestroyContext(context);
}
 
void generate_keypair(string keyPairFileName, string keyName, string keyPassword, string &certRequest)
{
            int result;
            int certLength;
 
            CRYPT_KEYSET keyset;
            CRYPT_CONTEXT context;
            CRYPT_CERTIFICATE certificate;
 
            result = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyPairFileName.c_str(), CRYPT_KEYOPT_CREATE);
            result = cryptCreateContext(&context, CRYPT_UNUSED, CRYPT_ALGO_RSA);
            result = cryptSetAttributeString(context, CRYPT_CTXINFO_LABEL, keyName.c_str(), keyName.length());
            result = cryptGenerateKey(context);
            result = cryptAddPrivateKey(keyset, context, keyPassword.c_str());
 
            result = cryptCreateCert(&certificate, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTREQUEST);
            result = cryptSetAttribute(certificate, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, context);
            result = cryptSetAttributeString(certificate, CRYPT_CERTINFO_COUNTRYNAME, "US", 2);
            result = cryptSetAttributeString(certificate, CRYPT_CERTINFO_COMMONNAME, "test", 4);
            result = cryptSignCert(certificate, context);
 
            result = cryptAddPublicKey(keyset, certificate);
 
            result = cryptExportCert(NULL, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, certificate);
            char *buffer = new char[certLength];
            result = cryptExportCert(buffer, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, certificate);
            
            certRequest.append(buffer, certLength);
 
            delete buffer;
 
            result = cryptKeysetClose(keyset);
            result = cryptDestroyContext(context);
            result = cryptDestroyCert(certificate);
}
 
void make_cert(string caOdbcName, string certRequest, string &newCert, string caKeyStoreName, string caKeyName, string caKeyPassword)
{
            int result;
            int certLength;
 
            CRYPT_CERTIFICATE certReq;
            CRYPT_CERTIFICATE cert;
            CRYPT_CONTEXT caPrivateKey;
            CRYPT_KEYSET odbc;
            CRYPT_KEYSET caKeys;
 
            result = cryptKeysetOpen(&odbc, CRYPT_UNUSED, CRYPT_KEYSET_ODBC_STORE, caOdbcName.c_str(),  CRYPT_KEYOPT_NONE);
            result = cryptKeysetOpen(&caKeys, CRYPT_UNUSED, CRYPT_KEYSET_FILE, caKeyStoreName.c_str(), CRYPT_KEYOPT_NONE);
 
            result = cryptGetPrivateKey(caKeys, &caPrivateKey, CRYPT_KEYID_NAME, caKeyName.c_str(), caKeyPassword.c_str());
 
            result = cryptImportCert(certRequest.c_str(), certRequest.length(), CRYPT_UNUSED, &certReq);
            result = cryptCAAddItem(odbc, certReq);
            result = cryptCACertManagement(&cert, CRYPT_CERTACTION_ISSUE_CERT, odbc, caPrivateKey, certReq);
 
            result = cryptExportCert(NULL, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, cert);
            char *buffer = new char[4096];
            result = cryptExportCert(buffer, 4096, &certLength, CRYPT_CERTFORMAT_CERTIFICATE, cert);
 
            newCert.append(buffer, certLength);
 
            delete buffer;
 
            result = cryptKeysetClose(odbc);
            result = cryptKeysetClose(caKeys);
            result = cryptDestroyCert(certReq);
            result = cryptDestroyCert(cert);
            result = cryptDestroyContext(caPrivateKey);
}
 
int main(int argc, char* argv[])
{
            int result;
 
            const string caKeyPairFileName = "CaKeys.p15";
            const string caKeyLabel = "CaKeys";
            const string caKeyStoreOdbcName = "CaKeyStore";
            const string caPrivateKeyPassword = "CaPassword";
 
            const string serverKeyPairFileName = "ServerKeys.p15";
            const string serverKeyLabel = "ServerKeys";
            const string serverPrivateKeyPassword = "ServerPassword";
 
            string certRequest;
            string issuedCert;
 
            result = cryptInit();
 
            create_ca(caKeyPairFileName, caKeyLabel, caPrivateKeyPassword, caKeyStoreOdbcName);       
            generate_keypair(serverKeyPairFileName, serverKeyLabel, serverPrivateKeyPassword, certRequest);
            make_cert(caKeyStoreOdbcName, certRequest, issuedCert, caKeyPairFileName, caKeyLabel, caPrivateKeyPassword);
            
            result = cryptEnd();
 
            return 0;
}

_______________________________________________
Cryptlib mailing list
[email protected] via Mail: [email protected]
Archive: ftp://ftp.franken.de/pub/crypt/cryptlib/archives/
http://news.gmane.org/gmane.comp.encryption.cryptlib
Posts from non-subscribed addresses are blocked to prevent spam, please
subscribe in order to post messages.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.