| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 | /* *  Public Key abstraction layer: wrapper functions * *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved *  SPDX-License-Identifier: Apache-2.0 * *  Licensed under the Apache License, Version 2.0 (the "License"); you may *  not use this file except in compliance with the License. *  You may obtain a copy of the License at * *  http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. * *  This file is part of mbed TLS (https://tls.mbed.org) */#if !defined(MBEDTLS_CONFIG_FILE)#include "mbedtls/config.h"#else#include MBEDTLS_CONFIG_FILE#endif#if defined(MBEDTLS_PK_C)#include "mbedtls/pk_internal.h"/* Even if RSA not activated, for the sake of RSA-alt */#include "mbedtls/rsa.h"#include "mbedtls/bignum.h"#include <string.h>#if defined(MBEDTLS_ECP_C)#include "mbedtls/ecp.h"#endif#if defined(MBEDTLS_ECDSA_C)#include "mbedtls/ecdsa.h"#endif#if defined(MBEDTLS_PLATFORM_C)#include "mbedtls/platform.h"#else#include <stdlib.h>#define mbedtls_calloc    calloc#define mbedtls_free       free#endif#include <limits.h>#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)/* Implementation that should never be optimized out by the compiler */static void mbedtls_zeroize( void *v, size_t n ) {    volatile unsigned char *p = v; while( n-- ) *p++ = 0;}#endif#if defined(MBEDTLS_RSA_C)static int rsa_can_do( mbedtls_pk_type_t type ){    return( type == MBEDTLS_PK_RSA ||            type == MBEDTLS_PK_RSASSA_PSS );}static size_t rsa_get_bitlen( const void *ctx ){    return( 8 * ((const mbedtls_rsa_context *) ctx)->len );}static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   const unsigned char *sig, size_t sig_len ){    int ret;#if defined(MBEDTLS_HAVE_INT64)    if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );#endif /* MBEDTLS_HAVE_INT64 */    if( sig_len < ((mbedtls_rsa_context *) ctx)->len )        return( MBEDTLS_ERR_RSA_VERIFY_FAILED );    if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL,                                  MBEDTLS_RSA_PUBLIC, md_alg,                                  (unsigned int) hash_len, hash, sig ) ) != 0 )        return( ret );    if( sig_len > ((mbedtls_rsa_context *) ctx)->len )        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );    return( 0 );}static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   unsigned char *sig, size_t *sig_len,                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){#if defined(MBEDTLS_HAVE_INT64)    if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );#endif /* MBEDTLS_HAVE_INT64 */    *sig_len = ((mbedtls_rsa_context *) ctx)->len;    return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,                md_alg, (unsigned int) hash_len, hash, sig ) );}static int rsa_decrypt_wrap( void *ctx,                    const unsigned char *input, size_t ilen,                    unsigned char *output, size_t *olen, size_t osize,                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    if( ilen != ((mbedtls_rsa_context *) ctx)->len )        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );    return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng,                MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );}static int rsa_encrypt_wrap( void *ctx,                    const unsigned char *input, size_t ilen,                    unsigned char *output, size_t *olen, size_t osize,                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    *olen = ((mbedtls_rsa_context *) ctx)->len;    if( *olen > osize )        return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );    return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx,                f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) );}static int rsa_check_pair_wrap( const void *pub, const void *prv ){    return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub,                                (const mbedtls_rsa_context *) prv ) );}static void *rsa_alloc_wrap( void ){    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) );    if( ctx != NULL )        mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 );    return( ctx );}static void rsa_free_wrap( void *ctx ){    mbedtls_rsa_free( (mbedtls_rsa_context *) ctx );    mbedtls_free( ctx );}static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ){    items->type = MBEDTLS_PK_DEBUG_MPI;    items->name = "rsa.N";    items->value = &( ((mbedtls_rsa_context *) ctx)->N );    items++;    items->type = MBEDTLS_PK_DEBUG_MPI;    items->name = "rsa.E";    items->value = &( ((mbedtls_rsa_context *) ctx)->E );}const mbedtls_pk_info_t mbedtls_rsa_info = {    MBEDTLS_PK_RSA,    "RSA",    rsa_get_bitlen,    rsa_can_do,    rsa_verify_wrap,    rsa_sign_wrap,    rsa_decrypt_wrap,    rsa_encrypt_wrap,    rsa_check_pair_wrap,    rsa_alloc_wrap,    rsa_free_wrap,    rsa_debug,};#endif /* MBEDTLS_RSA_C */#if defined(MBEDTLS_ECP_C)/* * Generic EC key */static int eckey_can_do( mbedtls_pk_type_t type ){    return( type == MBEDTLS_PK_ECKEY ||            type == MBEDTLS_PK_ECKEY_DH ||            type == MBEDTLS_PK_ECDSA );}static size_t eckey_get_bitlen( const void *ctx ){    return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits );}#if defined(MBEDTLS_ECDSA_C)/* Forward declarations */static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,                       const unsigned char *hash, size_t hash_len,                       const unsigned char *sig, size_t sig_len );static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   unsigned char *sig, size_t *sig_len,                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,                       const unsigned char *hash, size_t hash_len,                       const unsigned char *sig, size_t sig_len ){    int ret;    mbedtls_ecdsa_context ecdsa;    mbedtls_ecdsa_init( &ecdsa );    if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )        ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );    mbedtls_ecdsa_free( &ecdsa );    return( ret );}static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   unsigned char *sig, size_t *sig_len,                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    int ret;    mbedtls_ecdsa_context ecdsa;    mbedtls_ecdsa_init( &ecdsa );    if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )        ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,                               f_rng, p_rng );    mbedtls_ecdsa_free( &ecdsa );    return( ret );}#endif /* MBEDTLS_ECDSA_C */static int eckey_check_pair( const void *pub, const void *prv ){    return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub,                                (const mbedtls_ecp_keypair *) prv ) );}static void *eckey_alloc_wrap( void ){    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );    if( ctx != NULL )        mbedtls_ecp_keypair_init( ctx );    return( ctx );}static void eckey_free_wrap( void *ctx ){    mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx );    mbedtls_free( ctx );}static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ){    items->type = MBEDTLS_PK_DEBUG_ECP;    items->name = "eckey.Q";    items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q );}const mbedtls_pk_info_t mbedtls_eckey_info = {    MBEDTLS_PK_ECKEY,    "EC",    eckey_get_bitlen,    eckey_can_do,#if defined(MBEDTLS_ECDSA_C)    eckey_verify_wrap,    eckey_sign_wrap,#else    NULL,    NULL,#endif    NULL,    NULL,    eckey_check_pair,    eckey_alloc_wrap,    eckey_free_wrap,    eckey_debug,};/* * EC key restricted to ECDH */static int eckeydh_can_do( mbedtls_pk_type_t type ){    return( type == MBEDTLS_PK_ECKEY ||            type == MBEDTLS_PK_ECKEY_DH );}const mbedtls_pk_info_t mbedtls_eckeydh_info = {    MBEDTLS_PK_ECKEY_DH,    "EC_DH",    eckey_get_bitlen,         /* Same underlying key structure */    eckeydh_can_do,    NULL,    NULL,    NULL,    NULL,    eckey_check_pair,    eckey_alloc_wrap,       /* Same underlying key structure */    eckey_free_wrap,        /* Same underlying key structure */    eckey_debug,            /* Same underlying key structure */};#endif /* MBEDTLS_ECP_C */#if defined(MBEDTLS_ECDSA_C)static int ecdsa_can_do( mbedtls_pk_type_t type ){    return( type == MBEDTLS_PK_ECDSA );}static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,                       const unsigned char *hash, size_t hash_len,                       const unsigned char *sig, size_t sig_len ){    int ret;    ((void) md_alg);    ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx,                                hash, hash_len, sig, sig_len );    if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );    return( ret );}static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   unsigned char *sig, size_t *sig_len,                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx,                md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );}static void *ecdsa_alloc_wrap( void ){    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );    if( ctx != NULL )        mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx );    return( ctx );}static void ecdsa_free_wrap( void *ctx ){    mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx );    mbedtls_free( ctx );}const mbedtls_pk_info_t mbedtls_ecdsa_info = {    MBEDTLS_PK_ECDSA,    "ECDSA",    eckey_get_bitlen,     /* Compatible key structures */    ecdsa_can_do,    ecdsa_verify_wrap,    ecdsa_sign_wrap,    NULL,    NULL,    eckey_check_pair,   /* Compatible key structures */    ecdsa_alloc_wrap,    ecdsa_free_wrap,    eckey_debug,        /* Compatible key structures */};#endif /* MBEDTLS_ECDSA_C */#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)/* * Support for alternative RSA-private implementations */static int rsa_alt_can_do( mbedtls_pk_type_t type ){    return( type == MBEDTLS_PK_RSA );}static size_t rsa_alt_get_bitlen( const void *ctx ){    const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx;    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );}static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,                   const unsigned char *hash, size_t hash_len,                   unsigned char *sig, size_t *sig_len,                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;#if defined(MBEDTLS_HAVE_INT64)    if( UINT_MAX < hash_len )        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );#endif /* MBEDTLS_HAVE_INT64 */    *sig_len = rsa_alt->key_len_func( rsa_alt->key );    return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,                md_alg, (unsigned int) hash_len, hash, sig ) );}static int rsa_alt_decrypt_wrap( void *ctx,                    const unsigned char *input, size_t ilen,                    unsigned char *output, size_t *olen, size_t osize,                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ){    mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;    ((void) f_rng);    ((void) p_rng);    if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );    return( rsa_alt->decrypt_func( rsa_alt->key,                MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );}#if defined(MBEDTLS_RSA_C)static int rsa_alt_check_pair( const void *pub, const void *prv ){    unsigned char sig[MBEDTLS_MPI_MAX_SIZE];    unsigned char hash[32];    size_t sig_len = 0;    int ret;    if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );    memset( hash, 0x2a, sizeof( hash ) );    if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE,                                   hash, sizeof( hash ),                                   sig, &sig_len, NULL, NULL ) ) != 0 )    {        return( ret );    }    if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE,                         hash, sizeof( hash ), sig, sig_len ) != 0 )    {        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );    }    return( 0 );}#endif /* MBEDTLS_RSA_C */static void *rsa_alt_alloc_wrap( void ){    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) );    if( ctx != NULL )        memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) );    return( ctx );}static void rsa_alt_free_wrap( void *ctx ){    mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) );    mbedtls_free( ctx );}const mbedtls_pk_info_t mbedtls_rsa_alt_info = {    MBEDTLS_PK_RSA_ALT,    "RSA-alt",    rsa_alt_get_bitlen,    rsa_alt_can_do,    NULL,    rsa_alt_sign_wrap,    rsa_alt_decrypt_wrap,    NULL,#if defined(MBEDTLS_RSA_C)    rsa_alt_check_pair,#else    NULL,#endif    rsa_alt_alloc_wrap,    rsa_alt_free_wrap,    NULL,};#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */#endif /* MBEDTLS_PK_C */
 |