Split up the RSA PKCS#1 encrypt, decrypt, sign and verify functions

Split rsa_pkcs1_encrypt() into rsa_rsaes_oaep_encrypt() and
rsa_rsaes_pkcs1_v15_encrypt()
Split rsa_pkcs1_decrypt() into rsa_rsaes_oaep_decrypt() and
rsa_rsaes_pkcs1_v15_decrypt()
Split rsa_pkcs1_sign() into rsa_rsassa_pss_sign() and
rsa_rsassa_pkcs1_v15_sign()
Split rsa_pkcs1_verify() into rsa_rsassa_pss_verify() and
rsa_rsassa_pkcs1_v15_verify()

The original functions exist as generic wrappers to these functions.
This commit is contained in:
Paul Bakker 2013-02-28 17:21:01 +01:00
parent e3e4a59622
commit b386913f8b
3 changed files with 953 additions and 568 deletions

View File

@ -7,6 +7,11 @@ Bugfix
128-bits (found by Yawning Angel)
* Fixes for 64-bit compilation with MS Visual Studio
Changes
* Internally split up rsa_pkcs1_encrypt(), rsa_pkcs1_decrypt(),
rsa_pkcs1_sign() and rsa_pkcs1_verify() to separate PKCS#1 v1.5 and
PKCS#1 v2.1 functions
Security
* Removed further timing differences during SSL message decryption in
ssl_decrypt_buf()

View File

