OpenSSL TLS/DTLS PSK - ssl

I'm working on an application where Key Server (K) generates a symmetrical key and shares it with Server(A) and Client(B). A and B connects via UDP.
I'm using Memory BIOs, and was trying to use Cipher "PSK-AES128-CBC-SHA".
I have few questions related to this:
When we have a symmetrical key should we still call SSL_do_handshake ?
When I set the Cipher with this call SSL_CTX_set_cipher_list(context, "PSK-AES128-CBC-SHA"); I get an error SSL routines:ssl_cipher_list_to_bytes:no ciphers available
I tried using TLSV1_2_server_method, TLSV1_2_server_method, DTLS_server_method, DTLS_client_method but every method failed with the above error.
Is there any example code available for TLS-PSK encryption ? I couldn't find any good tutorial or example online.
I was referring to this article while doing this, but instead i'm using Memory BIOs
https://bitbucket.org/tiebingzhang/tls-psk-server-client-example/src/783092f802383421cfa1088b0e7b804b39d3cf7c/psk_server.c?at=default&fileviewer=file-view-default

I can't tell you why the cipher doesn't exist. I can only assume that it doesn't exist in the version of openssl that you have or it has to be added to openssl to begin with.
Did you know that PSK support is build into tls1.3? If you use openssl 1.1.1 you can do PSK from the openssl command line.
Server:
# use a 48 byte PSK
$ PSK=63ef2024b1de6417f856fab7005d38f6df70b6c5e97c220060e2ea122c4fdd054555827ab229457c366b2dd4817ff38b
$ openssl s_server -psk $PSK -cipher TLS13-AES-256-GCM-SHA384 -nocert -accept 2020
Client:
$ openssl s_client -psk $PSK -connect localhost:2020
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 195 bytes and written 475 bytes
Verification: OK
---
Reused, TLSv1.3, Cipher is TLS13-AES-256-GCM-SHA384
…
So I would recommend that you look up the source code for openssl 1.1.1 s_server and s_client commands to see a example of how to use PSK in tls1.3.

Related

unable to make tls1.2 connection via CLI

