1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2b887bd8fSJens Wiklander /* 3b887bd8fSJens Wiklander * Copyright (c) 2017, Linaro Limited 4e43ab7a8SCedric Neveux * Copyright 2020 NXP 5b887bd8fSJens Wiklander */ 6b887bd8fSJens Wiklander 7d7ac7d0fSJens Wiklander #include <assert.h> 8b887bd8fSJens Wiklander #include <compiler.h> 9e1770e71SJens Wiklander #include <crypto/crypto.h> 106648f482SJens Wiklander #include <crypto/crypto_impl.h> 1133790cc1SJens Wiklander #include <kernel/panic.h> 12d7ac7d0fSJens Wiklander #include <stdlib.h> 13d7ac7d0fSJens Wiklander #include <string.h> 146d259e05SJens Wiklander #include <utee_defines.h> 15b887bd8fSJens Wiklander 166648f482SJens Wiklander TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo) 17b887bd8fSJens Wiklander { 187222fc6aSCedric Neveux TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; 196648f482SJens Wiklander struct crypto_hash_ctx *c = NULL; 206648f482SJens Wiklander 217222fc6aSCedric Neveux /* 22e43ab7a8SCedric Neveux * Use default cryptographic implementation if no matching 237222fc6aSCedric Neveux * drvcrypt device. 247222fc6aSCedric Neveux */ 257222fc6aSCedric Neveux res = drvcrypt_hash_alloc_ctx(&c, algo); 267222fc6aSCedric Neveux 277222fc6aSCedric Neveux if (res == TEE_ERROR_NOT_IMPLEMENTED) { 286648f482SJens Wiklander switch (algo) { 296648f482SJens Wiklander case TEE_ALG_MD5: 306648f482SJens Wiklander res = crypto_md5_alloc_ctx(&c); 316648f482SJens Wiklander break; 326648f482SJens Wiklander case TEE_ALG_SHA1: 336648f482SJens Wiklander res = crypto_sha1_alloc_ctx(&c); 346648f482SJens Wiklander break; 356648f482SJens Wiklander case TEE_ALG_SHA224: 366648f482SJens Wiklander res = crypto_sha224_alloc_ctx(&c); 376648f482SJens Wiklander break; 386648f482SJens Wiklander case TEE_ALG_SHA256: 396648f482SJens Wiklander res = crypto_sha256_alloc_ctx(&c); 406648f482SJens Wiklander break; 416648f482SJens Wiklander case TEE_ALG_SHA384: 426648f482SJens Wiklander res = crypto_sha384_alloc_ctx(&c); 436648f482SJens Wiklander break; 446648f482SJens Wiklander case TEE_ALG_SHA512: 456648f482SJens Wiklander res = crypto_sha512_alloc_ctx(&c); 466648f482SJens Wiklander break; 4747645577SJerome Forissier case TEE_ALG_SM3: 4847645577SJerome Forissier res = crypto_sm3_alloc_ctx(&c); 4947645577SJerome Forissier break; 506648f482SJens Wiklander default: 517222fc6aSCedric Neveux break; 527222fc6aSCedric Neveux } 53b887bd8fSJens Wiklander } 54b887bd8fSJens Wiklander 556648f482SJens Wiklander if (!res) 566648f482SJens Wiklander *ctx = c; 576648f482SJens Wiklander 586648f482SJens Wiklander return res; 596648f482SJens Wiklander } 606648f482SJens Wiklander 616648f482SJens Wiklander static const struct crypto_hash_ops *hash_ops(void *ctx) 626648f482SJens Wiklander { 636648f482SJens Wiklander struct crypto_hash_ctx *c = ctx; 646648f482SJens Wiklander 656648f482SJens Wiklander assert(c && c->ops); 666648f482SJens Wiklander 676648f482SJens Wiklander return c->ops; 686648f482SJens Wiklander } 696648f482SJens Wiklander 706b3a371cSJens Wiklander void crypto_hash_free_ctx(void *ctx) 71ecf2e014SJens Wiklander { 72ce7a47f5SJerome Forissier if (ctx) 736648f482SJens Wiklander hash_ops(ctx)->free_ctx(ctx); 74ecf2e014SJens Wiklander } 75ecf2e014SJens Wiklander 766b3a371cSJens Wiklander void crypto_hash_copy_state(void *dst_ctx, void *src_ctx) 77ecf2e014SJens Wiklander { 786648f482SJens Wiklander hash_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); 79ecf2e014SJens Wiklander } 80ecf2e014SJens Wiklander 816b3a371cSJens Wiklander TEE_Result crypto_hash_init(void *ctx) 82b887bd8fSJens Wiklander { 836648f482SJens Wiklander return hash_ops(ctx)->init(ctx); 84b887bd8fSJens Wiklander } 856648f482SJens Wiklander 866b3a371cSJens Wiklander TEE_Result crypto_hash_update(void *ctx, const uint8_t *data, size_t len) 87b887bd8fSJens Wiklander { 886648f482SJens Wiklander return hash_ops(ctx)->update(ctx, data, len); 89b887bd8fSJens Wiklander } 906648f482SJens Wiklander 916b3a371cSJens Wiklander TEE_Result crypto_hash_final(void *ctx, uint8_t *digest, size_t len) 92b887bd8fSJens Wiklander { 936648f482SJens Wiklander return hash_ops(ctx)->final(ctx, digest, len); 94b887bd8fSJens Wiklander } 9582d91db1SJens Wiklander 9696098f01SJens Wiklander TEE_Result crypto_cipher_alloc_ctx(void **ctx, uint32_t algo) 9782d91db1SJens Wiklander { 98e43ab7a8SCedric Neveux TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; 9996098f01SJens Wiklander struct crypto_cipher_ctx *c = NULL; 10096098f01SJens Wiklander 101e43ab7a8SCedric Neveux /* 102e43ab7a8SCedric Neveux * Use default cryptographic implementation if no matching 103e43ab7a8SCedric Neveux * drvcrypt device. 104e43ab7a8SCedric Neveux */ 105e43ab7a8SCedric Neveux res = drvcrypt_cipher_alloc_ctx(&c, algo); 106e43ab7a8SCedric Neveux 107e43ab7a8SCedric Neveux if (res == TEE_ERROR_NOT_IMPLEMENTED) { 10896098f01SJens Wiklander switch (algo) { 10996098f01SJens Wiklander case TEE_ALG_AES_ECB_NOPAD: 11096098f01SJens Wiklander res = crypto_aes_ecb_alloc_ctx(&c); 11196098f01SJens Wiklander break; 11296098f01SJens Wiklander case TEE_ALG_AES_CBC_NOPAD: 11396098f01SJens Wiklander res = crypto_aes_cbc_alloc_ctx(&c); 11496098f01SJens Wiklander break; 11596098f01SJens Wiklander case TEE_ALG_AES_CTR: 11696098f01SJens Wiklander res = crypto_aes_ctr_alloc_ctx(&c); 11796098f01SJens Wiklander break; 11896098f01SJens Wiklander case TEE_ALG_AES_CTS: 11996098f01SJens Wiklander res = crypto_aes_cts_alloc_ctx(&c); 12096098f01SJens Wiklander break; 12196098f01SJens Wiklander case TEE_ALG_AES_XTS: 12296098f01SJens Wiklander res = crypto_aes_xts_alloc_ctx(&c); 12396098f01SJens Wiklander break; 12496098f01SJens Wiklander case TEE_ALG_DES_ECB_NOPAD: 12596098f01SJens Wiklander res = crypto_des_ecb_alloc_ctx(&c); 12696098f01SJens Wiklander break; 12796098f01SJens Wiklander case TEE_ALG_DES3_ECB_NOPAD: 12896098f01SJens Wiklander res = crypto_des3_ecb_alloc_ctx(&c); 12996098f01SJens Wiklander break; 13096098f01SJens Wiklander case TEE_ALG_DES_CBC_NOPAD: 13196098f01SJens Wiklander res = crypto_des_cbc_alloc_ctx(&c); 13296098f01SJens Wiklander break; 13396098f01SJens Wiklander case TEE_ALG_DES3_CBC_NOPAD: 13496098f01SJens Wiklander res = crypto_des3_cbc_alloc_ctx(&c); 13596098f01SJens Wiklander break; 136ade6f848SJerome Forissier case TEE_ALG_SM4_ECB_NOPAD: 137ade6f848SJerome Forissier res = crypto_sm4_ecb_alloc_ctx(&c); 138ade6f848SJerome Forissier break; 139ade6f848SJerome Forissier case TEE_ALG_SM4_CBC_NOPAD: 140ade6f848SJerome Forissier res = crypto_sm4_cbc_alloc_ctx(&c); 141ade6f848SJerome Forissier break; 142ade6f848SJerome Forissier case TEE_ALG_SM4_CTR: 143ade6f848SJerome Forissier res = crypto_sm4_ctr_alloc_ctx(&c); 144ade6f848SJerome Forissier break; 14596098f01SJens Wiklander default: 1461c5fdd1fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 14782d91db1SJens Wiklander } 148e43ab7a8SCedric Neveux } 14982d91db1SJens Wiklander 15096098f01SJens Wiklander if (!res) 15196098f01SJens Wiklander *ctx = c; 15296098f01SJens Wiklander 15396098f01SJens Wiklander return res; 15496098f01SJens Wiklander } 15596098f01SJens Wiklander 15696098f01SJens Wiklander static const struct crypto_cipher_ops *cipher_ops(void *ctx) 15796098f01SJens Wiklander { 15896098f01SJens Wiklander struct crypto_cipher_ctx *c = ctx; 15996098f01SJens Wiklander 16096098f01SJens Wiklander assert(c && c->ops); 16196098f01SJens Wiklander 16296098f01SJens Wiklander return c->ops; 16396098f01SJens Wiklander } 16496098f01SJens Wiklander 165cbda7091SJens Wiklander void crypto_cipher_free_ctx(void *ctx) 16672a9b1a0SJens Wiklander { 167ce7a47f5SJerome Forissier if (ctx) 16896098f01SJens Wiklander cipher_ops(ctx)->free_ctx(ctx); 16972a9b1a0SJens Wiklander } 17072a9b1a0SJens Wiklander 171cbda7091SJens Wiklander void crypto_cipher_copy_state(void *dst_ctx, void *src_ctx) 17272a9b1a0SJens Wiklander { 17396098f01SJens Wiklander cipher_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); 17472a9b1a0SJens Wiklander } 17572a9b1a0SJens Wiklander 176cbda7091SJens Wiklander TEE_Result crypto_cipher_init(void *ctx, TEE_OperationMode mode, 177cbda7091SJens Wiklander const uint8_t *key1, size_t key1_len, 178cbda7091SJens Wiklander const uint8_t *key2, size_t key2_len, 179cbda7091SJens Wiklander const uint8_t *iv, size_t iv_len) 18082d91db1SJens Wiklander { 18196098f01SJens Wiklander if (mode != TEE_MODE_DECRYPT && mode != TEE_MODE_ENCRYPT) 18296098f01SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 18396098f01SJens Wiklander 18496098f01SJens Wiklander return cipher_ops(ctx)->init(ctx, mode, key1, key1_len, key2, key2_len, 18596098f01SJens Wiklander iv, iv_len); 18682d91db1SJens Wiklander } 18782d91db1SJens Wiklander 188cbda7091SJens Wiklander TEE_Result crypto_cipher_update(void *ctx, TEE_OperationMode mode __unused, 18996098f01SJens Wiklander bool last_block, const uint8_t *data, 19096098f01SJens Wiklander size_t len, uint8_t *dst) 19182d91db1SJens Wiklander { 19296098f01SJens Wiklander return cipher_ops(ctx)->update(ctx, last_block, data, len, dst); 19382d91db1SJens Wiklander } 19482d91db1SJens Wiklander 195cbda7091SJens Wiklander void crypto_cipher_final(void *ctx) 19682d91db1SJens Wiklander { 19796098f01SJens Wiklander cipher_ops(ctx)->final(ctx); 19882d91db1SJens Wiklander } 199e9eaba5cSJens Wiklander 2006d259e05SJens Wiklander TEE_Result crypto_cipher_get_block_size(uint32_t algo, size_t *size) 2016d259e05SJens Wiklander { 2026d259e05SJens Wiklander uint32_t class = TEE_ALG_GET_CLASS(algo); 2036d259e05SJens Wiklander 2046d259e05SJens Wiklander if (class != TEE_OPERATION_CIPHER && class != TEE_OPERATION_MAC && 2056d259e05SJens Wiklander class != TEE_OPERATION_AE) 2066d259e05SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 2076d259e05SJens Wiklander 2086d259e05SJens Wiklander switch (TEE_ALG_GET_MAIN_ALG(algo)) { 2096d259e05SJens Wiklander case TEE_MAIN_ALGO_AES: 2106d259e05SJens Wiklander *size = TEE_AES_BLOCK_SIZE; 2116d259e05SJens Wiklander return TEE_SUCCESS; 2126d259e05SJens Wiklander case TEE_MAIN_ALGO_DES: 2136d259e05SJens Wiklander case TEE_MAIN_ALGO_DES3: 2146d259e05SJens Wiklander *size = TEE_DES_BLOCK_SIZE; 2156d259e05SJens Wiklander return TEE_SUCCESS; 216ade6f848SJerome Forissier case TEE_MAIN_ALGO_SM4: 217ade6f848SJerome Forissier *size = TEE_SM4_BLOCK_SIZE; 218ade6f848SJerome Forissier return TEE_SUCCESS; 2196d259e05SJens Wiklander default: 2206d259e05SJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 2216d259e05SJens Wiklander } 2226d259e05SJens Wiklander } 2236d259e05SJens Wiklander 2245da36a24SJens Wiklander TEE_Result crypto_mac_alloc_ctx(void **ctx, uint32_t algo) 225e9eaba5cSJens Wiklander { 2265da36a24SJens Wiklander TEE_Result res = TEE_SUCCESS; 2275da36a24SJens Wiklander struct crypto_mac_ctx *c = NULL; 2285da36a24SJens Wiklander 229*ea9ac29cSCedric Neveux /* 230*ea9ac29cSCedric Neveux * Use default cryptographic implementation if no matching 231*ea9ac29cSCedric Neveux * drvcrypt device. 232*ea9ac29cSCedric Neveux */ 233*ea9ac29cSCedric Neveux res = drvcrypt_mac_alloc_ctx(&c, algo); 234*ea9ac29cSCedric Neveux 235*ea9ac29cSCedric Neveux if (res == TEE_ERROR_NOT_IMPLEMENTED) { 2365da36a24SJens Wiklander switch (algo) { 2375da36a24SJens Wiklander case TEE_ALG_HMAC_MD5: 2385da36a24SJens Wiklander res = crypto_hmac_md5_alloc_ctx(&c); 2395da36a24SJens Wiklander break; 2405da36a24SJens Wiklander case TEE_ALG_HMAC_SHA1: 2415da36a24SJens Wiklander res = crypto_hmac_sha1_alloc_ctx(&c); 2425da36a24SJens Wiklander break; 2435da36a24SJens Wiklander case TEE_ALG_HMAC_SHA224: 2445da36a24SJens Wiklander res = crypto_hmac_sha224_alloc_ctx(&c); 2455da36a24SJens Wiklander break; 2465da36a24SJens Wiklander case TEE_ALG_HMAC_SHA256: 2475da36a24SJens Wiklander res = crypto_hmac_sha256_alloc_ctx(&c); 2485da36a24SJens Wiklander break; 2495da36a24SJens Wiklander case TEE_ALG_HMAC_SHA384: 2505da36a24SJens Wiklander res = crypto_hmac_sha384_alloc_ctx(&c); 2515da36a24SJens Wiklander break; 2525da36a24SJens Wiklander case TEE_ALG_HMAC_SHA512: 2535da36a24SJens Wiklander res = crypto_hmac_sha512_alloc_ctx(&c); 2545da36a24SJens Wiklander break; 25547645577SJerome Forissier case TEE_ALG_HMAC_SM3: 25647645577SJerome Forissier res = crypto_hmac_sm3_alloc_ctx(&c); 25747645577SJerome Forissier break; 2585da36a24SJens Wiklander case TEE_ALG_AES_CBC_MAC_NOPAD: 2595da36a24SJens Wiklander res = crypto_aes_cbc_mac_nopad_alloc_ctx(&c); 2605da36a24SJens Wiklander break; 2615da36a24SJens Wiklander case TEE_ALG_AES_CBC_MAC_PKCS5: 2625da36a24SJens Wiklander res = crypto_aes_cbc_mac_pkcs5_alloc_ctx(&c); 2635da36a24SJens Wiklander break; 2645da36a24SJens Wiklander case TEE_ALG_DES_CBC_MAC_NOPAD: 2655da36a24SJens Wiklander res = crypto_des_cbc_mac_nopad_alloc_ctx(&c); 2665da36a24SJens Wiklander break; 2675da36a24SJens Wiklander case TEE_ALG_DES_CBC_MAC_PKCS5: 2685da36a24SJens Wiklander res = crypto_des_cbc_mac_pkcs5_alloc_ctx(&c); 2695da36a24SJens Wiklander break; 2705da36a24SJens Wiklander case TEE_ALG_DES3_CBC_MAC_NOPAD: 2715da36a24SJens Wiklander res = crypto_des3_cbc_mac_nopad_alloc_ctx(&c); 2725da36a24SJens Wiklander break; 2735da36a24SJens Wiklander case TEE_ALG_DES3_CBC_MAC_PKCS5: 2745da36a24SJens Wiklander res = crypto_des3_cbc_mac_pkcs5_alloc_ctx(&c); 2755da36a24SJens Wiklander break; 2765da36a24SJens Wiklander case TEE_ALG_AES_CMAC: 2775da36a24SJens Wiklander res = crypto_aes_cmac_alloc_ctx(&c); 2785da36a24SJens Wiklander break; 2795da36a24SJens Wiklander default: 2805da36a24SJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 2815da36a24SJens Wiklander } 282*ea9ac29cSCedric Neveux } 2835da36a24SJens Wiklander 2845da36a24SJens Wiklander if (!res) 2855da36a24SJens Wiklander *ctx = c; 2865da36a24SJens Wiklander 2875da36a24SJens Wiklander return res; 2885da36a24SJens Wiklander } 2895da36a24SJens Wiklander 2905da36a24SJens Wiklander static const struct crypto_mac_ops *mac_ops(void *ctx) 2915da36a24SJens Wiklander { 2925da36a24SJens Wiklander struct crypto_mac_ctx *c = ctx; 2935da36a24SJens Wiklander 2945da36a24SJens Wiklander assert(c && c->ops); 2955da36a24SJens Wiklander 2965da36a24SJens Wiklander return c->ops; 297e9eaba5cSJens Wiklander } 298e9eaba5cSJens Wiklander 299c69bc615SJens Wiklander void crypto_mac_free_ctx(void *ctx) 30082ef73bcSJens Wiklander { 301ce7a47f5SJerome Forissier if (ctx) 3025da36a24SJens Wiklander mac_ops(ctx)->free_ctx(ctx); 30382ef73bcSJens Wiklander } 30482ef73bcSJens Wiklander 305c69bc615SJens Wiklander void crypto_mac_copy_state(void *dst_ctx, void *src_ctx) 30682ef73bcSJens Wiklander { 3075da36a24SJens Wiklander mac_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); 30882ef73bcSJens Wiklander } 30982ef73bcSJens Wiklander 310c69bc615SJens Wiklander TEE_Result crypto_mac_init(void *ctx, const uint8_t *key, size_t len) 311e9eaba5cSJens Wiklander { 3125da36a24SJens Wiklander return mac_ops(ctx)->init(ctx, key, len); 313e9eaba5cSJens Wiklander } 314e9eaba5cSJens Wiklander 315c69bc615SJens Wiklander TEE_Result crypto_mac_update(void *ctx, const uint8_t *data, size_t len) 316e9eaba5cSJens Wiklander { 3175da36a24SJens Wiklander if (!len) 3185da36a24SJens Wiklander return TEE_SUCCESS; 3195da36a24SJens Wiklander 3205da36a24SJens Wiklander return mac_ops(ctx)->update(ctx, data, len); 321e9eaba5cSJens Wiklander } 322e9eaba5cSJens Wiklander 323c69bc615SJens Wiklander TEE_Result crypto_mac_final(void *ctx, uint8_t *digest, size_t digest_len) 324e9eaba5cSJens Wiklander { 3255da36a24SJens Wiklander return mac_ops(ctx)->final(ctx, digest, digest_len); 326e9eaba5cSJens Wiklander } 327e9eaba5cSJens Wiklander 328d7ac7d0fSJens Wiklander TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo) 3298875ce46SJens Wiklander { 330f1e9b21bSJens Wiklander TEE_Result res = TEE_SUCCESS; 331f1e9b21bSJens Wiklander struct crypto_authenc_ctx *c = NULL; 332f1e9b21bSJens Wiklander 333d0620b01SJens Wiklander switch (algo) { 334d0620b01SJens Wiklander #if defined(CFG_CRYPTO_CCM) 335d0620b01SJens Wiklander case TEE_ALG_AES_CCM: 336f1e9b21bSJens Wiklander res = crypto_aes_ccm_alloc_ctx(&c); 337f1e9b21bSJens Wiklander break; 338d0620b01SJens Wiklander #endif 339d0620b01SJens Wiklander #if defined(CFG_CRYPTO_GCM) 340d0620b01SJens Wiklander case TEE_ALG_AES_GCM: 341f1e9b21bSJens Wiklander res = crypto_aes_gcm_alloc_ctx(&c); 342f1e9b21bSJens Wiklander break; 343d0620b01SJens Wiklander #endif 344d0620b01SJens Wiklander default: 3458875ce46SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 3468875ce46SJens Wiklander } 347f1e9b21bSJens Wiklander 348f1e9b21bSJens Wiklander if (!res) 349f1e9b21bSJens Wiklander *ctx = c; 350f1e9b21bSJens Wiklander 351f1e9b21bSJens Wiklander return res; 352d0620b01SJens Wiklander } 3538875ce46SJens Wiklander 354f1e9b21bSJens Wiklander static const struct crypto_authenc_ops *ae_ops(void *ctx) 355d7ac7d0fSJens Wiklander { 356f1e9b21bSJens Wiklander struct crypto_authenc_ctx *c = ctx; 357f1e9b21bSJens Wiklander 358f1e9b21bSJens Wiklander assert(c && c->ops); 359f1e9b21bSJens Wiklander 360f1e9b21bSJens Wiklander return c->ops; 361d7ac7d0fSJens Wiklander } 362d7ac7d0fSJens Wiklander 36352ee414bSJens Wiklander TEE_Result crypto_authenc_init(void *ctx, TEE_OperationMode mode, 364f1e9b21bSJens Wiklander const uint8_t *key, size_t key_len, 365f1e9b21bSJens Wiklander const uint8_t *nonce, size_t nonce_len, 366f1e9b21bSJens Wiklander size_t tag_len, size_t aad_len, 367f1e9b21bSJens Wiklander size_t payload_len) 368d7ac7d0fSJens Wiklander { 369f1e9b21bSJens Wiklander return ae_ops(ctx)->init(ctx, mode, key, key_len, nonce, nonce_len, 370f1e9b21bSJens Wiklander tag_len, aad_len, payload_len); 371d7ac7d0fSJens Wiklander } 372d7ac7d0fSJens Wiklander 37352ee414bSJens Wiklander TEE_Result crypto_authenc_update_aad(void *ctx, TEE_OperationMode mode __unused, 374f1e9b21bSJens Wiklander const uint8_t *data, size_t len) 3758875ce46SJens Wiklander { 376f1e9b21bSJens Wiklander return ae_ops(ctx)->update_aad(ctx, data, len); 377d0620b01SJens Wiklander } 3788875ce46SJens Wiklander 379d0620b01SJens Wiklander 38052ee414bSJens Wiklander TEE_Result crypto_authenc_update_payload(void *ctx, TEE_OperationMode mode, 381f1e9b21bSJens Wiklander const uint8_t *src_data, 382f1e9b21bSJens Wiklander size_t src_len, uint8_t *dst_data, 383f1e9b21bSJens Wiklander size_t *dst_len) 384f1e9b21bSJens Wiklander { 385f1e9b21bSJens Wiklander if (*dst_len < src_len) 386d0620b01SJens Wiklander return TEE_ERROR_SHORT_BUFFER; 387d0620b01SJens Wiklander *dst_len = src_len; 388d0620b01SJens Wiklander 389f1e9b21bSJens Wiklander return ae_ops(ctx)->update_payload(ctx, mode, src_data, src_len, 390f1e9b21bSJens Wiklander dst_data); 391d0620b01SJens Wiklander } 3928875ce46SJens Wiklander 39352ee414bSJens Wiklander TEE_Result crypto_authenc_enc_final(void *ctx, const uint8_t *src_data, 39452ee414bSJens Wiklander size_t src_len, uint8_t *dst_data, 39552ee414bSJens Wiklander size_t *dst_len, uint8_t *dst_tag, 39652ee414bSJens Wiklander size_t *dst_tag_len) 3978875ce46SJens Wiklander { 398f1e9b21bSJens Wiklander if (*dst_len < src_len) 399f1e9b21bSJens Wiklander return TEE_ERROR_SHORT_BUFFER; 400d0620b01SJens Wiklander *dst_len = src_len; 401d0620b01SJens Wiklander 402f1e9b21bSJens Wiklander return ae_ops(ctx)->enc_final(ctx, src_data, src_len, dst_data, 403f1e9b21bSJens Wiklander dst_tag, dst_tag_len); 4048875ce46SJens Wiklander } 4058875ce46SJens Wiklander 40652ee414bSJens Wiklander TEE_Result crypto_authenc_dec_final(void *ctx, const uint8_t *src_data, 40752ee414bSJens Wiklander size_t src_len, uint8_t *dst_data, 40852ee414bSJens Wiklander size_t *dst_len, const uint8_t *tag, 40952ee414bSJens Wiklander size_t tag_len) 4108875ce46SJens Wiklander { 411f1e9b21bSJens Wiklander if (*dst_len < src_len) 412f1e9b21bSJens Wiklander return TEE_ERROR_SHORT_BUFFER; 413f1e9b21bSJens Wiklander *dst_len = src_len; 414f1e9b21bSJens Wiklander 415f1e9b21bSJens Wiklander return ae_ops(ctx)->dec_final(ctx, src_data, src_len, dst_data, tag, 416f1e9b21bSJens Wiklander tag_len); 4178875ce46SJens Wiklander } 418f1e9b21bSJens Wiklander 41952ee414bSJens Wiklander void crypto_authenc_final(void *ctx) 420f1e9b21bSJens Wiklander { 421f1e9b21bSJens Wiklander ae_ops(ctx)->final(ctx); 422f1e9b21bSJens Wiklander } 423f1e9b21bSJens Wiklander 42452ee414bSJens Wiklander void crypto_authenc_free_ctx(void *ctx) 425f1e9b21bSJens Wiklander { 426f1e9b21bSJens Wiklander if (ctx) 427f1e9b21bSJens Wiklander ae_ops(ctx)->free_ctx(ctx); 428f1e9b21bSJens Wiklander } 429f1e9b21bSJens Wiklander 43052ee414bSJens Wiklander void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx) 431f1e9b21bSJens Wiklander { 432f1e9b21bSJens Wiklander ae_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); 433d0620b01SJens Wiklander } 43433790cc1SJens Wiklander 435da1de557SJens Wiklander #if !defined(CFG_CRYPTO_RSA) && !defined(CFG_CRYPTO_DSA) && \ 436da1de557SJens Wiklander !defined(CFG_CRYPTO_DH) && !defined(CFG_CRYPTO_ECC) 43733790cc1SJens Wiklander struct bignum *crypto_bignum_allocate(size_t size_bits __unused) 43833790cc1SJens Wiklander { 43933790cc1SJens Wiklander return NULL; 44033790cc1SJens Wiklander } 44133790cc1SJens Wiklander 44233790cc1SJens Wiklander TEE_Result crypto_bignum_bin2bn(const uint8_t *from __unused, 44333790cc1SJens Wiklander size_t fromsize __unused, 44433790cc1SJens Wiklander struct bignum *to __unused) 44533790cc1SJens Wiklander { 44633790cc1SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 44733790cc1SJens Wiklander } 44833790cc1SJens Wiklander 44933790cc1SJens Wiklander size_t crypto_bignum_num_bytes(struct bignum *a __unused) 45033790cc1SJens Wiklander { 45133790cc1SJens Wiklander return 0; 45233790cc1SJens Wiklander } 45333790cc1SJens Wiklander 45433790cc1SJens Wiklander size_t crypto_bignum_num_bits(struct bignum *a __unused) 45533790cc1SJens Wiklander { 45633790cc1SJens Wiklander return 0; 45733790cc1SJens Wiklander } 45833790cc1SJens Wiklander 45933790cc1SJens Wiklander /* 46033790cc1SJens Wiklander * crypto_bignum_allocate() and crypto_bignum_bin2bn() failing should be 46133790cc1SJens Wiklander * enough to guarantee that the functions calling this function aren't 46233790cc1SJens Wiklander * called, but just in case add a panic() here to avoid unexpected 46333790cc1SJens Wiklander * behavoir. 46433790cc1SJens Wiklander */ 46533790cc1SJens Wiklander static void bignum_cant_happen(void) 46633790cc1SJens Wiklander { 46733790cc1SJens Wiklander volatile bool b = true; 46833790cc1SJens Wiklander 46933790cc1SJens Wiklander /* Avoid warning about function does not return */ 47033790cc1SJens Wiklander if (b) 47133790cc1SJens Wiklander panic(); 47233790cc1SJens Wiklander } 47333790cc1SJens Wiklander 47433790cc1SJens Wiklander void crypto_bignum_bn2bin(const struct bignum *from __unused, 47533790cc1SJens Wiklander uint8_t *to __unused) 47633790cc1SJens Wiklander { 47733790cc1SJens Wiklander bignum_cant_happen(); 47833790cc1SJens Wiklander } 47933790cc1SJens Wiklander 48033790cc1SJens Wiklander void crypto_bignum_copy(struct bignum *to __unused, 48133790cc1SJens Wiklander const struct bignum *from __unused) 48233790cc1SJens Wiklander { 48333790cc1SJens Wiklander bignum_cant_happen(); 48433790cc1SJens Wiklander } 48533790cc1SJens Wiklander 48633790cc1SJens Wiklander void crypto_bignum_free(struct bignum *a) 48733790cc1SJens Wiklander { 48833790cc1SJens Wiklander if (a) 48933790cc1SJens Wiklander panic(); 49033790cc1SJens Wiklander } 49133790cc1SJens Wiklander 49233790cc1SJens Wiklander void crypto_bignum_clear(struct bignum *a __unused) 49333790cc1SJens Wiklander { 49433790cc1SJens Wiklander bignum_cant_happen(); 49533790cc1SJens Wiklander } 49633790cc1SJens Wiklander 49733790cc1SJens Wiklander /* return -1 if a<b, 0 if a==b, +1 if a>b */ 49833790cc1SJens Wiklander int32_t crypto_bignum_compare(struct bignum *a __unused, 49933790cc1SJens Wiklander struct bignum *b __unused) 50033790cc1SJens Wiklander { 50133790cc1SJens Wiklander bignum_cant_happen(); 50233790cc1SJens Wiklander return -1; 50333790cc1SJens Wiklander } 504da1de557SJens Wiklander #endif 505291e5450SJens Wiklander 506da1de557SJens Wiklander #if !defined(CFG_CRYPTO_RSA) 507291e5450SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s __unused, 508291e5450SJens Wiklander size_t key_size_bits __unused) 509291e5450SJens Wiklander { 510291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 511291e5450SJens Wiklander } 512291e5450SJens Wiklander 513291e5450SJens Wiklander TEE_Result 514291e5450SJens Wiklander crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s __unused, 515291e5450SJens Wiklander size_t key_size_bits __unused) 516291e5450SJens Wiklander { 517291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 518291e5450SJens Wiklander } 519291e5450SJens Wiklander 520291e5450SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s __unused) 521291e5450SJens Wiklander { 522291e5450SJens Wiklander } 523291e5450SJens Wiklander 524291e5450SJens Wiklander TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key __unused, 525291e5450SJens Wiklander size_t key_size __unused) 526291e5450SJens Wiklander { 527291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 528291e5450SJens Wiklander } 529291e5450SJens Wiklander 530291e5450SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key __unused, 531291e5450SJens Wiklander const uint8_t *src __unused, 532291e5450SJens Wiklander size_t src_len __unused, 533291e5450SJens Wiklander uint8_t *dst __unused, 534291e5450SJens Wiklander size_t *dst_len __unused) 535291e5450SJens Wiklander { 536291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 537291e5450SJens Wiklander } 538291e5450SJens Wiklander 539291e5450SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key __unused, 540291e5450SJens Wiklander const uint8_t *src __unused, 541291e5450SJens Wiklander size_t src_len __unused, 542291e5450SJens Wiklander uint8_t *dst __unused, 543291e5450SJens Wiklander size_t *dst_len __unused) 544291e5450SJens Wiklander { 545291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 546291e5450SJens Wiklander } 547291e5450SJens Wiklander 548291e5450SJens Wiklander TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo __unused, 549291e5450SJens Wiklander struct rsa_keypair *key __unused, 550291e5450SJens Wiklander const uint8_t *label __unused, 551291e5450SJens Wiklander size_t label_len __unused, 552291e5450SJens Wiklander const uint8_t *src __unused, 553291e5450SJens Wiklander size_t src_len __unused, 554291e5450SJens Wiklander uint8_t *dst __unused, 555291e5450SJens Wiklander size_t *dst_len __unused) 556291e5450SJens Wiklander { 557291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 558291e5450SJens Wiklander } 559291e5450SJens Wiklander 560291e5450SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo __unused, 561291e5450SJens Wiklander struct rsa_public_key *key __unused, 562291e5450SJens Wiklander const uint8_t *label __unused, 563291e5450SJens Wiklander size_t label_len __unused, 564291e5450SJens Wiklander const uint8_t *src __unused, 565291e5450SJens Wiklander size_t src_len __unused, 566291e5450SJens Wiklander uint8_t *dst __unused, 567291e5450SJens Wiklander size_t *dst_len __unused) 568291e5450SJens Wiklander { 569291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 570291e5450SJens Wiklander } 571291e5450SJens Wiklander 572291e5450SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo __unused, 573291e5450SJens Wiklander struct rsa_keypair *key __unused, 574291e5450SJens Wiklander int salt_len __unused, 575291e5450SJens Wiklander const uint8_t *msg __unused, 576291e5450SJens Wiklander size_t msg_len __unused, 577291e5450SJens Wiklander uint8_t *sig __unused, 578291e5450SJens Wiklander size_t *sig_len __unused) 579291e5450SJens Wiklander { 580291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 581291e5450SJens Wiklander } 582291e5450SJens Wiklander 583291e5450SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo __unused, 584291e5450SJens Wiklander struct rsa_public_key *key __unused, 585291e5450SJens Wiklander int salt_len __unused, 586291e5450SJens Wiklander const uint8_t *msg __unused, 587291e5450SJens Wiklander size_t msg_len __unused, 588291e5450SJens Wiklander const uint8_t *sig __unused, 589291e5450SJens Wiklander size_t sig_len __unused) 590291e5450SJens Wiklander { 591291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 592291e5450SJens Wiklander } 593da1de557SJens Wiklander #endif /*!CFG_CRYPTO_RSA*/ 594291e5450SJens Wiklander 595da1de557SJens Wiklander #if !defined(CFG_CRYPTO_DSA) 596291e5450SJens Wiklander TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s __unused, 597291e5450SJens Wiklander size_t key_size_bits __unused) 598291e5450SJens Wiklander { 599291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 600291e5450SJens Wiklander } 601291e5450SJens Wiklander 602291e5450SJens Wiklander TEE_Result 603291e5450SJens Wiklander crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s __unused, 604291e5450SJens Wiklander size_t key_size_bits __unused) 605291e5450SJens Wiklander { 606291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 607291e5450SJens Wiklander } 608291e5450SJens Wiklander 609291e5450SJens Wiklander TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key __unused, 610291e5450SJens Wiklander size_t key_size __unused) 611291e5450SJens Wiklander { 612291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 613291e5450SJens Wiklander } 614291e5450SJens Wiklander 615291e5450SJens Wiklander TEE_Result crypto_acipher_dsa_sign(uint32_t algo __unused, 616291e5450SJens Wiklander struct dsa_keypair *key __unused, 617291e5450SJens Wiklander const uint8_t *msg __unused, 618291e5450SJens Wiklander size_t msg_len __unused, 619291e5450SJens Wiklander uint8_t *sig __unused, 620291e5450SJens Wiklander size_t *sig_len __unused) 621291e5450SJens Wiklander { 622291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 623291e5450SJens Wiklander } 624291e5450SJens Wiklander 625291e5450SJens Wiklander TEE_Result crypto_acipher_dsa_verify(uint32_t algo __unused, 626291e5450SJens Wiklander struct dsa_public_key *key __unused, 627291e5450SJens Wiklander const uint8_t *msg __unused, 628291e5450SJens Wiklander size_t msg_len __unused, 629291e5450SJens Wiklander const uint8_t *sig __unused, 630291e5450SJens Wiklander size_t sig_len __unused) 631291e5450SJens Wiklander { 632291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 633291e5450SJens Wiklander } 634da1de557SJens Wiklander #endif /*!CFG_CRYPTO_DSA*/ 635291e5450SJens Wiklander 636da1de557SJens Wiklander #if !defined(CFG_CRYPTO_DH) 637291e5450SJens Wiklander TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s __unused, 638291e5450SJens Wiklander size_t key_size_bits __unused) 639291e5450SJens Wiklander { 640291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 641291e5450SJens Wiklander } 642291e5450SJens Wiklander 643291e5450SJens Wiklander TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key __unused, 644291e5450SJens Wiklander struct bignum *q __unused, 6459f4dcefbSJerome Forissier size_t xbits __unused, 6469f4dcefbSJerome Forissier size_t key_size __unused) 647291e5450SJens Wiklander { 648291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 649291e5450SJens Wiklander } 650291e5450SJens Wiklander 651291e5450SJens Wiklander TEE_Result 652291e5450SJens Wiklander crypto_acipher_dh_shared_secret(struct dh_keypair *private_key __unused, 653291e5450SJens Wiklander struct bignum *public_key __unused, 654291e5450SJens Wiklander struct bignum *secret __unused) 655291e5450SJens Wiklander { 656291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 657291e5450SJens Wiklander } 658da1de557SJens Wiklander #endif /*!CFG_CRYPTO_DH*/ 659291e5450SJens Wiklander 660da1de557SJens Wiklander #if !defined(CFG_CRYPTO_ECC) 661291e5450SJens Wiklander TEE_Result 662291e5450SJens Wiklander crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s __unused, 663291e5450SJens Wiklander size_t key_size_bits __unused) 664291e5450SJens Wiklander { 665291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 666291e5450SJens Wiklander } 667291e5450SJens Wiklander 668291e5450SJens Wiklander TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s __unused, 669291e5450SJens Wiklander size_t key_size_bits __unused) 670291e5450SJens Wiklander { 671291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 672291e5450SJens Wiklander } 673291e5450SJens Wiklander 674291e5450SJens Wiklander void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s __unused) 675291e5450SJens Wiklander { 676291e5450SJens Wiklander } 677291e5450SJens Wiklander 67821282baeSJerome Forissier TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key __unused, 67921282baeSJerome Forissier size_t key_size __unused) 680291e5450SJens Wiklander { 681291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 682291e5450SJens Wiklander } 683291e5450SJens Wiklander 684291e5450SJens Wiklander TEE_Result crypto_acipher_ecc_sign(uint32_t algo __unused, 685291e5450SJens Wiklander struct ecc_keypair *key __unused, 686291e5450SJens Wiklander const uint8_t *msg __unused, 687291e5450SJens Wiklander size_t msg_len __unused, 688291e5450SJens Wiklander uint8_t *sig __unused, 689291e5450SJens Wiklander size_t *sig_len __unused) 690291e5450SJens Wiklander { 691291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 692291e5450SJens Wiklander } 693291e5450SJens Wiklander 694291e5450SJens Wiklander TEE_Result crypto_acipher_ecc_verify(uint32_t algo __unused, 695291e5450SJens Wiklander struct ecc_public_key *key __unused, 696291e5450SJens Wiklander const uint8_t *msg __unused, 697291e5450SJens Wiklander size_t msg_len __unused, 698291e5450SJens Wiklander const uint8_t *sig __unused, 699291e5450SJens Wiklander size_t sig_len __unused) 700291e5450SJens Wiklander { 701291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 702291e5450SJens Wiklander } 703291e5450SJens Wiklander 704291e5450SJens Wiklander TEE_Result 705291e5450SJens Wiklander crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key __unused, 706291e5450SJens Wiklander struct ecc_public_key *public_key __unused, 707291e5450SJens Wiklander void *secret __unused, 708291e5450SJens Wiklander unsigned long *secret_len __unused) 709291e5450SJens Wiklander { 710291e5450SJens Wiklander return TEE_ERROR_NOT_IMPLEMENTED; 711291e5450SJens Wiklander } 712da1de557SJens Wiklander #endif /*!CFG_CRYPTO_ECC*/ 71391fc6bd8SJerome Forissier 71491fc6bd8SJerome Forissier #if !defined(CFG_CRYPTO_SM2_PKE) 71591fc6bd8SJerome Forissier TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key __unused, 71691fc6bd8SJerome Forissier const uint8_t *src __unused, 71791fc6bd8SJerome Forissier size_t src_len __unused, 71891fc6bd8SJerome Forissier uint8_t *dst __unused, 71991fc6bd8SJerome Forissier size_t *dst_len __unused) 72091fc6bd8SJerome Forissier { 72191fc6bd8SJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 72291fc6bd8SJerome Forissier } 72391fc6bd8SJerome Forissier 72491fc6bd8SJerome Forissier TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key __unused, 72591fc6bd8SJerome Forissier const uint8_t *src __unused, 72691fc6bd8SJerome Forissier size_t src_len __unused, 72791fc6bd8SJerome Forissier uint8_t *dst __unused, 72891fc6bd8SJerome Forissier size_t *dst_len __unused) 72991fc6bd8SJerome Forissier { 73091fc6bd8SJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 73191fc6bd8SJerome Forissier } 73291fc6bd8SJerome Forissier #endif /* !CFG_CRYPTO_SM2_PKE */ 7330f151943SJerome Forissier 7340f151943SJerome Forissier #if !defined(CFG_CRYPTO_SM2_DSA) 7350f151943SJerome Forissier TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo __unused, 7360f151943SJerome Forissier struct ecc_keypair *key __unused, 7370f151943SJerome Forissier const uint8_t *msg __unused, 7380f151943SJerome Forissier size_t msg_len __unused, 7390f151943SJerome Forissier uint8_t *sig __unused, 7400f151943SJerome Forissier size_t *sig_len __unused) 7410f151943SJerome Forissier { 7420f151943SJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 7430f151943SJerome Forissier } 7440f151943SJerome Forissier 7450f151943SJerome Forissier TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo __unused, 7460f151943SJerome Forissier struct ecc_public_key *key __unused, 7470f151943SJerome Forissier const uint8_t *msg __unused, 7480f151943SJerome Forissier size_t msg_len __unused, 7490f151943SJerome Forissier const uint8_t *sig __unused, 7500f151943SJerome Forissier size_t sig_len __unused) 7510f151943SJerome Forissier { 7520f151943SJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 7530f151943SJerome Forissier } 7540f151943SJerome Forissier #endif /* !CFG_CRYPTO_SM2_DSA */ 7555b385b3fSJerome Forissier #if !defined(CFG_CRYPTO_SM2_KEP) 7565b385b3fSJerome Forissier TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key __unused, 7575b385b3fSJerome Forissier struct ecc_keypair *my_eph_key 7585b385b3fSJerome Forissier __unused, 7595b385b3fSJerome Forissier struct ecc_public_key *peer_key 7605b385b3fSJerome Forissier __unused, 7615b385b3fSJerome Forissier struct ecc_public_key *peer_eph_key 7625b385b3fSJerome Forissier __unused, 7635b385b3fSJerome Forissier struct sm2_kep_parms *p __unused) 7645b385b3fSJerome Forissier { 7655b385b3fSJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 7665b385b3fSJerome Forissier } 7675b385b3fSJerome Forissier #endif 768