mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-03-25 04:43:32 +00:00
pk/rsa: move RSA parse/write private/public key functions to rsa module
These functions are meant to be used internally, so their prototype declaration is kept into rsa_internal.h. Signed-off-by: Valerio Setti <valerio.setti@nordicsemi.no>
This commit is contained in:
parent
429cd50ac8
commit
b328c44932
@ -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 mbedtls_rsa_pubkey_parse(mbedtls_rsa_context *rsa,
|
||||
unsigned char **p,
|
||||
const unsigned char *end)
|
||||
{
|
||||
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 {
|
||||
@ -944,195 +883,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 mbedtls_rsa_key_parse(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
|
||||
|
@ -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,135 +59,6 @@
|
||||
* Internal functions for RSA keys.
|
||||
******************************************************************************/
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
static int mbedtls_rsa_pubkey_write(unsigned char **p, unsigned char *start,
|
||||
const mbedtls_rsa_context *rsa)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int mbedtls_rsa_key_write(unsigned char **p, unsigned char *start,
|
||||
const mbedtls_rsa_context *rsa)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
||||
const mbedtls_pk_context *pk)
|
||||
{
|
||||
@ -204,7 +78,7 @@ static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
||||
return (int) len;
|
||||
}
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
return mbedtls_rsa_key_write(p, buf, mbedtls_pk_rsa(*pk));
|
||||
return mbedtls_rsa_key_write(mbedtls_pk_rsa(*pk), buf, p);
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
@ -542,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, mbedtls_rsa_pubkey_write(p, start, mbedtls_pk_rsa(*key)));
|
||||
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_pubkey_write(mbedtls_pk_rsa(*key), start, p));
|
||||
} else
|
||||
#endif
|
||||
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
||||
|
373
library/rsa.c
373
library/rsa.c
@ -31,6 +31,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"
|
||||
@ -659,6 +660,378 @@ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
|
||||
return ctx->len;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
int mbedtls_rsa_key_parse(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
*/
|
||||
int mbedtls_rsa_pubkey_parse(mbedtls_rsa_context *rsa, unsigned char **p,
|
||||
const unsigned char *end)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int mbedtls_rsa_key_write(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_pubkey_write(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_GENPRIME)
|
||||
|
||||
|
@ -16,6 +16,49 @@
|
||||
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \param rsa
|
||||
* \param key
|
||||
* \param keylen
|
||||
* \return int
|
||||
*/
|
||||
int mbedtls_rsa_key_parse(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \param rsa
|
||||
* \param p
|
||||
* \param end
|
||||
* \return int
|
||||
*/
|
||||
int mbedtls_rsa_pubkey_parse(mbedtls_rsa_context *rsa, unsigned char **p,
|
||||
const unsigned char *end);
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \param p
|
||||
* \param start
|
||||
* \param rsa
|
||||
* \return int
|
||||
*/
|
||||
int mbedtls_rsa_key_write(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p);
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \param p
|
||||
* \param start
|
||||
* \param rsa
|
||||
* \return int
|
||||
*/
|
||||
int mbedtls_rsa_pubkey_write(const mbedtls_rsa_context *rsa, unsigned char *start,
|
||||
unsigned char **p);
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V21)
|
||||
/**
|
||||
* \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign().
|
||||
|
Loading…
x
Reference in New Issue
Block a user