I'm making a DTLS client-server program with openssl. The program works fine, but I can't find a way to get the cipher signature after SSL handshake.
By after SSL handshake, I mean in the client side, after:
if (SSL_connect(ssl) <= 0)
{
//error handling
}
In the server side, after:
do
{
ret = SSL_accept(ssl);
} while (ret == 0);
I can see the actual cipher signature is sha256WithRSAEncryption from the captured DTLS packets, but how to get this information from openssl?
Note that even though I'm using DTLS protocol, the code is almost the same as TLS/SSL.
Cipher algorithm used is stored in a certificate. So when you have a certificate (x509), the type of cipher algorithm can be extracted. Numeric version only:
X509_get_signature_type(client_cert)
To get human readable string, convert the return value of the previous function with this:
OBJ_nid2ln(X509_get_signature_type(client_cert))
Related
I am writing a simple TLS client/server program to securely communicate over the network. Initially I am building and running both the client and server on the same machine running RHEL 8.2.
First, I am using custom self signned ssl certificate and key for my programs. I have placed the rootCA.crt (my custom CA certificate in /root/CA/rootCA.crt). Also copied the rootCA.pem to /etc/pki/ca-trust/source/anchors/ and executed update-ca-trust enable then update-ca-trust extract to install the certificate to the system. (Not sure if I need to reboot the system for it to take effect.)
Initially, the client and server were able to communicate usint TLS untill I added the certificate validation part of the code on the client side.
Certificate Verification snippet:
ctx = SSL_CTX_new(method); /* Create new context */
if ( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ctx, 4);
const long flags = SSL_OP_NO_SSLv2 |
SSL_OP_NO_SSLv3 |
SSL_OP_NO_TLSv1 |
SSL_OP_NO_TLSv1_1 |
SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
if(SSL_CTX_load_verify_locations(ctx, NULL,
"/root/CA/") == 0){
ERR_print_errors_fp(stderr);
abort();
}
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if ( SSL_connect(ssl) == FAIL ) /* perform the connection */
ERR_print_errors_fp(stderr);
else
{
sprintf(acClientRequest, "%s", cpRequestMessage); /* construct reply */
printf("\n\nConnected with %s encryption\n", SSL_get_ciphe
}
when I run the server and client programs I see the following error messafe =>
Onclient:
140736372886336:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1915:
On Server:
140736022137664:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:ssl/record/rec_layer_s3.c:1543:SSL alert number 48
Not sure, what is going wrong with the certificate validation process. Can anyone suggest me how to fix this error?
Just copying your rootCA.crt file into /root/CA/ is not enough.
SSL_CTX_load_verify_locations explicitly states that the files in this directory have to use a specific format:
If CApath is not NULL, it points to a directory containing CA
certificates in PEM format. The files each contain one CA certificate.
The files are looked up by the CA subject name hash value, which must
hence be available. If more than one CA certificate with the same name
hash value exist, the extension must be different (e.g. 9d66eef0.0,
9d66eef0.1 etc). The search is performed in the ordering of the
extension number, regardless of other properties of the certificates.
Use the c_rehash utility to create the necessary links.
Therefore make sure your rootCa.crt is in PEM format. And then generate the required hash and rename it accordingly. The following command generates the hashvalue. Rename the file to <hashvalue>.0.
openssl x509 -inform PEM -subject_hash_old -in rootCa.crt | head -1
If your code then still does not work I would first test if your code works at all. For doing so change the server URL to a real server that sues an HTTPS certificate that is already trusted on your system.
I am beginner. I have problem when use SSL.
I find a code c on internet. in server code, have a follow function:
void ShowCerts(SSL* ssl)
{ X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
if ( cert != NULL )
{
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line);
X509_free(cert);
}
else
printf("No certificates.\n");
}
when I use command: openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem and run ./sslserver.o 443 and then i run ./client localhost 443. server error: "No certificates.". I think reason SSL_get_peer_certificate(ssl) return null but i don't know way to fix it. Can you help?
Full code: http://simplestcodings.blogspot.com/2010/08/secure-server-client-using-openssl-in-c.html
SSL_get_peer_certificates only returns a certificate on the server side if the client has send a certificate. But the code your refer to does not request a client certificate which means that the client will not send one. To request a client certificate the server would need to use SSL_CTX_set_verify and set the mode to at least SSL_VERIFY_PEER, i.e. at the minimum you need to do:
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
But this will only request an optional client certificate. It will not cause a validation of it. Note that the code example you use is broken in this regard anyway since it does not do any kind of certificate validation. This means it is open to trivial man in the middle attack, i.e. does not provide the security you expect when using SSL. Thus I recommend to not use this code as example on how to write secure SSL client and server.
I am trying to build an EAP-TLS client. I am using OpenSSL to build the TLS part of the data. Since EAP works on lower layers, I have used memory BIOs with OpenSSL to send information to Freeradius server using raw sockets. This is my code to generate client hello
ctx = SSL_CTX_new(TLSv1_client_method());
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
ssl = SSL_new(ctx);
rbio = BIO_new(BIO_s_mem());
wbio = BIO_new(BIO_s_mem());
SSL_set_bio(ssl, rbio, wbio);
SSL_set_connect_state(ssl);
SSL_do_handshake(ssl);
readbytes = BIO_read(wbio, buf, BUF_SIZ);
and this is what i tried to do to read the reply of the server into the same ssl:
BIO_write(rbio, temp, numbytes);
SSL_do_handshake(ssl);
readbytes = BIO_read(wbio, read, BUF_SIZ); // read is a buffer
however, when i try to send a packet using the data held in read, wireshark shows the packet as: Does anyone know why this is happening? Is this due to improper configuration of the RADIUS server? Or am I making a mistake in reading the data? According to what I read, SSL_do_handshake should be called till all the handshake steps are completed, so I dont think that there is a mistake there. Thanks a lot! Full packet sequence(use filter EAP) : http://www.filehosting.org/file/details/453553/eap-tls.pcapng
I'm using OpenSSL in order to encrypt some emails, that a piece of hardware sends. But, whenever I try to call SSL_connect(), I get :
SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
After sending "EHLO" and "STARTTLS" I call the following function:
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
void CreateTLSSession(int sockfd)
{
printf("///////////////creating TLS Session/////////////////////\n");
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL)
{
printf("failed to initialize context\n");
return;
}
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
ssl = SSL_new(ctx);
if (!SSL_set_fd(ssl, sockfd))
{
printf("failed to bind to socket fd\n");
return;
}
if (SSL_connect(ssl) < 1)
{
ERR_print_errors_fp(stdout);
fflush(stdout);
printf("SSL_connect failed\n");
return;
}
}
I've tried connecting to :
smtp.live.com : 587 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
smtp.live.com : 25 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol s23_clnt.c:787:
smtp.gmail.com : 587 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
smtp.gmail.com : 465 --> no response from server at all!
smtp.gmail.com : 25 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
I've tried different ports, since some similar questions on this SO suggested, that such error is usually related to using the wrong port for SSL.
Am I missing something here?
UPDATE:
All other methods (i.e. TLSv1_1_method(), SSLv3_method() ...) lead to SSL3_GET_RECORD:wrong version number
UPDATE:
I was able to observe the following on wireshark:
"EHLO"
"at your service"
"STARTTLS"
"Ready to starttls"
-->now I call the above function
unreadable request (encrypted)
unreadable reply (encrypted)
--> ERROR
SMTP servers on ports 587 and 25 are usually plain text and will switch to TLS only after the initial SMTP dialog and a STARTTLS command from the client. And trying SSL_connect on the plain text socket will fail.
Another way to solve this problem may be to run your C program under Scott Gifford's sslclient (see http://www.superscript.com/ucspi-ssl/sslclient.html). sslclient will spawn your program and open an tcp connection to the server, and pipe your program's stdout to the server, and pipe output from the server to your program's stdin. He has a patched version for TLS that will start the connection off in plain text, then once the two sides have agreed on STARTTLS, your program can signal to sslcient to enable SSL encryption on the connection by writing a command to a file descriptor for this purpose. The nice thing about doing it this way is that you can let sslclient to all the heavy lifting as far as setting up the sockets and ssl, etc., and you can focus on the core function of your program.
The underlying socked was non-blocking. The problem was solved, by using select and waiting till the TLS handshake completes.
I created a SSL socket in C between a client and a host using the OpenSSL library.
I need the AES key of a SSL session to encrypt correctly a message and I can't use the standard functions ssl_write and ssl_read.
I found that there is a struct called AES_KEY, but I don't know how I can found it!
SSL_write and SSL_read work correctly only with packet type: 23 ("Application protocol")
How can I decrypt, for example, an SSL Hello Message that come from server (i opened the SSL channel with this server)? How can I encrypt an SSL Hello Client (it's in clair) that comes from an other client?
I'm trying to demonstrate an attack during the phase of "TLS Renegotiation" of TLS Protocol. I'm trying to simulate an attack MITM with a custom proxy.
Now, the server send to proxy a certain number of encrypted messages of type 22 (Handshake) and 20 (ChangeCipherSpec). How can I read these messages and decrypt them? The standard library ssl_read works only with messages 23 (Application).
Moreover, the client send to proxy a client Hello and other messages of type 22 and 20. How can I write these messages and encrypt them? I tried using ssl_write, but the server doesn't understand these messages.
Instead of manually (en|de)crypting records, you should use SSL_CTX_set_info_callback to get at the information you want.
I found the solution. The functions are:
int ssl3_read_bytes (SSL *s, int type, unsigned char *buf, int len, int peek);
int ssl3_write_bytes (SSL *s, int type, const void *buf_, int len);