Check error code = 20: Failed to get local issuer certificate

I have a certificate chain on the server:

Certificate chain 0 s:/******/O=Foobar International BV/OU**** i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/**** 1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/**** i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5 i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority 

And my local CA root certificate:

  s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/**** i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5 

And I use this snippet to verify the certificate:

 //gcc -lssl -lcrypto -o certverify certverify.c #include <openssl/ssl.h> #include <openssl/asn1.h> #include <openssl/bio.h> #include <openssl/x509.h> #include <openssl/x509_vfy.h> #include <openssl/pem.h> #include <openssl/x509v3.h> #include <openssl/err.h> #include <openssl/conf.h> #include <string.h> int main() { const char ca_bundlestr[] = "./ca-bundle.pem"; const char cert_filestr[] = "./cert-file.pem"; BIO *certbio = NULL; BIO *outbio = NULL; X509 *error_cert = NULL; X509 *cert = NULL; X509_NAME *certsubject = NULL; X509_STORE *store = NULL; X509_STORE_CTX *vrfy_ctx = NULL; int ret; /* ---------------------------------------------------------- * * These function calls initialize openssl for correct work. * * ---------------------------------------------------------- */ OpenSSL_add_all_algorithms(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); /* ---------------------------------------------------------- * * Create the Input/Output BIO's. * * ---------------------------------------------------------- */ certbio = BIO_new(BIO_s_file()); outbio = BIO_new_fp(stdout, BIO_NOCLOSE); /* ---------------------------------------------------------- * * Initialize the global certificate validation store object. * * ---------------------------------------------------------- */ if (!(store=X509_STORE_new())) BIO_printf(outbio, "Error creating X509_STORE_CTX object\n"); /* ---------------------------------------------------------- * * Create the context structure for the validation operation. * * ---------------------------------------------------------- */ vrfy_ctx = X509_STORE_CTX_new(); /* ---------------------------------------------------------- * * Load the certificate and cacert chain from file (PEM). * * ---------------------------------------------------------- */ ret = BIO_read_filename(certbio, cert_filestr); if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) { BIO_printf(outbio, "Error loading cert into memory\n"); exit(-1); } ret = X509_STORE_load_locations(store, ca_bundlestr, NULL); if (ret != 1) BIO_printf(outbio, "Error loading CA cert or chain file\n"); /* ---------------------------------------------------------- * * Initialize the ctx structure for a verification operation: * * Set the trusted cert store, the unvalidated cert, and any * * potential certs that could be needed (here we set it NULL) * * ---------------------------------------------------------- */ X509_STORE_CTX_init(vrfy_ctx, store, cert, NULL); /* ---------------------------------------------------------- * * Check the complete cert chain can be build and validated. * * Returns 1 on success, 0 on verification failures, and -1 * * for trouble with the ctx object (ie missing certificate) * * ---------------------------------------------------------- */ ret = X509_verify_cert(vrfy_ctx); BIO_printf(outbio, "Verification return code: %d\n", ret); if(ret == 0 || ret == 1) BIO_printf(outbio, "Verification result text: %s\n", X509_verify_cert_error_string(vrfy_ctx->error)); /* ---------------------------------------------------------- * * The error handling below shows how to get failure details * * from the offending certificate. * * ---------------------------------------------------------- */ if(ret == 0) { /* get the offending certificate causing the failure */ error_cert = X509_STORE_CTX_get_current_cert(vrfy_ctx); certsubject = X509_NAME_new(); certsubject = X509_get_subject_name(error_cert); BIO_printf(outbio, "Verification failed cert:\n"); X509_NAME_print_ex(outbio, certsubject, 0, XN_FLAG_MULTILINE); BIO_printf(outbio, "\n"); } /* ---------------------------------------------------------- * * Free up all structures * * ---------------------------------------------------------- */ X509_STORE_CTX_free(vrfy_ctx); X509_STORE_free(store); X509_free(cert); BIO_free_all(certbio); BIO_free_all(outbio); exit(0); } 

