1

I am very new to programming with the OpenSSL API and have difficulties understanding how things work by just reading openssl's documentation (now, why can't I put as many links as I want in a post???).

I have followed OpenSSL Certificate Authority | Create the root pair and OpenSSL Certificate Authority | Sign server and client certificates to create keys and certificates and now I want my application to use the server private key and certificate in communication with clients. This is what I have so far (please feel free to comment on every little detail you think is wrong with this code).

SSL_library_init();
SSL_METHOD const * method = SSLv3_server_method();
if (!method)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}

SSL_CTX * ctx = SSL_CTX_new(method);
if (!ctx)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}
if (!SSL_CTX_use_certificate_chain_file(ctx, certificate_chain_file))
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) private_key_file_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);

if (SSL_CTX_use_PrivateKey_file(ctx, private_key_file, SSL_FILETYPE_PEM) != 1)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}

Now, at the call of SSL_CTX_use_PrivateKey_file it fails with the following error printout:

139649166755520:error:0B080074:lib(11):func(128):reason(116):x509_cmp.c:330:

I have downloaded the corresponding source code of OpenSSL and on line 330 of x509_cmp.c it says:

  X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);

When googling this I have seen people saying that this means that the password is incorrect, but it definitely is not (because when I do enter any other password I get another stack trace of errors). What could be the cause for this error?

jww
  • 97,681
  • 90
  • 411
  • 885
Joachim
  • 81
  • 1
  • 3
  • 9

3 Answers3

0

Now, at the call of SSL_CTX_use_PrivateKey_file it fails with the following error printout:

139649166755520:error:0B080074:lib(11):func(128):reason(116):x509_cmp.c:330:

You don't have a problem reading. That seems to be working fine.

The complete error string is:

$ openssl errstr 0x0B080074
error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch

The private key you provided does not pair with the public key in the server's certificate.

certificate_chain_file should be a concatenation of PEM encoded certificates and include (1) Intermediate Certificate signed by your Root CA, and (2) Server Certificate signed by Intermediate CA. private_key_file should be the private key to the server certificate; and not one of the CAs. For completeness, clients have to trust your Root CA, and its not sent in the chain.

For the "... concatenation of PEM encoded certificates...", see (for example) Adding an intermediate certificates to a pkcs12 file and Is it possible to include the private key in a .CER certificate file?


Programmatically read private key file ...

For completeness, here's how to read and write them in both ASN.1/DER and PEM format, but I don't believe its your problem: Use OpenSSL RSA key with .Net.

Don't let the .Net fool you. The answer is in C/C++, and it shows you how to inspect the binary ASN.1/DER encoded keys; and the Base64 PEM encoded keys with ----- BEGIN XXX----- and ----- END XXX-----.


SSL_METHOD const * method = SSLv3_server_method();

Related, this probably has room for improvement.

See the setup code at TLS Client on the OpenSSL wiki for some suggestions.


I have followed OpenSSL Certificate Authority | Create the root pair and OpenSSL Certificate Authority | Sign server and client certificates to create keys and certificates ...

Related, you might want to have a look at How do you sign Certificate Signing Request with your Certification Authority and How to create a self-signed certificate with openssl? It provides a lot of background information on X.509 server certificates, and where the various rules come from.


UPDATE (from comments):

"... the private key file and the certificate file that corresponds to the private key are completely separate files and when I give the private key file to the SSL_CTX_use_PrivateKey_file function I think it could not know about the certificate file"

You have to know which private key to use with the server's certificate. That is the private key you have to load. The root and intermediate certificates don't need a private key because you don't perform private key operations with them.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
0

I am a bit lost here I think - the private key file and the certificate file that corresponds to the private key are completely separate files and when I give the private key file to the SSL_CTX_use_PrivateKey_file function I think it could not know about the certificate file. And I know that the key for the private key file is the right one. When I do put the wrong password the following appears

139818423899840:error:06065064:lib(6):func(101):reason(100):evp_enc.c:539:
139818423899840:error:0906A065:lib(9):func(106):reason(101):pem_lib.c:483:
139818423899840:error:140B0009:lib(20):func(176):reason(9):ssl_rsa.c:669:

this translates to

$ openssl errstr 140B0009
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
$ openssl errstr 0906A065
error:0906A065:PEM routines:PEM_do_header:bad decrypt
$ openssl errstr 06065064
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

So it has to be something else, like some encryption stuff that I have not understood.

