You should be able to install with
$ ./configure
$ make
$ make install
Programs using the ezs api must include
#include "ezs.h"
and link with at least these libraries (On linux at least you must specify the pthread library)
-lezs -lssl -lcrypto -lpthread
I have had success on AIX with CC=cc_r.
The windows distribution contains libraries compiled
for threaded debug and non-debug applications (MD, MDd).
It is built for version 0.9.8b of
OpenSSL for Windows.
Programs using the windows api must include
#include "ezs.h"
and link with one the correct library:
ezsMD.lib or
ezsMDd.lib.
The library provides procedure APIs that allow
clients and servers to connect, authenticate, and communicate.
When a procedure returns an error indication,
you may retrieve the error code or error code and a text
description. Individual error codes are maintained for
each connection (EZS). A global error code is
maintained for 'unconnected' functions.
Local system errors are indicated by a negative error code:
the negative of the system's errno.
If all else fails, setting the external variable
ezs_debug to one causes the library to print
debug output to stderr.
Description: | Get the last error code
|
Syntax: | int ezs_errno(EZS* E) |
Arguments: |
|
Return: | the error code
|
Errors: |
|
Notes: |
- If E is NULL the global error is returned.
|
Description: | Get the last error code and message
|
Syntax: | int *ezs_geterror(EZS* E, char** txt) |
Arguments: |
E: | An EZS structure |
txt: | Pointer to a character pointer to receive the error text. |
|
Return: | the error code
|
Errors: |
|
Notes: |
- If E is NULL the global error is returned.
- txt may be NULL. In which case no text is returned.
- Caller is responsible for freeing the error text.
- The error text includes a description of any SSL errors.
- SSL errors are cleared as they are retrieved, so this
call may be made only once per error.
|
SSL requires initialization for its thread mutexes
and its random number seed. You should provide
a read/write file for the random seed. You can
rewrite this file before exiting to update
its 'randomness'.
Usual sequence is
ezs_init(name);
ezs_load_rand_file(filename);
at the start of your program, and
ezs_save_rand_file(filename);
at the end.
Description: | Initializes the openssl and ezs libraries.
|
Syntax: | void *ezs_init(char* name) |
Arguments: |
name: | session name, may be NULL |
|
Return: | 1 (always success)
|
Errors: |
|
Notes: |
- This must be called prior to any thread
or openssl calls by the program.
- The first call to ezs_new will invoke ezs_init with a NULL name
if the caller has not already called ezs_init.
- Servers can use name to identify SSL sessions.
A NULL value deactivates sessions.
- The argument is ignored for clients.
|
Description: | Adds data from the file to SSL's 'randomness'.
|
Syntax: | void *ezs_load_rand_file(char* filename) |
Arguments: |
filename: | read/write file of random data |
|
Return: | 1
|
Errors: |
|
Notes: |
- This should be called prior to any SSL operation.
- You may call this more than once, with different filenames.
- This is implemented as a macro
|
Description: | Writes random data to the file.
|
Syntax: | void *ezs_save_rand_file(char* filename) |
Arguments: |
filename: | read/write file of random data |
|
Return: | 1
|
Errors: |
|
Notes: |
- This should be called just before your program exits
to update the random seed file, but it can be called any time.
- This is implemented as a macro
|
Description: | Allocates a new ezs struct, which will identify
a particular connection.
|
Syntax: | EZS *ezs_new() |
Arguments: |
|
Return: | Pointer to an EZS structure
|
Errors: |
|
Notes: |
- Initializes the library if ezs_init has not been called.
|
Description: | Frees an ezs struct.
|
Syntax: | void *ezs_free(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
|
There are several credentials involved in a secure ezs connection:
The authenticating certificate and key consists of a single certificate
and key pair that you are using to authenticate to your peer on the
connection. Your certificate must have been signed by a CA who is trusted
by the peer. Use
ezs_add_cert to
add certificates and keys to the list of certificates
you can use to authenticate to a peer.
Generally if a key file is not specified the key is assumed to
be in the same file as the certificate.
A CA certificate is the public certificate
of a Certificate Authority (CA) whose signatures you will accept.
Use
ezs_add_ca
to add certificates to the list of acceptable CAs.
A Certificate Revocation List (CRL) identifies certificates
that have been revoked by their CA and are no longer valid.
Use
ezs_add_ca
or
ezs_add_crl
to add to your list of CRLs.
Description: | Add one or more CAs to your list of acceptable CAs.
|
Syntax: | int ezs_add_ca(char* ca_file) |
Arguments: |
ca_file: | Contains the CA certificates to add (PEM) |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | invalid CA file |
|
Notes: |
- The certificates
will be added to the list of acceptable signers
of peer certificates.
- Must be PEM format
- If the file also contains CRLs they will
automatically be added to the CRL list.
|
Description: | Adds one or more CRLs to your list of CRLs.
|
Syntax: | int ezs_add_crl(char* crl_file) |
Arguments: |
crl_file: | Contains the CRLs to add |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | invalid CRL file |
|
Notes: |
- The CRLs will be added to the list of CRLs used to verify certificates.
- Must be PEM format
- You can use ezs_add_crl at any time
to load new CRLs or to refresh existing CRLs.
Changes will take effect on the next connect or accept.
Existing connections will be unaffected.
|
Description: | Adds a certificate to the list of available
certificates for authentication to peers.
|
Syntax: | int ezs_add_cert(char* crt, char* key, char** cn) |
Arguments: |
crt: | Certificate file (PEM) |
key: | Key file (PEM) |
cn: | If specified, returns the cert's cn. |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | invalid cert or key |
|
Notes: |
- If key is NULL the certificate's key will be looked for
in the crt file.
|
Description: | Sets the option to verify the server hostname vs. common name.
|
Syntax: | void ezs_set_verify(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- Normally a client or server may choose one of many
certificates for any given connection. This option
requires that the CN of the certificate match the hostname.
- This is implemented as a macro
|
Description: | Returns the CN of the connected peer's certificate
|
Syntax: | char ezs_get_peer_cn(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- The returned value is a pointer into the EZS
structure. DO NOT free it.
- This is implemented as a macro
|
SSL allows the connecting peer to record a session identifier, essentually
the private key used for encryption of data, and use that
saved identifier to facilitate subsequent sessions. This bypasses
the comparitively long public-key negotiation typical
of SSL. Session identifier lifetime is normally five minutes.
Server sessions are activated by a non-NULL session name
given to
ezs_init or by the
ezs_set_session_name function.
A NULL session name disables sessions for subsequent accpeted connections.
Sessions on the server each consume about 12K bytes of memory, and
can accumulate rapidly on busy servers. The expire after about
five minutes and are automatically purged.
Clients can save and reuse a session -- thereby saving
negotiating overhead on subsequent connections.
Description: | Set the server's session name or deactivate sessions
|
Syntax: | void ezs_set_session_name(char* name) |
Arguments: |
name: | name to use for subsequent accepted connections |
|
Return: | |
Errors: |
|
Notes: |
- If name is NULL sessions are deactivated.
|
Description: | Retrieve the session identifier associated with the
current connection
|
Syntax: | char *ezs_get_session(EZS* E) |
Arguments: |
|
Return: | A session identifier
|
Errors: |
EZS_ERR_NO_CONNECTION: | No session exists |
|
Notes: |
- The session identifier is a null-terminated character string.
- ezs_get_session must be called after the
connection is opened.
|
Description: | Specifies a session identifier to be used for the next connection.
|
Syntax: | int *ezs_set_session(EZS* E, char* session) |
Arguments: |
E: | An EZS structure |
session: | A session identifier. |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | invalid session |
|
Notes: |
- The session identifier is a null-terminated character string.
|
Connections are not symmetric. Servers generally wait
for connection requests from clients.
The library provides connection tools to perform both
the IP connect, or accept, and the SSL negotiation
or just the negotiation step.
If you want to use non-blocking IO, set the non-blocking
flag and timeout parameter prior to connecting to a server
or accepting client connections. In non-blocking mode
any operation may return an EZS_ERR_WOULDBLOCK error.
The blocked operation may be retried.
Description: | Sets blocking IO for this connection
|
Syntax: | int *ezs_use_blocking_io(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- This is the default mode
- This is implemented as a macro
|
Description: | Sets non-blocking IO for this connection
|
Syntax: | int *ezs_use_nonblocking_io(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- This is implemented as a macro
|
Description: | Sets semi-blocking timeout for this connection
|
Syntax: | int *ezs_set_timeout(EZS* E, int timeout) |
Arguments: |
E: | An EZS structure |
timeout: | seconds to block before reporting a wouldblock error. |
|
Return: | |
Errors: |
|
Notes: |
- This is implemented as a macro
|
Description: | Allow connections using SSLv2 protocol
|
Syntax: | void ezs_allow_v2(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- By default the library does not allow SSLv2.
- This is implemented as a macro
|
Description: | Allow connections using v3 protocol
|
Syntax: | void ezs_allow_v3(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- By default the library allows SSLv3.
- This is implemented as a macro
|
Description: | Deny use of the SSLv2 protocol
|
Syntax: | void ezs_deny_v2(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- By default the library does not allow SSLv2.
- This is implemented as a macro
|
Description: | Deny use of the SSLv3 protocol
|
Syntax: | void ezs_deny_v3(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
- By default the library allows SSLv3.
- This is implemented as a macro
|
Description: | Client connect and authenticate to a server
|
Syntax: | int ezs_connect(EZS* E, char* service, char* cn) |
Arguments: |
E: | An EZS structure |
service: | The service address: (host:port). |
cn: | CN of the certificate to use for authentication |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_NOCRT: | cert (cn) not loaded |
EZS_ERR_BADCRT: | cert invalid |
EZS_ERR_BADKEY: | key invalid |
EZS_ERR_SSL: | connection failure |
|
Notes: |
- The 'cn' must have been previously loaded with
ezs_add_cert.
- On success the connection will be open and verified.
- You can find the peer's cn with ezs_get_peer_cn.
- If you choose not to retry a WOULDBLOCK error you must
call ezs_disconnect to close the partially open connection.
|
Description: | Client authenticate to a server over already connected socket
|
Syntax: | int ezs_connect_fd(EZS* E, int fd, char* cn) |
Arguments: |
E: | An EZS structure |
fd: | The connected file descriptor |
cn: | CN of the certificate to use for authentication |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_NOCRT: | cert (cn) not loaded |
EZS_ERR_BADCRT: | cert invalid |
EZS_ERR_BADKEY: | key invalid |
EZS_ERR_SSL: | connection failure |
|
Notes: |
- You can find the peer's cn with ezs_get_peer_cn.
- If you choose not to retry a WOULDBLOCK error you must
call ezs_disconnect to close the partially open connection.
|
Description: | Listen on a port for connection requests.
|
Syntax: | int ezs_listen(EZS* E, char* port) |
Arguments: |
E: | An EZS structure |
port: | Port to listen on |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | listen failure |
|
Notes: |
- Note that the port is a character string
|
Description: | Server accept connection and verify client
|
Syntax: | EZS *ezs_accept(EZS* E, char* cn) |
Arguments: |
E: | An EZS structure |
cn: | CN of the certificate to use for authentication |
|
Return: | An EZS structure, NULL = error
|
Errors: |
EZS_ERR_NOCRT: | cert (cn) not loaded |
EZS_ERR_BADCRT: | cert invalid |
EZS_ERR_BADKEY: | key invalid |
EZS_ERR_SSL: | accept failure |
|
Notes: |
- On success the connection will be open and verified.
- You can find the peer's cn with ezs_get_peer_cn.
- If you choose not to retry a WOULDBLOCK error you must
call ezs_disconnect to close the partially open connection.
|
Description: | Server verify connected client
|
Syntax: | int ezs_accept_fd(EZS* E, int fd, char* cn) |
Arguments: |
E: | An EZS structure |
fd: | The connected file descriptor |
cn: | CN of the certificate to use for authentication |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_NOCRT: | cert (cn) not loaded |
EZS_ERR_BADCRT: | cert invalid |
EZS_ERR_BADKEY: | key invalid |
EZS_ERR_SSL: | accept failure |
|
Notes: |
- On success the connection will be open and verified.
- You can find the peer's cn with ezs_get_peer_cn.
- If you choose not to retry a WOULDBLOCK error you must
call ezs_disconnect to close the partially open connection.
|
Description: | Disconnect a connection
|
Syntax: | void ezs_disconnect(EZS* E) |
Arguments: |
|
Return: | |
Errors: |
|
Notes: |
|
Blocking reads and writes are 'semi-blocking'. The library will wait
timeout seconds for the operation to complete. Non-blocking
reads and writes will return immediately.
Regardless of the blocking mode, a read or write may return
one of the 'wouldblock' errors.
- EZS_ERR_READ_WOULDBLOCK: a read operation could not complete
- EZS_ERR_WRITE_WOULDBLOCK: a write operation could not complete
Because an SSL connection can be renegotiated either of these
conditions may be returned for either a read or a write.
You can use the ezs_wouldblock procedure to see if
the IO operation failed for either reason.
Because the SSL library buffers incoming data,
use the ezs_bytes_for_read procedure
in addition to a select to see if there are bytes available
for read.
Description: | Read bytes from a peer
len bytes.
|
Syntax: | int ezs_read(EZS* E, char* data, int len) |
Arguments: |
E: | An EZS structure |
data: | Memory location to receive data. Must be at least |
len: | maximum number of bytes to read |
|
Return: | number of bytes read, 0 = error
|
Errors: |
EZS_ERR_NO_CONNECTION: | no connection |
EZS_ERR_READ_WOULDBLOCK: | read blocked (waiting for read) |
EZS_ERR_WRITE_WOULDBLOCK: | read blocked (waiting for write) |
EZS_ERR_READ_EOF: | connection closed by peer |
EZS_ERR_SSL: | SSL error |
|
Notes: |
- If you choose to retry a blocked read you must
supply the exact same data with the retried ezs_read.
You may supply a copy of the original data however.
- If you choose not to retry a blocked read you must
call ezs_disconnect to close the open connection.
- You should call ezs_disconnect to
close a connection after receiving an end-of-file.
|
Description: | Write bytes to a peer
|
Syntax: | int ezs_write(EZS* E, char* data, int len) |
Arguments: |
E: | An EZS structure |
data: | Pointer to data. |
len: | number of bytes to write |
|
Return: | number of bytes written, 0 = error
|
Errors: |
EZS_ERR_NO_CONNECTION: | no connection |
EZS_ERR_READ_WOULDBLOCK: | write blocked (waiting for read) |
EZS_ERR_WRITE_WOULDBLOCK: | write blocked (waiting for write) |
EZS_ERR_READ_EOF: | connection closed by peer |
EZS_ERR_SSL: | SSL error |
|
Notes: |
- Success means all the data were written
- If you choose to retry a blocked write you must
supply the exact same data with the retried ezs_write.
You may supply a copy of the original data however.
- If you choose not to retry a blocked write you must
call ezs_disconnect to close the open connection.
- You should call ezs_disconnect to
close a connection after receiving an end-of-file.
|
Description: | Get number of bytes available for read
|
Syntax: | int ezs_bytes_for_read(EZS* E) |
Arguments: |
|
Return: | number of bytes buffered and available for a read operation
|
Errors: |
|
Notes: |
|
Description: | Test if the last IO attempt would have blocked
|
Syntax: | int ezs_wouldblock(EZS* E) |
Arguments: |
|
Return: | 1 if the last IO operation returned
EZS_ERR_READ_WOULDBLOCK or EZS_ERR_WRITE_WOULDBLOCK,
0 otherwise
|
Errors: |
|
Notes: |
|
Some convenience routines are provided to encrypt and decrypt
data and to compute MAC hashes. Encryption generally includes
an initialization vector (IV) that ensures randomness in
the start of a message. The same, random IV must be used
for both encryption and decryption.
Keys are any binary strings, and should be at least 32 bytes long.
The default encryption cipher is 128 bit AES in CBC mode.
The default hash algorithm is SHA-1.
Use ezs_set_cipher and ezs_set_hash to select
other algorithms.
Description: | Initialize cryption structures
|
Syntax: | int ezs_crypt_init(EZS* E, char* key, int len, char** iv) |
Arguments: |
E: | An EZS structure |
key: | Encryption key |
len: | length of the key |
iv: | initialization vector |
|
Return: | 1
|
Errors: |
|
Notes: |
- If
iv is NULL an IV will be computed, used and discarded.
If iv points to a NULL pointer an IV will be computed, used
and a pointer to it returned in iv . If iv points
to a non-NULL pointer it is assumed to be a predefined IV and will
be used.
- The IV used in for encryption must be provided to the decryption step or
the first block of decrypted data will be lost.
|
Description: | Encrypt or decrypt data
|
Syntax: | int ezs_crypt(EZS* E, int mode, char* out, int out_len, char* in, int in_len) |
Arguments: |
E: | An EZS structure |
mode: | Either EZS_ENCRYPT or EZS_DECRYPT |
out: | buffer to receive the crypted text |
out_len: | length of data stored in the buffer |
in: | data to encrypt or decrypt |
in_len: | length of data |
|
Return: | 1 = success, 0 = error
|
Errors: |
EZS_ERR_SSL: | cryption failure |
|
Notes: |
- Because of the possibility of block padding, the output
buffer's length should be at least
in_len + EZS_BLOCKSIZE(E)
- You must call ezs_crypt_init prior to ezs_crypt.
|
Description: | Generate a MAC of some data
|
Syntax: | int ezs_hmac(char** mac, int* mac_len, char* data, int data_len, char* key, int key_len) |
Arguments: |
data: | data for which the MAC will be computed |
data_len: | length of data |
key: | key for the MAC |
key_len: | length of the key |
mac: | computed MAC |
mac_len: | length of mac |
|
Return: | 1
|
Errors: |
|
Notes: |
|
Description: | Convert binary data to printable base64
|
Syntax: | int ezs_data_to_base64(char** b64, int* b64_len, char* data, int data_len) |
Arguments: |
data: | input binary data |
data_len: | length of data |
b64: | base64 representation of data |
b64_len: | length of b64 text |
|
Return: | 1
|
Errors: |
|
Notes: |
|
Description: | Convert base64 to binary data
|
Syntax: | int ezs_base64_to_data(char** data, int* data_len, char* b64, int b64_len) |
Arguments: |
b64: | input base64 representation of data |
b64_len: | length of b64 text |
data: | output binary data |
data_len: | length of data |
|
Return: | 1
|
Errors: |
|
Notes: |
|
Description: | Sets the cipher used by the encryption procedures
|
Syntax: | int ezs_set_cipher(EVP_CIPHER* (*cipher)()) |
Arguments: |
cipher: | any openssl cipher algorithm |
|
Return: | |
Errors: |
|
Notes: |
- Ciphers supported by your version of the openssl library
may be found in openssl's inlcude file evp.h.
- The default cipher is EVP_aes_128_cbc (128 bit AES in CBC mode)
|
Description: | Sets the hash algorithm used by the encryption and hash procedures
|
Syntax: | int ezs_set_hash(EVP_MD* (*hash)()) |
Arguments: |
cipher: | any openssl hash algorithm |
|
Return: | |
Errors: |
|
Notes: |
- Hashes supported by your version of the openssl library
may be found in openssl's inlcude file evp.h.
- The default is EVP_sha1 (SHA-1)
|
The EZS library will report both its own version and the
versions of openssl it was compiled and linked with.
The latter can help detect cases where the library is
linked with different and incompatible versions
of openssl.
Description: | Returns ezs and openssl version information.
|
Syntax: | char *ezs_version() |
Arguments: |
|
Return: | Version information as a string.
|
Errors: |
|
Notes: |
- Caller is responsible for freeing the returned version string.
|
* =================================================================
* Copyright (c) 2006 The University of Washington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =================================================================