blob: 130705b3301548c78e36e9eefa3035d9ec0594d6 [file] [log] [blame]
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +01001/*
Manuel Pégourié-Gonnard0e725c32022-01-27 11:15:33 +01002 * This is a simple example of multi-part HMAC computation using both the old
3 * MD API and the new PSA API; its goal is to help migration to PSA Crypto.
4 *
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +01005 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +010022 * When in comes to multi-part HMAC operations, the `mbedtls_md_context`
23 * serves a dual purpose (1) hold the key, and (2) save progress information
24 * for the current operation. With PSA those roles are held by two disinct
25 * objects: (1) a psa_key_id_t to hold the key, and (2) a psa_operation_t for
26 * multi-part progress.
27 *
28 * This program illustrates this by doing the same sequence of multi-part HMAC
Manuel Pégourié-Gonnard0e725c32022-01-27 11:15:33 +010029 * computation with both APIs; looking at the two functions md() and mac() side
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +010030 * by side should make the differences and similarities clear.
31 */
32
33#include <stdio.h>
34
35#include "mbedtls/build_info.h"
36
Manuel Pégourié-Gonnard9efbf532022-01-17 11:57:44 +010037#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_MD_C) || \
38 defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +010039int main( void )
40{
Manuel Pégourié-Gonnard9efbf532022-01-17 11:57:44 +010041 printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_MD_C not defined, "
42 "and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined\r\n" );
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +010043 return( 0 );
44}
45#else /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_MD_C */
46
47#include "mbedtls/md.h"
48#include "psa/crypto.h"
49
50/*
51 * Dummy inputs for HMAC
52 */
53const unsigned char part1[] = { 0x01, 0x02 };
54const unsigned char part2[] = { 0x03, 0x04 };
55const unsigned char part3[] = { 0x05, 0x05 };
56const unsigned char part4[] = { 0x06, 0x06 };
57
58const unsigned char key_bytes[32] = { 0 };
59
60unsigned char out[32];
61
62void print_out( const char *title )
63{
64 printf( "%s:", title );
65 for( size_t i = 0; i < sizeof( out ); i++ )
66 printf( " %02x", out[i] );
67 printf( "\n" );
68}
69
70#define CHK( code ) \
71 do { \
72 ret = code; \
73 if( ret != 0 ) \
74 goto exit; \
75 } while( 0 )
76
77int md(void)
78{
79 int ret;
80 mbedtls_md_context_t ctx;
81
82 mbedtls_md_init( &ctx );
83
84 /* prepare context and load key */
85 CHK( mbedtls_md_setup( &ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 ) );
86 CHK( mbedtls_md_hmac_starts( &ctx, key_bytes, sizeof( key_bytes ) ) );
87
88 /* compute HMAC(key, part 1 | part 2) */
89 CHK( mbedtls_md_hmac_update( &ctx, part1, sizeof( part1 ) ) );
90 CHK( mbedtls_md_hmac_update( &ctx, part2, sizeof( part2 ) ) );
91 CHK( mbedtls_md_hmac_finish( &ctx, out ) );
92 print_out( "12" );
93
94 /* compute HMAC(key, part 3 | part 4) */
95 CHK( mbedtls_md_hmac_reset( &ctx ) ); // prepare for new operation
96 CHK( mbedtls_md_hmac_update( &ctx, part3, sizeof( part3 ) ) );
97 CHK( mbedtls_md_hmac_update( &ctx, part4, sizeof( part4 ) ) );
98 CHK( mbedtls_md_hmac_finish( &ctx, out ) );
99 print_out( "34" );
100
101exit:
102 mbedtls_md_free( &ctx );
103
104 return( ret );
105}
106
107#undef CHK
108
109#define CHK( code ) \
110 do { \
111 status = code; \
112 if( status != PSA_SUCCESS ) \
113 goto exit; \
114 } while( 0 )
115
116psa_status_t mac(void)
117{
118 psa_status_t status;
119 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
120 psa_key_id_t key = 0;
121 psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
122
123 /* prepare key */
124 psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
125 psa_set_key_algorithm( &attributes, alg );
126 psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
127 psa_set_key_bits( &attributes, 8 * sizeof( key_bytes ) );
128
129 status = psa_import_key( &attributes, key_bytes, sizeof( key_bytes ), &key );
130 if( status != PSA_SUCCESS )
131 return( status );
132
133 /* prepare operation */
134 psa_mac_operation_t op = PSA_MAC_OPERATION_INIT;
135 size_t out_len = 0;
136
137 /* compute HMAC(key, part 1 | part 2) */
138 CHK( psa_mac_sign_setup( &op, key, alg ) );
139 CHK( psa_mac_update( &op, part1, sizeof( part1 ) ) );
140 CHK( psa_mac_update( &op, part2, sizeof( part2 ) ) );
141 CHK( psa_mac_sign_finish( &op, out, sizeof( out ), &out_len ) );
142 print_out( "12" );
143
144 /* compute HMAC(key, part 3 | part 4) */
145 CHK( psa_mac_sign_setup( &op, key, alg ) );
146 CHK( psa_mac_update( &op, part3, sizeof( part3 ) ) );
147 CHK( psa_mac_update( &op, part4, sizeof( part4 ) ) );
148 CHK( psa_mac_sign_finish( &op, out, sizeof( out ), &out_len ) );
149 print_out( "34" );
150
151exit:
152 psa_mac_abort( &op );
153
154 return( status );
155}
156
157#undef CHK
158
159int main(void)
160{
161 printf( "MD\n" );
162 int ret = md();
163 if( ret != 0 )
Manuel Pégourié-Gonnardecffd962022-01-14 13:06:14 +0100164 printf( "ret = %d (-0x%04x)\n", ret, (unsigned) -ret );
Manuel Pégourié-Gonnard667b5562021-11-22 13:00:17 +0100165
166 psa_status_t status = psa_crypto_init();
167 if( status != PSA_SUCCESS )
168 printf( "psa init: %d\n", status );
169
170 printf( "\nPSA\n" );
171 status = mac();
172 if( status != PSA_SUCCESS )
173 printf( "psa mac: %d\n", status );
174}
175
176#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_MD_C */