Joachim
  • 81
  • 1
  • 3
  • 9
  • I simply create my private key file like this: openssl genrsa -aes256 -out intermediate/private/mydomain.com.key.pem 2048 – Joachim Aug 13 '16 at 20:13
  • "mydomain.com.key.pem" can be seen as "private_key_file" in the example above – Joachim Aug 13 '16 at 20:25
  • The certificate chain file seems OK: $ openssl verify -CAfile certificate_chain_file private_key_file.cert.pem private_key_file.cert.pem: OK $ – Joachim Aug 13 '16 at 21:03
  • By the way - what check is being made in this SSL_CTX_use_PrivateKey_file? It says nothing about any check on https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_use_certificate.html, and also there is a SSL_CTX_check_private_key that seems to do verification against the certificate. – Joachim Aug 13 '16 at 21:37
  • *"... the private key file and the certificate file that corresponds to the private key are completely separate files and when I give the private key file to the SSL_CTX_use_PrivateKey_file function I think it could not know about the certificate file"* - you have to know which private key to use with the server's certificate. – jww Aug 13 '16 at 22:58
0

I am not sure if my question / explanation was too long since I got no answer. The short question now is:

When using the

SSL_CTX_use_PrivateKey_file

function; why do I get

139923876902592:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539:
139923876902592:error:0906A065:PEM routines:PEM_do_header:bad decrypt:pem_lib.c:483:
139923876902592:error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib:ssl_rsa.c:669:
ERROR: Failed to set private key file /home/jocke/ca/intermediate/private/xxx.key.pem. ERROR: 

when I give wrong password, and

39814590265024:error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch:x509_cmp.c:330:
ERROR: Failed to set private key file /home/jocke/ca/intermediate/private/xxx.key.pem. ERROR: 

when I give the right password?

OLD POST:


Sorry for the layout here, but the tool said something was code but not formatted as code, but I had no idea what it was so I will "code" everything.

Ok jww, I thought I did that. Let me show exactly what I am doing and explain why I think I am right (even though I am obviously not):

1) Generate root CA key / certificate

Directory setup

mkdir ~/ca/
cd ~/ca
mkdir certs crl newcerts private
chmod 700 private

The index.txt file is where the OpenSSL ca tool stores the certificate database. Do not delete or edit this file by hand. It should now contain a line that refers to the intermediate certificate.

touch index.txt
echo 1000 > serial

Create ~/ca/openssl.cnf like "Root CA configuration file" below, and make sure dir value is correct

openssl genrsa -aes256 -out private/ca.key.pem 4096
chmod 400 private/ca.key.pem

WARNING: Whenever you use the req tool, you must specify a configuration file to use with the -config option, otherwise OpenSSL will default to /etc/pki/tls/openssl.cnf. NOTE: Long expiry time, use 20 years (7300 days)

openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem

Verify certificate:

openssl x509 -noout -text -in certs/ca.cert.pem

ROOT CA PRIVATE KEY: ~/ca/private/ca.key.pem ROOT CA CERTIFICATE: ~/ca/certs/ca.cert.pem

2) Generate intermediate CA key / certificate

Directory setup

mkdir ~/ca/indermediate
cd ~/ca/indermediate
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > ~/ca/intermediate/crlnumber

Create ~/ca/intermediate/openssl.cnf like "Intermediate CA configuration file" below and make sure dir value is correct

cd ~/ca

Create intermediate CA private key:

openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096
chmod 400 intermediate/private/intermediate.key.pem

Create certificate signing request (CSR): (MAKE SURE TO SPECIFY THE INTERMEDIATE CA CONF FILE!)

cd ~/ca
openssl req -config intermediate/openssl.cnf -new -sha256 -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem

Create intermediate CA certificate by using the root certificate and the CSR: (MAKE SURE TO SPECIFY THE ROOT CA CONF FILE!!!) NOTE: Shorter expiry time, use 10 years (3650 days)

openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem
chmod 444 intermediate/certs/intermediate.cert.pem

Verify intermediate certificate:

openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem

INTERMEDIATE CA PRIVATE KEY: ~/ca/intermediate/private/intermediate.key.pem INTERMEDIATE CA CERTIFICATE: ~/ca/intermediate/certs/intermediate.cert.pem

3) Create certificate chain file

When an application (eg, a web browser) tries to verify a certificate signed by the intermediate CA, it must also verify the intermediate certificate against the root certificate. To complete the chain of trust, create a CA certificate chain to present to the application. To create the CA certificate chain, concatenate the intermediate and root certificates together. We will use this file later to verify certificates signed by the intermediate CA.

cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
chmod 444 intermediate/certs/ca-chain.cert.pem

CERTIFICATE CHAIN FILE: ~/ca/intermediate/certs/ca-chain.cert.pem

4) Sign server and client certificates

Sign certificates using the intermediate CA. Create a key:

cd ~/ca/
openssl genrsa -aes256 -out intermediate/private/myinternetaddr.key.pem 2048
chmod 400 intermediate/private/myinternetaddr.key.pem

