Topic: Generating my own certificates ... HowTo ?

OK, I'm new at this SSL/TLS stuff and am learning, I think.

So, using wolfSSL I have a client and server connecting. However, I'm using the 'example' certs that come with WolfSSL. I would like to learn how to generate my own certs. I'm pretty sure that even if you're using WolfSSL one needs to generate certs another way ... perhaps using openssl ? Is this correct?

For my server application I'm loading the following certs:

CyaSSL_CTX_load_verify_locations(ctx, "../../BRU-support/wolfssl/wolfssl-3.15.0/certs/ca-cert.pem",0)
CyaSSL_CTX_use_certificate_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-cert.pem"
CyaSSL_CTX_use_PrivateKey_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-key.pem"

My client also loads the first PEM that the server is loading. All seems to work just fine.

I did a search on certificates and come up with a few sites but none of them seems to put it all together for me. I left those site just as confused as when I entered...

If anyone can point me towards a site or book that can answer the following questions for me it would be greatly appreciated. Here's a few questions that I am seeking answers to:

1) Why does the server need to load 3 different PEM files ?
2) What is the relationship between those 3 PEM files?
3) What type of certs are those 3 PEM files?
4) How would I go about generating my own 3 PEM files using openssl or some other application?  For me to do this I think I need to know what type of PEM files they are ... ?

Unfortunately I don't see anything in the WolfSLL docs concerning this, so here I am.

Thats it for now. Any help appreciated.


Thanks, Jim

Share

2 (edited by Kaleb J. Himes 2018-11-13 10:37:45)

Re: Generating my own certificates ... HowTo ?

Hi jb3,

It would be my pleasure to provide some insight on these items!

1) Why does the server need to load 3 different PEM files ?
2) What is the relationship between those 3 PEM files?
3) What type of certs are those 3 PEM files?

The number three is not fixed! A server has two requirements to load:
1) An "entity certificate" and chain of trust
The "entity certificate" is used to identify the server to clients connecting to it, the cert that signed the "entity cert" (often times an intermediate CA), and all certs in the chain providing a complete chain of trust back to the ROOT CA. The server is NOT REQUIRED to load the ROOT CA because the client is expected to already have a copy in order to validate the server. Root CA's are provided by trusted entities such as GlobalSign, GoDaddy, LetsEncrypt, etc. When setting up a trust chain order does matter as each cert loaded must be able to validate the previously loaded cert in the chain with the only exception being the "entity cert". When loading a cert chain with wolfSSL_CTX_use_certificate_[file | buffer], the file or buffer must be organized with the "entity cert" first followed by the signer of the entity cert followed by the cert that signed that signer and so on up to the last cert in the trust chain. ONLY the Root CA is not required to be loaded but you can load the Root CA too if you wish, the Root CA is the only one that is optional and not required to be loaded.

2) The server must load a private key associated with the "entity certificate" ONLY. No other keys need to be loaded, just the one used when creating the entity certificate. Use wolfSSL_CTX_use_PrivateKey_[file | buffer] to load the private key.

(OPTIONAL ITEM) 3) If the server is validating clients that connect to it (99.9% of all servers do NOT do this) then the server will need to load the ROOT CA only** that ultimately signed the clients certificate chain. This is loaded with wolfSSL_CTX_load_verify_locations.

EXAMPLE:
If you go to https://www.google.com and look at the certificate chain for the website you will see three (again this is not a fixed number, just so happens to be 3 in this case) certificates. The top-most cert being "GlobalSign", the second cert being "Google Internet Authority G3" and the bottom most cert being the "Entity Cert" and it is "www.google.com". (See attached screen shot)

YOUR ITEMS:
So when you call CyaSSL_CTX_load_verify_locations(ctx, "../../BRU-support/wolfssl/wolfssl-3.15.0/certs/ca-cert.pem",0) you are loading the ca that signed the clients certificate chain. This means the server is doing mutual authentication. Again 99.9% of all servers do not do this, we have this as default in our example server because it is the most secure solution. However we are aware that it is not practical for servers such as google to load a cert unique to every phone, laptop, pc, tablet, smart TV, etc in the world that might connect to a google server.

When you call CyaSSL_CTX_use_certificate_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-cert.pem" you are loading the certificate that identifies the server and starts it's trust chain. The client will receive a copy of the certs in server-cert.pem (there are more than one in there) during the TLS handshake and use that chain to validate the server against any Root CA's the client has loaded to use for validating peers. (The client will be calling wolfSSL_CTX_load_verify_locations with ca-cert.pem which is the CA that signed the server-cert.pem chain)

Finally when you call CyaSSL_CTX_use_PrivateKey_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-key.pem" you are loading the private key used when creating the "entity cert" that is in server-cert.pem

4) How would I go about generating my own 3 PEM files using openssl or some other application?  For me to do this I think I need to know what type of PEM files they are ... ?

