Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Email **support@wolfssl.com** instead, and please keep the issue private until a

- **Heap hints on every allocation.** Allocate through `WOLFCERT_XMALLOC`, `WOLFCERT_XREALLOC` and `WOLFCERT_XFREE` from `wolfcert/memory.h` and pass the hint on to wolfSSL. A public API takes an optional `heap`, directly or in its config struct, and falls back to `wolfcert_default_heap()` when it is NULL.
- **No CryptoCb registration.** wolfCert never calls `wc_CryptoCb_RegisterDevice`; the application registers its backend and passes the `dev_id` in `WolfCertKeyCfg`.
- **A closed set of error codes.** Report every error with `WOLFCERT_ERR` or `WOLFCERT_ERR_WC` from `src/internal.h`, and keep `wolfcert_strerror` covering every code in `wolfcert/errors.h`.
- **A closed set of error codes.** Report every error with `WOLFCERT_ERR`, `WOLFCERT_ERR_WC` or `WOLFCERT_ERR_RC_WC` from `src/internal.h`, and keep `wolfcert_strerror` covering every code in `wolfcert/errors.h`.
- **Visibility.** Public and internal functions both use the `wolfcert_` prefix. The CMake build hides every symbol by default, so public prototypes in `wolfcert/*.h` carry `WOLFCERT_API`. Mark an internal function that the in-tree tests call `WOLFCERT_TEST_VIS`, which exports it only in a `WOLFCERT_BUILD_TESTING` build.
- **Append-only public structs.** The v0.1.0 ABI is released, so a new field in a public struct goes at its end.
- **License header.** Every `.c` and `.h` file opens with the full GPL copyright block, copied from an existing source file; the Lint workflow checks it. Build files (`CMakeLists.txt`, `configure.ac`, `Makefile.am`) use the `SPDX-License-Identifier: GPL-3.0-or-later` line instead.
Expand Down
6 changes: 6 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,12 @@ The contract:
implement the negative case with a call that lets it apply, rather than an
unbounded wait around a non-blocking transfer: the second shape silently
discards whatever the application configured.
- **The mode can change between requests on one connection.** wolfCert lets
an application make blocking and `_nb` requests on one HTTP or EST session,
one request at a time, so a transport can see `0` and a negative value on
the same connection. Take special care to honour each call's value if your
application needs this; otherwise keep a connection in one mode. Closing a
session always writes the TLS `close_notify` with `0`.
- **Never write more than `len` bytes.** wolfCert rejects a count larger than
it asked for, but that only keeps the overrun out of its own buffers - the
write into yours has already happened, so honouring `len` is the transport's
Expand Down
23 changes: 19 additions & 4 deletions docs/EMBEDDED.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ miscompile.
|----------|----------------|--------------|--------------|
| wolfSSL `Cert` (CSR / cert build) | **heap** (`wc_CertNew`) | ~20+ KB | `altNames[16384]` |
| wolfSSL `DecodedCert` (cert parse) | **stack** or **heap**, transient | several KB | parse scratch |
| HTTP request handling | **stack** (EST + client); **heap** (SCEP server) | 2-3 KB stack | request read buffer |
| HTTP request handling | **stack** (EST server); **heap** (SCEP server, client) | 2-3 KB stack | request read buffer |
| HTTP response (client) | **heap**, handed to the caller as `resp->body` | up to `max_response_bytes` + 8 KB | receive buffer; its allocation can exceed `body_len` |

The good news: wolfCert never stack-allocates a `Cert`. Every CSR/cert
build path (`src/csr.c`, `src/ca_issue.c`, `src/scep/scep_msg.c`) obtains
Expand Down Expand Up @@ -188,15 +189,15 @@ the request completes) so it never counts against the stack budget.
| `WOLFCERT_HTTP_QUERY_SZ` | `8192` | sized to hold a base64 GET `PKIOperation` message; on the SCEP server it extends the heap read buffer (`REQ_BUF_SZ + QUERY_SZ`) that `query` points into |
| `WOLFCERT_HTTP_AUTH_BUF_SZ` | `512` | client Basic-auth header line (`http.c`) |
| `WOLFCERT_HTTP_MAX_PATH_LEN` | `8192` | client-side ceiling on a request URL's path+query (`http.c`) |
| `WOLFCERT_HTTP_HEADER_BUDGET` | `8192` | client response allowance added to the caller's body cap, bounding the status line plus header block. Both the blocking and the non-blocking reader grow their accumulator to `max_response_bytes + this` (`http.c`) |
| `WOLFCERT_HTTP_HEADER_BUDGET` | `8192` | client limit on a response's status line plus header block; a longer block fails with `WOLFCERT_ERR_PROTOCOL`. The client's receive buffer holds at most `max_response_bytes + this` (`http.c`) |
| `WOLFCERT_SCEP_MAX_GET_URL` | `8192` | client cap on a GET `PKIOperation` URL; a larger message is refused with `WOLFCERT_ERR_UNSUPPORTED` so the caller POSTs (`internal.h`) |

