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
25 changes: 18 additions & 7 deletions .github/actions/zephyr-workspace/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ runs:
- name: Workspace cache key
id: wskey
shell: bash
env:
ZEPHYR_REF: ${{ inputs.zephyr-ref }}
WOLFSSL_REF: ${{ inputs.wolfssl-ref }}
SCRIPT_HASH: ${{ hashFiles('scripts/ci/zephyr-add-wolfssl.py') }}
run: |
h="${{ hashFiles('scripts/ci/zephyr-add-wolfssl.py') }}"
echo "key=zephyr-ws-${RUNNER_OS}-${{ inputs.zephyr-ref }}-${{ inputs.wolfssl-ref }}-${h:0:12}-$(python3 -V | tr -d ' ')" \
echo "key=zephyr-ws-${RUNNER_OS}-${ZEPHYR_REF}-${WOLFSSL_REF}-${SCRIPT_HASH:0:12}-$(python3 -V | tr -d ' ')" \
>> "$GITHUB_OUTPUT"

- name: Restore the Zephyr workspace
Expand All @@ -56,6 +59,8 @@ runs:

- name: Initialise the west workspace
shell: bash
env:
ZEPHYR_REF: ${{ inputs.zephyr-ref }}
run: |
set -euo pipefail
if [ ! -x "$HOME/zephyr-venv/bin/west" ]; then
Expand All @@ -64,14 +69,16 @@ runs:
fi
if [ ! -d "$HOME/zephyrproject/.west" ]; then
"$HOME/zephyr-venv/bin/west" init -m https://github.com/zephyrproject-rtos/zephyr \
--mr "${{ inputs.zephyr-ref }}" "$HOME/zephyrproject"
--mr "$ZEPHYR_REF" "$HOME/zephyrproject"
fi

- name: Add wolfSSL to the manifest
shell: bash
env:
WOLFSSL_REF: ${{ inputs.wolfssl-ref }}
run: |
./scripts/ci/zephyr-add-wolfssl.py \
"$HOME/zephyrproject/zephyr/west.yml" "${{ inputs.wolfssl-ref }}"
"$HOME/zephyrproject/zephyr/west.yml" "$WOLFSSL_REF"

- name: Update west modules
shell: bash
Expand All @@ -91,12 +98,16 @@ runs:

- name: Install the Zephyr SDK
shell: bash
env:
SDK_VERSION: ${{ inputs.sdk-version }}
TOOLCHAIN: ${{ inputs.toolchain }}
run: |
set -euo pipefail
v="${{ inputs.sdk-version }}"
v="$SDK_VERSION"
cd "$HOME"
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${v}/zephyr-sdk-${v}_linux-x86_64_minimal.tar.xz"
wget -q --tries=3 --retry-on-http-error=429,500,502,503,504 \
"https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${v}/zephyr-sdk-${v}_linux-x86_64_minimal.tar.xz"
tar xf "zephyr-sdk-${v}_linux-x86_64_minimal.tar.xz"
cd "zephyr-sdk-${v}"
./setup.sh -h -c -t "${{ inputs.toolchain }}"
./setup.sh -h -c -t "$TOOLCHAIN"
echo "ZEPHYR_SDK_INSTALL_DIR=$HOME/zephyr-sdk-${v}" >> "$GITHUB_ENV"
27 changes: 25 additions & 2 deletions cli/wolfcert_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,23 @@ static int scep_resolve_ca(const WolfCertServerCfg* srv, const CaPin* pin,
return rc;
}

/* Carry on without capabilities on a non-200 GetCACaps reply. */
static int scep_fetch_caps(const WolfCertServerCfg* srv, WolfCertScepCaps* caps,
const char* cmd)
{
int rc = wolfcert_scep_get_ca_caps(srv, caps);

if (rc == WOLFCERT_ERR_HTTP) {
fprintf(stderr, "%s: GetCACaps failed, assuming a CA without "
"capabilities (3DES unless --content-cipher)\n", cmd);
rc = WOLFCERT_OK;
}
else if (rc != WOLFCERT_OK) {
fprintf(stderr, "%s: GetCACaps: %s\n", cmd, wolfcert_strerror(rc));
}
return rc;
}

