mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-10-12 18:44:56 +03: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:
@@ -28,6 +28,7 @@
|
|||||||
/* Key types */
|
/* Key types */
|
||||||
#if defined(MBEDTLS_RSA_C)
|
#if defined(MBEDTLS_RSA_C)
|
||||||
#include "mbedtls/rsa.h"
|
#include "mbedtls/rsa.h"
|
||||||
|
#include "rsa_internal.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Extended formats */
|
/* Extended formats */
|
||||||
@@ -757,68 +758,6 @@ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
|
|||||||
|
|
||||||
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
|
#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
|
/* Get a PK algorithm identifier
|
||||||
*
|
*
|
||||||
* AlgorithmIdentifier ::= SEQUENCE {
|
* AlgorithmIdentifier ::= SEQUENCE {
|
||||||
@@ -944,195 +883,6 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
|
|||||||
return ret;
|
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)
|
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
||||||
/*
|
/*
|
||||||
* Parse a SEC1 encoded private EC key
|
* Parse a SEC1 encoded private EC key
|
||||||
|
@@ -32,6 +32,9 @@
|
|||||||
#if defined(MBEDTLS_PEM_WRITE_C)
|
#if defined(MBEDTLS_PEM_WRITE_C)
|
||||||
#include "mbedtls/pem.h"
|
#include "mbedtls/pem.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MBEDTLS_RSA_C)
|
||||||
|
#include "rsa_internal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||||
#include "psa/crypto.h"
|
#include "psa/crypto.h"
|
||||||
@@ -56,135 +59,6 @@
|
|||||||
* Internal functions for RSA keys.
|
* Internal functions for RSA keys.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#if defined(MBEDTLS_RSA_C)
|
#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,
|
static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
||||||
const mbedtls_pk_context *pk)
|
const mbedtls_pk_context *pk)
|
||||||
{
|
{
|
||||||
@@ -204,7 +78,7 @@ static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
|||||||
return (int) len;
|
return (int) len;
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
#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 */
|
#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 defined(MBEDTLS_RSA_C)
|
||||||
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
|
#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_alt_helpers.h"
|
||||||
#include "rsa_internal.h"
|
#include "rsa_internal.h"
|
||||||
#include "mbedtls/oid.h"
|
#include "mbedtls/oid.h"
|
||||||
|
#include "mbedtls/asn1write.h"
|
||||||
#include "mbedtls/platform_util.h"
|
#include "mbedtls/platform_util.h"
|
||||||
#include "mbedtls/error.h"
|
#include "mbedtls/error.h"
|
||||||
#include "constant_time_internal.h"
|
#include "constant_time_internal.h"
|
||||||
@@ -659,6 +660,378 @@ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
|
|||||||
return ctx->len;
|
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)
|
#if defined(MBEDTLS_GENPRIME)
|
||||||
|
|
||||||
|
@@ -16,6 +16,49 @@
|
|||||||
|
|
||||||
#include "mbedtls/rsa.h"
|
#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)
|
#if defined(MBEDTLS_PKCS1_V21)
|
||||||
/**
|
/**
|
||||||
* \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign().
|
* \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign().
|
||||||
|
Reference in New Issue
Block a user