But this code returns the following result:

 Verification return code: 0 Verification result text: unable to get issuer certificate Verification failed cert: countryName = US organizationName = Symantec Corporation organizationalUnitName = Symantec Trust Network commonName = Symantec Class 3 Secure Server CA - G4 

What is wrong here?

+3
source share
2 answers

Your root CA uses probably the same public key as the first intermediate CA in the chain (below the host certificate), and you probably don't have a root certification authority that can be used to trust the last certificate in the chain. Such installations are not very common, but actually occur. Unfortunately, OpenSSL has problems with this setting and will try to verify the longest chain, even if the shorter chain provides the trust you already need.

There is an error record in this OpenSSL problem, but none of the OpenSSL developers took care of this. You can also find the patch if you are looking for X509_V_FLAG_TRUSTED_FIRST . It seems that OpenSSL 1.0.2 (not yet released) will also have this option.

From my understanding, only OpenSSL has such a problem, that is, neither NSS (Firefox, Chrome on the desktop), nor SChannel (Microsoft).

+9
source

I think Steffen probably helped you solve this problem. But here a small thread that may have a side came up with the error you are experiencing and improved your safety.

const char ca_bundlestr [] = "./ca-bundle.pem";

You do not need a CA kit. You only need the Public Primary Certification Authority Verisign Class 3 (G5). You can get one CA certificate from Verisign in Using root certificates .

Improving your security position because you allow any CA to certify a server certificate (even the wrong ones), and not use the one that is known to certify a server certificate (Verisign).


And I use this snippet to verify the certificate ...

If you want to see an example of a simple TLS client, go to the SSL / TLS Client on the OpenSSL wiki. This is an example of fetching random numbers from random.org . It does not take a lot of work to change it to example.com .

Well notice . OpenSSL does not perform host name negotiation during validation. You still need to do this yourself if you are using OpenSSL 1.0.2, 1.0.1, 1.0.0 and smaller versions. OpenSSL provides hostname mapping in 1.1.0, but it is not yet available.

Sample code for extracting host names from Common Name (CN) and Subject Alt Names (SAN) in an X.509 certificate is provided in SSL / TLS , but you will need to provide the actual compliance code.


Based on the information in the comments, you need a certificate: "Symantec Class 3 Secure Server CA - G5". Below it is shown how it looks while ensuring the correct binding - it ends with Verify return code: 0 (ok) (and not with error 20).

A "Symantec Class 3 Secure Server CA - G5" is one that has a 4e b6 d5 78 49 9b 1c cf 5f 58 1e ad 56 be 3d 9b 67 44 a5 e5 . You can get it from Verisign Using root certificates .

The CAfile option used by s_client (below) is set inside s_client.c with an SSL_CTX_load_verify_locations call. Its set for one CA was supposed to certify a server certificate, not CA Zoo (i.e. cacerts.pem ).