When I do openssl s_client -CApath ~/cacert.pem -crlf -connect getcomposer.org:443 -servername getcomposer.org I get the following output:
CONNECTED(00000003)
depth=1 C = US, O = Let's Encrypt, CN = R3
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/CN=getcomposer.org
i:/C=US/O=Let's Encrypt/CN=R3
1 s:/C=US/O=Let's Encrypt/CN=R3
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFTzCCBDegAwIBAgISA4wAKXUPtnZXoYnne5MGiWlHMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMTA5MzAxMDI5MDlaFw0yMTEyMjkxMDI5MDhaMBoxGDAWBgNVBAMT
D2dldGNvbXBvc2VyLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMSpt0JoJU7PJQYHYWV5FRTheIQSFi3SM/qyt2RDwKG4g7QssLjmsAXKQ5ZgGNc2
0JOaJ6NS3LgckijVOBOgBpywXTBJ0XOF6JJpjmuivdHXw0tssD+7BD+9Z30M9vCV
i5OU2dw6VmPi7M/J9haO+/ONuMpojmPTI2IKQl7w13y+AN+EqOVn5tWKgMpKxY9y
dydsbqgGffa7aSuN4Rc6UXZ4ix4mfSdjrAxFsKeOAmVh8NfQ49PoEpNAIce7ZQkF
hzq1AZmBtpe76LYrNEO55bPbg5Z9NPBReBpVG4tpLVWPUrarxdhCLD+F5b3s7Ko/
SzAWf/mX/K89Zdd3G8q52gECAwEAAaOCAnUwggJxMA4GA1UdDwEB/wQEAwIFoDAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV
HQ4EFgQU6Z7XW6cbc9xNki5IDKUmJEgZrJ8wHwYDVR0jBBgwFoAUFC6zF7dYVsuu
UAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8v
cjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9y
Zy8wQwYDVR0RBDwwOoISY2EuZ2V0Y29tcG9zZXIub3Jngg9nZXRjb21wb3Nlci5v
cmeCE3d3dy5nZXRjb21wb3Nlci5vcmcwTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYL
KwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwggEGBgorBgEEAdZ5AgQCBIH3BIH0APIAdwBc3EOS/uarRUSxXprUVuYQ
N/vV+kfcoXOUsl7m9scOygAAAXw2dyOHAAAEAwBIMEYCIQCOGcPZTl5eD4E03Ted
RabOF+lXzyXOPBT3xDtrIYmgxgIhAJAJJzdWzyzX8f6TdbIzGr7xQFhQAIHn/3+1
8ffWn/FjAHcAfT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8NcAAAF8Nncj
ywAABAMASDBGAiEA97oAvcGhneZl1n+meqzcb6OK5SJoUxYmdlz5LO15BpICIQCL
jrrvGdWMIV/ujHDMAvQ4QUn25GBjf6kps6d6SO6xADANBgkqhkiG9w0BAQsFAAOC
AQEAciXzEuFF5zwYpwv65AkhD1yYGvsqjRNCAe+AqvBVPEfqES/kCBCKeM5UDpAV
+TuJq7OQAGyUHbSAf0JK9DGTN0chTJVShaJEAXgIvnykolab/eNwpxrEOG5wTpRz
p5bJQfR+kVVIyjg0BknDQZMopH1MtWny8LT3jqhBV9eAFaaBh/X46liDACe2VmRv
/MHYGZtMtVnYIcm4iqPMZShMrWkPB7mO6PrUo0QzAUhMpb/KCRb/2XIf+H2I9zzJ
Y5MhKksA3NqDLFW3dD/KrnLKkqtKiOsUGgG1yDR9+S64lNS+IswcsodirXyrtbac
pZAfDeIuhhZ8uGqZhfcdC2OONw==
-----END CERTIFICATE-----
subject=/CN=getcomposer.org
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
---
SSL handshake has read 3183 bytes and written 455 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: 222874F43D8C5CD5C5EBCE9519D767FC0847D4BCE75261020AEDA2337E84CE87
Session-ID-ctx:
Master-Key: 4C7B19187830AF58A6D03B37163A5C2CEF3222F6BC048D569B122DF372DFCA4CB7FAA0103AAE0C87B5C008E0692C48AD
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1634183395
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
closed
I don't understand this error. I just got cacert.pem by doing wget --no-check-certificate -O ~/cacert.pem https://curl.se/ca/cacert.pem and doing vim ~cacert.pem verifies that the newly created file is non-empty.
Since the community seems to have accepted this as ontopic:
As I commented, to use in openssl commandline a 'bundle' file in the format supplied by https://curl.se/ca/cacert.pem you must use -CAfile not -CApath.
-CApath works instead with a directory containing a separate file for each cert named by its subject hash, as described in man 1 verify on older versions or man 1 openssl-verification-options on 3.0 also here on the web and which you can use c_rehash to help create if that is really wanted for some reason.
This is a stab in the dark, as I don't understand that openssl output much, but judging by the timing and the keywords 'openssl' and 'Lets Encrypt' this has a reasonably high chance of success.
On September 30, 2021 Let's Encrypt's old Root Certificate has expired. This had a major implication that now they have started to use their own root cert which should be trusted by most devices. 'Most' part was troublesome as there are some devices alive which did not receive updates in years. So the people at Let's Encrypt found a way to still remain supported/trusted on those devices, just under one condition - its openssl version must be 1.1.0+ (which is already 4+ years old). Another important detail is that this openssl version requirement also applies to systems that would have otherwise trusted LE's new cert.
So I've seen numerous people over October scrambling to get LE issued certificates to be trusted again by their systems and the answer was always as simple as: Get your openssl / libopenssl updated to v1.1.0+

openssl s_client Error: verify error:num=2:unable to get issuer certificate

