Topic: [SOLVED] Verifying a Server's Certificate

Hi, I am in the process of evaluating WolfSSL for use in our products.  We are basically a client application that connects to many different servers(that we do not control).  I have hit a problem verifying a certificate(-188 error from wolf (No CA signer to verify with)).  This is verifiable through windows schannel and through an online cert checker.  I list the url and snipped from my code. Hopefully someone can tell me what is happening. 

The url is netconnectvar1.paymentech.net on port 443


in user_settings.h of the library added
#define DEBUG_WOLFSSL


#define NO_FILESYSTEM
#pragma message("No FIleSystem!")

///// my application ...
int MySend( WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
    CMyClient* p = (CMyClient*) ctx;
    return p->Send(buf,sz);
}

int MyRecv( WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
    CMyClient* p = (CMyClient*) ctx;
    return p->Receive(buf,sz);
}

void MyLogging(const int logLevel, const char *const logMessage)
{
    CString s = logMessage;
    TRACE("L->%d Msg->%s\n",logLevel,s.Left(256));
}
BYTE ROOT_CERTS_PEM[] =
//syamntec G4
//513fb9743870b73440418d30930699ff
"-----BEGIN CERTIFICATE-----\n"
"MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB\n"
"yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n"
"ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n"
"U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n"
"ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n"
"aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw\n"
"CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV\n"
"BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs\n"
"YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
"AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb\n"
"A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW\n"
"9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu\n"
"s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T\n"
"L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK\n"
"Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBYzCCAV8wEgYDVR0T\n"
"AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu\n"
"Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjAvBggrBgEFBQcBAQQjMCEw\n"
"HwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wawYDVR0gBGQwYjBgBgpg\n"
"hkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20v\n"
"Y3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMCkG\n"
"A1UdEQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0xLTUzNDAdBgNVHQ4E\n"
"FgQUX2DPYZBV34RDFIpgKrL1evRDGO8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnz\n"
"Qzn6Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBAF6UVkndji1l9cE2UbYD49qecxny\n"
"H1mrWH5sJgUs+oHXXCMXIiw3k/eG7IXmsKP9H+IyqEVv4dn7ua/ScKAyQmW/hP4W\n"
"Ko8/xabWo5N9Q+l0IZE1KPRj6S7t9/Vcf0uatSDpCr3gRRAMFJSaXaXjS5HoJJtG\n"
"QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t\n"
"TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY\n"
"Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc=\n"
"-----END CERTIFICATE-----\n"
//250ce8e030612e9f2b89f7054d7cf8fd
"-----BEGIN CERTIFICATE-----\n"
"MIIE0DCCBDmgAwIBAgIQJQzo4DBhLp8rifcFTXz4/TANBgkqhkiG9w0BAQUFADBf\n"
"MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT\n"
"LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw\n"
"HhcNMDYxMTA4MDAwMDAwWhcNMjExMTA3MjM1OTU5WjCByjELMAkGA1UEBhMCVVMx\n"
"FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz\n"
"dCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZv\n"
"ciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAz\n"
"IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEi\n"
"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8\n"
"RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs70Pb\n"
"ZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP6HBR\n"
"TdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/\n"
"Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNH\n"
"iDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMB\n"
"AAGjggGbMIIBlzAPBgNVHRMBAf8EBTADAQH/MDEGA1UdHwQqMCgwJqAkoCKGIGh0\n"
"dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA4GA1UdDwEB/wQEAwIBBjA9\n"
"BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVy\n"
"aXNpZ24uY29tL2NwczAdBgNVHQ4EFgQUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwbQYI\n"
"KwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQU\n"
"j+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29t\n"
"L3ZzbG9nby5naWYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v\n"
"b2NzcC52ZXJpc2lnbi5jb20wPgYDVR0lBDcwNQYIKwYBBQUHAwEGCCsGAQUFBwMC\n"
"BggrBgEFBQcDAwYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEBBQUA\n"
"A4GBABMC3fjohgDyWvj4IAxZiGIHzs73Tvm7WaGY5eE43U68ZhjTresY8g3JbT5K\n"
"lCDDPLq9ZVTGr0SzEK0saz6r1we2uIFjxfleLuUqZ87NMwwq14lWAyMfs77oOghZ\n"
"tOxFNfeKW/9mz1Cvxm1XjRl4t7mi0VfqH5pLr7rJjhJ+xr3/\n"
"-----END CERTIFICATE-----\n"
};