Shrinking `WOLFCERT_HTTP_REQ_BUF_SZ` lowers the largest request header
block the server accepts; `WOLFCERT_HTTP_PATH_SZ` / `WOLFCERT_HTTP_QUERY_SZ`
lower the longest request path / query; `WOLFCERT_HTTP_AUTH_BUF_SZ` lowers the
longest Basic-auth credential the client can send. `WOLFCERT_HTTP_HEADER_BUDGET`
trims the client's response accumulator, and with it the largest response
header block it will accept, so keep it above the headers your CA actually
sets the largest response header block the client accepts, and with it the
client's receive buffer, so keep it above the headers your CA actually
sends. A POST-only SCEP deployment
can trim `WOLFCERT_HTTP_QUERY_SZ` (and, on the client, `WOLFCERT_SCEP_MAX_GET_URL`
and `WOLFCERT_HTTP_MAX_PATH_LEN`) back down. Example:
Expand Down Expand Up @@ -266,6 +267,20 @@ keeping the large heap-allocated `Cert` off a general-purpose allocator.
See [`ARCHITECTURE.md` section 4.1](ARCHITECTURE.md#41-heap-hints--static-memory-pools)
for the three levels of hint granularity.

A pool realloc always copies, so a chunked or close-delimited HTTP response
first tries to take its whole receive buffer in one block of
`max_response_bytes + WOLFCERT_HTTP_HEADER_BUDGET`, 72 KB by default. If no
pool block is that large, the buffer doubles as bytes arrive, taking a new
block each time; with wolfSSL's default buckets it stops at 8192 bytes,
headers and read room included, and a response that needs more fails with
`WOLFCERT_ERR_MEMORY`. A `Content-Length` response takes one block of its
exact size. For larger responses, give the pool one block of that sum per
session receiving at the same time, or lower `max_response_bytes` (per
request, or per session at open) or `WOLFCERT_HTTP_HEADER_BUDGET` (at build
time) until their sum fits wolfSSL's largest bucket (`LARGEST_MEM_BUCKET`,
16128 bytes unless ML-DSA or `SESSION_CERTS` raises it): 7936 + 8192, for
example.

## 5. Threading

If your target is single-threaded, build wolfSSL with `SINGLE_THREADED`.
Expand Down
7 changes: 3 additions & 4 deletions src/est/est_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ struct WolfCertEstSession {
enum { EST_OP_GET_CACERTS, EST_OP_SIMPLE_ENROLL } in_op;
};

static int est_session_open_common(const WolfCertServerCfg* srv, int nonblocking,
static int est_session_open_common(const WolfCertServerCfg* srv,
WolfCertEstSession** out)
{
if (srv == NULL || srv->server_url == NULL || out == NULL)
Expand Down Expand Up @@ -450,7 +450,6 @@ static int est_session_open_common(const WolfCertServerCfg* srv, int nonblocking
.client_key = srv->client_key,
.client_key_len = srv->client_key_len,
.allow_post_handshake_auth = srv->proto_opts.est.allow_post_handshake_auth,
.nonblocking = nonblocking,
.transport = srv->transport,
.heap = heap,
};
Expand All @@ -470,13 +469,13 @@ static int est_session_open_common(const WolfCertServerCfg* srv, int nonblocking
int wolfcert_est_session_open(const WolfCertServerCfg* srv,
WolfCertEstSession** out)
{
return est_session_open_common(srv, 0, out);
return est_session_open_common(srv, out);
}

int wolfcert_est_session_open_async(const WolfCertServerCfg* srv,
WolfCertEstSession** out)
{
return est_session_open_common(srv, 1, out);
return est_session_open_common(srv, out);
}

int wolfcert_est_session_fd(const WolfCertEstSession* s)
Expand Down
Loading
Loading