@ -255,7 +255,9 @@ int rsa_private( rsa_context *ctx,
unsigned char *output );
/**
* \brief Add the message padding, then do an RSA operation
* \brief Generic wrapper to perform a PKCS#1 encryption using the
* mode from the context. Add the message padding, then do an
* RSA operation.
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
@ -278,7 +280,55 @@ int rsa_pkcs1_encrypt( rsa_context *ctx,
unsigned char *output );
/**
* \brief Do an RSA operation, then remove the message padding
* \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output );
/**
* \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output );
/**
* \brief Generic wrapper to perform a PKCS#1 decryption using the
* mode from the context. Do an RSA operation, then remove
* the message padding
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
@ -300,7 +350,53 @@ int rsa_pkcs1_decrypt( rsa_context *ctx,
size_t output_max_len );
/**
* \brief Do a private RSA to sign a message digest
* \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );
/**
* \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );
/**
* \brief Generic wrapper to perform a PKCS#1 signature using the
* mode from the context. Do a private RSA operation to sign
* a message digest
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
@ -333,7 +429,65 @@ int rsa_pkcs1_sign( rsa_context *ctx,
unsigned char *sig );
/**
* \brief Do a public RSA and check the message digest
* \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* encoding. hash_id in the function call is the type of hash
* that is encoded. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_rsassa_pss_sign( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Generic wrapper to perform a PKCS#1 verification using the
* mode from the context. Do a public RSA operation and check
* the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
@ -361,6 +515,59 @@ int rsa_pkcs1_verify( rsa_context *ctx,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY)
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
* \brief Do a public RSA and check the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* verification. hash_id in the function call is the type of hash
* that is verified. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_rsassa_pss_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Free the components of an RSA key
*

View File

@ -361,79 +361,33 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_
}
#endif
#if defined(POLARSSL_PKCS1_V21)
/*
* Add the message padding, then do an RSA operation
* Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
*/
int rsa_pkcs1_encrypt( rsa_context *ctx,
int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output )
{
size_t nb_pad, olen;
size_t olen;
int ret;
unsigned char *p = output;
#if defined(POLARSSL_PKCS1_V21)
unsigned int hlen;
const md_info_t *md_info;
md_context_t md_ctx;
#endif
olen = ctx->len;
if( f_rng == NULL )
if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( olen < ilen + 11 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
nb_pad = olen - 3 - ilen;
*p++ = 0;
if( mode == RSA_PUBLIC )
{
*p++ = RSA_CRYPT;
while( nb_pad-- > 0 )
{
int rng_dl = 100;
do {
ret = f_rng( p_rng, p, 1 );
} while( *p == 0 && --rng_dl && ret == 0 );
// Check if RNG failed to generate data
//
if( rng_dl == 0 || ret != 0)
return POLARSSL_ERR_RSA_RNG_FAILED + ret;
p++;
}
}
else
{
*p++ = RSA_SIGN;
while( nb_pad-- > 0 )
*p++ = 0xFF;
}
*p++ = 0;
memcpy( p, input, ilen );
break;
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
hlen = md_get_size( md_info );
if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
@ -471,13 +425,68 @@ int rsa_pkcs1_encrypt( rsa_context *ctx,
&md_ctx );
md_free_ctx( &md_ctx );
break;
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, output, output )
: rsa_private( ctx, output, output ) );
}
#endif /* POLARSSL_PKCS1_V21 */
/*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
*/
int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output )
{
size_t nb_pad, olen;
int ret;
unsigned char *p = output;
if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
if( olen < ilen + 11 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
nb_pad = olen - 3 - ilen;
*p++ = 0;
if( mode == RSA_PUBLIC )
{
*p++ = RSA_CRYPT;
while( nb_pad-- > 0 )
{
int rng_dl = 100;
do {
ret = f_rng( p_rng, p, 1 );
} while( *p == 0 && --rng_dl && ret == 0 );
// Check if RNG failed to generate data
//
if( rng_dl == 0 || ret != 0)
return POLARSSL_ERR_RSA_RNG_FAILED + ret;
p++;
}
}
else
{
*p++ = RSA_SIGN;
while( nb_pad-- > 0 )
*p++ = 0xFF;
}
*p++ = 0;
memcpy( p, input, ilen );
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, output, output )
@ -485,9 +494,37 @@ int rsa_pkcs1_encrypt( rsa_context *ctx,
}
/*
* Do an RSA operation, then remove the message padding
* Add the message padding, then do an RSA operation
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int rsa_pkcs1_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output )
{
switch( ctx->padding )
{
case RSA_PKCS_V15:
return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
input, output );
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
ilen, input, output );
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
}
#if defined(POLARSSL_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
*/
int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
@ -496,14 +533,14 @@ int rsa_pkcs1_decrypt( rsa_context *ctx,
int ret;
size_t ilen;
unsigned char *p;
unsigned char bt;
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
#if defined(POLARSSL_PKCS1_V21)
unsigned char lhash[POLARSSL_MD_MAX_SIZE];
unsigned int hlen;
const md_info_t *md_info;
md_context_t md_ctx;
#endif
if( ctx->padding != RSA_PKCS_V21 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
@ -519,46 +556,6 @@ int rsa_pkcs1_decrypt( rsa_context *ctx,
p = buf;
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( *p++ != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
bt = *p++;
if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) ||
( bt != RSA_SIGN && mode == RSA_PUBLIC ) )
{
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
if( bt == RSA_CRYPT )
{
while( *p != 0 && p < buf + ilen - 1 )
p++;
if( *p != 0 || p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
else
{
while( *p == 0xFF && p < buf + ilen - 1 )
p++;
if( *p != 0 || p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
break;
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
if( *p++ != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
@ -603,12 +600,77 @@ int rsa_pkcs1_decrypt( rsa_context *ctx,
if( *p++ != 0x01 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
break;
#endif
if (ilen - (p - buf) > output_max_len)
return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
default:
*olen = ilen - (p - buf);
memcpy( output, p, *olen );
return( 0 );
}
#endif /* POLARSSL_PKCS1_V21 */
/*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
*/
int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len)
{
int ret;
size_t ilen;
unsigned char *p;
unsigned char bt;
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
if( ilen < 16 || ilen > sizeof( buf ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, input, buf )
: rsa_private( ctx, input, buf );
if( ret != 0 )
return( ret );
p = buf;
if( *p++ != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
bt = *p++;
if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) ||
( bt != RSA_SIGN && mode == RSA_PUBLIC ) )
{
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
if( bt == RSA_CRYPT )
{
while( *p != 0 && p < buf + ilen - 1 )
p++;
if( *p != 0 || p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
else
{
while( *p == 0xFF && p < buf + ilen - 1 )
p++;
if( *p != 0 || p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
if (ilen - (p - buf) > output_max_len)
@ -621,9 +683,36 @@ int rsa_pkcs1_decrypt( rsa_context *ctx,
}
/*
* Do an RSA operation to sign the message digest
* Do an RSA operation, then remove the message padding
*/
int rsa_pkcs1_sign( rsa_context *ctx,
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len)
{
switch( ctx->padding )
{
case RSA_PKCS_V15:
return rsa_rsaes_pkcs1_v15_decrypt( ctx, mode, olen, input, output,
output_max_len );
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
return rsa_rsaes_oaep_decrypt( ctx, mode, NULL, 0, olen, input,
output, output_max_len );
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
}
#if defined(POLARSSL_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
*/
int rsa_rsassa_pss_sign( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
@ -632,25 +721,132 @@ int rsa_pkcs1_sign( rsa_context *ctx,
const unsigned char *hash,
unsigned char *sig )
{
size_t nb_pad, olen;
size_t olen;
unsigned char *p = sig;
#if defined(POLARSSL_PKCS1_V21)
unsigned char salt[POLARSSL_MD_MAX_SIZE];
unsigned int slen, hlen, offset = 0;
int ret;
size_t msb;
const md_info_t *md_info;
md_context_t md_ctx;
#else
(void) f_rng;
(void) p_rng;
#endif
if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
switch( ctx->padding )
switch( hash_id )
{
case RSA_PKCS_V15:
case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
hashlen = 16;
break;
case SIG_RSA_SHA1:
hashlen = 20;
break;
case SIG_RSA_SHA224:
hashlen = 28;
break;
case SIG_RSA_SHA256:
hashlen = 32;
break;
case SIG_RSA_SHA384:
hashlen = 48;
break;
case SIG_RSA_SHA512:
hashlen = 64;
break;
default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hlen = md_get_size( md_info );
slen = hlen;
if( olen < hlen + slen + 2 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
memset( sig, 0, olen );
msb = mpi_msb( &ctx->N ) - 1;
// Generate salt of length slen
//
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
// Note: EMSA-PSS encoding is over the length of N - 1 bits
//
msb = mpi_msb( &ctx->N ) - 1;
p += olen - hlen * 2 - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
p += slen;
md_init_ctx( &md_ctx, md_info );
// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, p, 8 );
md_update( &md_ctx, hash, hashlen );
md_update( &md_ctx, salt, slen );
md_finish( &md_ctx, p );
// Compensate for boundary condition when applying mask
//
if( msb % 8 == 0 )
offset = 1;
// maskedDB: Apply dbMask to DB
//
mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
md_free_ctx( &md_ctx );
msb = mpi_msb( &ctx->N ) - 1;
sig[0] &= 0xFF >> ( olen * 8 - msb );
p += hlen;
*p++ = 0xBC;
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig )
: rsa_private( ctx, sig, sig ) );
}
#endif /* POLARSSL_PKCS1_V21 */
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
*/
/*
* Do an RSA operation to sign the message digest
*/
int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
size_t nb_pad, olen;
unsigned char *p = sig;
if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
switch( hash_id )
{
@ -748,116 +944,45 @@ int rsa_pkcs1_sign( rsa_context *ctx,
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
break;
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
if( f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
switch( hash_id )
{
case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
hashlen = 16;
break;
case SIG_RSA_SHA1:
hashlen = 20;
break;
case SIG_RSA_SHA224:
hashlen = 28;
break;
case SIG_RSA_SHA256:
hashlen = 32;
break;
case SIG_RSA_SHA384:
hashlen = 48;
break;
case SIG_RSA_SHA512:
hashlen = 64;
break;
default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hlen = md_get_size( md_info );
slen = hlen;
if( olen < hlen + slen + 2 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
memset( sig, 0, olen );
msb = mpi_msb( &ctx->N ) - 1;
// Generate salt of length slen
//
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
// Note: EMSA-PSS encoding is over the length of N - 1 bits
//
msb = mpi_msb( &ctx->N ) - 1;
p += olen - hlen * 2 - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
p += slen;
md_init_ctx( &md_ctx, md_info );
// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, p, 8 );
md_update( &md_ctx, hash, hashlen );
md_update( &md_ctx, salt, slen );
md_finish( &md_ctx, p );
// Compensate for boundary condition when applying mask
//
if( msb % 8 == 0 )
offset = 1;
// maskedDB: Apply dbMask to DB
//
mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
md_free_ctx( &md_ctx );
msb = mpi_msb( &ctx->N ) - 1;
sig[0] &= 0xFF >> ( olen * 8 - msb );
p += hlen;
*p++ = 0xBC;
break;
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig )
: rsa_private( ctx, sig, sig ) );
}
/*
* Do an RSA operation and check the message digest
* Do an RSA operation to sign the message digest
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int rsa_pkcs1_sign( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
switch( ctx->padding )
{
case RSA_PKCS_V15:
return rsa_rsassa_pkcs1_v15_sign( ctx, mode, hash_id,
hashlen, hash, sig );
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, hash_id,
hashlen, hash, sig );
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
}
#if defined(POLARSSL_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
*/
int rsa_rsassa_pss_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
@ -865,17 +990,19 @@ int rsa_pkcs1_verify( rsa_context *ctx,
unsigned char *sig )
{
int ret;
size_t len, siglen;
unsigned char *p, c;
size_t siglen;
unsigned char *p;
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
#if defined(POLARSSL_PKCS1_V21)
unsigned char result[POLARSSL_MD_MAX_SIZE];
unsigned char zeros[8];
unsigned int hlen;
size_t slen, msb;
const md_info_t *md_info;
md_context_t md_ctx;
#endif
if( ctx->padding != RSA_PKCS_V21 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
siglen = ctx->len;
if( siglen < 16 || siglen > sizeof( buf ) )
@ -890,88 +1017,6 @@ int rsa_pkcs1_verify( rsa_context *ctx,
p = buf;
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( *p++ != 0 || *p++ != RSA_SIGN )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
len = siglen - ( p - buf );
if( len == 33 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
memcmp( p + 13, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == 34 )
{
c = p[13];
p[13] = 0;
if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
( c == 4 && hash_id == SIG_RSA_MD4 ) ||
( c == 5 && hash_id == SIG_RSA_MD5 ) )
{
if( memcmp( p + 18, hash, 16 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
}
if( len == 35 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
memcmp( p + 15, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
{
c = p[1] - 17;
p[1] = 17;
p[14] = 0;
if( p[18] == c &&
memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
memcmp( p + 19, hash, c ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == hashlen && hash_id == SIG_RSA_RAW )
{
if( memcmp( p, hash, hashlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
break;
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
if( buf[siglen - 1] != 0xBC )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
@ -1062,15 +1107,143 @@ int rsa_pkcs1_verify( rsa_context *ctx,
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
#endif
}
#endif /* POLARSSL_PKCS1_V21 */
default:
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
*/
int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
int ret;
size_t len, siglen;
unsigned char *p, c;
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
siglen = ctx->len;
if( siglen < 16 || siglen > sizeof( buf ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, buf )
: rsa_private( ctx, sig, buf );
if( ret != 0 )
return( ret );
p = buf;
if( *p++ != 0 || *p++ != RSA_SIGN )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
len = siglen - ( p - buf );
if( len == 33 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
memcmp( p + 13, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == 34 )
{
c = p[13];
p[13] = 0;
if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
( c == 4 && hash_id == SIG_RSA_MD4 ) ||
( c == 5 && hash_id == SIG_RSA_MD5 ) )
{
if( memcmp( p + 18, hash, 16 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
}
if( len == 35 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
memcmp( p + 15, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
{
c = p[1] - 17;
p[1] = 17;
p[14] = 0;
if( p[18] == c &&
memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
memcmp( p + 19, hash, c ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == hashlen && hash_id == SIG_RSA_RAW )
{
if( memcmp( p, hash, hashlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
/*
* Do an RSA operation and check the message digest
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
switch( ctx->padding )
{
case RSA_PKCS_V15:
return rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id,
hashlen, hash, sig );
#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:
return rsa_rsassa_pss_verify( ctx, mode, hash_id,
hashlen, hash, sig );
#endif
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
}
/*
* Free the components of an RSA key