Create a certificate signing request (CSR):

openssl req -config intermediate/openssl.cnf -key intermediate/private/myinternetaddr.key.pem -keyform PEM -new -sha256 -out intermediate/csr/myinternetaddr.csr.pem

Create server certificate:

openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/myinternetaddr.csr.pem -out intermediate/certs/myinternetaddr.cert.pem
chmod 444 intermediate/certs/myinternetaddr.cert.pem
cat index.txt

FOR THE WEBMASTERS: The following line is considered as "code" - why? The similar lines above are not. CLIENT PRIVATE KEY: ~/ca/intermediate/private/myinternetaddr.key.pem CLIENT CERTIFICATE SIGNING REQUEST: ~/ca/intermediate/csr/myinternetaddr.csr.pem CLIENT CERTIFICATE: ~/ca/intermediate/certs/myinternetaddr.cert.pem

Verify the certificate:

openssl x509 -noout -text -in intermediate/certs/myinternetaddr.cert.pem

Use the CA certificate chain file we created earlier (ca-chain.cert.pem) to verify that the new certificate has a valid chain of trust.

$ openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/myinternetaddr.cert.pem
intermediate/certs/myinternetaddr.cert.pem: OK

After this I then run the program, as below. As you can see I am using the certificate chain file (that is verified to have the server certificate - see bottom) with the corresponding private key file to the server certificate.

SSL_library_init();
SSL_METHOD const * method = SSLv3_server_method();
if (!method)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}

SSL_CTX * ctx = SSL_CTX_new(method);
if (!ctx)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}
if (!SSL_CTX_use_certificate_chain_file(ctx, "~/ca/intermediate/certs/ca-chain.cert.pem"))
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) private_key_file_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);

if (SSL_CTX_use_PrivateKey_file(ctx, "~/ca/intermediate/private/myinternetaddr.key.pem", SSL_FILETYPE_PEM) != 1)
{
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
}

The password callback:

static int pem_passwd_cb(char * buf, int size, int rwflag, void * userdata)
{
    char const * const password = (char const * const) userdata;
    Logger & logger = Logger::get_instance();
    logger << "Setting password to [" << password << "]";
    logger.log_info();
    strncpy(buf, (char *) password, size);
    buf[size - 1] = '\0';
    fprintf(stdout, "BUFLEN: %d\nBUF: [%s]\n", (int) strlen(buf), buf);
    return strlen(buf);
}

Now, when having done the following I thought everything should be ok.

$ openssl req -config intermediate/openssl.cnf -key intermediate/private/myinternetaddr.key.pem -new -sha256 -out intermediate/csr/myinternetaddr.csr.pem
Enter pass phrase for intermediate/private/myinternetaddr.key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:SE
State or Province Name [England]:Sweden
Locality Name []:NA
Organization Name [Alice Ltd]:NA
Organizational Unit Name []:NA
Common Name []:Jocke
Email Address []:yyy@hotmail.com
$ openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/myinternetaddr.csr.pem -out intermediate/certs/myinternetaddr.cert.pem
Using configuration from intermediate/openssl.cnf
Enter pass phrase for ~/ca/intermediate/private/intermediate.key.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 4098 (0x1002)
        Validity
            Not Before: Aug 13 20:58:46 2016 GMT
            Not After : Aug 23 20:58:46 2017 GMT
        Subject:
            countryName               = SE
            stateOrProvinceName       = Sweden
            localityName              = NA
            organizationName          = NA
            organizationalUnitName    = NA
            commonName                = Jocke
            emailAddress              = yyy@hotmail.com
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Cert Type: 
                SSL Server
            Netscape Comment: 
                OpenSSL Generated Server Certificate
            X509v3 Subject Key Identifier: 
                    D5:D6:F4:38:24:18:41:F7:F0:29:9F:99:6C:D3:08:38:CE:35:B8:43
                X509v3 Authority Key Identifier: 
                    keyid:2C:EB:99:69:BE:00:EE:C2:FD:86:B7:CF:6C:AD:47:4E:65:AA:90:5A
                    DirName:/C=SE/ST=Sweden/L=/O=Joachim Person/CN=Joachim Person/emailAddress=xxx@gmail.com
                    serial:10:00

                X509v3 Key Usage: critical
                    Digital Signature, Key Encipherment
                X509v3 Extended Key Usage: 
                    TLS Web Server Authentication
    Certificate is to be certified until Aug 23 20:58:46 2017 GMT (375 days)
    Sign the certificate? [y/n]:y


    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated

But apparently it is not - why?

Joachim
  • 81
  • 1
  • 3
  • 9