Merge pull request #8740 from valeriosetti/issue8647
Move RSA basic key parsing/writing to rsa.c
This commit is contained in:
commit
7bf1e98f44
16 changed files with 731 additions and 572 deletions
|
@ -32,6 +32,7 @@
|
|||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
#include "pkwrite.h"
|
||||
#include "rsa_internal.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
|
||||
|
@ -69,9 +70,9 @@ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
|
|||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status;
|
||||
mbedtls_pk_context key;
|
||||
int key_len;
|
||||
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
|
||||
unsigned char *p = buf + sizeof(buf);
|
||||
psa_algorithm_t psa_alg_md =
|
||||
PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
|
||||
size_t rsa_len = mbedtls_rsa_get_len(rsa);
|
||||
|
@ -86,11 +87,7 @@ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
|
|||
return MBEDTLS_ERR_RSA_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
/* mbedtls_pk_write_pubkey_der() expects a full PK context;
|
||||
* re-construct one to make it happy */
|
||||
key.pk_info = &mbedtls_rsa_info;
|
||||
key.pk_ctx = rsa;
|
||||
key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
|
||||
key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
|
||||
if (key_len <= 0) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
}
|
||||
|
@ -172,14 +169,15 @@ int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
|
|||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status;
|
||||
mbedtls_pk_context key;
|
||||
int key_len;
|
||||
unsigned char *buf = NULL;
|
||||
unsigned char *p;
|
||||
|
||||
buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);
|
||||
if (buf == NULL) {
|
||||
return MBEDTLS_ERR_PK_ALLOC_FAILED;
|
||||
}
|
||||
mbedtls_pk_info_t pk_info = mbedtls_rsa_info;
|
||||
p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES;
|
||||
|
||||
*sig_len = mbedtls_rsa_get_len(rsa_ctx);
|
||||
if (sig_size < *sig_len) {
|
||||
|
@ -187,11 +185,7 @@ int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
|
|||
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* mbedtls_pk_write_key_der() expects a full PK context;
|
||||
* re-construct one to make it happy */
|
||||
key.pk_info = &pk_info;
|
||||
key.pk_ctx = rsa_ctx;
|
||||
key_len = mbedtls_pk_write_key_der(&key, buf, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);
|
||||
key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p);
|
||||
if (key_len <= 0) {
|
||||
mbedtls_free(buf);
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
|
@ -282,9 +276,9 @@ static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
|
|||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status;
|
||||
mbedtls_pk_context key;
|
||||
int key_len;
|
||||
unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
|
||||
unsigned char *p = buf + sizeof(buf);
|
||||
|
||||
((void) f_rng);
|
||||
((void) p_rng);
|
||||
|
@ -299,11 +293,7 @@ static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
|
|||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* mbedtls_pk_write_key_der() expects a full PK context;
|
||||
* re-construct one to make it happy */
|
||||
key.pk_info = &mbedtls_rsa_info;
|
||||
key.pk_ctx = rsa;
|
||||
key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
|
||||
key_len = mbedtls_rsa_write_key(rsa, buf, &p);
|
||||
if (key_len <= 0) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
}
|
||||
|
@ -368,9 +358,9 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
|
|||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status;
|
||||
mbedtls_pk_context key;
|
||||
int key_len;
|
||||
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
|
||||
unsigned char *p = buf + sizeof(buf);
|
||||
|
||||
((void) f_rng);
|
||||
((void) p_rng);
|
||||
|
@ -385,11 +375,7 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
|
|||
return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* mbedtls_pk_write_pubkey_der() expects a full PK context;
|
||||
* re-construct one to make it happy */
|
||||
key.pk_info = &mbedtls_rsa_info;
|
||||
key.pk_ctx = rsa;
|
||||
key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
|
||||
key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
|
||||
if (key_len <= 0) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
/* Key types */
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "rsa_internal.h"
|
||||
#endif
|
||||
|
||||
/* Extended formats */
|
||||
|
@ -757,68 +758,6 @@ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
|
|||
|
||||
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
static int pk_get_rsapubkey(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_rsa_context *rsa)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len;
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
|
||||
}
|
||||
|
||||
if (*p + len != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
/* Import N */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
|
||||
NULL, 0, NULL, 0)) != 0) {
|
||||
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
|
||||
}
|
||||
|
||||
*p += len;
|
||||
|
||||
/* Import E */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
|
||||
NULL, 0, *p, len)) != 0) {
|
||||
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
|
||||
}
|
||||
|
||||
*p += len;
|
||||
|
||||
if (mbedtls_rsa_complete(rsa) != 0 ||
|
||||
mbedtls_rsa_check_pubkey(rsa) != 0) {
|
||||
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
|
||||
}
|
||||
|
||||
if (*p != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
/* Get a PK algorithm identifier
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
|
@ -911,7 +850,17 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
|
|||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if (pk_alg == MBEDTLS_PK_RSA) {
|
||||
ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
|
||||
ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
|
||||
if (ret == 0) {
|
||||
/* On success all the input has been consumed by the parsing function. */
|
||||
*p += end - *p;
|
||||
} else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
|
||||
(ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
|
||||
/* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
|
||||
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
|
||||
}
|
||||
} else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
||||
|
@ -944,195 +893,6 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
/*
|
||||
* Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
|
||||
*
|
||||
* The value zero is:
|
||||
* - never a valid value for an RSA parameter
|
||||
* - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
|
||||
*
|
||||
* Since values can't be omitted in PKCS#1, passing a zero value to
|
||||
* rsa_complete() would be incorrect, so reject zero values early.
|
||||
*/
|
||||
static int asn1_get_nonzero_mpi(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_mpi *X)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mbedtls_asn1_get_mpi(p, end, X);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int(X, 0) == 0) {
|
||||
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a PKCS#1 encoded private RSA key
|
||||
*/
|
||||
static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret, version;
|
||||
size_t len;
|
||||
unsigned char *p, *end;
|
||||
|
||||
mbedtls_mpi T;
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
p = (unsigned char *) key;
|
||||
end = p + keylen;
|
||||
|
||||
/*
|
||||
* This function parses the RSAPrivateKey (PKCS#1)
|
||||
*
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version Version,
|
||||
* 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
|
||||
* otherPrimeInfos OtherPrimeInfos OPTIONAL
|
||||
* }
|
||||
*/
|
||||
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
|
||||
}
|
||||
|
||||
end = p + len;
|
||||
|
||||
if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
|
||||
}
|
||||
|
||||
if (version != 0) {
|
||||
return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
|
||||
}
|
||||
|
||||
/* Import N */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import E */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
|
||||
NULL, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import D */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
|
||||
&T, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import P */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import Q */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
|
||||
/*
|
||||
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in
|
||||
* that they can be easily recomputed from D, P and Q. However by
|
||||
* parsing them from the PKCS1 structure it is possible to avoid
|
||||
* recalculating them which both reduces the overhead of loading
|
||||
* RSA private keys into memory and also avoids side channels which
|
||||
* can arise when computing those values, since all of D, P, and Q
|
||||
* are secret. See https://eprint.iacr.org/2020/055 for a
|
||||
* description of one such attack.
|
||||
*/
|
||||
|
||||
/* Import DP */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import DQ */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import QP */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Verify existence of the CRT params */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* rsa_complete() doesn't complete anything with the default
|
||||
* implementation but is still called:
|
||||
* - for the benefit of alternative implementation that may want to
|
||||
* pre-compute stuff beyond what's provided (eg Montgomery factors)
|
||||
* - as is also sanity-checks the key
|
||||
*
|
||||
* Furthermore, we also check the public part for consistency with
|
||||
* mbedtls_pk_parse_pubkey(), as it includes size minima for example.
|
||||
*/
|
||||
if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
|
||||
(ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (p != end) {
|
||||
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
|
||||
if (ret != 0) {
|
||||
/* Wrap error code if it's coming from a lower level */
|
||||
if ((ret & 0xff80) == 0) {
|
||||
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
mbedtls_rsa_free(rsa);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
||||
/*
|
||||
* Parse a SEC1 encoded private EC key
|
||||
|
@ -1348,7 +1108,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
|
|||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if (pk_alg == MBEDTLS_PK_RSA) {
|
||||
if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
|
||||
if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
|
||||
mbedtls_pk_free(pk);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1538,8 +1298,8 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
|
|||
if (ret == 0) {
|
||||
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
|
||||
if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
|
||||
(ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
|
||||
pem.buf, pem.buflen)) != 0) {
|
||||
(ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
|
||||
pem.buf, pem.buflen)) != 0) {
|
||||
mbedtls_pk_free(pk);
|
||||
}
|
||||
|
||||
|
@ -1679,7 +1439,7 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
|
|||
|
||||
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
|
||||
if (mbedtls_pk_setup(pk, pk_info) == 0 &&
|
||||
pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
|
||||
mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1754,7 +1514,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
|
||||
if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
|
||||
mbedtls_pk_free(ctx);
|
||||
}
|
||||
|
||||
|
@ -1801,13 +1561,12 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
|
|||
}
|
||||
|
||||
p = (unsigned char *) key;
|
||||
ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
|
||||
ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
|
||||
if (ret == 0) {
|
||||
return ret;
|
||||
}
|
||||
mbedtls_pk_free(ctx);
|
||||
if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
|
||||
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
|
||||
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
|
||||
return ret;
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#if defined(MBEDTLS_PEM_WRITE_C)
|
||||
#include "mbedtls/pem.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
#include "rsa_internal.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
#include "psa/crypto.h"
|
||||
|
@ -56,60 +59,13 @@
|
|||
* Internal functions for RSA keys.
|
||||
******************************************************************************/
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
|
||||
const mbedtls_pk_context *pk)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len = 0;
|
||||
mbedtls_mpi T;
|
||||
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
|
||||
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
/* Export E */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export N */
|
||||
if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
end_of_export:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
return (int) len;
|
||||
}
|
||||
|
||||
static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
||||
const mbedtls_pk_context *pk)
|
||||
{
|
||||
size_t len = 0;
|
||||
int ret;
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
|
||||
uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
|
||||
size_t tmp_len = 0;
|
||||
size_t len = 0, tmp_len = 0;
|
||||
|
||||
if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
|
@ -118,94 +74,11 @@ static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
|||
memcpy(*p, tmp, tmp_len);
|
||||
len += tmp_len;
|
||||
mbedtls_platform_zeroize(tmp, sizeof(tmp));
|
||||
} else
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
{
|
||||
mbedtls_mpi T; /* Temporary holding the exported parameters */
|
||||
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
|
||||
|
||||
/*
|
||||
* Export the parameters one after another to avoid simultaneous copies.
|
||||
*/
|
||||
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
/* Export QP */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export DQ */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export DP */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export Q */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
||||
&T, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export P */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
|
||||
NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export D */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
||||
NULL, &T, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export E */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
|
||||
NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export N */
|
||||
if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
|
||||
NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
end_of_export:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return (int) len;
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
|
@ -543,7 +416,7 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
|
|||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
|
||||
MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key));
|
||||
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
|
||||
} else
|
||||
#endif
|
||||
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
|
||||
#include <mbedtls/rsa.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/pk.h>
|
||||
#include "pk_wrap.h"
|
||||
#include "rsa_internal.h"
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
|
||||
|
@ -62,50 +61,38 @@ psa_status_t mbedtls_psa_rsa_load_representation(
|
|||
mbedtls_rsa_context **p_rsa)
|
||||
{
|
||||
psa_status_t status;
|
||||
mbedtls_pk_context ctx;
|
||||
size_t bits;
|
||||
mbedtls_pk_init(&ctx);
|
||||
|
||||
*p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
|
||||
if (*p_rsa == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
mbedtls_rsa_init(*p_rsa);
|
||||
|
||||
/* Parse the data. */
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_pk_parse_key(&ctx, data, data_length, NULL, 0,
|
||||
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE));
|
||||
status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));
|
||||
} else {
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_pk_parse_public_key(&ctx, data, data_length));
|
||||
status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));
|
||||
}
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* We have something that the pkparse module recognizes. If it is a
|
||||
* valid RSA key, store it. */
|
||||
if (mbedtls_pk_get_type(&ctx) != MBEDTLS_PK_RSA) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
|
||||
* supports non-byte-aligned key sizes, but not well. For example,
|
||||
* mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
|
||||
bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(mbedtls_pk_rsa(ctx)));
|
||||
bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));
|
||||
if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
status = psa_check_rsa_key_byte_aligned(mbedtls_pk_rsa(ctx));
|
||||
status = psa_check_rsa_key_byte_aligned(*p_rsa);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Copy out the pointer to the RSA context, and reset the PK context
|
||||
* such that pk_free doesn't free the RSA context we just grabbed. */
|
||||
*p_rsa = mbedtls_pk_rsa(ctx);
|
||||
ctx.pk_info = NULL;
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&ctx);
|
||||
return status;
|
||||
}
|
||||
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
|
||||
|
@ -168,20 +155,15 @@ psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,
|
|||
size_t *data_length)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context pk;
|
||||
uint8_t *pos = data + data_size;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
pk.pk_info = &mbedtls_rsa_info;
|
||||
pk.pk_ctx = rsa;
|
||||
uint8_t *end = data + data_size;
|
||||
|
||||
/* PSA Crypto API defines the format of an RSA key as a DER-encoded
|
||||
* representation of the non-encrypted PKCS#1 RSAPrivateKey for a
|
||||
* private key and of the RFC3279 RSAPublicKey for a public key. */
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
|
||||
ret = mbedtls_pk_write_key_der(&pk, data, data_size);
|
||||
ret = mbedtls_rsa_write_key(rsa, data, &end);
|
||||
} else {
|
||||
ret = mbedtls_pk_write_pubkey(&pos, data, &pk);
|
||||
ret = mbedtls_rsa_write_pubkey(rsa, data, &end);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
|
|
363
library/rsa.c
363
library/rsa.c
|
@ -32,6 +32,7 @@
|
|||
#include "rsa_alt_helpers.h"
|
||||
#include "rsa_internal.h"
|
||||
#include "mbedtls/oid.h"
|
||||
#include "mbedtls/asn1write.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "constant_time_internal.h"
|
||||
|
@ -46,6 +47,367 @@
|
|||
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
/*
|
||||
* Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
|
||||
*
|
||||
* The value zero is:
|
||||
* - never a valid value for an RSA parameter
|
||||
* - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
|
||||
*
|
||||
* Since values can't be omitted in PKCS#1, passing a zero value to
|
||||
* rsa_complete() would be incorrect, so reject zero values early.
|
||||
*/
|
||||
static int asn1_get_nonzero_mpi(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_mpi *X)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mbedtls_asn1_get_mpi(p, end, X);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int(X, 0) == 0) {
|
||||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret, version;
|
||||
size_t len;
|
||||
unsigned char *p, *end;
|
||||
|
||||
mbedtls_mpi T;
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
p = (unsigned char *) key;
|
||||
end = p + keylen;
|
||||
|
||||
/*
|
||||
* This function parses the RSAPrivateKey (PKCS#1)
|
||||
*
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version Version,
|
||||
* 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
|
||||
* otherPrimeInfos OtherPrimeInfos OPTIONAL
|
||||
* }
|
||||
*/
|
||||
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
|
||||
end = p + len;
|
||||
|
||||
if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (version != 0) {
|
||||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Import N */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import E */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
|
||||
NULL, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import D */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
|
||||
&T, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import P */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import Q */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
|
||||
NULL, NULL)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
|
||||
/*
|
||||
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in
|
||||
* that they can be easily recomputed from D, P and Q. However by
|
||||
* parsing them from the PKCS1 structure it is possible to avoid
|
||||
* recalculating them which both reduces the overhead of loading
|
||||
* RSA private keys into memory and also avoids side channels which
|
||||
* can arise when computing those values, since all of D, P, and Q
|
||||
* are secret. See https://eprint.iacr.org/2020/055 for a
|
||||
* description of one such attack.
|
||||
*/
|
||||
|
||||
/* Import DP */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import DQ */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Import QP */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Verify existence of the CRT params */
|
||||
if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
|
||||
(ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* rsa_complete() doesn't complete anything with the default
|
||||
* implementation but is still called:
|
||||
* - for the benefit of alternative implementation that may want to
|
||||
* pre-compute stuff beyond what's provided (eg Montgomery factors)
|
||||
* - as is also sanity-checks the key
|
||||
*
|
||||
* Furthermore, we also check the public part for consistency with
|
||||
* mbedtls_pk_parse_pubkey(), as it includes size minima for example.
|
||||
*/
|
||||
if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
|
||||
(ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (p != end) {
|
||||
ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
|
||||
if (ret != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) key;
|
||||
unsigned char *end = (unsigned char *) (key + keylen);
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
|
||||
end = p + len;
|
||||
|
||||
/* Import N */
|
||||
if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0,
|
||||
NULL, 0, NULL, 0)) != 0) {
|
||||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
p += len;
|
||||
|
||||
/* Import E */
|
||||
if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
|
||||
NULL, 0, p, len)) != 0) {
|
||||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
p += len;
|
||||
|
||||
if (mbedtls_rsa_complete(rsa) != 0 ||
|
||||
mbedtls_rsa_check_pubkey(rsa) != 0) {
|
||||
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (p != end) {
|
||||
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p)
|
||||
{
|
||||
size_t len = 0;
|
||||
int ret;
|
||||
|
||||
mbedtls_mpi T; /* Temporary holding the exported parameters */
|
||||
|
||||
/*
|
||||
* Export the parameters one after another to avoid simultaneous copies.
|
||||
*/
|
||||
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
/* Export QP */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export DQ */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export DP */
|
||||
if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export Q */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export P */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export D */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export E */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export N */
|
||||
if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
end_of_export:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0));
|
||||
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));
|
||||
|
||||
return (int) len;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len = 0;
|
||||
mbedtls_mpi T;
|
||||
|
||||
mbedtls_mpi_init(&T);
|
||||
|
||||
/* Export E */
|
||||
if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
/* Export N */
|
||||
if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
|
||||
(ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
|
||||
goto end_of_export;
|
||||
}
|
||||
len += ret;
|
||||
|
||||
end_of_export:
|
||||
|
||||
mbedtls_mpi_free(&T);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
return (int) len;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
|
@ -660,7 +1022,6 @@ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
|
|||
return ctx->len;
|
||||
}
|
||||
|
||||
|
||||
#if defined(MBEDTLS_GENPRIME)
|
||||
|
||||
/*
|
||||
|
|
|
@ -15,6 +15,85 @@
|
|||
#define MBEDTLS_RSA_INTERNAL_H
|
||||
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
|
||||
/**
|
||||
* \brief Parse a PKCS#1 (ASN.1) encoded private RSA key.
|
||||
*
|
||||
* \param rsa The RSA context where parsed data will be stored.
|
||||
* \param key The buffer that contains the key.
|
||||
* \param keylen The length of the key buffer in bytes.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
|
||||
* \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
|
||||
* parsing data.
|
||||
* \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
|
||||
* provided key fail.
|
||||
*/
|
||||
int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
|
||||
|
||||
/**
|
||||
* \brief Parse a PKCS#1 (ASN.1) encoded public RSA key.
|
||||
*
|
||||
* \param rsa The RSA context where parsed data will be stored.
|
||||
* \param key The buffer that contains the key.
|
||||
* \param keylen The length of the key buffer in bytes.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
|
||||
* \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
|
||||
* parsing data.
|
||||
* \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
|
||||
* provided key fail.
|
||||
*/
|
||||
int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
|
||||
|
||||
/**
|
||||
* \brief Write a PKCS#1 (ASN.1) encoded private RSA key.
|
||||
*
|
||||
* \param rsa The RSA context which contains the data to be written.
|
||||
* \param start Beginning of the buffer that will be filled with the
|
||||
* private key.
|
||||
* \param p End of the buffer that will be filled with the private key.
|
||||
* On successful return, the referenced pointer will be
|
||||
* updated in order to point to the beginning of written data.
|
||||
*
|
||||
* \return On success, the number of bytes written to the output buffer
|
||||
* (i.e. a value > 0).
|
||||
* \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
|
||||
* contain a valid key pair.
|
||||
* \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
|
||||
* output buffer.
|
||||
*
|
||||
* \note The output buffer is filled backward, i.e. starting from its
|
||||
* end and moving toward its start.
|
||||
*/
|
||||
int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p);
|
||||
|
||||
/**
|
||||
* \brief Parse a PKCS#1 (ASN.1) encoded public RSA key.
|
||||
*
|
||||
* \param rsa The RSA context which contains the data to be written.
|
||||
* \param start Beginning of the buffer that will be filled with the
|
||||
* private key.
|
||||
* \param p End of the buffer that will be filled with the private key.
|
||||
* On successful return, the referenced pointer will be
|
||||
* updated in order to point to the beginning of written data.
|
||||
*
|
||||
* \return On success, the number of bytes written to the output buffer
|
||||
* (i.e. a value > 0).
|
||||
* \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
|
||||
* contain a valid public key.
|
||||
* \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
|
||||
* output buffer.
|
||||
*
|
||||
* \note The output buffer is filled backward, i.e. starting from its
|
||||
* end and moving toward its start.
|
||||
*/
|
||||
int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p);
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V21)
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue