Skip to content
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ if (s2n_connection_set_fd(conn, fd) < 0) {
}

/* Negotiate the TLS handshake */
int more;
if (s2n_negotiate(conn, &more) < 0) {
s2n_blocked_status blocked;
if (s2n_negotiate(conn, &blocked) < 0) {
... error ...
}

/* Write data to the connection */
int bytes_written;
bytes_written = s2n_send(conn, "Hello World", sizeof("Hello World"), &more);
bytes_written = s2n_send(conn, "Hello World", sizeof("Hello World"), &blocked);
```

For details on building the s2n library and how to use s2n in an application you are developing, see the [API Reference](https://github.com/awslabs/s2n/blob/master/docs/USAGE-GUIDE.md).
Expand Down
9 changes: 5 additions & 4 deletions api/s2n.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@ extern const char *s2n_get_server_name(struct s2n_connection *conn);
extern const char *s2n_get_application_protocol(struct s2n_connection *conn);
extern const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length);

extern int s2n_negotiate(struct s2n_connection *conn, int *more);
extern ssize_t s2n_send(struct s2n_connection *conn, void *buf, ssize_t size, int *more);
extern ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, int *more);
typedef enum { S2N_NOT_BLOCKED = 0, S2N_BLOCKED_ON_READ, S2N_BLOCKED_ON_WRITE } s2n_blocked_status;
extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked);
extern ssize_t s2n_send(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked);
extern ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked);

extern int s2n_connection_wipe(struct s2n_connection *conn);
extern int s2n_connection_free(struct s2n_connection *conn);
extern int s2n_shutdown(struct s2n_connection *conn, int *more);
extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked);

extern uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn);
extern uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn);
Expand Down
14 changes: 7 additions & 7 deletions bin/echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ int echo(struct s2n_connection *conn, int sockfd)
readers[1].fd = STDIN_FILENO;
readers[1].events = POLLIN;

int more;
s2n_blocked_status blocked;
do {
if (s2n_negotiate(conn, &more) < 0) {
if (s2n_negotiate(conn, &blocked) < 0) {
fprintf(stderr, "Failed to negotiate: '%s' %d\n", s2n_strerror(s2n_errno, "EN"), s2n_connection_get_alert(conn));
exit(1);
}
} while (more);
} while (blocked);

/* Now that we've negotiated, print some parameters */
int client_hello_version;
Expand Down Expand Up @@ -96,7 +96,7 @@ int echo(struct s2n_connection *conn, int sockfd)

if (readers[0].revents & POLLIN) {
do {
bytes_read = s2n_recv(conn, buffer, 10240, &more);
bytes_read = s2n_recv(conn, buffer, 10240, &blocked);
if (bytes_read == 0) {
/* Connection has been closed */
s2n_connection_wipe(conn);
Expand All @@ -111,7 +111,7 @@ int echo(struct s2n_connection *conn, int sockfd)
fprintf(stderr, "Error writing to stdout\n");
exit(1);
}
} while (more);
} while (blocked);
}
if (readers[1].revents & POLLIN) {
int bytes_available;
Expand Down Expand Up @@ -139,15 +139,15 @@ int echo(struct s2n_connection *conn, int sockfd)

char *buf_ptr = buffer;
do {
bytes_written = s2n_send(conn, buf_ptr, bytes_available, &more);
bytes_written = s2n_send(conn, buf_ptr, bytes_available, &blocked);
if (bytes_written < 0) {
fprintf(stderr, "Error writing to connection: '%s'\n", s2n_strerror(s2n_errno, "EN"));
exit(1);
}

bytes_available -= bytes_written;
buf_ptr += bytes_written;
} while (bytes_available || more);
} while (bytes_available || blocked);
}
}
if (p < 0 && errno == EINTR) {
Expand Down
42 changes: 27 additions & 15 deletions docs/USAGE-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ but does accept SSL2.0 hello messages.

## Enums

s2n defines three enum types:
s2n defines four enum types:

```c
typedef enum { S2N_SERVER, S2N_CLIENT } s2n_mode;
Expand All @@ -168,6 +168,15 @@ typedef enum { S2N_SERVER, S2N_CLIENT } s2n_mode;
respectively. At this time, s2n does not function as a client and only
S2N_SERVER should be used.

```c
typedef enum { S2N_NOT_BLOCKED, S2N_BLOCKED_ON_READ, S2N_BLOCKED_ON_WRITE } s2n_blocked_status;
```

**s2n_blocked_status** is used in non-blocking mode to indicate in which
direction s2n became blocked on I/O before it returned control to the caller.
This allows an application to avoid retrying s2n operations until I/O is
possible in that direction.

```c
typedef enum { S2N_BUILT_IN_BLINDING, S2N_SELF_SERVICE_BLINDING } s2n_blinding;
```
Expand Down Expand Up @@ -529,16 +538,17 @@ s2n supports both blocking and non-blocking I/O. To use s2n in non-blocking
mode, set the underlying file descriptors as non-blocking (i.e. with
**fcntl**). In blocking mode, each s2n I/O function will not return until it is
complete. In non-blocking mode an s2n I/O function may return while there is
still I/O pending. In this case the value of the **more** parameter will be set
to 1.
still I/O pending. In this case the value of the **blocked** parameter will be set
to either **S2N_BLOCKED_ON_READ** or **S2N_BLOCKED_ON_WRITE**, depending on the
direction in which s2n is blocked.

s2n I/O functions should be called repeatedly until the **more** parameter is
zero.
s2n I/O functions should be called repeatedly until the **blocked** parameter is
**S2N_NOT_BLOCKED**.

### s2n\_negotiate

```c
int s2n_negotiate(struct s2n_connection *conn, int *more);
int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked);
```

**s2n_negotiate** performs the initial "handshake" phase of a TLS connection and must be called before any **s2n_recv** or **s2n_send** calls.
Expand All @@ -549,22 +559,23 @@ int s2n_negotiate(struct s2n_connection *conn, int *more);
ssize_t s2n_send(struct s2n_connection *conn
void *buf,
ssize_t size,
int *more);
s2n_blocked_status *blocked);
```

**s2n_send** writes and encrypts **size* of **buf** data to the associated connection. **s2n_send** will return the number of bytes written, and may indicate a partial write. Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active. **NOTE:** Unlike OpenSSL, repeated calls to **s2n_send** should not duplicate the original parameters, but should update **buf** and **size** per the indication of size written. For example;

```c
int more, written = 0;
s2n_blocked_status blocked;
int written = 0;
char data[10]; /* Some data we want to write */
do {
int w = s2n_send(conn, data + written, 10 - written, &more);
int w = s2n_send(conn, data + written, 10 - written, &blocked);
if (w < 0) {
/* Some kind of error */
break;
}
written += w;
} while (more);
} while (blocked != S2N_NOT_BLOCKED);
```

### s2n\_recv
Expand All @@ -573,7 +584,7 @@ do {
ssize_t s2n_recv(struct s2n_connection *conn,
void *buf,
ssize_t size,
int *more);
s2n_blocked_status *blocked);
```