We have examples of using the openssl command line tool in the script <wolfssl-root>/certs/renewcerts.sh You can use those examples to generate your own keys and certs. Those certificates however will only be good for testing. Ultimately if you are looking to stand up your own valid website you will need to use openssl command line tool to create what is called a "certificate signing request" or CSR for short. You would then send that "CSR" to a trusted root provider such as GoDaddy, GlobalSign, LetsEncrypt, etc and they will use your CSR to generate a certificate for you and sign it using their trust chain. This way your website will be trusted by all common browsers (Chrome, IE, FireFox, Safari, etc).

Please let me know if you have any other questions on this subject or if you need clarification on any of my answer above.


Warm Regards,

- Kaleb


** There are cases where servers or clients that send trust chains do not send the entire chain of trust and the other side must then load all certs from the trust chain that were not sent during the connection in addition to the ROOT CA. For example:

If you have a chain for your server where "E" is the entity cert and "A" is the Root CA where A signed B signed C signed D signed E

(A->B->C->D->E)

Now lets assume the server is improperly setup and only loads C->D->E when calling wolfSSL_CTX_use_certificate_[file | buffer] and the client has only loaded "A" using wolfSSL_CTX_load_verify_locations. This connection would fail because the client ends up with a missing link in the chain:

(A->?->C->D->E)

In this scenario the client would have to load both certs "A" and "B" since the server is improperly not sending it's entire trust chain with the only exception being the Root CA.

Post's attachments

Screen Shot 2018-11-07 at 1.07.24 PM.png
Screen Shot 2018-11-07 at 1.07.24 PM.png 34.47 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

Re: Generating my own certificates ... HowTo ?

Thanks Kaleb. But there isn't a renew certs.sh script anywhere in my 3.15.0 distribution. In fact, the only file ending in .sh is this one: 

                ./valgrind-error.sh

Did you mean to inform me about some other file?


Thanks, Jim




Kaleb J. Himes wrote:

Hi jb3,

It would be my pleasure to provide some insight on these items!

1) Why does the server need to load 3 different PEM files ?
2) What is the relationship between those 3 PEM files?
3) What type of certs are those 3 PEM files?

The number three is not fixed! A server has two requirements to load:
1) An "entity certificate" and chain of trust
The "entity certificate" is used to identify the server to clients connecting to it, the cert that signed the "entity cert" (often times an intermediate CA), and all certs in the chain providing a complete chain of trust back to the ROOT CA. The server is NOT REQUIRED to load the ROOT CA because the client is expected to already have a copy in order to validate the server. Root CA's are provided by trusted entities such as GlobalSign, GoDaddy, LetsEncrypt, etc. When setting up a trust chain order does matter as each cert loaded must be able to validate the previously loaded cert in the chain with the only exception being the "entity cert". When loading a cert chain with wolfSSL_CTX_use_certificate_[file | buffer], the file or buffer must be organized with the "entity cert" first followed by the signer of the entity cert followed by the cert that signed that signer and so on up to the last cert in the trust chain. ONLY the Root CA is not required to be loaded but you can load the Root CA too if you wish, the Root CA is the only one that is optional and not required to be loaded.

2) The server must load a private key associated with the "entity certificate" ONLY. No other keys need to be loaded, just the one used when creating the entity certificate. Use wolfSSL_CTX_use_PrivateKey_[file | buffer] to load the private key.

(OPTIONAL ITEM) 3) If the server is validating clients that connect to it (99.9% of all servers do NOT do this) then the server will need to load the ROOT CA only** that ultimately signed the clients certificate chain. This is loaded with wolfSSL_CTX_load_verify_locations.

EXAMPLE:
If you go to https://www.google.com and look at the certificate chain for the website you will see three (again this is not a fixed number, just so happens to be 3 in this case) certificates. The top-most cert being "GlobalSign", the second cert being "Google Internet Authority G3" and the bottom most cert being the "Entity Cert" and it is "www.google.com". (See attached screen shot)

YOUR ITEMS:
So when you call CyaSSL_CTX_load_verify_locations(ctx, "../../BRU-support/wolfssl/wolfssl-3.15.0/certs/ca-cert.pem",0) you are loading the ca that signed the clients certificate chain. This means the server is doing mutual authentication. Again 99.9% of all servers do not do this, we have this as default in our example server because it is the most secure solution. However we are aware that it is not practical for servers such as google to load a cert unique to every phone, laptop, pc, tablet, smart TV, etc in the world that might connect to a google server.

When you call CyaSSL_CTX_use_certificate_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-cert.pem" you are loading the certificate that identifies the server and starts it's trust chain. The client will receive a copy of the certs in server-cert.pem (there are more than one in there) during the TLS handshake and use that chain to validate the server against any Root CA's the client has loaded to use for validating peers. (The client will be calling wolfSSL_CTX_load_verify_locations with ca-cert.pem which is the CA that signed the server-cert.pem chain)

