Skip to content

Commit

Permalink
Compatibility with mbedTLS v3.0
Browse files Browse the repository at this point in the history
Unlike normal releases, mbedTLS 3.0 breaks compatibility with previous
versions. This commit allows uacme to work with mbedTLS v3.x.
Backwards compatibility with mbedTLS v2.x is maintained.
  • Loading branch information
ndilieto committed Feb 27, 2022
1 parent 7f1ffbd commit 64d1b3c
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 34 deletions.
96 changes: 66 additions & 30 deletions crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ static bool openssl_hmac_fast(const EVP_MD *type, const void *key,
#error mbedTLS version 2.16 or later is required
#endif

#if !defined(MBEDTLS_PRIVATE)
#define MBEDTLS_PRIVATE(member) member
#endif

static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context ctr_drbg;

Expand Down Expand Up @@ -587,18 +591,27 @@ static bool rsa_params(privkey_t key, char **m, char **e)
#elif defined(USE_MBEDTLS)
unsigned char *data = NULL;
size_t len;
mbedtls_mpi mn, me;
mbedtls_mpi_init(&mn);
mbedtls_mpi_init(&me);
if (!mbedtls_pk_can_do(key, MBEDTLS_PK_RSA)) {
warnx("rsa_params: not a RSA key");
goto out;
}
const mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
len = mbedtls_mpi_size(&rsa->N);
r = mbedtls_rsa_export(rsa, &mn, NULL, NULL, NULL, &me);
if (r) {
warnx("rsa_params: mbedtls_rsa_export failed: %s",
_mbedtls_strerror(r));
goto out;
}
len = mbedtls_mpi_size(&mn);
data = calloc(1, len);
if (!data) {
warnx("rsa_params: calloc failed");
goto out;
}
r = mbedtls_mpi_write_binary(&rsa->N, data, len);
r = mbedtls_mpi_write_binary(&mn, data, len);
if (r) {
warnx("rsa_params: mbedtls_mpi_write_binary failed: %s",
_mbedtls_strerror(r));
Expand All @@ -610,13 +623,13 @@ static bool rsa_params(privkey_t key, char **m, char **e)
goto out;
}
free(data);
len = mbedtls_mpi_size(&rsa->E);
len = mbedtls_mpi_size(&me);
data = calloc(1, len);
if (!data) {
warnx("rsa_params: calloc failed");
goto out;
}
r = mbedtls_mpi_write_binary(&rsa->E, data, len);
r = mbedtls_mpi_write_binary(&me, data, len);
if (r) {
warnx("rsa_params: mbedtls_mpi_write_binary failed: %s",
_mbedtls_strerror(r));
Expand All @@ -636,6 +649,8 @@ static bool rsa_params(privkey_t key, char **m, char **e)
free(data);
#elif defined(USE_MBEDTLS)
free(data);
mbedtls_mpi_free(&mn);
mbedtls_mpi_free(&me);
#endif
if (_e && _m) {
if (e)
Expand Down Expand Up @@ -771,13 +786,13 @@ static size_t ec_params(privkey_t key, char **x, char **y)
}
#elif defined(USE_MBEDTLS)
unsigned char *data = NULL;
size_t len;
size_t len, olen, plen;
if (!mbedtls_pk_can_do(key, MBEDTLS_PK_ECKEY)) {
warnx("ec_params: not a EC key");
goto out;
}
const mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
switch (ec->grp.id) {
switch (ec->MBEDTLS_PRIVATE(grp).id) {
case MBEDTLS_ECP_DP_SECP256R1:
bits = 256;
break;
Expand All @@ -791,37 +806,35 @@ static size_t ec_params(privkey_t key, char **x, char **y)
"Elliptic Curves supported");
goto out;
}
len = mbedtls_mpi_size(&ec->Q.X);
plen = mbedtls_mpi_size(&ec->MBEDTLS_PRIVATE(grp).P);
len = 1 + 2 * plen;
data = calloc(1, len);
if (!data) {
warnx("ec_params: calloc failed");
goto out;
}
r = mbedtls_mpi_write_binary(&ec->Q.X, data, len);
r = mbedtls_ecp_point_write_binary(&ec->MBEDTLS_PRIVATE(grp),
&ec->MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED,
&olen, data, len);
if (r) {
warnx("ec_params: mbedtls_mpi_write_binary failed: %s",
warnx("ec_params: mbedtls_ecp_point_write_binary failed: %s",
_mbedtls_strerror(r));
goto out;
}
_x = bn2str(data, len, (bits+7)/8);
if (!_x) {
warnx("ec_params: bn2str failed");
if (olen != len) {
warnx("ec_params: wrong length (actual %zu, expected %zu)", olen, len);
goto out;
}
free(data);
len = mbedtls_mpi_size(&ec->Q.Y);
data = calloc(1, len);
if (!data) {
warnx("ec_params: calloc failed");
if (data[0] != 0x04) {
warnx("ec_params: key data corruption");
goto out;
}
r = mbedtls_mpi_write_binary(&ec->Q.Y, data, len);
if (r) {
warnx("ec_params: mbedtls_mpi_write_binary failed: %s",
_mbedtls_strerror(r));
_x = bn2str(data + 1, plen, (bits+7)/8);
if (!_x) {
warnx("ec_params: bn2str failed");
goto out;
}
_y = bn2str(data, len, (bits+7)/8);
_y = bn2str(data + 1 + plen, plen, (bits+7)/8);
if (!_y) {
warnx("ec_params: bn2str failed");
goto out;
Expand Down Expand Up @@ -1480,11 +1493,13 @@ char *jws_encode(const char *protected, const char *payload,
}
switch (mbedtls_pk_get_type(key)) {
case MBEDTLS_PK_RSA:
signature = calloc(1, mbedtls_pk_get_len(key));
signature_size = mbedtls_pk_get_len(key);
signature = calloc(1, signature_size);
break;

case MBEDTLS_PK_ECKEY:
signature = calloc(1, 9+2*mbedtls_pk_get_len(key));
signature_size = 9+2*mbedtls_pk_get_len(key);
signature = calloc(1, signature_size);
break;

default:
Expand All @@ -1496,6 +1511,9 @@ char *jws_encode(const char *protected, const char *payload,
goto out;
}
r = mbedtls_pk_sign(key, hash_type, hash, hash_size, signature,
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
signature_size,
#endif
&signature_size, mbedtls_ctr_drbg_random, &ctr_drbg);
if (r != 0) {
warnx("jws_encode: mbedtls_pk_sign failed: %s",
Expand Down Expand Up @@ -1947,7 +1965,11 @@ privkey_t key_load(keytype_t type, int bits, const char *format, ...)
goto out;
}
mbedtls_pk_init(key);
r = mbedtls_pk_parse_key(key, keydata, keysize+1, NULL, 0);
r = mbedtls_pk_parse_key(key, keydata, keysize+1, NULL, 0
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
, mbedtls_ctr_drbg_random, &ctr_drbg
#endif
);
if (r) {
warnx("key_load: mbedtls_pk_parse failed: %s",
_mbedtls_strerror(r));
Expand Down Expand Up @@ -2436,6 +2458,9 @@ char *csr_gen(char * const *names, bool status_req, privkey_t key)
r = mbedtls_x509write_csr_set_extension(&csr,
MBEDTLS_OID_SUBJECT_ALT_NAME,
MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
0,
#endif
buf + buflen - len, len);
if (r) {
warnx("csr_gen: mbedtls_x509write_csr_set_extension failed: %s",
Expand Down Expand Up @@ -2483,6 +2508,9 @@ char *csr_gen(char * const *names, bool status_req, privkey_t key)
// pe(1) id-pe-tlsfeature(24)
MBEDTLS_OID_PKIX "\x01\x18",
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKIX "\x01\x18"),
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
0,
#endif
buf + buflen - len, len);
if (r) {
warnx("csr_gen: mbedtls_x509write_csr_set_extension failed: %s",
Expand Down Expand Up @@ -3159,14 +3187,14 @@ char *csr_load(const char *file, char ***names)
goto out;
}
free(csrdata);
csrsize = ctx.buflen;
csrsize = ctx.MBEDTLS_PRIVATE(buflen);
csrdata = calloc(1, csrsize);
if (!csrdata) {
warn("csr_load: calloc failed");
mbedtls_pem_free(&ctx);
goto out;
}
memcpy(csrdata, ctx.buf, ctx.buflen);
memcpy(csrdata, ctx.MBEDTLS_PRIVATE(buf), ctx.MBEDTLS_PRIVATE(buflen));
mbedtls_pem_free(&ctx);
#endif
r = base64_ENCODED_LEN(csrsize, base64_VARIANT_URLSAFE_NO_PADDING);
Expand Down Expand Up @@ -3929,7 +3957,11 @@ static int ocsp_req(mbedtls_x509_crt *crt, unsigned char *req, size_t size,
unsigned char *c = buf + buf_size;
ret = mbedtls_pk_write_pubkey(&c, buf, &issuer->pk);
if (ret >= 0)
#if MBEDTLS_VERSION_NUMBER < 0x03000000
ret = mbedtls_sha1_ret(buf + buf_size - ret, ret, hash);
#else
ret = mbedtls_sha1(buf + buf_size - ret, ret, hash);
#endif
mbedtls_free(buf);
if (ret == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
buf_size *= 2;
Expand All @@ -3943,7 +3975,11 @@ static int ocsp_req(mbedtls_x509_crt *crt, unsigned char *req, size_t size,
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_octet_string(&p, req,
hash, sizeof(hash)));

#if MBEDTLS_VERSION_NUMBER < 0x03000000
ret = mbedtls_sha1_ret(crt->issuer_raw.p, crt->issuer_raw.len, hash);
#else
ret = mbedtls_sha1(crt->issuer_raw.p, crt->issuer_raw.len, hash);
#endif
if (ret)
return ret;

Expand Down Expand Up @@ -4419,7 +4455,7 @@ bool cert_valid(const char *certfile, char * const *names, int validity,
goto out;
}

if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
if (crt->MBEDTLS_PRIVATE(ext_types) & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
int r = ext_san(crt->v3_ext.p, crt->v3_ext.len, &san);
if (r) {
warnx("cert_valid: ext_san failed: %s", _mbedtls_strerror(r));
Expand Down Expand Up @@ -4560,14 +4596,14 @@ char *cert_der_base64url(const char *certfile)
goto out;
}
free(certdata);
certsize = ctx.buflen;
certsize = ctx.MBEDTLS_PRIVATE(buflen);
certdata = calloc(1, certsize);
if (!certdata) {
warn("cert_der_base64url: calloc failed");
mbedtls_pem_free(&ctx);
goto out;
}
memcpy(certdata, ctx.buf, ctx.buflen);
memcpy(certdata, ctx.MBEDTLS_PRIVATE(buf), ctx.MBEDTLS_PRIVATE(buflen));
mbedtls_pem_free(&ctx);
#endif
r = base64_ENCODED_LEN(certsize, base64_VARIANT_URLSAFE_NO_PADDING);
Expand Down
20 changes: 16 additions & 4 deletions ualpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ static void openssl_error(const char *prefix)
#error mbedTLS earlier than version 2.23 needs to be configured with \
MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
#endif
#if !defined(MBEDTLS_PRIVATE)
#define MBEDTLS_PRIVATE(member) member
#endif

static const char *_mbedtls_strerror(int code)
{
static char buf[0x100];
Expand Down Expand Up @@ -2273,13 +2277,13 @@ int ext_callback(void *ctx, mbedtls_x509_crt const *crt,
static int do_handshake(client_t *c)
{
int rc = 0;
while (c->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
while (c->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) {
rc = mbedtls_ssl_handshake_step(&c->ssl);
if (rc)
break;
if (c->state == STATE_ACME)
continue;
if (c->ssl.state > MBEDTLS_SSL_CLIENT_HELLO) {
if (c->ssl.MBEDTLS_PRIVATE(state) > MBEDTLS_SSL_CLIENT_HELLO) {
const char *proto = mbedtls_ssl_get_alpn_protocol(&c->ssl);
if (proto && strcmp(proto, "acme-tls/1") == 0) {
auth_t *auth = get_auth(c->ident);
Expand Down Expand Up @@ -2310,7 +2314,11 @@ static int do_handshake(client_t *c)
#endif
mbedtls_pk_free(&c->key);
rc = mbedtls_pk_parse_key(&c->key, auth->key,
auth->key_size, NULL, 0);
auth->key_size, NULL, 0
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
, mbedtls_ctr_drbg_random, &g.ctr_drbg
#endif
);
if (rc) {
warnx("client %08x: mbedtls_pk_parse_key for %s: %s",
c->id, c->ident, _mbedtls_strerror(rc));
Expand Down Expand Up @@ -2450,7 +2458,11 @@ static int tls_session_init(client_t *c, uint8_t *buf, size_t buf_len)
}
#endif
mbedtls_pk_init(&c->key);
rc = mbedtls_pk_parse_key(&c->key, g.key, g.key_len, NULL, 0);
rc = mbedtls_pk_parse_key(&c->key, g.key, g.key_len, NULL, 0
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
, mbedtls_ctr_drbg_random, &g.ctr_drbg
#endif
);
if (rc) {
warnx("client %08x: mbedtls_pk_parse_key: %s", c->id,
_mbedtls_strerror(rc));
Expand Down

0 comments on commit 64d1b3c

Please sign in to comment.