I need to connect to some https://website.com. So, the site is available via VPN. I'm connected to the VPN and I can open the site in browser.
I've downloaded certificates from browser:
Then I cat both file into one certificate.pem
But when I'm trying to execute command
openssl s_client -connect website.com:443 -CAfile /path/to/certificate.pem
When I execute it in a terminal I have an error.
CONNECTED(00000003)
depth=1 /C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
verify error:num=2:unable to get issuer certificate
issuer= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
verify return:0
---
Certificate chain
0 s:/C=AU/ST=Wales/L=Place/O=Company
Ltd/OU=D&D/CN=website.com
i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/C=AU/ST=Wales/L=Place/O=Company
Ltd/OU=D&D/CN=website.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 2034 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES128-SHA
Session-ID: 1533BA958D51B9FEAE4C3534F4A417A5896ED17DCAAE83E89E6C2A7F615A583A
Session-ID-ctx:
Master-Key: 5CF D4ACA242B602AAFSDF1234X23E99BD4C62862888947FACFF0E7503BA34C2DD0EC193FA525204A539
Key-Arg : None
Start Time: 1509781851
Timeout : 300 (sec)
Verify return code: 0 (ok)
openssl historically and by default validates a certificate chain only if it ends at a root. Having the server aka end-entity or leaf cert in the truststore is useless, and the intermediate(s) should not be needed because RFCs require the server to send it(them), but your server is apparently defective or misconfigured because it does not. Thus for your server having the intermediate and root, but not the server cert, in the file used for -CAfile will work, assuming they are in PEM format.
Alternatively, recent (and supported) releases 1.0.2 and 1.1.0 add an option -partial_chain. If specified, this validates if the truststore has any anchor, not just a root. For your server, having either the server cert or the intermediate in the file used for -CAfile is sufficient, again in PEM format.
These cases are described on the man page for verify(1) which is referenced from the man page for s_client(1). Some systems may make the section 1ssl or similar, and if your system is not properly installed or is Windows, they are on the web here.
Remember that openssl historically and by default does not check the server name in the cert. 1.1.0 has new options -verify_name and -verify_hostname that do so. These are described on the man page for verify and referenced on that for s_client.
Also remember that many servers, though apparently not yours, now use Server Name Indication (SNI) extension to support multiple 'virtual' hosts with different certificates, and will either give a wrong cert or reject or fail the connection if SNI is missing. openssl s_client does not send SNI by default, but the option -servername does so; this is described on the man page. Update: OpenSSL 1.1.1 in 2018 s_client now does send SNI by default.
In general looking at the man pages for a program tells you useful information about how the program works and how to use it, and is recommended.
Especially since this is not a programming or development question, and really off-topic for StackOverflow; I would try to propose migration to SuperUser or ServerFault, but they already have numerous dupes.
This error means that openssl is looking for the issuer certificate with the subject "/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA" but it is not provided in the file /path/to/certificate.pem. Suggest to run "openssl x509 -in /path/to/certificate.pem -text" to see the subject of the certificate in this file - should be different from the requested one.

How to use id_prefix with OpenSSL s_server

