Skip to main content

If you don't have an IBM ID and password, register here.

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

Secure programming with the OpenSSL API, Part 3: Providing a secure service

OpenSSL adds the necessary power

Kenneth Ballard (kballard@kennethballard.com), Software Engineer, MediNotes Corp.
Kenneth is a Software Engineer working for the MediNotes Corp. in West Des Moines, Iowa. He graduated from Peru State College in Peru, Nebraska, with a Bachelor of Science in Business Administration. He also has an Associate of Science in Computer Programming from Southwestern Community College in Creston, Iowa. Kenneth has written several applications and programming libraries.

Summary:  Without secure server applications, the need for secure client applications is nonexistent. With OpenSSL, you can create secure server applications, and although the documentation makes it look intimidating, it's really not difficult. Learn how to build a secure server app by building on the concepts covered in Part 1 of this three-part series.

View more content in this series

Date:  27 Sep 2006
Level:  Intermediate

Comments:  

The first two parts of this series discuss creating client-side applications using OpenSSL. Part 1 discusses creating a basic secure client using OpenSSL, while Part 2 talks more in depth about digital certificates. After a few e-mails and some positive feedback from readers of these articles, it was clear that the next logical discussion should be about servers.

Servers provide a network and the Internet with access to resources such as files and devices. At times it is necessary to provide these services across a secure channel. OpenSSL lets you write services using both secure and open channels.

Creating a basic server application using OpenSSL is almost identical in nature to creating a basic client application. The differences are relatively few. One, obviously, is that the server will be set up to accept incoming connections instead of creating outgoing connections. And, as you might recall from the digital certificates discussion in Part 2 of this series, the server must also provide the security certificate used during the handshake.

Playing the waiting game

Servers pretty much just sit and wait for incoming connections. After all, that's what they're there for. Web servers wait for browsers to request pages, FTP servers wait for clients to request files, and chat servers wait for incoming chat client connections. They just wait.

There is very little difference between secure client and server communication, except that the server is the reverse side of the coin in terms of the handshake. Everything else is the same.

This makes writing a secure server application with OpenSSL a piece of cake, assuming you know how to write a client application with OpenSSL. (If you haven't already done so, please read Part 1 in the series, "Overview of the API," to learn how to set up the OpenSSL library.)


Two forms of identification, please

SSL context

To set up an SSL context for use with this article, use the following code. This function will return NULL on error:

SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());

Or, rather, two parts to the identification.

The server is responsible for providing the security certificate that will be used during the handshake. The complete server certificate consists of two parts: a public key and a private key. The public key is what is sent off to the client, while the private key is kept private.

Just as the trust certificates must be provided to the library for a client application, the server keys must be provided to the library for a server application. There are several functions that provide this:


Listing 1. Functions to load a server certificate
SSL_CTX_use_certificate(SSL_CTX *, X509 *)
SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);
SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);

The ASN1 variety of this function loads an ASN1-encoded digital certificate from the specified memory location into the SSL context. The first function loads an X.509 certificate provided in the given memory structure, while the last function, the _file one, loads a PEM-encoded digital certificate from a file. The type parameter of that function allows a DER-encoded certificate to be loaded.

To load the private key, use one of the following functions:


Listing 2. Functions for loading a private key
SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, long len);
SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len);
SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);


Some interaction required

Any private key is best stored encrypted. The trouble, though, is that the functions that load the certificates do not ask for a password for encrypted certificates. Instead, OpenSSL provides a callback mechanism for obtaining the password.

The format of the callback is:


Listing 3. Callback format
int password_callback(char *buf, int size, int rwflag, void *userdata);

For the purposes of this article, the final parameter, userdata, is not necessary. The buffer is allocated before this function is called, so you have no control over how large the buffer is.

Server private keys

Note that with server certificates, the private key should not be stored encrypted. Otherwise, an administrator would potentially have to enter the password quite often.

The parameter rwflag is the read/write flag. It is used so you can programmatically determine if the password is being used to encrypt information (rwflag = 1) or decrypt information (rwflag = 0). If the callback is being used to request a password for encrypting data, it is preferable to ask for the password twice, in some fashion, to catch any typos.

The password is only requested once when the certificate is loaded so that it can be decrypted and stored in memory. How the password is obtained from the user is entirely up to your implementation.

Once you have your password callback function created, you install it into the SSL context using SSL_CTX_set_default_passwd_cb as follows:


Listing 4. Installing the callback function
/* ctx is a pointer to a previously created SSL context, and cb is the pointer
 * to the callback function you created.
 */

SSL_CTX_set_default_passwd_cb(ctx, cb);


Putting the key in the ignition

Now that the callback function has been created so the user can be prompted for a password, the functions to actually import the certificates can be used. The certificate can be imported from an existing memory structure or a file.

To be more in line with common practice in handling digital certificates, such as that of the Apache HTTP Server Project, I'll demonstrate how to load a certificate from a file. If you've read Part 1 in this series, loading a certificate is similar to the way the trust store is loaded in the demonstration given in that earlier article.

I'll start with the public certificate, which is the one that gets sent to the client.


Listing 5. Loading the public certificate
/**
 * ctx is the SSL context created earlier
 */

if(SSL_CTX_use_certificate_file(ctx, "/path/to/certificate.pem", SSL_FILETYPE_PEM) < 1)
{
    /* Handle failed load here */
}

