123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- /*
- * Copyright (c) 2023, Christian Huitema
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
- #ifdef _WINDOWS
- #include "wincompat.h"
- #endif
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <picotls.h>
- #include <mbedtls/mbedtls_config.h>
- #include <mbedtls/build_info.h>
- #include <mbedtls/pk.h>
- #include <mbedtls/pem.h>
- #include <mbedtls/error.h>
- #include <psa/crypto.h>
- #include <psa/crypto_struct.h>
- #include <psa/crypto_values.h>
- /* #include "ptls_mbedtls.h" */
- typedef struct st_ptls_mbedtls_signature_scheme_t {
- uint16_t scheme_id;
- psa_algorithm_t hash_algo;
- } ptls_mbedtls_signature_scheme_t;
- typedef struct st_ptls_mbedtls_sign_certificate_t {
- ptls_sign_certificate_t super;
- mbedtls_svc_key_id_t key_id;
- psa_key_attributes_t attributes;
- const ptls_mbedtls_signature_scheme_t *schemes;
- } ptls_mbedtls_sign_certificate_t;
- static const unsigned char ptls_mbedtls_oid_ec_key[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01};
- static const unsigned char ptls_mbedtls_oid_rsa_key[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01};
- static const unsigned char ptls_mbedtls_oid_ed25519[] = {0x2b, 0x65, 0x70};
- static const ptls_mbedtls_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, PSA_ALG_SHA_256},
- {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, PSA_ALG_SHA_384},
- {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PSA_ALG_SHA_512},
- {UINT16_MAX, PSA_ALG_NONE}};
- static const ptls_mbedtls_signature_scheme_t secp256r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, PSA_ALG_SHA_256}, {UINT16_MAX, PSA_ALG_NONE}};
- static const ptls_mbedtls_signature_scheme_t secp384r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, PSA_ALG_SHA_384}, {UINT16_MAX, PSA_ALG_NONE}};
- static const ptls_mbedtls_signature_scheme_t secp521r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, PSA_ALG_SHA_512}, {UINT16_MAX, PSA_ALG_NONE}};
- static const ptls_mbedtls_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, PSA_ALG_NONE},
- {UINT16_MAX, PSA_ALG_NONE}};
- #if defined(MBEDTLS_PEM_PARSE_C)
- /* Mapping of MBEDTLS APIs to Picotls */
- static int ptls_mbedtls_parse_der_length(const unsigned char *pem_buf, size_t pem_len, size_t *px, size_t *pl)
- {
- int ret = 0;
- size_t x = *px;
- size_t l = pem_buf[x++];
- if (l > 128) {
- size_t ll = l & 0x7F;
- l = 0;
- while (ll > 0 && x + l < pem_len) {
- l *= 256;
- l += pem_buf[x++];
- ll--;
- }
- }
- *pl = l;
- *px = x;
- return ret;
- }
- static int ptls_mbedtls_parse_ecdsa_field(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length)
- {
- int ret = 0;
- size_t x = 0;
- // const unsigned char head = { 0x30, l-2, 0x02, 0x01, 0x01, 0x04 }
- if (pem_len < 16 || pem_buf[x++] != 0x30 /* type = sequence */) {
- ret = -1;
- } else {
- size_t l = 0;
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l);
- if (x + l != pem_len) {
- ret = -1;
- }
- }
- if (ret == 0) {
- if (pem_buf[x++] != 0x02 /* type = int */ || pem_buf[x++] != 0x01 /* length of int = 1 */ ||
- pem_buf[x++] != 0x01 /* version = 1 */ || pem_buf[x++] != 0x04 /*octet string */ || pem_buf[x] + x >= pem_len) {
- ret = -1;
- } else {
- *key_index = x + 1;
- *key_length = pem_buf[x];
- x += 1 + pem_buf[x];
- if (x < pem_len && pem_buf[x] == 0xa0) {
- /* decode the EC parameters, identify the curve */
- x++;
- if (x + pem_buf[x] >= pem_len) {
- /* EC parameters extend beyond buffer */
- ret = -1;
- } else {
- x += pem_buf[x] + 1;
- }
- }
- if (ret == 0 && x < pem_len) {
- /* skip the public key parameter */
- if (pem_buf[x++] != 0xa1 || x >= pem_len) {
- ret = -1;
- } else {
- size_t l = 0;
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l);
- x += l;
- }
- }
- if (x != pem_len) {
- ret = -1;
- }
- }
- }
- return ret;
- }
- /* On input, key_index points at the "key information" in a
- * "private key" message. For EDDSA, this contains an
- * octet string carrying the key itself. On return, key index
- * and key length are updated to point at the key field.
- */
- static int ptls_mbedtls_parse_eddsa_key(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length)
- {
- int ret = 0;
- size_t x = *key_index;
- size_t l_key = 0;
- if (*key_length < 2 || pem_buf[x++] != 0x04) {
- ret = -1;
- } else {
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key);
- if (x + l_key != *key_index + *key_length) {
- ret = -1;
- } else {
- *key_index = x;
- *key_length = l_key;
- }
- }
- return ret;
- }
- /* If using PKCS8 encoding, the "private key" field contains the
- * same "ecdsa field" found in PEM "EC PRIVATE KEY" files. We
- * use the same parser, but we need to reset indices so they
- * reflect the unwrapped key.
- */
- int ptls_mbedtls_parse_ec_private_key(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length)
- {
- size_t x_offset = 0;
- size_t x_len = 0;
- int ret = ptls_mbedtls_parse_ecdsa_field(pem_buf + *key_index, *key_length, &x_offset, &x_len);
- if (ret == 0) {
- *key_index += x_offset;
- *key_length = x_len;
- }
- return ret;
- }
- int test_parse_private_key_field(const unsigned char *pem_buf, size_t pem_len, size_t *oid_index, size_t *oid_length,
- size_t *key_index, size_t *key_length)
- {
- int ret = 0;
- size_t l_oid = 0;
- size_t x_oid = 0;
- size_t l_key = 0;
- size_t x_key = 0;
- size_t x = 0;
- /* const unsigned char head = {0x30, l - 2, 0x02, 0x01, 0x00} */
- if (pem_len < 16 || pem_buf[x++] != 0x30 /* type = sequence */) {
- ret = -1;
- } else {
- size_t l = 0;
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l);
- if (x + l != pem_len) {
- ret = -1;
- }
- }
- if (ret == 0) {
- if (pem_buf[x++] != 0x02 /* type = int */ || pem_buf[x++] != 0x01 /* length of int = 1 */ ||
- pem_buf[x++] != 0x00 /* version = 0 */ || pem_buf[x++] != 0x30 /* sequence */) {
- ret = -1;
- } else {
- /* the sequence contains the OID and optional key attributes,
- * which we ignore for now.
- */
- size_t l_seq = 0;
- size_t x_seq;
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_seq);
- x_seq = x;
- if (x + l_seq >= pem_len || pem_buf[x++] != 0x06) {
- ret = -1;
- } else {
- l_oid = pem_buf[x++];
- x_oid = x;
- if (x + l_oid > x_seq + l_seq) {
- ret = -1;
- } else {
- x = x_seq + l_seq;
- }
- }
- }
- }
- if (ret == 0) {
- /* At that point the oid has been identified.
- * The next parameter is an octet string containing the key info.
- */
- if (x + 2 > pem_len || pem_buf[x++] != 0x04) {
- ret = -1;
- } else {
- ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key);
- x_key = x;
- x += l_key;
- if (x > pem_len) {
- ret = -1;
- }
- }
- }
- *oid_index = x_oid;
- *oid_length = l_oid;
- *key_index = x_key;
- *key_length = l_key;
- return ret;
- }
- int ptls_mbedtls_get_der_key(mbedtls_pem_context *pem, mbedtls_pk_type_t *pk_type, const unsigned char *key, size_t keylen,
- const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
- {
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- #if defined(MBEDTLS_PEM_PARSE_C)
- size_t len;
- #endif
- if (keylen == 0) {
- return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
- mbedtls_pem_init(pem);
- #if defined(MBEDTLS_RSA_C)
- /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if (key[keylen - 1] != '\0') {
- ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
- } else {
- ret = mbedtls_pem_read_buffer(pem, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", key, pwd, pwdlen,
- &len);
- }
- if (ret == 0) {
- *pk_type = MBEDTLS_PK_RSA;
- return ret;
- } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
- return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
- } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
- return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
- } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
- return ret;
- }
- #endif /* MBEDTLS_RSA_C */
- #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
- /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if (key[keylen - 1] != '\0') {
- ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
- } else {
- ret =
- mbedtls_pem_read_buffer(pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", key, pwd, pwdlen, &len);
- }
- if (ret == 0) {
- *pk_type = MBEDTLS_PK_ECKEY;
- return ret;
- } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
- return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
- } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
- return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
- } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
- return ret;
- }
- #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
- /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if (key[keylen - 1] != '\0') {
- ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
- } else {
- ret = mbedtls_pem_read_buffer(pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", key, NULL, 0, &len);
- if (ret == 0) {
- /* info is unknown */
- return ret;
- } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
- return ret;
- }
- }
- #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
- /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if (key[keylen - 1] != '\0') {
- ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
- } else {
- ret = mbedtls_pem_read_buffer(pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----", key,
- NULL, 0, &len);
- }
- if (ret == 0) {
- /* infor is unknown */
- return ret;
- } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
- return ret;
- }
- #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
- return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
- #endif
- const ptls_mbedtls_signature_scheme_t *ptls_mbedtls_select_signature_scheme(const ptls_mbedtls_signature_scheme_t *available,
- const uint16_t *algorithms, size_t num_algorithms)
- {
- const ptls_mbedtls_signature_scheme_t *scheme;
- /* select the algorithm, driven by server-isde preference of `available` */
- for (scheme = available; scheme->scheme_id != UINT16_MAX; ++scheme) {
- for (size_t i = 0; i != num_algorithms; ++i) {
- if (algorithms[i] == scheme->scheme_id) {
- return scheme;
- }
- }
- }
- return NULL;
- }
- int ptls_mbedtls_set_available_schemes(ptls_mbedtls_sign_certificate_t *signer)
- {
- int ret = 0;
- psa_algorithm_t algo = psa_get_key_algorithm(&signer->attributes);
- size_t nb_bits = psa_get_key_bits(&signer->attributes);
- switch (algo) {
- case PSA_ALG_RSA_PKCS1V15_SIGN_RAW:
- signer->schemes = rsa_signature_schemes;
- break;
- case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):
- signer->schemes = secp256r1_signature_schemes;
- break;
- case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):
- signer->schemes = secp384r1_signature_schemes;
- break;
- case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512):
- signer->schemes = secp521r1_signature_schemes;
- break;
- case PSA_ALG_ECDSA_BASE:
- switch (nb_bits) {
- case 521:
- signer->schemes = secp521r1_signature_schemes;
- break;
- case 384:
- signer->schemes = secp384r1_signature_schemes;
- break;
- case 256:
- signer->schemes = secp256r1_signature_schemes;
- break;
- default:
- signer->schemes = secp256r1_signature_schemes;
- ret = -1;
- break;
- }
- break;
- case PSA_ALG_ED25519PH:
- signer->schemes = ed25519_signature_schemes;
- break;
- default:
- printf("Unknown algo: %x\n", algo);
- ret = -1;
- }
- return ret;
- }
- /*
- * Sign a certificate
- * - step1, selected a signature algorithm compatible with the public key algorithm
- * and with the list specified by the application.
- * - step2, compute the hash with the specified algorithm.
- * - step3, compute the signature of the hash using psa_sign_hash.
- *
- * In the case of RSA, we use the algorithm PSA_ALG_RSA_PKCS1V15_SIGN_RAW, which
- * pads the hash according to PKCS1V15 before doing the private key operation.
- * The implementation of RSA/PKCS1V15 also includes a verification step to protect
- * against key attacks through partial faults.
- *
- * MBEDTLS has a "psa_sign_message" that combines step2 and step3. However, it
- * requires specifying an algorithm type that exactly specifies the signature
- * algorithm, such as "RSA with SHA384". This is not compatible with the
- * "RSA sign raw" algorithm. Instead, we decompose the operation in two steps.
- * There is no performance penalty doing so, as "psa_sign_message" is only
- * a convenience API.
- */
- int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async,
- uint16_t *selected_algorithm, ptls_buffer_t *outbuf, ptls_iovec_t input,
- const uint16_t *algorithms, size_t num_algorithms)
- {
- int ret = 0;
- ptls_mbedtls_sign_certificate_t *self =
- (ptls_mbedtls_sign_certificate_t *)(((unsigned char *)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super));
- /* First, find the set of compatible algorithms */
- const ptls_mbedtls_signature_scheme_t *scheme = ptls_mbedtls_select_signature_scheme(self->schemes, algorithms, num_algorithms);
- if (scheme == NULL) {
- ret = PTLS_ERROR_INCOMPATIBLE_KEY;
- } else {
- /* First prepare the hash */
- unsigned char hash_buffer[PTLS_MAX_DIGEST_SIZE];
- unsigned char *hash_value = NULL;
- size_t hash_length = 0;
- if (scheme->hash_algo == PSA_ALG_NONE) {
- hash_value = input.base;
- hash_length = input.len;
- } else {
- if (psa_hash_compute(scheme->hash_algo, input.base, input.len, hash_buffer, PTLS_MAX_DIGEST_SIZE, &hash_length) !=
- PSA_SUCCESS) {
- ret = PTLS_ERROR_NOT_AVAILABLE;
- } else {
- hash_value = hash_buffer;
- }
- }
- if (ret == 0) {
- psa_algorithm_t sign_algo = psa_get_key_algorithm(&self->attributes);
- size_t nb_bits = psa_get_key_bits(&self->attributes);
- size_t nb_bytes = (nb_bits + 7) / 8;
- if (nb_bits == 0) {
- if (sign_algo == PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
- /* assume at most 4096 bit key */
- nb_bytes = 512;
- } else {
- /* Max size assumed, secp521r1 */
- nb_bytes = 124;
- }
- } else if (sign_algo != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
- nb_bytes *= 2;
- }
- if ((ret = ptls_buffer_reserve(outbuf, nb_bytes)) == 0) {
- size_t signature_length = 0;
- if (psa_sign_hash(self->key_id, sign_algo, hash_value, hash_length, outbuf->base + outbuf->off, nb_bytes,
- &signature_length) != 0) {
- ret = PTLS_ERROR_INCOMPATIBLE_KEY;
- } else {
- outbuf->off += signature_length;
- }
- }
- }
- }
- return ret;
- }
- void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t *_self)
- {
- if (_self != NULL) {
- ptls_mbedtls_sign_certificate_t *self =
- (ptls_mbedtls_sign_certificate_t *)(((unsigned char *)_self) -
- offsetof(struct st_ptls_mbedtls_sign_certificate_t, super));
- /* Destroy the key */
- psa_destroy_key(self->key_id);
- psa_reset_key_attributes(&self->attributes);
- memset(self, 0, sizeof(ptls_mbedtls_sign_certificate_t));
- free(self);
- }
- }
- /*
- * An RSa key is encoded in DER as:
- * RSAPrivateKey ::= SEQUENCE {
- * version INTEGER, -- must be 0
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * }
- *
- * The number of key bits is the size in bits of the integer N.
- * We must decode the length in octets of the integer representation,
- * then subtract the number of zeros at the beginning of the data.
- */
- int ptls_mbedtls_rsa_get_key_bits(const unsigned char *key_value, size_t key_length, size_t *p_nb_bits)
- {
- int ret = 0;
- size_t nb_bytes = 0;
- size_t nb_bits = 0;
- size_t x = 0;
- if (key_length > 16 && key_value[x++] == 0x30) {
- /* get the length of the sequence. */
- size_t l = 0;
- ret = ptls_mbedtls_parse_der_length(key_value, key_length, &x, &l);
- if (x + l != key_length) {
- ret = -1;
- }
- }
- if (ret == 0 && key_value[x] == 0x02 && key_value[x + 1] == 0x01 && key_value[x + 2] == 0x00 && key_value[x + 3] == 0x02) {
- x += 4;
- ret = ptls_mbedtls_parse_der_length(key_value, key_length, &x, &nb_bytes);
- } else {
- ret = -1;
- }
- if (ret == 0) {
- unsigned char v = key_value[x];
- nb_bits = 8 * nb_bytes;
- if (v == 0) {
- nb_bits -= 8;
- } else {
- while ((v & 0x80) == 0) {
- nb_bits--;
- v <<= 1;
- }
- }
- }
- *p_nb_bits = nb_bits;
- return ret;
- }
- void ptls_mbedtls_set_rsa_key_attributes(ptls_mbedtls_sign_certificate_t *signer, const unsigned char *key_value, size_t key_length)
- {
- size_t nb_bits = 0;
- psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH);
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW);
- psa_set_key_type(&signer->attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
- if (ptls_mbedtls_rsa_get_key_bits(key_value, key_length, &nb_bits) == 0) {
- psa_set_key_bits(&signer->attributes, nb_bits);
- }
- }
- int ptls_mbedtls_set_ec_key_attributes(ptls_mbedtls_sign_certificate_t *signer, size_t key_length)
- {
- int ret = 0;
- psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH);
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_ECDSA_BASE);
- psa_set_key_type(&signer->attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
- if (key_length == 32) {
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
- psa_set_key_bits(&signer->attributes, 256);
- } else if (key_length == 48) {
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384));
- psa_set_key_bits(&signer->attributes, 384);
- } else if (key_length == 66) {
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512));
- psa_set_key_bits(&signer->attributes, 521);
- } else {
- ret = -1;
- }
- return ret;
- }
- int ptls_mbedtls_load_private_key(ptls_context_t *ctx, char const *pem_fname)
- {
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n;
- unsigned char *buf;
- mbedtls_pem_context pem = {0};
- mbedtls_pk_type_t pk_type = 0;
- /* mbedtls_svc_key_id_t key_id = 0; */
- size_t key_length = 0;
- size_t key_index = 0;
- ptls_mbedtls_sign_certificate_t *signer = (ptls_mbedtls_sign_certificate_t *)malloc(sizeof(ptls_mbedtls_sign_certificate_t));
- if (signer == NULL) {
- return (PTLS_ERROR_NO_MEMORY);
- }
- memset(signer, 0, sizeof(ptls_mbedtls_sign_certificate_t));
- signer->attributes = psa_key_attributes_init();
- if ((ret = mbedtls_pk_load_file(pem_fname, &buf, &n)) != 0) {
- if (ret == MBEDTLS_ERR_PK_ALLOC_FAILED) {
- return (PTLS_ERROR_NO_MEMORY);
- } else {
- return (PTLS_ERROR_NOT_AVAILABLE);
- }
- }
- ret = ptls_mbedtls_get_der_key(&pem, &pk_type, buf, n, NULL, 0, NULL, NULL);
- /* We cannot use the platform API:
- mbedtls_zeroize_and_free(buf, n);
- so we do our own thing.
- */
- memset(buf, 0, n);
- free(buf);
- if (ret == 0) {
- if (pk_type == MBEDTLS_PK_RSA) {
- key_length = pem.private_buflen;
- ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length);
- } else if (pk_type == MBEDTLS_PK_ECKEY) {
- ret = ptls_mbedtls_parse_ecdsa_field(pem.private_buf, pem.private_buflen, &key_index, &key_length);
- if (ret == 0) {
- ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length);
- }
- } else if (pk_type == MBEDTLS_PK_NONE) {
- /* TODO: not clear whether MBDED TLS supports ED25519 yet. Probably not. */
- /* Should have option to encode RSA or ECDSA using PKCS8 */
- size_t oid_index = 0;
- size_t oid_length = 0;
- psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH);
- ret =
- test_parse_private_key_field(pem.private_buf, pem.private_buflen, &oid_index, &oid_length, &key_index, &key_length);
- if (ret == 0) {
- /* need to parse the OID in order to set the parameters */
- if (oid_length == sizeof(ptls_mbedtls_oid_ec_key) &&
- memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ec_key, sizeof(ptls_mbedtls_oid_ec_key)) == 0) {
- ret = ptls_mbedtls_parse_ec_private_key(pem.private_buf, pem.private_buflen, &key_index, &key_length);
- if (ret == 0) {
- ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length);
- }
- } else if (oid_length == sizeof(ptls_mbedtls_oid_ed25519) &&
- memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ed25519, sizeof(ptls_mbedtls_oid_ed25519)) == 0) {
- /* We recognized ED25519 -- PSA_ECC_FAMILY_TWISTED_EDWARDS -- PSA_ALG_ED25519PH */
- psa_set_key_algorithm(&signer->attributes, PSA_ALG_PURE_EDDSA);
- psa_set_key_type(&signer->attributes, PSA_ECC_FAMILY_TWISTED_EDWARDS);
- ret = ptls_mbedtls_parse_eddsa_key(pem.private_buf, pem.private_buflen, &key_index, &key_length);
- psa_set_key_bits(&signer->attributes, 256);
- } else if (oid_length == sizeof(ptls_mbedtls_oid_rsa_key) &&
- memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_rsa_key, sizeof(ptls_mbedtls_oid_rsa_key)) == 0) {
- /* We recognized RSA */
- key_length = pem.private_buflen;
- ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length);
- } else {
- ret = PTLS_ERROR_NOT_AVAILABLE;
- }
- }
- } else {
- ret = -1;
- }
- if (ret == 0) {
- /* Now that we have the DER or bytes for the key, try import into PSA */
- psa_status_t status = psa_import_key(&signer->attributes, pem.private_buf + key_index, key_length, &signer->key_id);
- if (status != PSA_SUCCESS) {
- ret = -1;
- } else {
- ret = ptls_mbedtls_set_available_schemes(signer);
- }
- }
- /* Free the PEM buffer */
- mbedtls_pem_free(&pem);
- }
- if (ret == 0) {
- signer->super.cb = ptls_mbedtls_sign_certificate;
- ctx->sign_certificate = &signer->super;
- } else {
- /* Dispose of what we have allocated. */
- ptls_mbedtls_dispose_sign_certificate(&signer->super);
- }
- return ret;
- }
|