bool SendAuthWolf(const CString packet, const bool bIsDebit,const CString debitConfpacket)
{
    gPort = (443);
    gHost = ("netconnectvar1.paymentech.net");

    //int sockfd;
    WOLFSSL_CTX* ctx;
    WOLFSSL* ssl;
    wolfSSL_method_func method = NULL;
    wolfSSL_Init();
   
    wolfSSL_SetLoggingCb(MyLogging);
    wolfSSL_Debugging_ON();   

    CMyClient cl;
    if(!cl.ConnectToServer(gHost,gPort,10000) )
    {
        err_sys("Connect Failed");
    }


    method = wolfTLSv1_2_client_method_ex; /* use TLS v1.2 */

    /* make new ssl context */
    if ( (ctx = wolfSSL_CTX_new(method(NULL))) == NULL)
    {
          err_sys("wolfSSL_CTX_new error");
    }
   
   
    wolfSSL_SetIOSend(ctx,MySend);
    wolfSSL_SetIORecv(ctx,MyRecv);

    ssl = wolfSSL_new(ctx);
    if (ssl == NULL)
    {
        wolfSSL_CTX_free(ctx);
        err_sys("unable to get SSL object");
    }


    /* Add cert to ctx */
    int x =     wolfSSL_CTX_load_verify_buffer(ctx, ROOT_CERTS_PEM,sizeof ROOT_CERTS_PEM, WOLFSSL_FILETYPE_PEM);

if (x != WOLFSSL_SUCCESS)
{
    x = wolfSSL_get_error(ssl, 0);
    CString errStr;
    errStr.Format("%d",x);
    AfxMessageBox( errStr);
}

    /* Connect wolfssl to the socket, server, then send message */

    wolfSSL_SetIOWriteCtx(ssl,&cl);
    wolfSSL_SetIOReadCtx(ssl,&cl);


    int ret,err;

    ret = wolfSSL_connect(ssl);
    if (ret != WOLFSSL_SUCCESS)
    {
        err = wolfSSL_get_error(ssl, 0);
        CString errStr,temp = wc_GetErrorString(err);
        errStr.Format(_T("%s[%d]"),temp,err);
        AfxMessageBox( errStr);
    }
    char buffer[5000];
   
    #define CRLF "\r\n"   
    m_lastError = "Value Not Set";   

    CString payLoad = "TEST PAYLOAD GOES HERE";
    CString Packet =    "POST /interfaces/bp10emu HTTP/1.0"            CRLF;
    Packet +=            "Host: " + gHost; Packet +=                             CRLF;
    Packet +=            "Content-Type: application/x-www-form-urlencoded"    CRLF;
    CString content;
    content.Format("Content-Length: %d"CRLF,payLoad.GetLength());
    Packet +=            content;
    Packet +=            CRLF;
    Packet +=            payLoad;
    wolfSSL_write(ssl, Packet, Packet.GetLength());
    memset(buffer,'\0',sizeof buffer);
    int bytes = wolfSSL_read(ssl, buffer, sizeof buffer);
    if(bytes > 0)
    {
        printf("%s",buffer);
        m_strAuthResponse = buffer;
    }
    /* frees all data before client termination */
    wolfSSL_free(ssl);
    wolfSSL_CTX_free(ctx);
    wolfSSL_Cleanup();
    cl.CloseConnection();
    return 555 != 0;
}
Thanks in Advance,
Bob

Share

Re: [SOLVED] Verifying a Server's Certificate

Hi bob.carleone,

Great question! I did a quick check as I just suspected the wrong CA was being used, curiously though I keep getting a "Malformed buffer error" on the "server hello" message coming back from that server. It's the end of my work day unfortunately so I will get back on this first thing in the morning and let you know what I find. Thank you for your question!


Cheers,

Kaleb

Re: [SOLVED] Verifying a Server's Certificate

Hi bob.carleone,

OK so I was able to connect to that server with this certificate loaded in "wolfSSL_CTX_load_verify_buffer", could you try it out and let me know your results:

-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
-----END CERTIFICATE-----

Also could you tell me which version of wolfSSL you are working with? I ask because I tracked down the malformed buffer error I was getting the other day and it looks like we added some logic that may impact connecting to that server in our latest release. I want to make sure you have a release without this logic.

Warm Regards,

Kaleb

4 (edited by bob.carleone 2018-03-24 05:35:51)

Re: [SOLVED] Verifying a Server's Certificate

