1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * PSA PAKE layer on top of Mbed TLS software crypto 3a8e1175bSopenharmony_ci */ 4a8e1175bSopenharmony_ci/* 5a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 6a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7a8e1175bSopenharmony_ci */ 8a8e1175bSopenharmony_ci 9a8e1175bSopenharmony_ci#include "common.h" 10a8e1175bSopenharmony_ci 11a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_CRYPTO_C) 12a8e1175bSopenharmony_ci 13a8e1175bSopenharmony_ci#include <psa/crypto.h> 14a8e1175bSopenharmony_ci#include "psa_crypto_core.h" 15a8e1175bSopenharmony_ci#include "psa_crypto_pake.h" 16a8e1175bSopenharmony_ci#include "psa_crypto_slot_management.h" 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci#include <mbedtls/ecjpake.h> 19a8e1175bSopenharmony_ci#include "psa_util_internal.h" 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#include <mbedtls/platform.h> 22a8e1175bSopenharmony_ci#include <mbedtls/error.h> 23a8e1175bSopenharmony_ci#include <string.h> 24a8e1175bSopenharmony_ci 25a8e1175bSopenharmony_ci/* 26a8e1175bSopenharmony_ci * State sequence: 27a8e1175bSopenharmony_ci * 28a8e1175bSopenharmony_ci * psa_pake_setup() 29a8e1175bSopenharmony_ci * | 30a8e1175bSopenharmony_ci * |-- In any order: 31a8e1175bSopenharmony_ci * | | psa_pake_set_password_key() 32a8e1175bSopenharmony_ci * | | psa_pake_set_user() 33a8e1175bSopenharmony_ci * | | psa_pake_set_peer() 34a8e1175bSopenharmony_ci * | | psa_pake_set_role() 35a8e1175bSopenharmony_ci * | 36a8e1175bSopenharmony_ci * |--- In any order: (First round input before or after first round output) 37a8e1175bSopenharmony_ci * | | 38a8e1175bSopenharmony_ci * | |------ In Order 39a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) 40a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) 41a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) 42a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) 43a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) 44a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) 45a8e1175bSopenharmony_ci * | | 46a8e1175bSopenharmony_ci * | |------ In Order: 47a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) 48a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) 49a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) 50a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) 51a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) 52a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) 53a8e1175bSopenharmony_ci * | 54a8e1175bSopenharmony_ci * |--- In any order: (Second round input before or after second round output) 55a8e1175bSopenharmony_ci * | | 56a8e1175bSopenharmony_ci * | |------ In Order 57a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) 58a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) 59a8e1175bSopenharmony_ci * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) 60a8e1175bSopenharmony_ci * | | 61a8e1175bSopenharmony_ci * | |------ In Order: 62a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) 63a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) 64a8e1175bSopenharmony_ci * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) 65a8e1175bSopenharmony_ci * | 66a8e1175bSopenharmony_ci * psa_pake_get_implicit_key() 67a8e1175bSopenharmony_ci * psa_pake_abort() 68a8e1175bSopenharmony_ci */ 69a8e1175bSopenharmony_ci 70a8e1175bSopenharmony_ci/* 71a8e1175bSopenharmony_ci * Possible sequence of calls to implementation: 72a8e1175bSopenharmony_ci * 73a8e1175bSopenharmony_ci * |--- In any order: 74a8e1175bSopenharmony_ci * | | 75a8e1175bSopenharmony_ci * | |------ In Order 76a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE) 77a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC) 78a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF) 79a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE) 80a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC) 81a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF) 82a8e1175bSopenharmony_ci * | | 83a8e1175bSopenharmony_ci * | |------ In Order: 84a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE) 85a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC) 86a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF) 87a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE) 88a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC) 89a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF) 90a8e1175bSopenharmony_ci * | 91a8e1175bSopenharmony_ci * |--- In any order: 92a8e1175bSopenharmony_ci * | | 93a8e1175bSopenharmony_ci * | |------ In Order 94a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE) 95a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC) 96a8e1175bSopenharmony_ci * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF) 97a8e1175bSopenharmony_ci * | | 98a8e1175bSopenharmony_ci * | |------ In Order: 99a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE) 100a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC) 101a8e1175bSopenharmony_ci * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF) 102a8e1175bSopenharmony_ci */ 103a8e1175bSopenharmony_ci 104a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 105a8e1175bSopenharmony_cistatic psa_status_t mbedtls_ecjpake_to_psa_error(int ret) 106a8e1175bSopenharmony_ci{ 107a8e1175bSopenharmony_ci switch (ret) { 108a8e1175bSopenharmony_ci case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: 109a8e1175bSopenharmony_ci case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: 110a8e1175bSopenharmony_ci case MBEDTLS_ERR_ECP_INVALID_KEY: 111a8e1175bSopenharmony_ci case MBEDTLS_ERR_ECP_VERIFY_FAILED: 112a8e1175bSopenharmony_ci return PSA_ERROR_DATA_INVALID; 113a8e1175bSopenharmony_ci case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: 114a8e1175bSopenharmony_ci case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: 115a8e1175bSopenharmony_ci return PSA_ERROR_BUFFER_TOO_SMALL; 116a8e1175bSopenharmony_ci case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: 117a8e1175bSopenharmony_ci return PSA_ERROR_NOT_SUPPORTED; 118a8e1175bSopenharmony_ci case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: 119a8e1175bSopenharmony_ci return PSA_ERROR_CORRUPTION_DETECTED; 120a8e1175bSopenharmony_ci default: 121a8e1175bSopenharmony_ci return PSA_ERROR_GENERIC_ERROR; 122a8e1175bSopenharmony_ci } 123a8e1175bSopenharmony_ci} 124a8e1175bSopenharmony_ci#endif 125a8e1175bSopenharmony_ci 126a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_PAKE) 127a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 128a8e1175bSopenharmony_cistatic psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation) 129a8e1175bSopenharmony_ci{ 130a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 131a8e1175bSopenharmony_ci 132a8e1175bSopenharmony_ci mbedtls_ecjpake_init(&operation->ctx.jpake); 133a8e1175bSopenharmony_ci 134a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_setup(&operation->ctx.jpake, 135a8e1175bSopenharmony_ci operation->role, 136a8e1175bSopenharmony_ci MBEDTLS_MD_SHA256, 137a8e1175bSopenharmony_ci MBEDTLS_ECP_DP_SECP256R1, 138a8e1175bSopenharmony_ci operation->password, 139a8e1175bSopenharmony_ci operation->password_len); 140a8e1175bSopenharmony_ci 141a8e1175bSopenharmony_ci mbedtls_platform_zeroize(operation->password, operation->password_len); 142a8e1175bSopenharmony_ci 143a8e1175bSopenharmony_ci if (ret != 0) { 144a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 145a8e1175bSopenharmony_ci } 146a8e1175bSopenharmony_ci 147a8e1175bSopenharmony_ci return PSA_SUCCESS; 148a8e1175bSopenharmony_ci} 149a8e1175bSopenharmony_ci#endif 150a8e1175bSopenharmony_ci 151a8e1175bSopenharmony_ci/* The only two JPAKE user/peer identifiers supported in built-in implementation. */ 152a8e1175bSopenharmony_cistatic const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; 153a8e1175bSopenharmony_cistatic const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; 154a8e1175bSopenharmony_ci 155a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, 156a8e1175bSopenharmony_ci const psa_crypto_driver_pake_inputs_t *inputs) 157a8e1175bSopenharmony_ci{ 158a8e1175bSopenharmony_ci psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 159a8e1175bSopenharmony_ci size_t user_len = 0, peer_len = 0, password_len = 0; 160a8e1175bSopenharmony_ci uint8_t *peer = NULL, *user = NULL; 161a8e1175bSopenharmony_ci size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0; 162a8e1175bSopenharmony_ci psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_password_len(inputs, &password_len); 165a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 166a8e1175bSopenharmony_ci return status; 167a8e1175bSopenharmony_ci } 168a8e1175bSopenharmony_ci 169a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_user_len(inputs, &user_len); 170a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 171a8e1175bSopenharmony_ci return status; 172a8e1175bSopenharmony_ci } 173a8e1175bSopenharmony_ci 174a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len); 175a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 176a8e1175bSopenharmony_ci return status; 177a8e1175bSopenharmony_ci } 178a8e1175bSopenharmony_ci 179a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite); 180a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 181a8e1175bSopenharmony_ci return status; 182a8e1175bSopenharmony_ci } 183a8e1175bSopenharmony_ci 184a8e1175bSopenharmony_ci operation->password = mbedtls_calloc(1, password_len); 185a8e1175bSopenharmony_ci if (operation->password == NULL) { 186a8e1175bSopenharmony_ci status = PSA_ERROR_INSUFFICIENT_MEMORY; 187a8e1175bSopenharmony_ci goto error; 188a8e1175bSopenharmony_ci } 189a8e1175bSopenharmony_ci 190a8e1175bSopenharmony_ci user = mbedtls_calloc(1, user_len); 191a8e1175bSopenharmony_ci if (user == NULL) { 192a8e1175bSopenharmony_ci status = PSA_ERROR_INSUFFICIENT_MEMORY; 193a8e1175bSopenharmony_ci goto error; 194a8e1175bSopenharmony_ci } 195a8e1175bSopenharmony_ci 196a8e1175bSopenharmony_ci peer = mbedtls_calloc(1, peer_len); 197a8e1175bSopenharmony_ci if (peer == NULL) { 198a8e1175bSopenharmony_ci status = PSA_ERROR_INSUFFICIENT_MEMORY; 199a8e1175bSopenharmony_ci goto error; 200a8e1175bSopenharmony_ci } 201a8e1175bSopenharmony_ci 202a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_password(inputs, operation->password, 203a8e1175bSopenharmony_ci password_len, &actual_password_len); 204a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 205a8e1175bSopenharmony_ci goto error; 206a8e1175bSopenharmony_ci } 207a8e1175bSopenharmony_ci 208a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_user(inputs, user, 209a8e1175bSopenharmony_ci user_len, &actual_user_len); 210a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 211a8e1175bSopenharmony_ci goto error; 212a8e1175bSopenharmony_ci } 213a8e1175bSopenharmony_ci 214a8e1175bSopenharmony_ci status = psa_crypto_driver_pake_get_peer(inputs, peer, 215a8e1175bSopenharmony_ci peer_len, &actual_peer_len); 216a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 217a8e1175bSopenharmony_ci goto error; 218a8e1175bSopenharmony_ci } 219a8e1175bSopenharmony_ci 220a8e1175bSopenharmony_ci operation->password_len = actual_password_len; 221a8e1175bSopenharmony_ci operation->alg = cipher_suite.algorithm; 222a8e1175bSopenharmony_ci 223a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 224a8e1175bSopenharmony_ci if (cipher_suite.algorithm == PSA_ALG_JPAKE) { 225a8e1175bSopenharmony_ci if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC || 226a8e1175bSopenharmony_ci cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 || 227a8e1175bSopenharmony_ci cipher_suite.bits != 256 || 228a8e1175bSopenharmony_ci cipher_suite.hash != PSA_ALG_SHA_256) { 229a8e1175bSopenharmony_ci status = PSA_ERROR_NOT_SUPPORTED; 230a8e1175bSopenharmony_ci goto error; 231a8e1175bSopenharmony_ci } 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length 234a8e1175bSopenharmony_ci if (actual_user_len != user_peer_len || 235a8e1175bSopenharmony_ci actual_peer_len != user_peer_len) { 236a8e1175bSopenharmony_ci status = PSA_ERROR_NOT_SUPPORTED; 237a8e1175bSopenharmony_ci goto error; 238a8e1175bSopenharmony_ci } 239a8e1175bSopenharmony_ci 240a8e1175bSopenharmony_ci if (memcmp(user, jpake_client_id, actual_user_len) == 0 && 241a8e1175bSopenharmony_ci memcmp(peer, jpake_server_id, actual_peer_len) == 0) { 242a8e1175bSopenharmony_ci operation->role = MBEDTLS_ECJPAKE_CLIENT; 243a8e1175bSopenharmony_ci } else 244a8e1175bSopenharmony_ci if (memcmp(user, jpake_server_id, actual_user_len) == 0 && 245a8e1175bSopenharmony_ci memcmp(peer, jpake_client_id, actual_peer_len) == 0) { 246a8e1175bSopenharmony_ci operation->role = MBEDTLS_ECJPAKE_SERVER; 247a8e1175bSopenharmony_ci } else { 248a8e1175bSopenharmony_ci status = PSA_ERROR_NOT_SUPPORTED; 249a8e1175bSopenharmony_ci goto error; 250a8e1175bSopenharmony_ci } 251a8e1175bSopenharmony_ci 252a8e1175bSopenharmony_ci operation->buffer_length = 0; 253a8e1175bSopenharmony_ci operation->buffer_offset = 0; 254a8e1175bSopenharmony_ci 255a8e1175bSopenharmony_ci status = psa_pake_ecjpake_setup(operation); 256a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 257a8e1175bSopenharmony_ci goto error; 258a8e1175bSopenharmony_ci } 259a8e1175bSopenharmony_ci 260a8e1175bSopenharmony_ci /* Role has been set, release user/peer buffers. */ 261a8e1175bSopenharmony_ci mbedtls_free(user); mbedtls_free(peer); 262a8e1175bSopenharmony_ci 263a8e1175bSopenharmony_ci return PSA_SUCCESS; 264a8e1175bSopenharmony_ci } else 265a8e1175bSopenharmony_ci#else 266a8e1175bSopenharmony_ci (void) operation; 267a8e1175bSopenharmony_ci (void) inputs; 268a8e1175bSopenharmony_ci#endif 269a8e1175bSopenharmony_ci { status = PSA_ERROR_NOT_SUPPORTED; } 270a8e1175bSopenharmony_ci 271a8e1175bSopenharmony_cierror: 272a8e1175bSopenharmony_ci mbedtls_free(user); mbedtls_free(peer); 273a8e1175bSopenharmony_ci /* In case of failure of the setup of a multipart operation, the PSA driver interface 274a8e1175bSopenharmony_ci * specifies that the core does not call any other driver entry point thus does not 275a8e1175bSopenharmony_ci * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean 276a8e1175bSopenharmony_ci * up like freeing the memory that may have been allocated to store the password. 277a8e1175bSopenharmony_ci */ 278a8e1175bSopenharmony_ci mbedtls_psa_pake_abort(operation); 279a8e1175bSopenharmony_ci return status; 280a8e1175bSopenharmony_ci} 281a8e1175bSopenharmony_ci 282a8e1175bSopenharmony_cistatic psa_status_t mbedtls_psa_pake_output_internal( 283a8e1175bSopenharmony_ci mbedtls_psa_pake_operation_t *operation, 284a8e1175bSopenharmony_ci psa_crypto_driver_pake_step_t step, 285a8e1175bSopenharmony_ci uint8_t *output, 286a8e1175bSopenharmony_ci size_t output_size, 287a8e1175bSopenharmony_ci size_t *output_length) 288a8e1175bSopenharmony_ci{ 289a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 290a8e1175bSopenharmony_ci size_t length; 291a8e1175bSopenharmony_ci (void) step; // Unused parameter 292a8e1175bSopenharmony_ci 293a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 294a8e1175bSopenharmony_ci /* 295a8e1175bSopenharmony_ci * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different 296a8e1175bSopenharmony_ci * handling of output sequencing. 297a8e1175bSopenharmony_ci * 298a8e1175bSopenharmony_ci * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data 299a8e1175bSopenharmony_ci * at once, on the other side the PSA CRYPTO PAKE api requires 300a8e1175bSopenharmony_ci * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be 301a8e1175bSopenharmony_ci * retrieved in sequence. 302a8e1175bSopenharmony_ci * 303a8e1175bSopenharmony_ci * In order to achieve API compatibility, the whole X1+X2 or X2S steps 304a8e1175bSopenharmony_ci * data is stored in an intermediate buffer at first step output call, 305a8e1175bSopenharmony_ci * and data is sliced down by parsing the ECPoint records in order 306a8e1175bSopenharmony_ci * to return the right parts on each step. 307a8e1175bSopenharmony_ci */ 308a8e1175bSopenharmony_ci if (operation->alg == PSA_ALG_JPAKE) { 309a8e1175bSopenharmony_ci /* Initialize & write round on KEY_SHARE sequences */ 310a8e1175bSopenharmony_ci if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) { 311a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake, 312a8e1175bSopenharmony_ci operation->buffer, 313a8e1175bSopenharmony_ci sizeof(operation->buffer), 314a8e1175bSopenharmony_ci &operation->buffer_length, 315a8e1175bSopenharmony_ci mbedtls_psa_get_random, 316a8e1175bSopenharmony_ci MBEDTLS_PSA_RANDOM_STATE); 317a8e1175bSopenharmony_ci if (ret != 0) { 318a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 319a8e1175bSopenharmony_ci } 320a8e1175bSopenharmony_ci 321a8e1175bSopenharmony_ci operation->buffer_offset = 0; 322a8e1175bSopenharmony_ci } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) { 323a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake, 324a8e1175bSopenharmony_ci operation->buffer, 325a8e1175bSopenharmony_ci sizeof(operation->buffer), 326a8e1175bSopenharmony_ci &operation->buffer_length, 327a8e1175bSopenharmony_ci mbedtls_psa_get_random, 328a8e1175bSopenharmony_ci MBEDTLS_PSA_RANDOM_STATE); 329a8e1175bSopenharmony_ci if (ret != 0) { 330a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 331a8e1175bSopenharmony_ci } 332a8e1175bSopenharmony_ci 333a8e1175bSopenharmony_ci operation->buffer_offset = 0; 334a8e1175bSopenharmony_ci } 335a8e1175bSopenharmony_ci 336a8e1175bSopenharmony_ci /* 337a8e1175bSopenharmony_ci * mbedtls_ecjpake_write_round_xxx() outputs thing in the format 338a8e1175bSopenharmony_ci * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is 339a8e1175bSopenharmony_ci * that the data for each step is prepended with a length byte, and 340a8e1175bSopenharmony_ci * then they're concatenated. Additionally, the server's second round 341a8e1175bSopenharmony_ci * output is prepended with a 3-bytes ECParameters structure. 342a8e1175bSopenharmony_ci * 343a8e1175bSopenharmony_ci * In PSA, we output each step separately, and don't prepend the 344a8e1175bSopenharmony_ci * output with a length byte, even less a curve identifier, as that 345a8e1175bSopenharmony_ci * information is already available. 346a8e1175bSopenharmony_ci */ 347a8e1175bSopenharmony_ci if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE && 348a8e1175bSopenharmony_ci operation->role == MBEDTLS_ECJPAKE_SERVER) { 349a8e1175bSopenharmony_ci /* Skip ECParameters, with is 3 bytes (RFC 8422) */ 350a8e1175bSopenharmony_ci operation->buffer_offset += 3; 351a8e1175bSopenharmony_ci } 352a8e1175bSopenharmony_ci 353a8e1175bSopenharmony_ci /* Read the length byte then move past it to the data */ 354a8e1175bSopenharmony_ci length = operation->buffer[operation->buffer_offset]; 355a8e1175bSopenharmony_ci operation->buffer_offset += 1; 356a8e1175bSopenharmony_ci 357a8e1175bSopenharmony_ci if (operation->buffer_offset + length > operation->buffer_length) { 358a8e1175bSopenharmony_ci return PSA_ERROR_DATA_CORRUPT; 359a8e1175bSopenharmony_ci } 360a8e1175bSopenharmony_ci 361a8e1175bSopenharmony_ci if (output_size < length) { 362a8e1175bSopenharmony_ci return PSA_ERROR_BUFFER_TOO_SMALL; 363a8e1175bSopenharmony_ci } 364a8e1175bSopenharmony_ci 365a8e1175bSopenharmony_ci memcpy(output, 366a8e1175bSopenharmony_ci operation->buffer + operation->buffer_offset, 367a8e1175bSopenharmony_ci length); 368a8e1175bSopenharmony_ci *output_length = length; 369a8e1175bSopenharmony_ci 370a8e1175bSopenharmony_ci operation->buffer_offset += length; 371a8e1175bSopenharmony_ci 372a8e1175bSopenharmony_ci /* Reset buffer after ZK_PROOF sequence */ 373a8e1175bSopenharmony_ci if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) || 374a8e1175bSopenharmony_ci (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) { 375a8e1175bSopenharmony_ci mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); 376a8e1175bSopenharmony_ci operation->buffer_length = 0; 377a8e1175bSopenharmony_ci operation->buffer_offset = 0; 378a8e1175bSopenharmony_ci } 379a8e1175bSopenharmony_ci 380a8e1175bSopenharmony_ci return PSA_SUCCESS; 381a8e1175bSopenharmony_ci } else 382a8e1175bSopenharmony_ci#else 383a8e1175bSopenharmony_ci (void) step; 384a8e1175bSopenharmony_ci (void) output; 385a8e1175bSopenharmony_ci (void) output_size; 386a8e1175bSopenharmony_ci (void) output_length; 387a8e1175bSopenharmony_ci#endif 388a8e1175bSopenharmony_ci { return PSA_ERROR_NOT_SUPPORTED; } 389a8e1175bSopenharmony_ci} 390a8e1175bSopenharmony_ci 391a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, 392a8e1175bSopenharmony_ci psa_crypto_driver_pake_step_t step, 393a8e1175bSopenharmony_ci uint8_t *output, 394a8e1175bSopenharmony_ci size_t output_size, 395a8e1175bSopenharmony_ci size_t *output_length) 396a8e1175bSopenharmony_ci{ 397a8e1175bSopenharmony_ci psa_status_t status = mbedtls_psa_pake_output_internal( 398a8e1175bSopenharmony_ci operation, step, output, output_size, output_length); 399a8e1175bSopenharmony_ci 400a8e1175bSopenharmony_ci return status; 401a8e1175bSopenharmony_ci} 402a8e1175bSopenharmony_ci 403a8e1175bSopenharmony_cistatic psa_status_t mbedtls_psa_pake_input_internal( 404a8e1175bSopenharmony_ci mbedtls_psa_pake_operation_t *operation, 405a8e1175bSopenharmony_ci psa_crypto_driver_pake_step_t step, 406a8e1175bSopenharmony_ci const uint8_t *input, 407a8e1175bSopenharmony_ci size_t input_length) 408a8e1175bSopenharmony_ci{ 409a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 410a8e1175bSopenharmony_ci (void) step; // Unused parameter 411a8e1175bSopenharmony_ci 412a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 413a8e1175bSopenharmony_ci /* 414a8e1175bSopenharmony_ci * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different 415a8e1175bSopenharmony_ci * handling of input sequencing. 416a8e1175bSopenharmony_ci * 417a8e1175bSopenharmony_ci * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data 418a8e1175bSopenharmony_ci * at once as input, on the other side the PSA CRYPTO PAKE api requires 419a8e1175bSopenharmony_ci * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be 420a8e1175bSopenharmony_ci * given in sequence. 421a8e1175bSopenharmony_ci * 422a8e1175bSopenharmony_ci * In order to achieve API compatibility, each X1+X2 or X4S step data 423a8e1175bSopenharmony_ci * is stored sequentially in an intermediate buffer and given to the 424a8e1175bSopenharmony_ci * Mbed TLS JPAKE API on the last step. 425a8e1175bSopenharmony_ci * 426a8e1175bSopenharmony_ci * This causes any input error to be only detected on the last step. 427a8e1175bSopenharmony_ci */ 428a8e1175bSopenharmony_ci if (operation->alg == PSA_ALG_JPAKE) { 429a8e1175bSopenharmony_ci /* 430a8e1175bSopenharmony_ci * Copy input to local buffer and format it as the Mbed TLS API 431a8e1175bSopenharmony_ci * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7. 432a8e1175bSopenharmony_ci * The summary is that the data for each step is prepended with a 433a8e1175bSopenharmony_ci * length byte, and then they're concatenated. Additionally, the 434a8e1175bSopenharmony_ci * server's second round output is prepended with a 3-bytes 435a8e1175bSopenharmony_ci * ECParameters structure - which means we have to prepend that when 436a8e1175bSopenharmony_ci * we're a client. 437a8e1175bSopenharmony_ci */ 438a8e1175bSopenharmony_ci if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE && 439a8e1175bSopenharmony_ci operation->role == MBEDTLS_ECJPAKE_CLIENT) { 440a8e1175bSopenharmony_ci /* We only support secp256r1. */ 441a8e1175bSopenharmony_ci /* This is the ECParameters structure defined by RFC 8422. */ 442a8e1175bSopenharmony_ci unsigned char ecparameters[3] = { 443a8e1175bSopenharmony_ci 3, /* named_curve */ 444a8e1175bSopenharmony_ci 0, 23 /* secp256r1 */ 445a8e1175bSopenharmony_ci }; 446a8e1175bSopenharmony_ci 447a8e1175bSopenharmony_ci if (operation->buffer_length + sizeof(ecparameters) > 448a8e1175bSopenharmony_ci sizeof(operation->buffer)) { 449a8e1175bSopenharmony_ci return PSA_ERROR_BUFFER_TOO_SMALL; 450a8e1175bSopenharmony_ci } 451a8e1175bSopenharmony_ci 452a8e1175bSopenharmony_ci memcpy(operation->buffer + operation->buffer_length, 453a8e1175bSopenharmony_ci ecparameters, sizeof(ecparameters)); 454a8e1175bSopenharmony_ci operation->buffer_length += sizeof(ecparameters); 455a8e1175bSopenharmony_ci } 456a8e1175bSopenharmony_ci 457a8e1175bSopenharmony_ci /* 458a8e1175bSopenharmony_ci * The core checks that input_length is smaller than 459a8e1175bSopenharmony_ci * PSA_PAKE_INPUT_MAX_SIZE. 460a8e1175bSopenharmony_ci * Thus no risk of integer overflow here. 461a8e1175bSopenharmony_ci */ 462a8e1175bSopenharmony_ci if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) { 463a8e1175bSopenharmony_ci return PSA_ERROR_BUFFER_TOO_SMALL; 464a8e1175bSopenharmony_ci } 465a8e1175bSopenharmony_ci 466a8e1175bSopenharmony_ci /* Write the length byte */ 467a8e1175bSopenharmony_ci operation->buffer[operation->buffer_length] = (uint8_t) input_length; 468a8e1175bSopenharmony_ci operation->buffer_length += 1; 469a8e1175bSopenharmony_ci 470a8e1175bSopenharmony_ci /* Finally copy the data */ 471a8e1175bSopenharmony_ci memcpy(operation->buffer + operation->buffer_length, 472a8e1175bSopenharmony_ci input, input_length); 473a8e1175bSopenharmony_ci operation->buffer_length += input_length; 474a8e1175bSopenharmony_ci 475a8e1175bSopenharmony_ci /* Load buffer at each last round ZK_PROOF */ 476a8e1175bSopenharmony_ci if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) { 477a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake, 478a8e1175bSopenharmony_ci operation->buffer, 479a8e1175bSopenharmony_ci operation->buffer_length); 480a8e1175bSopenharmony_ci 481a8e1175bSopenharmony_ci mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); 482a8e1175bSopenharmony_ci operation->buffer_length = 0; 483a8e1175bSopenharmony_ci 484a8e1175bSopenharmony_ci if (ret != 0) { 485a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 486a8e1175bSopenharmony_ci } 487a8e1175bSopenharmony_ci } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) { 488a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake, 489a8e1175bSopenharmony_ci operation->buffer, 490a8e1175bSopenharmony_ci operation->buffer_length); 491a8e1175bSopenharmony_ci 492a8e1175bSopenharmony_ci mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); 493a8e1175bSopenharmony_ci operation->buffer_length = 0; 494a8e1175bSopenharmony_ci 495a8e1175bSopenharmony_ci if (ret != 0) { 496a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 497a8e1175bSopenharmony_ci } 498a8e1175bSopenharmony_ci } 499a8e1175bSopenharmony_ci 500a8e1175bSopenharmony_ci return PSA_SUCCESS; 501a8e1175bSopenharmony_ci } else 502a8e1175bSopenharmony_ci#else 503a8e1175bSopenharmony_ci (void) step; 504a8e1175bSopenharmony_ci (void) input; 505a8e1175bSopenharmony_ci (void) input_length; 506a8e1175bSopenharmony_ci#endif 507a8e1175bSopenharmony_ci { return PSA_ERROR_NOT_SUPPORTED; } 508a8e1175bSopenharmony_ci} 509a8e1175bSopenharmony_ci 510a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, 511a8e1175bSopenharmony_ci psa_crypto_driver_pake_step_t step, 512a8e1175bSopenharmony_ci const uint8_t *input, 513a8e1175bSopenharmony_ci size_t input_length) 514a8e1175bSopenharmony_ci{ 515a8e1175bSopenharmony_ci psa_status_t status = mbedtls_psa_pake_input_internal( 516a8e1175bSopenharmony_ci operation, step, input, input_length); 517a8e1175bSopenharmony_ci 518a8e1175bSopenharmony_ci return status; 519a8e1175bSopenharmony_ci} 520a8e1175bSopenharmony_ci 521a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_pake_get_implicit_key( 522a8e1175bSopenharmony_ci mbedtls_psa_pake_operation_t *operation, 523a8e1175bSopenharmony_ci uint8_t *output, size_t output_size, 524a8e1175bSopenharmony_ci size_t *output_length) 525a8e1175bSopenharmony_ci{ 526a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 527a8e1175bSopenharmony_ci 528a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 529a8e1175bSopenharmony_ci if (operation->alg == PSA_ALG_JPAKE) { 530a8e1175bSopenharmony_ci ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake, 531a8e1175bSopenharmony_ci output, 532a8e1175bSopenharmony_ci output_size, 533a8e1175bSopenharmony_ci output_length, 534a8e1175bSopenharmony_ci mbedtls_psa_get_random, 535a8e1175bSopenharmony_ci MBEDTLS_PSA_RANDOM_STATE); 536a8e1175bSopenharmony_ci if (ret != 0) { 537a8e1175bSopenharmony_ci return mbedtls_ecjpake_to_psa_error(ret); 538a8e1175bSopenharmony_ci } 539a8e1175bSopenharmony_ci 540a8e1175bSopenharmony_ci return PSA_SUCCESS; 541a8e1175bSopenharmony_ci } else 542a8e1175bSopenharmony_ci#else 543a8e1175bSopenharmony_ci (void) output; 544a8e1175bSopenharmony_ci#endif 545a8e1175bSopenharmony_ci { return PSA_ERROR_NOT_SUPPORTED; } 546a8e1175bSopenharmony_ci} 547a8e1175bSopenharmony_ci 548a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation) 549a8e1175bSopenharmony_ci{ 550a8e1175bSopenharmony_ci mbedtls_zeroize_and_free(operation->password, operation->password_len); 551a8e1175bSopenharmony_ci operation->password = NULL; 552a8e1175bSopenharmony_ci operation->password_len = 0; 553a8e1175bSopenharmony_ci 554a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) 555a8e1175bSopenharmony_ci if (operation->alg == PSA_ALG_JPAKE) { 556a8e1175bSopenharmony_ci operation->role = MBEDTLS_ECJPAKE_NONE; 557a8e1175bSopenharmony_ci mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); 558a8e1175bSopenharmony_ci operation->buffer_length = 0; 559a8e1175bSopenharmony_ci operation->buffer_offset = 0; 560a8e1175bSopenharmony_ci mbedtls_ecjpake_free(&operation->ctx.jpake); 561a8e1175bSopenharmony_ci } 562a8e1175bSopenharmony_ci#endif 563a8e1175bSopenharmony_ci 564a8e1175bSopenharmony_ci operation->alg = PSA_ALG_NONE; 565a8e1175bSopenharmony_ci 566a8e1175bSopenharmony_ci return PSA_SUCCESS; 567a8e1175bSopenharmony_ci} 568a8e1175bSopenharmony_ci 569a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ 570a8e1175bSopenharmony_ci 571a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_CRYPTO_C */ 572