/* Fetch the CA, resolve any pin against it, then run PKCSReq and any polling. */
static int scep_enroll(const Opts* opts, const WolfCertServerCfg* srv,
const CaPin* pin, const WolfCertKey* key,
Expand All @@ -1029,8 +1046,9 @@ static int scep_enroll(const Opts* opts, const WolfCertServerCfg* srv,
rc = scep_resolve_ca(srv, pin, "enroll", &ca_pem, &ca_bundle, &ca_der,
&bundle, &bundle_len);

if (rc == WOLFCERT_OK)
rc = scep_fetch_caps(srv, &caps, "enroll");
if (rc == WOLFCERT_OK) {
wolfcert_scep_get_ca_caps(srv, &caps);
rc = wolfcert_scep_pkcs_req_ex(srv, &caps, ca_der->buffer,
ca_der->length, bundle, bundle_len,
key, csr->data, csr->len, &scep_result);
Expand Down Expand Up @@ -1699,7 +1717,12 @@ static int cmd_getcert(int argc, char** argv)
}

if (ret == 0) {
wolfcert_scep_get_ca_caps(&srv, &caps);
rc = scep_fetch_caps(&srv, &caps, "getcert");
if (rc != WOLFCERT_OK)
ret = 2;
}

if (ret == 0) {
rc = wolfcert_scep_get_cert(&srv, &caps, ra_der->buffer, ra_der->length,
bundle, bundle_len,
signer_der->buffer, signer_der->length,
Expand Down
8 changes: 6 additions & 2 deletions examples/enroll_scep.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,13 @@ int main(int argc, char** argv)
return 2;
}

/* 2) Optionally query capabilities. */
/* 2) Query capabilities; carry on without them on a non-200. */
WolfCertScepCaps caps = { 0 };
wolfcert_scep_get_ca_caps(&srv, &caps);
rc = wolfcert_scep_get_ca_caps(&srv, &caps);
if (rc != WOLFCERT_OK && rc != WOLFCERT_ERR_HTTP) {
fprintf(stderr, "GetCACaps failed: %s\n", wolfcert_strerror(rc));
return 2;
}

/* 3) Generate RSA key + CSR. */
WolfCertKeyCfg kcfg = { .type = WOLFCERT_KEY_RSA, .param = 2048,
Expand Down
62 changes: 51 additions & 11 deletions src/csr.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ static int assign_rdn(CertName* subject, const char* key, size_t klen,
return WOLFCERT_ERR(WOLFCERT_ERR_BAD_ARG, "csr",
"subject %.*s is %zu bytes, limit %zu", (int)klen, key,
vlen, rdn_fields[i].cap - 1);
/* wolfSSL encodes these two as PrintableString. */
Comment thread
yosuke-wolfssl marked this conversation as resolved.
if ((rdn_fields[i].off == offsetof(CertName, country) ||
rdn_fields[i].off == offsetof(CertName, serialDev)) &&
!wolfcert_is_printable_string((const uint8_t*)val, vlen))
return WOLFCERT_ERR(WOLFCERT_ERR_BAD_ARG, "csr",
"subject %.*s is not a PrintableString", (int)klen, key);
/* And emailAddress as IA5String, which is 7-bit. */
if (rdn_fields[i].off == offsetof(CertName, email)) {
for (size_t j = 0; j < vlen; ++j) {
if ((unsigned char)val[j] >= 0x80)
return WOLFCERT_ERR(WOLFCERT_ERR_BAD_ARG, "csr",
"subject %.*s is not an IA5String", (int)klen, key);
}
}
memcpy(dst, val, vlen);
dst[vlen] = '\0';
return WOLFCERT_OK;
Expand Down Expand Up @@ -167,20 +181,37 @@ static int build_san_seq(const WolfCertCertMeta* meta, Cert* cert, void* heap)
return WOLFCERT_OK;
}

/* RFC 5480 pairs P-256, P-384 and P-521 with SHA-256, SHA-384 and SHA-512. */
#ifdef WOLFCERT_HAVE_ECC
static int ecdsa_sig_for_curve(int curve_id)
/* 1 when the wolfSSL build has SHA-<bits>. */
static int sha2_in_build(int bits)
{
switch (curve_id) {
case ECC_SECP384R1:
return CTC_SHA384wECDSA;
case ECC_SECP521R1:
return CTC_SHA512wECDSA;
case ECC_SECP256R1:
switch (bits) {
case 256:
return 1;
#ifdef WOLFSSL_SHA384
case 384:
return 1;
#endif
#ifdef WOLFSSL_SHA512
case 512:
return 1;
#endif
Comment thread
yosuke-wolfssl marked this conversation as resolved.
default:
return CTC_SHA256wECDSA;
return 0;
}
}

/* RFC 5480 pairs P-256, P-384 and P-521 with SHA-256, SHA-384 and SHA-512;
* a hash wolfSSL lacks steps down to the next one. */
#ifdef WOLFCERT_HAVE_ECC
static int ecdsa_sig_for_curve(int curve_id)
{
if (curve_id == ECC_SECP521R1 && sha2_in_build(512))
return CTC_SHA512wECDSA;
if ((curve_id == ECC_SECP521R1 || curve_id == ECC_SECP384R1) &&
sha2_in_build(384))
return CTC_SHA384wECDSA;
return CTC_SHA256wECDSA;
}
#endif

/* CTC_* signature type for a hash size in bits, or 0 when the key's family
Expand Down Expand Up @@ -225,6 +256,10 @@ static int choose_sig_type(const WolfCertKey* key, const WolfCertKeyAlg* alg,
{
if (meta != NULL && meta->preferred_hash != 0) {
int sig = sig_type_for_hash(key->type, meta->preferred_hash);
if (sig != 0 && !sha2_in_build(meta->preferred_hash))
return WOLFCERT_ERR(WOLFCERT_ERR_UNSUPPORTED, "csr",
"preferred_hash %d: wolfSSL lacks SHA-%d",
meta->preferred_hash, meta->preferred_hash);
if (sig != 0)
return sig;
}
Expand Down Expand Up @@ -408,7 +443,12 @@ int wolfcert_csr_build_ex(const WolfCertKey* key, const WolfCertCertMeta* meta,
wc_CertFree(cert);
return WOLFCERT_ERR_UNSUPPORTED;
}
cert->sigType = choose_sig_type(key, alg, meta);
int sig_type = choose_sig_type(key, alg, meta);
if (sig_type < 0) {
wc_CertFree(cert);
return sig_type;
}
cert->sigType = sig_type;

size_t der_cap = alg->der_cap_hint + 1024;
if (key->type == WOLFCERT_KEY_RSA) {
Expand Down
52 changes: 12 additions & 40 deletions src/est/est_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
Expand Down Expand Up @@ -228,15 +227,6 @@ static int chunked_body_complete(const uint8_t* raw, size_t raw_len)
return 0;
}

/* 1 when the line's field name is `name`, followed directly by ':'. */
static int hdr_is(const char* line, size_t llen, const char* name)
{
size_t n = strlen(name);

return llen > n && line[n] == ':' &&
wolfcert_ascii_ncasecmp(line, name, n) == 0;
}

static int parse_request_in(WolfCertServer* s, int fd, EstRequest* out,
void* heap, char* buf, size_t buf_sz)
{
Expand Down Expand Up @@ -285,47 +275,29 @@ static int parse_request_in(WolfCertServer* s, int fd, EstRequest* out,

int chunked = 0;
while (read_line(&p, end, &line, &llen) == 0 && llen > 0) {
const char* hc = memchr(line, ':', llen);
const char* v;
size_t vlen;

/* RFC 9112 section 5.1: whitespace before the colon is a 400. */
if (hc != NULL && hc > line && (hc[-1] == ' ' || hc[-1] == '\t'))
if (wolfcert_http_hdr_split(line, llen, &v, &vlen) != 0)
return WOLFCERT_ERR_PROTOCOL;
if (hdr_is(line, llen, "Content-Length")) {
out->content_length = (size_t)strtoul(hc + 1, NULL, 10);
if (wolfcert_http_hdr_is(line, llen, "Content-Length")) {
out->content_length = (size_t)strtoul(v, NULL, 10);
}
else if (hdr_is(line, llen, "Transfer-Encoding")) {
const char* v = hc + 1;
while (v < line + llen && (*v == ' ' || *v == '\t')) {
++v;
}

size_t vlen = (size_t)(line + llen - v);
else if (wolfcert_http_hdr_is(line, llen, "Transfer-Encoding")) {
if (vlen >= 7 && wolfcert_ascii_ncasecmp(v, "chunked", 7) == 0)
chunked = 1;
}
else if (hdr_is(line, llen, "Authorization")) {
else if (wolfcert_http_hdr_is(line, llen, "Authorization")) {
if (out->auth_header != NULL)
return WOLFCERT_ERR_PROTOCOL;

const char* val = hc + 1;
while (val < line + llen && (*val == ' ' || *val == '\t')) {
++val;
}

size_t vlen = (size_t)(line + llen - val);
out->auth_header = (char*)WOLFCERT_XMALLOC(vlen + 1, heap);
if (out->auth_header) {
memcpy(out->auth_header, val, vlen);
memcpy(out->auth_header, v, vlen);
out->auth_header[vlen] = '\0';
}
}
else if (hdr_is(line, llen, "Connection")) {
const char* v = hc + 1;
while (v < line + llen && (*v == ' ' || *v == '\t')) {
++v;
}

size_t vlen = (size_t)(line + llen - v);
else if (wolfcert_http_hdr_is(line, llen, "Connection")) {
if (vlen >= 5 && wolfcert_ascii_ncasecmp(v, "close", 5) == 0)
out->connection_close = 1;
}
Expand Down Expand Up @@ -542,8 +514,8 @@ static int check_basic_auth(const WolfCertServer* s, const char* auth_header)
if (auth_header == NULL)
return 0;

if (strncasecmp(auth_header, EST_BASIC_AUTH_SCHEME,
EST_BASIC_AUTH_SCHEME_LEN) != 0)
if (wolfcert_ascii_ncasecmp(auth_header, EST_BASIC_AUTH_SCHEME,
EST_BASIC_AUTH_SCHEME_LEN) != 0)
return 0;

size_t ul = strlen(s->cfg_basic_user);
Expand Down Expand Up @@ -639,7 +611,7 @@ static int ensure_post_handshake_auth(WolfCertServer* s)
size_t fin_len;
size_t cur_len;
char probe;
long deadline;
int64_t deadline;
int r;
int err;

Expand Down
Loading
Loading