I'm not sure what argument do I have to pass to switch -id_prefix for openssl s_server.
What I am trying to do is to run openssl s_server on one side, and openssl s_client on the other, and verify that Session-ID and Master-Key matches on both sides.
The problem is, that I only get to see the Session-ID and Master-Key on the client side. I'm not sure how to obtain them on the server side as well, so I can compare them.
id_prefix seems to be one option, but I don't see the prefix in the Session-ID on the client side.
Any ideas?
I can see how you can check the Master-Key using openssl s_server and openssl s_client, but not the Session-ID; I'm not sure why.
Here's what I did. First, I started a server running locally:
$ openssl s_server -accept 4433 -cert ./server.pem -tls1_2
Then, in a different terminal/window, I connected to that server:
$ openssl s_client -connect 127.0.0.1:4433 -debug
In the server terminal, I saw the SSL session started:
Using default temp DH parameters
ACCEPT
-----BEGIN SSL SESSION PARAMETERS-----
MFUCAQECAgMDBALAMAQABDDAOWXb47pESLXfWW1DYfaccOPGQcfgeaHW4sFP/avj
ejwVgvWNXGXy1vn6U3uLOeWhBgIEVqrm26IEAgIcIKQGBAQBAAAA
-----END SSL SESSION PARAMETERS-----
...
CIPHER is ECDHE-RSA-AES256-GCM-SHA384
Secure Renegotiation IS supported
The key thing thing to notice here is that base64-encoded data for the SSL session parameters. I copy and pasted that data into a separate file, e.g. sess.pem.
Then, I used openssl sess_id to decode that sess.pem file:
$ openssl sess_id -noout -text < ./sess.pem
SSL-Session:
Protocol : TLSv1.2
Cipher : C030
Session-ID:
Session-ID-ctx: 01000000
Master-Key: 9C921511052D3F212FF718704518FC526474D69FC26BC1165DBD203C6E221BB3A84686BC5D15A7BD9FA7BB72201A7276
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1454040610
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Compare that Master-Key value with the one that the openssl s_client terminal shows (note that it's important to use the -debug command-line option for openssl s_client to see this):
...
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 417D443BFD5702BEA974C5758FD65A0FC217B0FD9750C4CECF0915895C4E616D
Session-ID-ctx:
Master-Key: 9C921511052D3F212FF718704518FC526474D69FC26BC1165DBD203C6E221BB3A84686BC5D15A7BD9FA7BB72201A7276
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
....
So I'm not sure why the server output doesn't show the session ID generated, but you can at least use the above to compare the Master-Key values. I experimented with using both the -context and -id_prefix command-line options for openssl s_server, e.g.:
$ openssl s_server -accept 4433 -context FOO -id_prefix BAR ...
but it did not substantially change the data, nor did it cause the Session-ID to be displayed by openssl s_server.
Hope this helps!

SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol

I have a problem, i made a command "openssl s_client -connect server.server:143", and the error is:
CONNECTED(00000003)
140719622096768:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown proto col:s23_clnt.c:769:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 249 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
I made that because the horde connection gives an error in login.
How can i resolve this?
openssl s_client -connect server.server:143
Port 143 is plain IMAP, that is you can not talk directly TLS to this port. If you try it you will get some data back which are not TLS, and thus strange error messages will occure. If you want to have TLS you have to either use imaps (port 993) or issue a STARTTLS command. You can also use openssl for this with
openssl s_client -connect server:143 -starttls imap
From your output it might even be that you used this option but did not put it into your question (because 7 bytes from the server would match a TLS alert, but is unusually short for an IMAP greeting). If this is the case there might be lots of reasons why the connection fails and it is not possible to pin the problem down just from your description. If you get more help look at http://noxxi.de/howto/ssl-debugging.html#hdr2.2 on how you could narrow down the problem and what you should provide on information if you need help from others.

Problems getting a site's https certificates

I have an Android app that has some trouble with a site's certificate when connecting via https. As I'm experiencing trouble even when using a custom keystore with the certificates ("No peer certificate") I'm trying to get more information about the connection, handshake and certificates actually given by the server.
The version of openssl is follows:
$ openssl version
OpenSSL 1.0.1e 11 Feb 2013
When I just try to get info about the certificates I get this response:
$ openssl s_client -showcerts -connect [hostname]:443 </dev/null
CONNECTED(00000003)
3069977808:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:749:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 308 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
This is how Chrome describes the connection (sorry for the Norwegian text, but you get an idea of the connection and encryption type:
Based on the info from Chrome I've tried different commands to get the certificates, but they all seem to fail. My top candidate was this one:
$ openssl s_client -showcerts -connect [hostname]:443 -tls1_2 -cipher RC4-MD5
CONNECTED(00000003)
3069396176:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1258:SSL alert number 40
3069396176:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1414399499
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
Anyone got any hints based on the info given?
This might be an SNI issue, where the server has no default certificate defined for non-SNI clients. Android included a version of Apaches httpclient which is known to not support SNI and your openssl s_client command also does not use SNI.
Please try openssl s_client -servername hostname -connect ... to use SNI and see if this helps.