const md_info_t * md_kt_get (const char *digest) { const md_info_t *md = NULL; ASSERT (digest); md = md_info_from_string(digest); if (!md) msg (M_FATAL, "Message hash algorithm '%s' not found", digest); if (md_get_size(md) > MAX_HMAC_KEY_LENGTH) msg (M_FATAL, "Message hash algorithm '%s' uses a default hash size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum hash size (%d bytes)", digest, md_get_size(md), MAX_HMAC_KEY_LENGTH); return md; }
int md_kt_size (const md_info_t *kt) { if (NULL == kt) return 0; return md_get_size(kt); }
int hmac_ctx_size (const md_context_t *ctx) { if (NULL == ctx) return 0; return md_get_size(ctx->md_info); }
/* * HMAC_DRBG random function with optional additional data: * 10.1.2.5 (arabic) + 9.3 (Roman) */ SSL_ROM_TEXT_SECTION int hmac_drbg_random_with_add( void *p_rng, unsigned char *output, size_t out_len, const unsigned char *additional, size_t add_len ) { int ret; hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng; size_t md_len = md_get_size( ctx->md_ctx.md_info ); size_t left = out_len; unsigned char *out = output; /* II. Check request length */ if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST ) return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); /* III. Check input length */ if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT ) return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); /* 1. (aka VII and IX) Check reseed counter and PR */ if( ctx->f_entropy != NULL && /* For no-reseeding instances */ ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON || ctx->reseed_counter > ctx->reseed_interval ) ) { if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) return( ret ); add_len = 0; /* VII.4 */ } /* 2. Use additional data if any */ if( additional != NULL && add_len != 0 ) hmac_drbg_update( ctx, additional, add_len ); /* 3, 4, 5. Generate bytes */ while( left != 0 ) { size_t use_len = left > md_len ? md_len : left; md_hmac_reset( &ctx->md_ctx ); md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); md_hmac_finish( &ctx->md_ctx, ctx->V ); memcpy( out, ctx->V, use_len ); out += use_len; left -= use_len; } /* 6. Update */ hmac_drbg_update( ctx, additional, add_len ); /* 7. Update reseed counter */ ctx->reseed_counter++; /* 8. Done */ return( 0 ); }
/* * TODO: re-enable dmsg for crypto debug */ void hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info_t *kt) { ASSERT(NULL != kt && NULL != ctx); CLEAR(*ctx); ASSERT(0 == md_init_ctx(ctx, kt)); ASSERT(0 == md_hmac_starts(ctx, key, key_len)); /* make sure we used a big enough key */ ASSERT (md_get_size(kt) <= key_len); }
void show_available_digests () { const int *digests = md_list(); #ifndef ENABLE_SMALL printf ("The following message digests are available for use with\n" PACKAGE_NAME ". A message digest is used in conjunction with\n" "the HMAC function, to authenticate received packets.\n" "You can specify a message digest as parameter to\n" "the --auth option.\n\n"); #endif while (*digests != 0) { const md_info_t *info = md_info_from_type(*digests); if (info) printf ("%s %d bit default key\n", md_get_name(info), md_get_size(info) * 8); digests++; } printf ("\n"); }
/* * Do an RSA operation, then remove the message padding */ int rsa_pkcs1_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 buf[1024]; #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 ilen = ctx->len; if( ilen < 16 || ilen > (int) 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; switch( ctx->padding ) { case RSA_PKCS_V15: if( *p++ != 0 || *p++ != RSA_CRYPT ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); while( *p != 0 ) { if( p >= buf + ilen - 1 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p++; } p++; break; #if defined(POLARSSL_PKCS1_V21) case RSA_PKCS_V21: if( *p++ != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); 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 ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); // Generate lHash // md( md_info, lhash, 0, lhash ); // seed: Apply seedMask to maskedSeed // mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); // DB: Apply dbMask to maskedDB // mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); p += hlen; // Check validity // if( memcmp( lhash, p, hlen ) != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p += hlen; while( *p == 0 && p < buf + ilen ) p++; if( p == buf + ilen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } if (ilen - (int)(p - buf) > output_max_len) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (int)(p - buf); memcpy( output, p, *olen ); return( 0 ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function */ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig ) { int ret; size_t len, siglen, asn1_len; unsigned char *p, *end; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; md_type_t msg_md_alg; const md_info_t *md_info; asn1_buf oid; if( mode == RSA_PRIVATE && 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, f_rng, p_rng, 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 == hashlen && md_alg == POLARSSL_MD_NONE ) { if( memcmp( p, hash, hashlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); end = p + len; // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure // if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 2 != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 6 + hashlen != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); oid.p = p; p += oid.len; if( oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( md_alg != msg_md_alg ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); /* * assume the algorithm parameters must be NULL */ if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len != hashlen ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( memcmp( p, hash, hashlen ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); p += hashlen; if( p != end ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); return( 0 ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int rsa_rsassa_pss_verify_ext( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig ) { int ret; size_t siglen; unsigned char *p; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; 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; if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) 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, f_rng, p_rng, sig, buf ); if( ret != 0 ) return( ret ); p = buf; if( buf[siglen - 1] != 0xBC ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( md_alg != POLARSSL_MD_NONE ) { // Gather length of hash to sign // md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); } md_info = md_info_from_type( mgf1_hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = siglen - hlen - 1; /* Currently length of salt + padding */ memset( zeros, 0, 8 ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_init( &md_ctx ); md_init_ctx( &md_ctx, md_info ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( p < buf + siglen && *p == 0 ) p++; if( p == buf + siglen || *p++ != 0x01 ) { md_free( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } /* Actual salt len */ slen -= p - buf; if( expected_salt_len != RSA_SALT_LEN_ANY && slen != (size_t) expected_salt_len ) { md_free( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, result ); md_free( &md_ctx ); if( memcmp( p + slen, result, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int rsa_rsaes_oaep_decrypt( rsa_context *ctx, int mode, const unsigned char *label, size_t label_len, 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 buf[POLARSSL_MPI_MAX_SIZE]; unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 ) 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 ); 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 ); md_init_ctx( &md_ctx, md_info ); // Generate lHash // md( md_info, label, label_len, lhash ); // seed: Apply seedMask to maskedSeed // mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); // DB: Apply dbMask to maskedDB // mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); p += hlen; md_free_ctx( &md_ctx ); // Check validity // if( memcmp( lhash, p, hlen ) != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p += hlen; while( *p == 0 && p < buf + ilen ) p++; if( p == buf + ilen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if (ilen - (p - buf) > output_max_len) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); }
/* * 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, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t olen; unsigned char *p = sig; 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; if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; 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; return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, sig ) : rsa_private( ctx, sig, sig ) ); }
/* * 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, const unsigned char *hash, unsigned char *sig ) { int ret; size_t siglen; unsigned char *p; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; 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; if( ctx->padding != RSA_PKCS_V21 ) 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( buf[siglen - 1] != 0xBC ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); 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 = siglen - hlen - 1; memset( zeros, 0, 8 ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_init_ctx( &md_ctx, md_info ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( *p == 0 && p < buf + siglen ) p++; if( p == buf + siglen || *p++ != 0x01 ) { md_free_ctx( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } slen -= p - buf; // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, result ); md_free_ctx( &md_ctx ); if( memcmp( p + slen, result, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function */ int rsa_rsaes_oaep_encrypt( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output ) { size_t olen; int ret; unsigned char *p = output; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) 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 ); olen = ctx->len; hlen = md_get_size( md_info ); if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); memset( output, 0, olen ); *p++ = 0; // Generate a random octet string seed // if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); p += hlen; // Construct DB // md( md_info, label, label_len, p ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; memcpy( p, input, ilen ); md_init_ctx( &md_ctx, md_info ); // maskedDB: Apply dbMask to DB // mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, &md_ctx ); // maskedSeed: Apply seedMask to seed // mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, &md_ctx ); md_free_ctx( &md_ctx ); return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, output, output ) : rsa_private( ctx, output, output ) ); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int rsa_rsaes_oaep_decrypt( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ) { int ret; size_t ilen, i, pad_len; unsigned char *p, bad, pad_done; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; /* * Parameters sanity checks */ if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ilen = ctx->len; if( ilen < 16 || ilen > sizeof( buf ) ) 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 ); /* * RSA operation */ ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, input, buf ) : rsa_private( ctx, f_rng, p_rng, input, buf ); if( ret != 0 ) return( ret ); /* * Unmask data and generate lHash */ hlen = md_get_size( md_info ); md_init( &md_ctx ); md_init_ctx( &md_ctx, md_info ); /* Generate lHash */ md( md_info, label, label_len, lhash ); /* seed: Apply seedMask to maskedSeed */ mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); /* DB: Apply dbMask to maskedDB */ mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); md_free( &md_ctx ); /* * Check contents, in "constant-time" */ p = buf; bad = 0; bad |= *p++; /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ for( i = 0; i < hlen; i++ ) bad |= lhash[i] ^ *p++; /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; pad_done = 0; for( i = 0; i < ilen - 2 * hlen - 2; i++ ) { pad_done |= p[i]; pad_len += ( pad_done == 0 ); } p += pad_len; bad |= *p++ ^ 0x01; /* * The only information "leaked" is whether the padding was correct or not * (eg, no data is copied if it was not correct). This meets the * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ if( bad != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( ilen - ( p - buf ) > output_max_len ) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); }
/* * 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 ) { int ret; size_t len, siglen; unsigned char *p, c; unsigned char buf[1024]; #if defined(POLARSSL_PKCS1_V21) unsigned char zeros[8]; unsigned int hlen; size_t slen, msb; const md_info_t *md_info; md_context_t md_ctx; #endif siglen = ctx->len; if( siglen < 16 || siglen > (int) 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; 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 - (int)( p - buf ); 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 ); 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 = siglen - hlen - 1; memset( &md_ctx, 0, sizeof( md_context_t ) ); memset( zeros, 0, 8 ); md_init_ctx( &md_ctx, md_info ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( *p == 0 && p < buf + siglen ) p++; if( p == buf + siglen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); slen -= p - buf; // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, p ); if( memcmp( p, p + slen, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } return( POLARSSL_ERR_RSA_INVALID_PADDING ); }
/* * Do an RSA operation to sign the message digest */ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t nb_pad, olen, oid_size = 0; unsigned char *p = sig; const char *oid; if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; nb_pad = olen - 3; if( md_alg != POLARSSL_MD_NONE ) { const md_info_t *md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); nb_pad -= 10 + oid_size; hashlen = md_get_size( md_info ); } nb_pad -= hashlen; if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); *p++ = 0; *p++ = RSA_SIGN; memset( p, 0xFF, nb_pad ); p += nb_pad; *p++ = 0; if( md_alg == POLARSSL_MD_NONE ) { memcpy( p, hash, hashlen ); } else { /* * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING */ *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x04 + oid_size ); *p++ = ASN1_OID; *p++ = oid_size & 0xFF; memcpy( p, oid, oid_size ); p += oid_size; *p++ = ASN1_NULL; *p++ = 0x00; *p++ = ASN1_OCTET_STRING; *p++ = hashlen; memcpy( p, hash, hashlen ); } return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, sig ) : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); }
/* * Add the message padding, then do an RSA operation */ int rsa_pkcs1_encrypt( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, int mode, size_t ilen, const unsigned char *input, unsigned char *output ) { size_t nb_pad, olen; unsigned char *p = output; #if defined(POLARSSL_PKCS1_V21) unsigned int i, hlen; const md_info_t *md_info; md_context_t md_ctx; #endif olen = ctx->len; if( 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; *p++ = RSA_CRYPT; while( nb_pad-- > 0 ) { int rng_dl = 100; do { *p = (unsigned char) f_rng( p_rng ); } while( *p == 0 && --rng_dl ); // Check if RNG failed to generate data // if( rng_dl == 0 ) return POLARSSL_ERR_RSA_RNG_FAILED; p++; } *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 ); hlen = md_get_size( md_info ); if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); memset( output, 0, olen ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); *p++ = 0; // Generate a random octet string seed // for( i = 0; i < hlen; ++i ) *p++ = (unsigned char) f_rng( p_rng ); // Construct DB // md( md_info, p, 0, p ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; memcpy( p, input, ilen ); // maskedDB: Apply dbMask to DB // mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, &md_ctx ); // maskedSeed: Apply seedMask to seed // mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, &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 ) ); }
int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8_t *pass, uint8_t *key, uint8_t *iv) { size_t datal; datal = strlen((const char *) pass); #if defined(USE_CRYPTO_OPENSSL) return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv); #elif defined(USE_CRYPTO_POLARSSL) md_context_t c; unsigned char md_buf[MAX_MD_SIZE]; int niv; int nkey; int addmd; unsigned int mds; unsigned int i; int rv; nkey = cipher_key_size(cipher); niv = cipher_iv_size(cipher); rv = nkey; if (pass == NULL) { return nkey; } memset(&c, 0, sizeof(md_context_t)); if (md_init_ctx(&c, md)) { return 0; } addmd = 0; mds = md_get_size(md); for (;;) { int error; do { error = 1; if (md_starts(&c)) { break; } if (addmd) { if (md_update(&c, &(md_buf[0]), mds)) { break; } } else { addmd = 1; } if (md_update(&c, pass, datal)) break; if (md_finish(&c, &(md_buf[0]))) break; error = 0; } while (0); if (error) { md_free_ctx(&c); memset(md_buf, 0, MAX_MD_SIZE); return 0; } i=0; if (nkey) { for (;;) { if (nkey == 0) break; if (i == mds) break; if (key != NULL) *(key++)=md_buf[i]; nkey--; i++; } } if (niv && (i != mds)) { for (;;) { if (niv == 0) break; if (i == mds) break; if (iv != NULL) *(iv++)=md_buf[i]; niv--; i++; } } if ((nkey == 0) && (niv == 0)) break; } md_free_ctx(&c); memset(md_buf, 0, MAX_MD_SIZE); return rv; #endif }
int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output ) { int ret, j; unsigned int i; unsigned char md1[POLARSSL_MD_MAX_SIZE]; unsigned char work[POLARSSL_MD_MAX_SIZE]; unsigned char md_size = md_get_size( ctx->md_info ); size_t use_len; unsigned char *out_p = output; unsigned char counter[4]; memset( counter, 0, 4 ); counter[3] = 1; if( iteration_count > 0xFFFFFFFF ) return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA ); while( key_length ) { // U1 ends up in work // if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) return( ret ); if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 ) return( ret ); if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 ) return( ret ); if( ( ret = md_hmac_finish( ctx, work ) ) != 0 ) return( ret ); memcpy( md1, work, md_size ); for ( i = 1; i < iteration_count; i++ ) { // U2 ends up in md1 // if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) return( ret ); if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 ) return( ret ); if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 ) return( ret ); // U1 xor U2 // for( j = 0; j < md_size; j++ ) work[j] ^= md1[j]; } use_len = ( key_length < md_size ) ? key_length : md_size; memcpy( out_p, work, use_len ); key_length -= use_len; out_p += use_len; for( i = 4; i > 0; i-- ) if( ++counter[i - 1] != 0 ) break; } return( 0 ); }
int pkcs11_sign( pkcs11_context *ctx, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t sig_len = 0, asn_len = 0, oid_size = 0; unsigned char *p = sig; const char *oid; if( NULL == ctx ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( RSA_PRIVATE != mode ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( md_alg != POLARSSL_MD_NONE ) { const md_info_t *md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); asn_len = 10 + oid_size; } sig_len = ctx->len; if( hashlen > sig_len || asn_len > sig_len || hashlen + asn_len > sig_len ) { return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } if( md_alg != POLARSSL_MD_NONE ) { /* * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING */ *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x04 + oid_size ); *p++ = ASN1_OID; *p++ = oid_size & 0xFF; memcpy( p, oid, oid_size ); p += oid_size; *p++ = ASN1_NULL; *p++ = 0x00; *p++ = ASN1_OCTET_STRING; *p++ = hashlen; } memcpy( p, hash, hashlen ); if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, asn_len + hashlen, sig, &sig_len ) != CKR_OK ) { return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } return( 0 ); }
int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8_t *pass, uint8_t *key, uint8_t *iv) { size_t datal; datal = strlen((const char *)pass); #if defined(USE_CRYPTO_OPENSSL) return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv); #elif defined(USE_CRYPTO_POLARSSL) md_context_t c; unsigned char md_buf[MAX_MD_SIZE]; int niv; int nkey; int addmd; unsigned int mds; unsigned int i; int rv; nkey = cipher_key_size(cipher); niv = cipher_iv_size(cipher); rv = nkey; if (pass == NULL) { return nkey; } memset(&c, 0, sizeof(md_context_t)); if (md_init_ctx(&c, md)) { return 0; } addmd = 0; mds = md_get_size(md); for (;;) { int error; do { error = 1; if (md_starts(&c)) { break; } if (addmd) { if (md_update(&c, &(md_buf[0]), mds)) { break; } } else { addmd = 1; } if (md_update(&c, pass, datal)) { break; } if (md_finish(&c, &(md_buf[0]))) { break; } error = 0; } while (0); if (error) { md_free_ctx(&c); memset(md_buf, 0, MAX_MD_SIZE); return 0; } i = 0; if (nkey) { for (;;) { if (nkey == 0) { break; } if (i == mds) { break; } if (key != NULL) { *(key++) = md_buf[i]; } nkey--; i++; } } if (niv && (i != mds)) { for (;;) { if (niv == 0) { break; } if (i == mds) { break; } if (iv != NULL) { *(iv++) = md_buf[i]; } niv--; i++; } } if ((nkey == 0) && (niv == 0)) { break; } } md_free_ctx(&c); memset(md_buf, 0, MAX_MD_SIZE); return rv; #elif defined(USE_CRYPTO_MBEDTLS) /* * * Generic message digest context. * * typedef struct { * Information about the associated message digest * const mbedtls_md_info_t *md_info; * * Digest-specific context * void *md_ctx; * * HMAC part of the context * void *hmac_ctx; * } mbedtls_md_context_t; // mbedtls 2.0.0 * * typedef struct { * Information about the associated message digest * const md_info_t *md_info; * * Digest-specific context * void *md_ctx; * } md_context_t; //polarssl 1.3 * */ // NOTE: different struct body, initialize new param hmac 0 to disable HMAC mbedtls_md_context_t c; unsigned char md_buf[MAX_MD_SIZE]; int niv; int nkey; int addmd; unsigned int mds; unsigned int i; int rv; nkey = cipher_key_size(cipher); niv = cipher_iv_size(cipher); rv = nkey; if (pass == NULL) { return nkey; } memset(&c, 0, sizeof(mbedtls_md_context_t)); // XXX: md_init_ctx superseded by mbedtls_md_setup() in 2.0.0 // new param hmac 0 to save some memory if HMAC will not be used, // non-zero is HMAC is going to be used with this context. if (mbedtls_md_setup(&c, md, 1)) { return 0; } addmd = 0; mds = mbedtls_md_get_size(md); for (;;) { int error; do { error = 1; if (mbedtls_md_starts(&c)) { break; } if (addmd) { if (mbedtls_md_update(&c, &(md_buf[0]), mds)) { break; } } else { addmd = 1; } if (mbedtls_md_update(&c, pass, datal)) { break; } if (mbedtls_md_finish(&c, &(md_buf[0]))) { break; } error = 0; } while (0); if (error) { mbedtls_md_free(&c); // md_free_ctx deprecated, Use mbedtls_md_free() instead memset(md_buf, 0, MAX_MD_SIZE); return 0; } i = 0; if (nkey) { for (;;) { if (nkey == 0) { break; } if (i == mds) { break; } if (key != NULL) { *(key++) = md_buf[i]; } nkey--; i++; } } if (niv && (i != mds)) { for (;;) { if (niv == 0) { break; } if (i == mds) { break; } if (iv != NULL) { *(iv++) = md_buf[i]; } niv--; i++; } } if ((nkey == 0) && (niv == 0)) { break; } } mbedtls_md_free(&c); // NOTE: md_free_ctx deprecated, Use mbedtls_md_free() instead memset(md_buf, 0, MAX_MD_SIZE); return rv; #endif }
/* * Do an RSA operation to sign the message digest */ int rsa_pkcs1_sign( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, 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 defined(POLARSSL_PKCS1_V21) unsigned char salt[POLARSSL_MD_MAX_SIZE]; unsigned int i, slen, hlen, offset = 0; size_t msb; const md_info_t *md_info; md_context_t md_ctx; #else (void) f_rng; (void) p_rng; #endif olen = ctx->len; switch( ctx->padding ) { case RSA_PKCS_V15: switch( hash_id ) { case SIG_RSA_RAW: nb_pad = olen - 3 - hashlen; break; case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: nb_pad = olen - 3 - 34; break; case SIG_RSA_SHA1: nb_pad = olen - 3 - 35; break; case SIG_RSA_SHA224: nb_pad = olen - 3 - 47; break; case SIG_RSA_SHA256: nb_pad = olen - 3 - 51; break; case SIG_RSA_SHA384: nb_pad = olen - 3 - 67; break; case SIG_RSA_SHA512: nb_pad = olen - 3 - 83; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } if( nb_pad < 8 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); *p++ = 0; *p++ = RSA_SIGN; memset( p, 0xFF, nb_pad ); p += nb_pad; *p++ = 0; switch( hash_id ) { case SIG_RSA_RAW: memcpy( p, hash, hashlen ); break; case SIG_RSA_MD2: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 2; break; case SIG_RSA_MD4: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 4; break; case SIG_RSA_MD5: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 5; break; case SIG_RSA_SHA1: memcpy( p, ASN1_HASH_SHA1, 15 ); memcpy( p + 15, hash, 20 ); break; case SIG_RSA_SHA224: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 28 ); p[1] += 28; p[14] = 4; p[18] += 28; break; case SIG_RSA_SHA256: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 32 ); p[1] += 32; p[14] = 1; p[18] += 32; break; case SIG_RSA_SHA384: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 48 ); p[1] += 48; p[14] = 2; p[18] += 48; break; case SIG_RSA_SHA512: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 64 ); p[1] += 64; p[14] = 3; p[18] += 64; break; default: 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; memset( sig, 0, olen ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); msb = mpi_msb( &ctx->N ) - 1; // Generate salt of length slen // for( i = 0; i < slen; ++i ) salt[i] = (unsigned char) f_rng( p_rng ); // 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; // 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 ); 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 ) ); }