Finally when you call CyaSSL_CTX_use_PrivateKey_file(ctx,"../../BRU-support/wolfssl/wolfssl-3.15.0/certs/server-key.pem" you are loading the private key used when creating the "entity cert" that is in server-cert.pem

4) How would I go about generating my own 3 PEM files using openssl or some other application?  For me to do this I think I need to know what type of PEM files they are ... ?

We have examples of using the openssl command line tool in the script <wolfssl-root>/certs/renewcerts.sh You can use those examples to generate your own keys and certs. Those certificates however will only be good for testing. Ultimately if you are looking to stand up your own valid website you will need to use openssl command line tool to create what is called a "certificate signing request" or CSR for short. You would then send that "CSR" to a trusted root provider such as GoDaddy, GlobalSign, LetsEncrypt, etc and they will use your CSR to generate a certificate for you and sign it using their trust chain. This way your website will be trusted by all common browsers (Chrome, IE, FireFox, Safari, etc).

Please let me know if you have any other questions on this subject or if you need clarification on any of my answer above.


Warm Regards,

- Kaleb


** There are cases where servers or clients that send trust chains do not send the entire chain of trust and the other side must then load all certs from the trust chain that were not sent during the connection in addition to the ROOT CA. For example:

If you have a chain for your server where "E" is the entity cert and "A" is the Root CA where A signed B signed C signed D signed E

(A->B->C->D->E)

Now lets assume the server is improperly setup and only loads C->D->E when calling wolfSSL_CTX_use_certificate_[file | buffer] and the client has only loaded "A" using wolfSSL_CTX_load_verify_locations. This connection would fail because the client ends up with a missing link in the chain:

(A->?->C->D->E)

In this scenario the client would have to load both certs "A" and "B" since the server is improperly not sending it's entire trust chain with the only exception being the Root CA.

Share

Re: Generating my own certificates ... HowTo ?

Would still love to see the renew certs.sh file that is supposedly in the WolfSSL distribution, but it's not in mine.

I would another site that gave some instructions on how to create a .pem file. I tried this as follows:

$ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

The result of this were 2 files: certificate.pem and key.pem.

I loaded both of these files in to WolfSSL as follows:

                /* Load CA certificates into CYASSL_CTX */
                if (CyaSSL_CTX_load_verify_locations(ctx,"./certificate.pem",0) !=
                    SSL_SUCCESS) {
                        fprintf(stderr, "Error loading cert2/certificate.pem, "
                        "please check the file.\n");
                        return -1;
                }

                /* Load server key into CYASSL_CTX */
                if (CyaSSL_CTX_use_PrivateKey_file(ctx,"./key.pem",
                        SSL_FILETYPE_PEM) != SSL_SUCCESS) {
                   fprintf(stderr, "Error loading cert2/key.pem, "
                       "please check the file.\n");
                   return -1;
                }

But I am getting an error back when I call CyaSSL_read() to read data over the network. So I go thought the following sequence to try and determine what happened:

            int err = wolfSSL_get_error(ssl, nbytes);

            char errorString[80];

            wolfSSL_ERR_error_string(err, errorString);

            // send back an internal error message, but we need to
            // get more detailed into from WolfSSL into a log file.
            cout << "WolfSSL Error: " << err << "  Error string: "
                << errorString << endl;

The output form the above error code is this:

                      WolfSSL Error: -308  Error string: error state on socket

I believe, obviously, there are differences in how I created my certificate as opposed to how the ca-cert.pem file that came with WolfSSL was created. Looking at the cert, I see the following differences, when  I analyze they with the following command:

$ openssl x509 -text -noout -in certificate.pem > certificate.txt

Do thi to both cert files, the one that comes with WolfSSL and the one I generated yields the following differences i the cert files ... yes, I've cut out a lot of the stuff that would obviously be different:

macbook: /Users/balson/sw/bru/server/cert2 > diff certificate.txt ../certs/ca-cert.txt
...

<                 keyid:0B:AE:B9:67:62:8E:0D:FE:4F:51:3E:DA:B2:B8:E9:7B:82:BA:B2:70
---
>                 keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
>                 DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
>                 serial:9A:41:47:CD:A1:14:62:8C

Ignoring the 'keyed' line, the only difference that stand out to me are the 2 lines from the cert that came with WolfSSL that start "DirName" and the line after that one that starts with "serial".

The cert that I generated has neither of these lines. I don't know if this would cause the problem with my test server application getting the error as I described above.

Any help appreciated.


Thanks, Jim

Share

Re: Generating my own certificates ... HowTo ?

@jb3,

If it is not in your distribution it is accessible at this link: https://github.com/wolfSSL/wolfssl/blob … ewcerts.sh

- K