---
name: "peks-session"
section: "3"
platform: "linux"
package: "libnessus-dev"
version: "1.0.10-2"
release: "Debian 3.0 (Woody)"
platforms: ["linux"]
url: "https://new.carta.tech/peks-session"
---

# peks-session(3)

public key encryption tunnel negotiation

## NAME

server\_negotiate\_session\_key, \
 client\_negotiate\_session\_key - public key encryption tunnel negotiation

## SYNOPSIS

```
#include <peks.h>

int server_negotiate_session_key
       (peks_key *private_key, int socket,
         const char *client_name, peks_key *dh_group);

int client_negotiate_session_key
       (const char *cipher_type, int socket,
        const char *server_name, const char *key_file);

extern int peks_recv_timeout;
```

## DESCRIPTION

**Server\_negotiate\_session\_key ()** starts an encrypted client session on the server. After a successful initalization all io data passed through the iostream transparent socket layer (see [**iostream**(3)](/iostream/3.md) for details) will be encrypted.

The first argument *private\_key* must be non-NULL.  It is used to authenticate the server while setting up the session.

The second argument *socket* is an open TCP socket.  The other arguments are used to find a private key to derive the public key from, needed to negotiate the session keys.

If the last argument *dh\_group* is non-NULL, its prime module and generator is used for the Diffie Hellman key negotiation. Otherwise the module and generator are taken from the *private\_key*.

By setting the global variable *peks\_recv\_timeout* to some  positive value n, a timeout is imposed on waiting for an answer while the handshake is active. This is done by temporarily changing the receive timeout value using **io\_recv\_tmo()**.

Note:\

A client that connects to the server for the first time will store  the public key from the server and tell the server to terminate key negotiation. So -1 is returned on the server and the global variable *errno* will be set the as the error code for the symbol *SRV\_CLIENT\_KNOCKING* (see also [**peks-errnum**(3)](/peks-errnum/3.md)).

Example:

```
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <peks.h>
#include <messages.h>

/* ERROR () and EXIT () are macros with
the obvious functionality */

for (;;) {
int n = server_negotiate_session_key
(key,                           /* default key */
socket,                        /* open socket */
inet_ntoa (address->sin_addr), /* client addr  */
"/etc/peks/private.keys") ;    /* key file */

if (n >= 0)                       /* success */
break;

if (errno != errnum (SRV_CLIENT_KNOCKING)) {
ERROR ("Cannot negotiate keys: %s - aborting",
peks_strerr (errno)) ;
EXIT (1);
}
} /* end for (;;) */
```

**Clinet\_negotiate\_session\_key ()** starts an encrypted session on the client. The function starts waiting for a peks server to negotiate session keys. For communication, the open socket passed as second argument *socket* is used.

The argument *cipher\_type* is a string "\<block-cipher\>/\<hash-type\>" composed of two text fields separated by a slash.  For the values that can be used here consult the file **cipher.h** from the sorce code. Currently, the following block ciphers are available

```
blowfish    - 16 byte key length, 8 byte block length
blowfish160 - 16 byte key length, 16 byte block length
twofish     - 16 byte key length, 16 byte block length
3des        - 16 byte key length (hashed to 24 bytes),
              8 byte block length
```

and the hash types

```
ripem160    - 20 byte result
sha1        - 20 byte result
md5         - 20 byte result
```

Thanks to the gnupg people where I got the sources, from.

The other two the arguments *server\_name* and *key\_file* are used to check the public key from the server against the list of servers, already known.

If both, the argument *key\_file* is non-NULL and the argument *server\_name* is non-NULL, the server key just received is checked as follows:

If there is no file with name *key\_file*, it is just created.

An existing key file file must be privately owned and must neither be world nor group read/writable.

If the file with name *key\_file* exists, it is searched for a line tag  matching the argument *server\_name*.  Host names in the key file can be used as well as ip addesses.   If the argument *server\_name* matches line tag, the corresponding key fields are checked against the public key just received from the server.

If the public key received does not match the ones found in the file *key\_file*, an error value -1 is returned and no session is opened.

If there is no public key from this server in the file *key\_file*, a line with the public server keys is appended to the file and an error value -1 is returned.  No session will be opened. The global error varaiable  *errno* will be set to the error symbol *STORED\_SERVER\_KEY* (see **peks\_stderr**(3) for details).

Otherwise, an encrypted session with the server will have been opened and pushed (see [**io\_push**(3)](/io_push/3.md) for details) upon the transparent socket layer.

Example:

```
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <peks.h>
#include <messages.h>

/* ERROR () and EXIT () are macros with
the obvious functionality */

for (;;) {
int n = client_negotiate_session_key
("blowfish160/sha1",            /* encr type */
socket,                        /* open socket */
inet_ntoa (address->sin_addr), /* server addr */
"~/.server.keys") ;            /* key file */

if (n >= 0)                       /* success */
break;

if (errno != errnum (STORED_SERVER_KEY)) {
ERROR ("Cannot negotiate keys: %s - aborting",
peks_strerr (errno)) ;
EXIT (1);
}
} /* end for (;;) */
```

## RETURN VALUE

**Server\_negotiate\_session\_key ()** returns 0, on success while an encrypted session with the client will have been opened and pushed (see [**io\_push**(3)](/io_push/3.md) for details) upon the transparent socket layer. On error, -1 is returned while the global variable *errno* will be set.

**Clinet\_negotiate\_session\_key ()** returns 0, on success while an encrypted session with the server will have been opened and pushed (see [**io\_push**(3)](/io_push/3.md) for details) upon the transparent socket layer. On error, -1 is returned while the global variable *errno* will be set.

## ERROR CODES

Some error codes besides the [**errno**(3)](/errno/3.md) interface are used, here. They are referred to as error symbols (see [**peks-errnum**(3)](/peks-errnum/3.md) for details):

```
SRV_MAGIC_FAILED    Server could not read magic string
SRV_WRONG_MAGIC     Client sent incompatible magic string
SRV_CLIENT_KNOCKING Client was knocking at the door, only
SRV_CLIENT_RESPERR  Initial client response was garbage

CANT_EXPAND_FNAME   Cannot expand file name ($HOME missing?)
SERVER_SPOOF_ALERT  Spoof alert: Server key has changed
STORED_SERVER_KEY   Host key for that server has been saved
```

## ENVIRONMENT VARIABLES

- **HOME**

  Used for the key file name expansion when there is a leading tilde-slash as in "~/\<key\_file\>".

## SEE ALSO

**socket**(3), [**iostream**(3)](/iostream/3.md), [**io\_push**(3)](/io_push/3.md), [**io\_ctrl**(3)](/io_ctrl/3.md),  [**io\_recv\_tmo**(3)](/io_recv_tmo/3.md),  [**gethostbyname**(3)](/gethostbyname/3.md), [**peks-keyfile**(5)](/peks-keyfile/5.md),  [**errno**(3)](/errno/3.md), [**peks-errnum**(3)](/peks-errnum/3.md),

## AUTHOR

The **peks** package where these functions belong to was written by Jordan Hrycaj \<jordan@teddy-net.com\>, originally to support the **nessus** security scanner.
