2013-09-15 14:54:56 +02:00
|
|
|
/*
|
|
|
|
* Public Key layer for writing key files and structures
|
|
|
|
*
|
2020-08-07 13:07:28 +02:00
|
|
|
* Copyright The Mbed TLS Contributors
|
2015-09-04 14:21:07 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2013-09-15 14:54:56 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2013-09-15 14:54:56 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2013-09-15 14:54:56 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2013-09-15 14:54:56 +02:00
|
|
|
*/
|
|
|
|
|
2020-06-03 01:43:33 +02:00
|
|
|
#include "common.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_PK_WRITE_C)
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/pk.h"
|
|
|
|
#include "mbedtls/asn1write.h"
|
|
|
|
#include "mbedtls/oid.h"
|
2019-01-31 14:20:20 +01:00
|
|
|
#include "mbedtls/platform_util.h"
|
2019-11-22 14:21:35 +01:00
|
|
|
#include "mbedtls/error.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-02-06 14:43:58 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_RSA_C)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/rsa.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_ECP_C)
|
2018-08-11 00:48:44 +02:00
|
|
|
#include "mbedtls/bignum.h"
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/ecp.h"
|
2018-08-11 00:48:44 +02:00
|
|
|
#include "mbedtls/platform_util.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2022-02-25 08:57:19 +01:00
|
|
|
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
|
|
|
|
#include "pkwrite.h"
|
|
|
|
#endif
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_ECDSA_C)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/ecdsa.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_PEM_WRITE_C)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/pem.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
|
|
|
|
2018-11-19 16:07:36 +01:00
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
|
|
#include "psa/crypto.h"
|
2019-02-01 12:55:03 +01:00
|
|
|
#include "mbedtls/psa_util.h"
|
2018-11-19 16:07:36 +01:00
|
|
|
#endif
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/platform.h"
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_RSA_C)
|
2013-09-15 14:54:56 +02:00
|
|
|
/*
|
|
|
|
* RSAPublicKey ::= SEQUENCE {
|
|
|
|
* modulus INTEGER, -- n
|
|
|
|
* publicExponent INTEGER -- e
|
|
|
|
* }
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
|
|
|
|
mbedtls_rsa_context *rsa)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t len = 0;
|
2017-08-23 13:38:27 +02:00
|
|
|
mbedtls_mpi T;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_mpi_init(&T);
|
2017-08-23 13:38:27 +02:00
|
|
|
|
|
|
|
/* Export E */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export N */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
end_of_export:
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_mpi_free(&T);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
|
|
|
|
MBEDTLS_ASN1_SEQUENCE));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_RSA_C */
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-04-05 18:17:13 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2013-09-15 14:54:56 +02:00
|
|
|
/*
|
|
|
|
* EC public key is an EC point
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
|
|
|
|
mbedtls_ecp_keypair *ec)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t len = 0;
|
2015-04-08 12:49:31 +02:00
|
|
|
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
|
|
|
|
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
|
|
|
&len, buf, sizeof(buf))) != 0) {
|
|
|
|
return ret;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (*p < start || (size_t) (*p - start) < len) {
|
|
|
|
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
|
|
|
*p -= len;
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(*p, buf, len);
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ECParameters ::= CHOICE {
|
|
|
|
* namedCurve OBJECT IDENTIFIER
|
|
|
|
* }
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
static int pk_write_ec_param(unsigned char **p, unsigned char *start,
|
2023-05-03 13:05:33 +02:00
|
|
|
mbedtls_ecp_group_id grp_id)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t len = 0;
|
|
|
|
const char *oid;
|
|
|
|
size_t oid_len;
|
|
|
|
|
2023-05-03 13:05:33 +02:00
|
|
|
if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
|
2023-01-11 14:50:10 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
2018-08-11 00:48:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* privateKey OCTET STRING -- always of length ceil(log2(n)/8)
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
static int pk_write_ec_private(unsigned char **p, unsigned char *start,
|
|
|
|
mbedtls_ecp_keypair *ec)
|
2018-08-11 00:48:44 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2023-01-11 14:50:10 +01:00
|
|
|
size_t byte_length = (ec->grp.pbits + 7) / 8;
|
2018-08-11 00:48:44 +02:00
|
|
|
unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
|
|
|
|
if (ret != 0) {
|
2018-08-11 00:48:44 +02:00
|
|
|
goto exit;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
|
|
|
ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
|
2018-08-11 00:48:44 +02:00
|
|
|
|
|
|
|
exit:
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_platform_zeroize(tmp, byte_length);
|
|
|
|
return ret;
|
2018-08-11 00:48:44 +02:00
|
|
|
}
|
2023-04-05 18:17:13 +02:00
|
|
|
#endif /* MBEDTLS_ECP_LIGHT */
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
|
|
|
|
const mbedtls_pk_context *key)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t len = 0;
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_RSA_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
|
|
|
|
} else
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2023-04-05 18:17:13 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
|
|
|
|
} else
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2018-11-19 16:07:36 +01:00
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
|
2018-11-20 00:09:59 +01:00
|
|
|
size_t buffer_size;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (*p < start) {
|
|
|
|
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
2018-11-19 16:07:36 +01:00
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
|
|
|
|
buffer_size = (size_t) (*p - start);
|
2023-05-02 14:15:59 +02:00
|
|
|
if (psa_export_public_key(key->priv_id, start, buffer_size, &len)
|
2023-01-11 14:50:10 +01:00
|
|
|
!= PSA_SUCCESS) {
|
|
|
|
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
|
|
|
} else {
|
2019-02-01 10:57:20 +01:00
|
|
|
*p -= len;
|
2023-01-11 14:50:10 +01:00
|
|
|
memmove(*p, start, len);
|
2018-11-19 16:07:36 +01:00
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
} else
|
2018-11-19 16:07:36 +01:00
|
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
2023-01-11 14:50:10 +01:00
|
|
|
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2013-09-15 14:54:56 +02:00
|
|
|
unsigned char *c;
|
2023-04-19 14:08:14 +02:00
|
|
|
int has_par = 1;
|
|
|
|
size_t len = 0, par_len = 0, oid_len = 0;
|
Adapt mbedtls_pk_write_pubkey_der() to the new PSA public key format
Context: There are two public key writing functions in Mbed TLS. First,
mbedtls_pk_write_pubkey(), which exports a public key in the form of a
SubjectPublicKey structure containing the raw keying material
(for example, EC point coordinates for an EC public key, without
reference to the underlying curve). Secondly, mbedtls_pk_write_pubkey_der(),
which exports a public key in the form of a SubjectPublicKeyInfo structure,
wrapping the SubjectPublicKey structure by additional information
identifying the type of public key (and for ECC, e.g., it'd also contain
the ECC group identifier). The implementation of mbedtls_pk_write_pubkey_der()
calls mbedtls_pk_write_pubkey() first and then adds the corresponding
algorithm identifier wrapper.
Both of these functions need to be provided for PSA-based opaque PK contexts,
based on PSA's public key export function.
Previously, PSA used the SubjectPublicKeyInfo structure as its export format,
so mbedtls_pk_write_pubkey_der() could be easily implemented, while
mbedtls_pk_write_pubkey() would need to trim the output of the PSA export.
The previous implementation of mbedtls_pk_write_pubkey() is not quite right
because it calls PSA export doesn't do any trimming, hence exporting the large
SubjectPublicKeyInfo structure instead of the small SubjectPublicKey.
mbedtls_pk_write_pubkey_der(), in turn, immediately returns after calling
mbedtls_pk_write_pubkey(), hence also returning the SubjectPublicKeyInfo
structure, which is correct.
By now, the PSA public key export format has changed to the smaller
SubjectPublicKey structure. This means that, now, mbedtls_pk_write_pubkey()
can be implemented by just calling the PSA export, and that
mbedtls_pk_write_pubkey_der() needs to add the algorithm information around
it, just as in the other types of PK contexts. While not correct for the
old format, the existing code for mbedtls_pk_write_pubkey() is therefore
correct for the new PSA public key format, and needs no change apart from
the missing pointer shift in the last commit.
The implementation of mbedtls_pk_write_pubkey_der() needs a special code
path for PSA-based opaque PK contexts, as the PK context only contains
the PSA key handle, and the PSA API needs to be used to extract the
underlying EC curve to be able to write the AlgorithmParameter structure
that's part of the SubjectPublicKeyInfo structure.
That's what this commit does, (hopefully) making both
mbedtls_pk_write_pubkey() and mbedtls_pk_write_pubkey_der() export
the correctly formatted public key based on the new PSA public key format.
2019-02-01 11:07:07 +01:00
|
|
|
mbedtls_pk_type_t pk_type;
|
2023-05-04 10:11:58 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-05-04 12:28:49 +02:00
|
|
|
mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
|
2023-05-04 10:11:58 +02:00
|
|
|
#endif
|
2013-09-15 14:54:56 +02:00
|
|
|
const char *oid;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (size == 0) {
|
|
|
|
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
|
|
|
}
|
2019-01-31 14:20:20 +01:00
|
|
|
|
2013-09-15 14:54:56 +02:00
|
|
|
c = buf + size;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (c - buf < 1) {
|
|
|
|
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* SubjectPublicKeyInfo ::= SEQUENCE {
|
|
|
|
* algorithm AlgorithmIdentifier,
|
|
|
|
* subjectPublicKey BIT STRING }
|
|
|
|
*/
|
|
|
|
*--c = 0;
|
|
|
|
len += 1;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
pk_type = mbedtls_pk_get_type(key);
|
2023-04-05 18:17:13 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (pk_type == MBEDTLS_PK_ECKEY) {
|
2023-05-03 13:05:33 +02:00
|
|
|
ec_grp_id = mbedtls_pk_ec(*key)->grp.id;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
2023-04-05 18:17:13 +02:00
|
|
|
#endif /* MBEDTLS_ECP_LIGHT */
|
Adapt mbedtls_pk_write_pubkey_der() to the new PSA public key format
Context: There are two public key writing functions in Mbed TLS. First,
mbedtls_pk_write_pubkey(), which exports a public key in the form of a
SubjectPublicKey structure containing the raw keying material
(for example, EC point coordinates for an EC public key, without
reference to the underlying curve). Secondly, mbedtls_pk_write_pubkey_der(),
which exports a public key in the form of a SubjectPublicKeyInfo structure,
wrapping the SubjectPublicKey structure by additional information
identifying the type of public key (and for ECC, e.g., it'd also contain
the ECC group identifier). The implementation of mbedtls_pk_write_pubkey_der()
calls mbedtls_pk_write_pubkey() first and then adds the corresponding
algorithm identifier wrapper.
Both of these functions need to be provided for PSA-based opaque PK contexts,
based on PSA's public key export function.
Previously, PSA used the SubjectPublicKeyInfo structure as its export format,
so mbedtls_pk_write_pubkey_der() could be easily implemented, while
mbedtls_pk_write_pubkey() would need to trim the output of the PSA export.
The previous implementation of mbedtls_pk_write_pubkey() is not quite right
because it calls PSA export doesn't do any trimming, hence exporting the large
SubjectPublicKeyInfo structure instead of the small SubjectPublicKey.
mbedtls_pk_write_pubkey_der(), in turn, immediately returns after calling
mbedtls_pk_write_pubkey(), hence also returning the SubjectPublicKeyInfo
structure, which is correct.
By now, the PSA public key export format has changed to the smaller
SubjectPublicKey structure. This means that, now, mbedtls_pk_write_pubkey()
can be implemented by just calling the PSA export, and that
mbedtls_pk_write_pubkey_der() needs to add the algorithm information around
it, just as in the other types of PK contexts. While not correct for the
old format, the existing code for mbedtls_pk_write_pubkey() is therefore
correct for the new PSA public key format, and needs no change apart from
the missing pointer shift in the last commit.
The implementation of mbedtls_pk_write_pubkey_der() needs a special code
path for PSA-based opaque PK contexts, as the PK context only contains
the PSA key handle, and the PSA API needs to be used to extract the
underlying EC curve to be able to write the AlgorithmParameter structure
that's part of the SubjectPublicKeyInfo structure.
That's what this commit does, (hopefully) making both
mbedtls_pk_write_pubkey() and mbedtls_pk_write_pubkey_der() export
the correctly formatted public key based on the new PSA public key format.
2019-02-01 11:07:07 +01:00
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (pk_type == MBEDTLS_PK_OPAQUE) {
|
2019-05-27 14:53:13 +02:00
|
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
Adapt mbedtls_pk_write_pubkey_der() to the new PSA public key format
Context: There are two public key writing functions in Mbed TLS. First,
mbedtls_pk_write_pubkey(), which exports a public key in the form of a
SubjectPublicKey structure containing the raw keying material
(for example, EC point coordinates for an EC public key, without
reference to the underlying curve). Secondly, mbedtls_pk_write_pubkey_der(),
which exports a public key in the form of a SubjectPublicKeyInfo structure,
wrapping the SubjectPublicKey structure by additional information
identifying the type of public key (and for ECC, e.g., it'd also contain
the ECC group identifier). The implementation of mbedtls_pk_write_pubkey_der()
calls mbedtls_pk_write_pubkey() first and then adds the corresponding
algorithm identifier wrapper.
Both of these functions need to be provided for PSA-based opaque PK contexts,
based on PSA's public key export function.
Previously, PSA used the SubjectPublicKeyInfo structure as its export format,
so mbedtls_pk_write_pubkey_der() could be easily implemented, while
mbedtls_pk_write_pubkey() would need to trim the output of the PSA export.
The previous implementation of mbedtls_pk_write_pubkey() is not quite right
because it calls PSA export doesn't do any trimming, hence exporting the large
SubjectPublicKeyInfo structure instead of the small SubjectPublicKey.
mbedtls_pk_write_pubkey_der(), in turn, immediately returns after calling
mbedtls_pk_write_pubkey(), hence also returning the SubjectPublicKeyInfo
structure, which is correct.
By now, the PSA public key export format has changed to the smaller
SubjectPublicKey structure. This means that, now, mbedtls_pk_write_pubkey()
can be implemented by just calling the PSA export, and that
mbedtls_pk_write_pubkey_der() needs to add the algorithm information around
it, just as in the other types of PK contexts. While not correct for the
old format, the existing code for mbedtls_pk_write_pubkey() is therefore
correct for the new PSA public key format, and needs no change apart from
the missing pointer shift in the last commit.
The implementation of mbedtls_pk_write_pubkey_der() needs a special code
path for PSA-based opaque PK contexts, as the PK context only contains
the PSA key handle, and the PSA API needs to be used to extract the
underlying EC curve to be able to write the AlgorithmParameter structure
that's part of the SubjectPublicKeyInfo structure.
That's what this commit does, (hopefully) making both
mbedtls_pk_write_pubkey() and mbedtls_pk_write_pubkey_der() export
the correctly formatted public key based on the new PSA public key format.
2019-02-01 11:07:07 +01:00
|
|
|
psa_key_type_t key_type;
|
2023-04-28 15:26:11 +02:00
|
|
|
|
2023-05-02 14:15:59 +02:00
|
|
|
if (PSA_SUCCESS != psa_get_key_attributes(key->priv_id,
|
2023-04-28 15:26:11 +02:00
|
|
|
&attributes)) {
|
2023-01-11 14:50:10 +01:00
|
|
|
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
|
|
}
|
|
|
|
key_type = psa_get_key_type(&attributes);
|
|
|
|
|
2023-05-04 10:11:58 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
|
2023-05-04 12:05:55 +02:00
|
|
|
psa_ecc_family_t curve;
|
2023-01-11 14:50:10 +01:00
|
|
|
|
2023-05-04 12:05:55 +02:00
|
|
|
curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
|
|
|
|
if (curve != 0) {
|
|
|
|
ec_grp_id = mbedtls_ecc_group_of_psa(curve, psa_get_key_bits(&attributes), 0);
|
|
|
|
if (ec_grp_id != MBEDTLS_ECP_DP_NONE) {
|
|
|
|
/* The rest of the function works as for legacy EC contexts. */
|
|
|
|
pk_type = MBEDTLS_PK_ECKEY;
|
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2023-05-04 12:05:55 +02:00
|
|
|
}
|
2023-05-04 10:11:58 +02:00
|
|
|
#endif /* MBEDTLS_ECP_LIGHT */
|
|
|
|
if (PSA_KEY_TYPE_IS_RSA(key_type)) {
|
2022-03-15 16:25:41 +01:00
|
|
|
/* The rest of the function works as for legacy RSA contexts. */
|
|
|
|
pk_type = MBEDTLS_PK_RSA;
|
|
|
|
}
|
2023-05-04 12:05:55 +02:00
|
|
|
|
|
|
|
psa_reset_key_attributes(&attributes);
|
|
|
|
}
|
|
|
|
/* `pk_type` will have been changed to non-opaque by here if this function can handle it */
|
|
|
|
if (pk_type == MBEDTLS_PK_OPAQUE) {
|
|
|
|
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
|
Adapt mbedtls_pk_write_pubkey_der() to the new PSA public key format
Context: There are two public key writing functions in Mbed TLS. First,
mbedtls_pk_write_pubkey(), which exports a public key in the form of a
SubjectPublicKey structure containing the raw keying material
(for example, EC point coordinates for an EC public key, without
reference to the underlying curve). Secondly, mbedtls_pk_write_pubkey_der(),
which exports a public key in the form of a SubjectPublicKeyInfo structure,
wrapping the SubjectPublicKey structure by additional information
identifying the type of public key (and for ECC, e.g., it'd also contain
the ECC group identifier). The implementation of mbedtls_pk_write_pubkey_der()
calls mbedtls_pk_write_pubkey() first and then adds the corresponding
algorithm identifier wrapper.
Both of these functions need to be provided for PSA-based opaque PK contexts,
based on PSA's public key export function.
Previously, PSA used the SubjectPublicKeyInfo structure as its export format,
so mbedtls_pk_write_pubkey_der() could be easily implemented, while
mbedtls_pk_write_pubkey() would need to trim the output of the PSA export.
The previous implementation of mbedtls_pk_write_pubkey() is not quite right
because it calls PSA export doesn't do any trimming, hence exporting the large
SubjectPublicKeyInfo structure instead of the small SubjectPublicKey.
mbedtls_pk_write_pubkey_der(), in turn, immediately returns after calling
mbedtls_pk_write_pubkey(), hence also returning the SubjectPublicKeyInfo
structure, which is correct.
By now, the PSA public key export format has changed to the smaller
SubjectPublicKey structure. This means that, now, mbedtls_pk_write_pubkey()
can be implemented by just calling the PSA export, and that
mbedtls_pk_write_pubkey_der() needs to add the algorithm information around
it, just as in the other types of PK contexts. While not correct for the
old format, the existing code for mbedtls_pk_write_pubkey() is therefore
correct for the new PSA public key format, and needs no change apart from
the missing pointer shift in the last commit.
The implementation of mbedtls_pk_write_pubkey_der() needs a special code
path for PSA-based opaque PK contexts, as the PK context only contains
the PSA key handle, and the PSA API needs to be used to extract the
underlying EC curve to be able to write the AlgorithmParameter structure
that's part of the SubjectPublicKeyInfo structure.
That's what this commit does, (hopefully) making both
mbedtls_pk_write_pubkey() and mbedtls_pk_write_pubkey_der() export
the correctly formatted public key based on the new PSA public key format.
2019-02-01 11:07:07 +01:00
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
|
2023-05-03 13:05:33 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
|
|
|
if (pk_type == MBEDTLS_PK_ECKEY) {
|
|
|
|
/* Some groups have their own AlgorithmIdentifier OID, others are handled by mbedtls_oid_get_oid_by_pk_alg() below */
|
|
|
|
ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
/* Currently, none of the supported algorithms that have their own AlgorithmIdentifier OID have any parameters */
|
|
|
|
has_par = 0;
|
|
|
|
} else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
|
|
|
|
} else {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_ECP_LIGHT */
|
|
|
|
|
2023-04-19 14:08:14 +02:00
|
|
|
if (oid_len == 0) {
|
|
|
|
if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
|
|
|
|
&oid_len)) != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
Adapt mbedtls_pk_write_pubkey_der() to the new PSA public key format
Context: There are two public key writing functions in Mbed TLS. First,
mbedtls_pk_write_pubkey(), which exports a public key in the form of a
SubjectPublicKey structure containing the raw keying material
(for example, EC point coordinates for an EC public key, without
reference to the underlying curve). Secondly, mbedtls_pk_write_pubkey_der(),
which exports a public key in the form of a SubjectPublicKeyInfo structure,
wrapping the SubjectPublicKey structure by additional information
identifying the type of public key (and for ECC, e.g., it'd also contain
the ECC group identifier). The implementation of mbedtls_pk_write_pubkey_der()
calls mbedtls_pk_write_pubkey() first and then adds the corresponding
algorithm identifier wrapper.
Both of these functions need to be provided for PSA-based opaque PK contexts,
based on PSA's public key export function.
Previously, PSA used the SubjectPublicKeyInfo structure as its export format,
so mbedtls_pk_write_pubkey_der() could be easily implemented, while
mbedtls_pk_write_pubkey() would need to trim the output of the PSA export.
The previous implementation of mbedtls_pk_write_pubkey() is not quite right
because it calls PSA export doesn't do any trimming, hence exporting the large
SubjectPublicKeyInfo structure instead of the small SubjectPublicKey.
mbedtls_pk_write_pubkey_der(), in turn, immediately returns after calling
mbedtls_pk_write_pubkey(), hence also returning the SubjectPublicKeyInfo
structure, which is correct.
By now, the PSA public key export format has changed to the smaller
SubjectPublicKey structure. This means that, now, mbedtls_pk_write_pubkey()
can be implemented by just calling the PSA export, and that
mbedtls_pk_write_pubkey_der() needs to add the algorithm information around
it, just as in the other types of PK contexts. While not correct for the
old format, the existing code for mbedtls_pk_write_pubkey() is therefore
correct for the new PSA public key format, and needs no change apart from
the missing pointer shift in the last commit.
The implementation of mbedtls_pk_write_pubkey_der() needs a special code
path for PSA-based opaque PK contexts, as the PK context only contains
the PSA key handle, and the PSA API needs to be used to extract the
underlying EC curve to be able to write the AlgorithmParameter structure
that's part of the SubjectPublicKeyInfo structure.
That's what this commit does, (hopefully) making both
mbedtls_pk_write_pubkey() and mbedtls_pk_write_pubkey_der() export
the correctly formatted public key based on the new PSA public key format.
2019-02-01 11:07:07 +01:00
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-04-19 14:08:14 +02:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
|
|
|
|
par_len, has_par));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
|
|
|
|
MBEDTLS_ASN1_SEQUENCE));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-04-19 14:08:14 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
|
|
|
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
|
|
|
|
/*
|
|
|
|
* RFC8410
|
|
|
|
*
|
|
|
|
* OneAsymmetricKey ::= SEQUENCE {
|
|
|
|
* version Version,
|
|
|
|
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
|
|
|
|
* privateKey PrivateKey,
|
|
|
|
* attributes [0] IMPLICIT Attributes OPTIONAL,
|
|
|
|
* ...,
|
|
|
|
* [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
|
|
|
|
* ...
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* CurvePrivateKey ::= OCTET STRING
|
|
|
|
*/
|
|
|
|
static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
|
|
|
|
mbedtls_ecp_keypair *ec)
|
|
|
|
{
|
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
|
|
size_t len = 0;
|
|
|
|
size_t oid_len = 0;
|
|
|
|
const char *oid;
|
|
|
|
|
|
|
|
/* privateKey */
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, ec));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
|
|
|
|
|
|
|
|
/* privateKeyAlgorithm */
|
|
|
|
if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec->grp.id, &oid, &oid_len)) != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len,
|
|
|
|
mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
|
|
|
|
|
|
|
|
/* version */
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
|
|
|
|
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
|
|
|
|
MBEDTLS_ASN1_SEQUENCE));
|
|
|
|
|
|
|
|
return (int) len;
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
|
|
|
|
#endif /* MBEDTLS_ECP_LIGHT */
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2019-01-31 14:20:20 +01:00
|
|
|
unsigned char *c;
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t len = 0;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (size == 0) {
|
|
|
|
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
|
|
|
}
|
2019-01-31 14:20:20 +01:00
|
|
|
|
|
|
|
c = buf + size;
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_RSA_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
|
2017-08-23 13:38:27 +02:00
|
|
|
mbedtls_mpi T; /* Temporary holding the exported parameters */
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
|
2015-04-08 12:49:31 +02:00
|
|
|
|
2017-08-23 13:38:27 +02:00
|
|
|
/*
|
|
|
|
* Export the parameters one after another to avoid simultaneous copies.
|
|
|
|
*/
|
2015-04-08 12:49:31 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_mpi_init(&T);
|
2017-08-23 13:38:27 +02:00
|
|
|
|
|
|
|
/* Export QP */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export DQ */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export DP */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export Q */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
|
|
|
&T, NULL, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export P */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
|
|
|
|
NULL, NULL, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export D */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
|
|
|
NULL, &T, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export E */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
|
|
|
NULL, NULL, &T)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
|
|
|
/* Export N */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
|
|
|
|
NULL, NULL, NULL)) != 0 ||
|
|
|
|
(ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
|
2017-08-23 13:38:27 +02:00
|
|
|
goto end_of_export;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
len += ret;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
end_of_export:
|
2017-08-23 13:38:27 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_mpi_free(&T);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2017-08-23 13:38:27 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c,
|
|
|
|
buf, MBEDTLS_ASN1_CONSTRUCTED |
|
|
|
|
MBEDTLS_ASN1_SEQUENCE));
|
|
|
|
} else
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_RSA_C */
|
2023-04-05 18:17:13 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
|
|
|
|
mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
|
2013-09-15 14:54:56 +02:00
|
|
|
size_t pub_len = 0, par_len = 0;
|
|
|
|
|
2023-04-19 14:08:14 +02:00
|
|
|
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
|
|
|
|
if (mbedtls_pk_is_rfc8410_curve(ec->grp.id)) {
|
|
|
|
return pk_write_ec_rfc8410_der(&c, buf, ec);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-09-15 14:54:56 +02:00
|
|
|
/*
|
|
|
|
* RFC 5915, or SEC1 Appendix C.4
|
|
|
|
*
|
|
|
|
* ECPrivateKey ::= SEQUENCE {
|
|
|
|
* version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
|
|
|
|
* privateKey OCTET STRING,
|
|
|
|
* parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
|
|
|
|
* publicKey [1] BIT STRING OPTIONAL
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* publicKey */
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (c - buf < 1) {
|
|
|
|
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
*--c = 0;
|
|
|
|
pub_len += 1;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf,
|
|
|
|
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
|
|
|
|
MBEDTLS_ASN1_CONSTRUCTED | 1));
|
2013-09-15 14:54:56 +02:00
|
|
|
len += pub_len;
|
|
|
|
|
|
|
|
/* parameters */
|
2023-05-03 13:05:33 +02:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec->grp.id));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf,
|
|
|
|
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
|
|
|
|
MBEDTLS_ASN1_CONSTRUCTED | 0));
|
2013-09-15 14:54:56 +02:00
|
|
|
len += par_len;
|
|
|
|
|
2018-08-11 00:48:44 +02:00
|
|
|
/* privateKey */
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
|
|
|
/* version */
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1));
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
|
|
|
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
|
|
|
|
MBEDTLS_ASN1_SEQUENCE));
|
|
|
|
} else
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_ECP_C */
|
2023-01-11 14:50:10 +01:00
|
|
|
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_PEM_WRITE_C)
|
2013-09-15 14:54:56 +02:00
|
|
|
|
|
|
|
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
|
|
|
|
#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
|
|
|
|
|
|
|
|
#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
|
|
|
|
#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
|
|
|
|
#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
|
|
|
|
#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
|
2023-04-19 14:08:14 +02:00
|
|
|
#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n"
|
|
|
|
#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n"
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2022-03-01 10:03:21 +01:00
|
|
|
#define PUB_DER_MAX_BYTES \
|
2023-01-11 14:50:10 +01:00
|
|
|
(MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
|
|
|
|
MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
|
2022-03-01 10:03:21 +01:00
|
|
|
#define PRV_DER_MAX_BYTES \
|
2023-01-11 14:50:10 +01:00
|
|
|
(MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
|
|
|
|
MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
|
2014-07-21 16:37:15 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2014-07-21 16:37:15 +02:00
|
|
|
unsigned char output_buf[PUB_DER_MAX_BYTES];
|
2013-09-15 20:03:26 +02:00
|
|
|
size_t olen = 0;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
|
|
|
|
sizeof(output_buf))) < 0) {
|
|
|
|
return ret;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
|
|
|
|
output_buf + sizeof(output_buf) - ret,
|
|
|
|
ret, buf, size, &olen)) != 0) {
|
|
|
|
return ret;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
|
2013-09-15 14:54:56 +02:00
|
|
|
{
|
2019-11-22 14:21:35 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2014-07-21 16:37:15 +02:00
|
|
|
unsigned char output_buf[PRV_DER_MAX_BYTES];
|
2013-10-11 09:36:52 +02:00
|
|
|
const char *begin, *end;
|
2013-09-15 20:03:26 +02:00
|
|
|
size_t olen = 0;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_RSA_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
|
2013-09-15 14:54:56 +02:00
|
|
|
begin = PEM_BEGIN_PRIVATE_KEY_RSA;
|
|
|
|
end = PEM_END_PRIVATE_KEY_RSA;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2023-04-07 15:53:51 +02:00
|
|
|
#if defined(MBEDTLS_ECP_LIGHT)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
|
2023-04-19 14:08:14 +02:00
|
|
|
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
|
|
|
|
if (mbedtls_pk_is_rfc8410_curve(mbedtls_pk_ec(*key)->grp.id)) {
|
|
|
|
begin = PEM_BEGIN_PRIVATE_KEY_PKCS8;
|
|
|
|
end = PEM_END_PRIVATE_KEY_PKCS8;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
begin = PEM_BEGIN_PRIVATE_KEY_EC;
|
|
|
|
end = PEM_END_PRIVATE_KEY_EC;
|
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
} else
|
2013-09-15 14:54:56 +02:00
|
|
|
#endif
|
2023-01-11 14:50:10 +01:00
|
|
|
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_pem_write_buffer(begin, end,
|
|
|
|
output_buf + sizeof(output_buf) - ret,
|
|
|
|
ret, buf, size, &olen)) != 0) {
|
|
|
|
return ret;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2013-09-15 14:54:56 +02:00
|
|
|
}
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_PEM_WRITE_C */
|
2013-09-15 14:54:56 +02:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_PK_WRITE_C */
|