diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 7c674ab1f..d97f834e3 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -270,14 +270,19 @@ int pk_can_do( pk_context *ctx, pk_type_t type ); * \brief Verify signature * * \param ctx PK context to use - * \param md_alg Hash algorithm used + * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign - * \param hash_len Hash length + * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length * * \return 0 on success (signature is valid), * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 */ int pk_verify( pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, @@ -287,15 +292,20 @@ int pk_verify( pk_context *ctx, md_type_t md_alg, * \brief Make signature * * \param ctx PK context to use - * \param md_alg Hash algorithm used + * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign - * \param hash_len Hash length + * \param hash_len Hash length or 0 (see notes) * \param sig Place to write the signature * \param sig_len Number of bytes written * \param f_rng RNG function * \param p_rng RNG parameter * * \return 0 on success, or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 */ int pk_sign( pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, diff --git a/library/pk.c b/library/pk.c index 0923afe45..77f503404 100644 --- a/library/pk.c +++ b/library/pk.c @@ -149,6 +149,23 @@ int pk_can_do( pk_context *ctx, pk_type_t type ) return( ctx->pk_info->can_do( type ) ); } +/* + * Helper for pk_sign and pk_verify + */ +static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len ) +{ + const md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = md_info->size; + return( 0 ); +} + /* * Verify a signature */ @@ -156,7 +173,8 @@ int pk_verify( pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->verify_func == NULL ) @@ -174,7 +192,8 @@ int pk_sign( pk_context *ctx, md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->sign_func == NULL ) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 511d61d5b..6c584c01b 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1164,8 +1164,6 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl, size_t *hash_len, pk_type_t *pk_alg ) { - const md_info_t *md_info; - ((void) ssl); *md_alg = POLARSSL_MD_NONE; *pk_alg = POLARSSL_PK_NONE; @@ -1180,6 +1178,9 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl, if( (*p) + 2 > end ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + /* Info from md_alg will be used instead */ + *hash_len = 0; + /* * Get hash algorithm */ @@ -1190,18 +1191,6 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl, return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - /* - * Get hash_len from hash alg - */ - if( ( md_info = md_info_from_type( *md_alg ) ) == NULL ) - { - SSL_DEBUG_MSG( 2, ( "Server used unsupported " - "HashAlgorithm %d", *(p)[0] ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - *hash_len = md_info->size; - /* * Get signature algorithm */ @@ -1956,7 +1945,6 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) } else { - const md_info_t *md_info; /* * digitally-signed struct { * opaque handshake_messages[handshake_messages_length]; @@ -1985,13 +1973,8 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) } ssl->out_msg[5] = ssl_sig_from_pk( ssl->pk_key ); - if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) - { - SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - hashlen = md_info->size; + /* Info from md_alg will be used instead */ + hashlen = 0; offset = 2; } diff --git a/library/ssl_srv.c b/library/ssl_srv.c index f13b9c220..731d2bdf2 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1989,7 +1989,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) else { md_context_t ctx; - const md_info_t *md_info; + + /* Info from md_alg will be used instead */ + hashlen = 0; /* * digitally-signed struct { @@ -1998,17 +2000,14 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) * ServerDHParams params; * }; */ - md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg ); - - if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) + if( ( md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg ) ) + == POLARSSL_MD_NONE ) { SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } - hashlen = md_info->size; - - if( ( ret = md_init_ctx( &ctx, md_info ) ) != 0 ) + if( ( ret = md_init_ctx( &ctx, md_info_from_type(md_alg) ) ) != 0 ) { SSL_DEBUG_RET( 1, "md_init_ctx", ret ); return( ret ); @@ -2502,7 +2501,6 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) size_t hashlen; pk_type_t pk_alg; md_type_t md_alg; - const md_info_t *md_info; const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); @@ -2575,15 +2573,8 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) md_alg = ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg ); - /* - * Get hashlen from MD - */ - if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) - { - SSL_DEBUG_MSG( 1, ( "requested hash not available " ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); - } - hashlen = md_info->size; + /* Info from md_alg will be used instead */ + hashlen = 0; /* * Signature