After the public certificate is loaded, the private certificate must be loaded. This part is needed during the handshake, because the client will be sending information to the server encrypted to the public certificate. That data can only be decrypted using the private key. Again, to keep things consistent, I'm loading the key from a file.


Listing 6. Loading the private key
if(SSL_CTX_use_PrivateKey_file(ctx, "/path/to/private.key", SSL_FILETYPE_PEM) < 1)
{
    /* Handle failed load here */
}


Finishing the setup

After setting up the context (see the SSL context sidebar, above) and loading the keys, now is the time to finish the setup by creating the BIO object. You may recall from Part 1 how I established both SSL and non-SSL communication using OpenSSL's BIO library. To be consistent with that article, the same will be done here.


Listing 7. BIO pointers
BIO *bio, *abio, *out;

Three BIO objects? Why do we need three? They all have a purpose, trust me. (Remember, trust and security go together.)

The first one, bio, is the main BIO object that will be created from the SSL context. The second object, abio, is the accept BIO, the one that will accept incoming connections. And the third BIO, out, is what the server will be talking through to the client.


Listing 8. Setting up the main BIO object
bio = BIO_new_ssl(ctx, 0);
if(bio == NULL)
{
    /* Handle failure here */
}

/* Here, ssl is an SSL* (see Part 1) */

BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

Setting up the BIO object here is a little different from setting it up for a client connection. You may recall from Part 1 that a client connection is set up using BIO_new_ssl_connect.

Here, the setup is done using BIO_new_ssl with two parameters: a pointer to an SSL_CTX object and a flag. This flag tells OpenSSL what kind of BIO object to create: 0 for server, 1 for client. Since this code is attempting to set up a client connection, the flag is set to 0.


Listing 9. Setting up the accept BIO
abio = BIO_new_accept("4422");
BIO_set_accept_bios(abio, bio);

Where BIO_do_connect creates a BIO for client connections, BIO_new_accept creates a BIO for server connections. It takes just one argument, the port to listen on encoded in a string.

Because this is supposed to be listening for secure connections, we need to chain a secure BIO onto this accept BIO. That is where the second function call, BIO_set_accept_bios, comes into play. It chains the previously created SSL BIO onto the accept BIO.

This function call also takes away the need to free the SSL BIO. It will be automatically freed when the accept BIO is destroyed.


Now to sit and wait

A server is fisherman of sorts; it just sits and waits until a client bites. Servers play the waiting game, just waiting for an incoming connection.

If you've had any experience with Winsock or BSD Sockets, you've probably come across the function accept. The OpenSSL counterpart is BIO_do_accept, except that where you could call accept once to have it sit and wait, you must call BIO_do_accept twice before it will sit and wait.


Listing 10. Telling the server to sit
/* First call to set up for accepting incoming connections... */

if(BIO_do_accept(abio) <= 0)
{
    /* Handle fail here */
}

/* Second call to actually wait */

if(BIO_do_accept(abio) <= 0)
{
    /* Handle fail here */
}

/* Any other call will cause it to wait automatically */

The first call to BIO_do_accept sets the BIO up to accept incoming connections. The second call is needed to actually get it to sit and wait. Any subsequent time after that will allow it to just wait.


Answering the incoming call

BIO_do_accept will return 1 when it receives an incoming connection. But you can't just talk through the accept BIO. Instead, OpenSSL creates another BIO that must be popped off of the accept BIO using BIO_pop.


Listing 11. Popping the connection to talk
out = BIO_pop(abio);

if(BIO_do_handshake(out) <= 0)
{
    /* Handle fail here */
}

After popping the incoming connection off the accept BIO, the handshake needs to be handled with a call to BIO_do_handshake. If the setup from the previous sections succeeded, then handshake should succeed as well.

The server would actually talk with the client through the various read and write functions available to the BIO library. I talked about those in Part 1, so you can find more discussion there.


Providing excellent service

Overall, creating a secure server application with OpenSSL is not difficult once you understand the basics of how it's done. From here, you can extend the code samples provided to create a full SSL server application to suit your needs. Be forewarned, however, that the code samples provided here and in the Downloads section below are minimal at best and should be used only for experimentation purposes. Before actually creating a full SSL server application, be sure to read and research the latest security recommendations.



Download

DescriptionNameSizeDownload method
Code samples for this articleopenssl3.tar.gz4KBHTTP

Information about download methods


Resources

Learn

Get products and technologies

  • Download the latest OpenSSL library and related documentation.

  • Order the SEK for Linux, a two-DVD set containing the latest IBM trial software for Linux from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

  • With IBM trial software, available for download directly from developerWorks, build your next development project on Linux.

Discuss

About the author

Kenneth is a Software Engineer working for the MediNotes Corp. in West Des Moines, Iowa. He graduated from Peru State College in Peru, Nebraska, with a Bachelor of Science in Business Administration. He also has an Associate of Science in Computer Programming from Southwestern Community College in Creston, Iowa. Kenneth has written several applications and programming libraries.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in

If you don't have an IBM ID and password, register here.


Forgot your IBM ID?


Forgot your password?
Change your password


By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)


By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux, Open source
ArticleID=163942
ArticleTitle=Secure programming with the OpenSSL API, Part 3: Providing a secure service
publish-date=09272006
author1-email=kballard@kennethballard.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).