**s2n_recv** decrypts and reads **size* to **buf** data from the associated
Expand All @@ -583,23 +594,24 @@ connection. **s2n_recv** will return the number of bytes read and also return
**NOTE:** Unlike OpenSSL, repeated calls to **s2n_recv** should not duplicate the original parameters, but should update **buf** and **size** per the indication of size read. For example;

```c
int more, bytes_read = 0;
s2n_blocked_status blocked;
int bytes_read = 0;
char data[10];
do {
int r = s2n_recv(conn, data + bytes_read, 10 - bytes_read, &more);
int r = s2n_recv(conn, data + bytes_read, 10 - bytes_read, &blocked);
if (r < 0) {
/* Some kind of error */
break;
}
bytes_read += r;
} while (more);
} while (blocked != S2N_NOT_BLOCKED);
```

### s2n_shutdown

```c
int s2n_shutdown(struct s2n_connection *conn,
int *more);
s2n_blocked_status *blocked);
```

**s2n_shutdown** shuts down the s2n connection. Once a connection has been shut down it is not available for reading or writing.
Expand Down
2 changes: 1 addition & 1 deletion stuffer/s2n_stuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t size)
}

/* Use '0' instead of 0 precisely to prevent C string compatibility */
memset(stuffer->blob.data + stuffer->write_cursor - n, '0', n);
memset_check(stuffer->blob.data + stuffer->write_cursor - n, '0', n);
stuffer->write_cursor -= n;

if (stuffer->write_cursor == 0) {
Expand Down
Loading