From 667b556dbc3c82b13521088e92a4456c85fda7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 22 Nov 2021 13:00:17 +0100 Subject: [PATCH] Add example program psa/hmac_md_psa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is meant to highlight similarities and differences in the multi-part HMAC APIs. Signed-off-by: Manuel Pégourié-Gonnard --- programs/.gitignore | 1 + programs/Makefile | 13 ++- programs/psa/CMakeLists.txt | 1 + programs/psa/hmac_md_psa.c | 174 ++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 programs/psa/hmac_md_psa.c diff --git a/programs/.gitignore b/programs/.gitignore index deb104a40..72ccb5bd4 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -39,6 +39,7 @@ pkey/rsa_sign_pss pkey/rsa_verify pkey/rsa_verify_pss psa/crypto_examples +psa/hmac_md_psa psa/key_ladder_demo psa/psa_constant_names random/gen_entropy diff --git a/programs/Makefile b/programs/Makefile index 7f9d11e80..782cf9050 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -85,6 +85,7 @@ APPS = \ pkey/rsa_verify \ pkey/rsa_verify_pss \ psa/crypto_examples \ + psa/hmac_md_psa \ psa/key_ladder_demo \ psa/psa_constant_names \ random/gen_entropy \ @@ -261,6 +262,14 @@ pkey/rsa_encrypt$(EXEXT): pkey/rsa_encrypt.c $(DEP) echo " CC pkey/rsa_encrypt.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_encrypt.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +psa/crypto_examples$(EXEXT): psa/crypto_examples.c $(DEP) + echo " CC psa/crypto_examples.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/crypto_examples.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +psa/hmac_md_psa$(EXEXT): psa/hmac_md_psa.c $(DEP) + echo " CC psa/hmac_md_psa.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/hmac_md_psa.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + psa/key_ladder_demo$(EXEXT): psa/key_ladder_demo.c $(DEP) echo " CC psa/key_ladder_demo.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/key_ladder_demo.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ @@ -396,10 +405,6 @@ x509/req_app$(EXEXT): x509/req_app.c $(DEP) echo " CC x509/req_app.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ -psa/crypto_examples$(EXEXT): psa/crypto_examples.c $(DEP) - echo " CC psa/crypto_examples.c" - $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/crypto_examples.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ - clean: ifndef WINDOWS rm -f $(EXES) diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt index 26ca73c18..27732308c 100644 --- a/programs/psa/CMakeLists.txt +++ b/programs/psa/CMakeLists.txt @@ -1,5 +1,6 @@ set(executables crypto_examples + hmac_md_psa key_ladder_demo psa_constant_names ) diff --git a/programs/psa/hmac_md_psa.c b/programs/psa/hmac_md_psa.c new file mode 100644 index 000000000..cde78f18b --- /dev/null +++ b/programs/psa/hmac_md_psa.c @@ -0,0 +1,174 @@ +/* + * Copyright The Mbed TLS Contributors + * 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 is a simple example of multi-part HMAC computation using both the old + * MD API and the new PSA API; its goal is to help migration to PSA Crypto. + * + * When in comes to multi-part HMAC operations, the `mbedtls_md_context` + * serves a dual purpose (1) hold the key, and (2) save progress information + * for the current operation. With PSA those roles are held by two disinct + * objects: (1) a psa_key_id_t to hold the key, and (2) a psa_operation_t for + * multi-part progress. + * + * This program illustrates this by doing the same sequence of multi-part HMAC + * computation with both APIs; looking at the two function md() and mac() side + * by side should make the differences and similarities clear. + */ + +#include + +#include "mbedtls/build_info.h" + +#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_MD_C) +int main( void ) +{ + printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_MD_C not defined.\r\n" ); + return( 0 ); +} +#else /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_MD_C */ + +#include "mbedtls/md.h" +#include "psa/crypto.h" + +/* + * Dummy inputs for HMAC + */ +const unsigned char part1[] = { 0x01, 0x02 }; +const unsigned char part2[] = { 0x03, 0x04 }; +const unsigned char part3[] = { 0x05, 0x05 }; +const unsigned char part4[] = { 0x06, 0x06 }; + +const unsigned char key_bytes[32] = { 0 }; + +unsigned char out[32]; + +void print_out( const char *title ) +{ + printf( "%s:", title ); + for( size_t i = 0; i < sizeof( out ); i++ ) + printf( " %02x", out[i] ); + printf( "\n" ); +} + +#define CHK( code ) \ + do { \ + ret = code; \ + if( ret != 0 ) \ + goto exit; \ + } while( 0 ) + +int md(void) +{ + int ret; + mbedtls_md_context_t ctx; + + mbedtls_md_init( &ctx ); + + /* prepare context and load key */ + CHK( mbedtls_md_setup( &ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 ) ); + CHK( mbedtls_md_hmac_starts( &ctx, key_bytes, sizeof( key_bytes ) ) ); + + /* compute HMAC(key, part 1 | part 2) */ + CHK( mbedtls_md_hmac_update( &ctx, part1, sizeof( part1 ) ) ); + CHK( mbedtls_md_hmac_update( &ctx, part2, sizeof( part2 ) ) ); + CHK( mbedtls_md_hmac_finish( &ctx, out ) ); + print_out( "12" ); + + /* compute HMAC(key, part 3 | part 4) */ + CHK( mbedtls_md_hmac_reset( &ctx ) ); // prepare for new operation + CHK( mbedtls_md_hmac_update( &ctx, part3, sizeof( part3 ) ) ); + CHK( mbedtls_md_hmac_update( &ctx, part4, sizeof( part4 ) ) ); + CHK( mbedtls_md_hmac_finish( &ctx, out ) ); + print_out( "34" ); + +exit: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +#undef CHK + +#define CHK( code ) \ + do { \ + status = code; \ + if( status != PSA_SUCCESS ) \ + goto exit; \ + } while( 0 ) + +psa_status_t mac(void) +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key = 0; + psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256); + + /* prepare key */ + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC ); + psa_set_key_bits( &attributes, 8 * sizeof( key_bytes ) ); + + status = psa_import_key( &attributes, key_bytes, sizeof( key_bytes ), &key ); + if( status != PSA_SUCCESS ) + return( status ); + + /* prepare operation */ + psa_mac_operation_t op = PSA_MAC_OPERATION_INIT; + size_t out_len = 0; + + /* compute HMAC(key, part 1 | part 2) */ + CHK( psa_mac_sign_setup( &op, key, alg ) ); + CHK( psa_mac_update( &op, part1, sizeof( part1 ) ) ); + CHK( psa_mac_update( &op, part2, sizeof( part2 ) ) ); + CHK( psa_mac_sign_finish( &op, out, sizeof( out ), &out_len ) ); + print_out( "12" ); + + /* compute HMAC(key, part 3 | part 4) */ + CHK( psa_mac_sign_setup( &op, key, alg ) ); + CHK( psa_mac_update( &op, part3, sizeof( part3 ) ) ); + CHK( psa_mac_update( &op, part4, sizeof( part4 ) ) ); + CHK( psa_mac_sign_finish( &op, out, sizeof( out ), &out_len ) ); + print_out( "34" ); + +exit: + psa_mac_abort( &op ); + + return( status ); +} + +#undef CHK + +int main(void) +{ + printf( "MD\n" ); + int ret = md(); + if( ret != 0 ) + printf( "ret = %d (-0x%04x)\n", ret, -ret ); + + psa_status_t status = psa_crypto_init(); + if( status != PSA_SUCCESS ) + printf( "psa init: %d\n", status ); + + printf( "\nPSA\n" ); + status = mac(); + if( status != PSA_SUCCESS ) + printf( "psa mac: %d\n", status ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_MD_C */