verify the clientcertificate on the server-side manually

We are using Schannel to implement tls communication between server and client. We have implemented the attached code, we are able to manually verify the server certificate on the client side, we are getting server certificate on client-side bu using
Status = QueryContextAttributes(&hContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext);
and we are able to very the certificate by passing the pRemoteCertContext to CertGetCertificateChain and followed by CertVerifyCertificateChainPolicy.
We have a requirement to verify the client certificate on the server-side manually. We tried different combinations of flags for schannelcred and fContextReq on the server and client-side. We failed with different errors like 0x80090302 returned by InitializeSecurityContext. If we succeed in the handshake we will fail at :
Status = QueryContextAttributes(&hContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext);
with 0x80090301 error code
For the detailed code please go through the links client and server
Client-side code
these falgs were passed to InitializeSecurityContextA for the handshake
dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY |
ISC_RET_EXTENDED_ERROR |
ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION |
ISC_REQ_MUTUAL_AUTH;;
We used the below method to get the certificate and create schannelcred on client side
cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM,
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
L"MY");
if(!cert_store) {
printf("\nschannel: Failed to open cert store last error is 0x%x", GetLastError());
}
client_cert = CertFindCertificateInStore(cert_store,
X509_ASN_ENCODING,
0,
CERT_FIND_HASH,
&blob,
NULL);
if(client_cert == NULL)
{
printf("\n\ncertificate not found");
return -1;
}
else
printf("\n\ncertificate found");
// Build Schannel credential structure. Currently, this sample only
// specifies the protocol to be used (and optionally the certificate,
// of course). Real applications may wish to specify other parameters as well.
ZeroMemory( &SchannelCred, sizeof(SchannelCred) );
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
if(client_cert)
{
SchannelCred.cCreds = 1;
SchannelCred.paCred = &client_cert;
}
SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
SchannelCred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE ;
above flags were set for the schannel cred structure
// Create an SSPI credential.
Status = AcquireCredentialsHandle(NULL, // Name of principal
UNISP_NAME, // Name of package
SECPKG_CRED_OUTBOUND, // Flags indicating use
NULL, // Pointer to logon ID
&SchannelCred, // Package specific data
NULL, // Pointer to GetKey() func
NULL, // Value to pass to GetKey()
phCreds, // (out) Cred Handle
&tsExpiry ); // (out) Lifetime (optional)
Server-side code:
below flags were passed to AcceptSecurityContext for the handshake
DWORD dwSSPIFlags =
ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM |
ASC_REQ_MUTUAL_AUTH;
We used the below method to get the certificate and create schannelcred on serverside
cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM,
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
L"MY");
if(!cert_store) {
printf("\nschannel: Failed to open cert store last error is 0x%x", GetLastError());
}
client_cert = CertFindCertificateInStore(cert_store,
X509_ASN_ENCODING,
0,
CERT_FIND_HASH,
&blob,
NULL);
if(client_cert == NULL)
{
printf("\n\ncertificate not found");
//return -1;
}
else
printf("\n\ncertificate found");
// Build Schannel credential structure. Currently, this sample only
// specifies the protocol to be used (and optionally the certificate,
// of course). Real applications may wish to specify other parameters as well.
ZeroMemory( &SchannelCred, sizeof(SchannelCred) );
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
if(client_cert)
{
SchannelCred.cCreds = 1;
SchannelCred.paCred = &client_cert;
}
SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
SchannelCred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE ;
// Create an SSPI credential.
Status = AcquireCredentialsHandle(NULL, // Name of principal
UNISP_NAME, // Name of package
SECPKG_CRED_OUTBOUND, // Flags indicating use
NULL, // Pointer to logon ID
&SchannelCred, // Package specific data
NULL, // Pointer to GetKey() func
NULL, // Value to pass to GetKey()
phCreds, // (out) Cred Handle
&tsExpiry ); // (out) Lifetime (optional)
With these flags set we are failing with 0x80090302 returned by InitializeSecurityContext.
For the detailed code please go through the links client and server
I'm sorry. Have you seen The SSL sample?
115353-new-text-document.txt
We used the commands in the text file attached to generate the self signed certificates.