AcquireCredentialsHandle fails with SEC_E_ALGORITHM_MISMATCH RRS feed

  • Question

  • I'm creating an application that accepts TLS connections.  When I call AcquireCredentialsHandle it fails with SEC_E_ALGORITHM_MISMATCH.  I've tried several variations: loading the certificate via CertCreateCertificateContext, loading the certificate from a PKCS#12 file using CertOpenStore/CERT_STORE_PROV_PKCS12, and loading it from the system store using CertOpenStore/CERT_STORE_PROV_SYSTEM_A.  In each case the certificate loads fine, but AcquireCredentialsHandle  fails.  I have also tried providing an explicit algorithm list and permitting SSL3 and TLS1.X in the SCHANNEL_CRED structure.  All cases fail with SEC_E_ALGORITHM_MISMATCH.  I can verify the certificate works by accepting TLS connections with it using the .NET SslSocket class.

    How do I get a CredHandle for a certificate that I can use to accept TLS connections?

    Here's the C++ code I'm working with:

    #include <Windows.h>
    #define SECURITY_WIN32
    #include <Security.h>
    #include <schannel.h>
    #include <sspi.h> 
    #include <stdio.h>
    #include <stdlib.h>
    int main( int argc, char **argv ) {
        PCCERT_CONTEXT cert;
        HANDLE cert_file;
        DWORD size,read;
        BYTE *buffer;
        SECURITY_STATUS src;
        SCHANNEL_CRED scred;
        CredHandle cred;
        int rc;
        /* Load certificate from file */
        cert_file = CreateFile( argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
        if( cert_file == INVALID_HANDLE_VALUE )
            die("open certificate file");
        size = GetFileSize(cert_file, NULL);
        buffer = (BYTE*)malloc(size);
        if( buffer == NULL )
            die("allocate buffer");
        if( !ReadFile( cert_file, buffer, size, &read, NULL ) )
            die("read file");
        if( read != size )
            die("read entire file");
        cert = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, size );
        if( cert == NULL )
            die("create certificate context");
        /* Create the Credentials structure */
        scred.dwVersion = SCHANNEL_CRED_VERSION;
        scred.cCreds = 1;
        scred.paCred = &cert;
        scred.hRootStore = NULL;
        scred.cSupportedAlgs = 0;
        scred.palgSupportedAlgs = NULL;
        scred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER;
        scred.dwMinimumCipherStrength = 0;
        scred.dwMaximumCipherStrength = 0;
        scred.dwSessionLifespan = 0;
        scred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
        scred.dwCredFormat = 0;
        scred.cMappers = 0;
        scred.aphMappers = NULL;
        src = AcquireCredentialsHandle( NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &scred, NULL, NULL, &cred, NULL );
        if( src != SEC_E_OK )
            die("acquire credentials");
        /* ... SNIP socket code that never gets to run ... */

    Also, is there high-level documentation for the schannel & related APIs?  I've been working from the documentation of the APIs & Desktop Technologies on MSDN, but I feel that I'm missing some of the big picture.

    Previously posted http://forums.devshed.com/c-programming-42/tls-using-schannel-953943.html

    Monday, November 11, 2013 7:57 PM