You can check for alternative object names (SANs) in the certificate using $ openssl s_client -connect www.smartbabymonitor.ugrow.example.com:443 | openssl x509 -text -noout $ openssl s_client -connect www.smartbabymonitor.ugrow.example.com:443 | openssl x509 -text -noout . You will be fine because the host www.smartbabymonitor.ugrow.example.com is listed in the SAN. You can even add the -servername parameter to the command to use server name identification (SNI).


 $ openssl s_client -showcerts -connect www.smartbabymonitor.ugrow.example.com:443 -CAfile VeriSign-Class\ 3-Public-Primary-Certification-Authority-G5.pem CONNECTED(00000003) depth=3 C = US, O = "VeriSign, Inc.", OU = Class 3 Public Primary Certification Authority verify return:1 depth=2 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 verify return:1 depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 Secure Server CA - G4 verify return:1 depth=0 C = NL, ST = Netherlands, L = Eindhoven, O = Example International BV, OU = Consumer Lifestyle, CN = smartbabymonitor.ugrow.example.com verify return:1 --- Certificate chain 0 s:/C=NL/ST=Netherlands/L=Eindhoven/O=Example International BV/OU=Consumer Lifestyle/CN=smartbabymonitor.ugrow.example.com i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4 -----BEGIN CERTIFICATE----- MIIF+DCCBOCgAwIBAgIQa0fyuH2bp1ucngiNHVoV4jANBgkqhkiG9w0BAQsFADB+ MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd ... +eGxGqm8e1jgxB/fQePrh1vG4V40nr0cBKh6t52HmksBCfM0wOlMMJyUYiO0p44W s4nxNrvMJS6e4bwdECI0UNhJznWr0tAu+ilFoTsfOlQpngCBDJEkZYr3mRjpIjX8 Sz4+hGzIhZVyjDvbcVCrsvCpM67cU2rQpJ2nkYM4ol/z6VDRs/G5aPiXe7o= -----END CERTIFICATE----- 1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4 i:/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 -----BEGIN CERTIFICATE----- MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ... QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc= -----END CERTIFICATE----- 2 s:/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 i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority -----BEGIN CERTIFICATE----- MIIE0DCCBDmgAwIBAgIQJQzo4DBhLp8rifcFTXz4/TANBgkqhkiG9w0BAQUFADBf MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT ... A4GBABMC3fjohgDyWvj4IAxZiGIHzs73Tvm7WaGY5eE43U68ZhjTresY8g3JbT5K lCDDPLq9ZVTGr0SzEK0saz6r1we2uIFjxfleLuUqZ87NMwwq14lWAyMfs77oOghZ tOxFNfeKW/9mz1Cvxm1XjRl4t7mi0VfqH5pLr7rJjhJ+xr3/ -----END CERTIFICATE----- --- Server certificate subject=/C=NL/ST=Netherlands/L=Eindhoven/O=Example International BV/OU=Consumer Lifestyle/CN=smartbabymonitor.ugrow.example.com issuer=/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 Secure Server CA - G4 --- No client certificate CA names sent --- SSL handshake has read 4805 bytes and written 434 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: F1B9C9DFA3CFC6CB3F958FAD4ECBBAFA0E72EA8A86F6AC9601CF8204819DB0F0 Session-ID-ctx: Master-Key: EC4C5B32E60B5A0458BC85CC02529EA18DE61AFB8583D85D275C2822AC84E0E5E0C5B5E2C3C2D90F8B6E0EBB518EAA99 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 27 e0 fb b8 dd c9 9f 29-31 85 2b 6c d1 5a b3 d1 '......)1.+lZ. 0010 - 55 d6 e4 8a 4d f5 ef 2e-51 95 21 90 47 9d b6 0a U...M...Q.!.G... 0020 - df a5 d2 10 3d 03 e5 07-41 81 92 09 30 0e 08 3d ....=...A...0..= 0030 - fc ea 24 93 29 ed 60 9a-d0 d9 57 88 e4 4d 18 e3 ..$.).`...W..M.. 0040 - ba aa 97 ee bf 39 9e 5b-76 5b 76 f7 81 c4 03 08 .....9.[v[v..... 0050 - fb b9 a3 4f 11 b0 99 4c-8c f2 a6 8a 9a e4 fe c6 ...O...L........ 0060 - 0d 7b 6d a7 5b 53 b5 33-15 4f c4 ab 6b 29 7b 8f .{m.[S.3.O..k){. 0070 - ec 00 7f b2 6f 91 e4 ca-63 45 58 73 3a 78 8b 29 ....o...cEXs:x.) 0080 - 44 fc d5 e8 ad 4d dd 9c-22 df 50 eb d5 bf b9 90 D....M..".P..... 0090 - d8 6a 7d 6d bd 61 f2 63-07 75 8b d0 fc 40 64 76 .j} m.a.c.u...@dv 00a0 - 2b 97 53 aa 47 bc 3d d1-76 aa 8a 07 e1 60 14 d1 +.SG=.v....`.. 00b0 - f7 88 8f f6 d9 b9 6b 0c-64 96 b5 f0 46 73 27 d6 ......kd..Fs'. Start Time: 1419835334 Timeout : 300 (sec) Verify return code: 0 (ok) --- 
+2
source

All Articles