Kaleb, That worked perfectly, thanks so much!  This brings up another question.  Is there a easy, or not so easy, way of determining the root?  In this case it didn't seem apparent.  In checking different servers I have been iterating though the certificates they provide (other than the server's certificate itself) during the handshake and then trying to find those certificates by serial number and loading  them.   How should I determine the root? 
Thanks again!
Bob
p.s. I just downloaded the source a couple days ago, so it should be the latest release.  I am not at the office right now, I can get you the version on Monday if that's important.

Share

Re: [SOLVED] Verifying a Server's Certificate

Hi Bob,

If you just downloaded the source that tells me you are more than likely working with 3.14.0 but the issue is not affecting you with your current settings so that is good, no need to get me the version. I have already taken action to address the issue I found anyway.

Very happy to hear the cert worked for you. It's pretty simple to determine a root CA once you know what to look for. Are you familiar with the OpenSSL command line utility?

If you download a cert in DER format you can easily convert it to PEM with this command from a terminal:

openssl x509 -inform der -in cert.crt -outform pem -text > cert.pem

Or if you download a PEM formatted cert just do:

openssl x509 -inform PEM -in cert.pem -outform pem -text > cert-human.pem

The "-text" option tells openSSL to put human-readable information at the top of the PEM.

That human-readable information is where you track down the CA from. The first few lines will always be something like this:

  1 Certificate:                                                                     
  2     Data:                                                                        
  3         Version: 3 (0x2)                                                         
  4         Serial Number: 0 (0x0)                                                   
  5     Signature Algorithm: sha1WithRSAEncryption                                   
  6         Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
  7         Validity                                                                 
  8             Not Before: Jun 29 17:06:20 2004 GMT                                 
  9             Not After : Jun 29 17:06:20 2034 GMT                                 
 10         Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority

The lines I pay attention to in a case like yours are line 6 and line 10 in the above. The lines that specify the "Issuer" and the "Subject". You had all the right steps for finding the certs but what might not be so obvious is that a server is NOT required to send it's root CA since a client has to have a copy of that loaded anyway in order to verify the server. It's just extra memory the client has to allocate to receive it and then ends up with two copies of the same thing.

So if you connect to a server and get the top-most cert in the chain it sends just convert it using the OpenSSL command line tool and check the Subject and Issuer lines. If they are identical then you know you have a copy of the Root CA. If they are not identical then look at what is in the "Issuer" line. That is the cert that "Issued" the current cert you are looking at. Track that cert down and repeat the process until you find the top-level cert where the Issuer and Subject lines match. That is the true ROOT CA. Anything else is just an intermediate CA or an entity cert.

The server in question is a perfect example because the top-most cert in the chain that IT sent was: "VeriSign Class 3 Public Primary Certification Authority - G5" When I check the Subject Issuer lines for that cert I got:

  1 Certificate:                                                                     
  2     Data:                                                                        
  3         Version: 3 (0x2)                                                         
  4         Serial Number:                                                           
  5             25:0c:e8:e0:30:61:2e:9f:2b:89:f7:05:4d:7c:f8:fd                      
  6     Signature Algorithm: sha1WithRSAEncryption                                   
  7         Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
  8         Validity                                                                 
  9             Not Before: Nov  8 00:00:00 2006 GMT                                 
 10             Not After : Nov  7 23:59:59 2021 GMT                                 
 11         Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized     use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5

We can see in the above that line 7 and line 11 are NOT identical.
So since the issuer was "Class 3 Public Primary Certification Authority" I tracked that cert down and checked it. The result was:

  1 Certificate:                                                                     
  2     Data:                                                                        
  3         Version: 1 (0x0)                                                         
  4         Serial Number:                                                           
  5             70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf                      
  6     Signature Algorithm: md2WithRSAEncryption                                    
  7         Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
  8         Validity                                                                 
  9             Not Before: Jan 29 00:00:00 1996 GMT                                 
 10             Not After : Aug  1 23:59:59 2028 GMT                                 
 11         Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority

Since the Subject and Issuers match I now know I have found the True Root CA. That is the cert I sent you.

Cheers,

Kaleb

Re: [SOLVED] Verifying a Server's Certificate

Kaleb,
This is great.   Thanks so much for taking  the time to explain this!  We really appreciate the verbose response.
Thanks,
Bob

Share

Re: [SOLVED] Verifying a Server's Certificate

Bob,

It's my pleasure, glad we were able to be of assistance here.
Let us know if anything else comes up.

Warm Regards,

Kaleb